From 34bd0273b631742e8d929c80e90cb7782105d8da Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 24 Mar 2011 17:16:08 +0200 Subject: Bluetooth: delete hanging L2CAP channel Sometimes L2CAP connection remains hanging. Make sure that L2CAP channel is deleted. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index fc85e7ae33c..f77308e63e5 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -923,8 +923,9 @@ void __l2cap_sock_close(struct sock *sk, int reason) rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); l2cap_send_cmd(conn, l2cap_pi(sk)->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); - } else - l2cap_chan_del(sk, reason); + } + + l2cap_chan_del(sk, reason); break; case BT_CONNECT: -- cgit v1.2.3-70-g09d2 From 48454079c2d4b9ee65c570a22c5fdfe1827996a4 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 00:22:30 -0300 Subject: Bluetooth: Create struct l2cap_chan struct l2cap_chan cames to create a clear separation between what properties and data belongs to the L2CAP channel and what belongs to the socket. By now we just fold the struct sock * in struct l2cap_chan as all the channel info is struct l2cap_pinfo today. In the next commits we will see a move of channel stuff to struct l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 18 ++- net/bluetooth/l2cap_core.c | 247 +++++++++++++++++++++++++++--------------- net/bluetooth/l2cap_sock.c | 6 +- 3 files changed, 175 insertions(+), 96 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 2b9ca0d5c4a..6378bcc94e2 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -276,9 +276,16 @@ struct l2cap_conn_param_update_rsp { #define L2CAP_CONN_PARAM_ACCEPTED 0x0000 #define L2CAP_CONN_PARAM_REJECTED 0x0001 -/* ----- L2CAP connections ----- */ +/* ----- L2CAP channels and connections ----- */ + +struct l2cap_chan { + struct sock *sk; + struct l2cap_chan *next_c; + struct l2cap_chan *prev_c; +}; + struct l2cap_chan_list { - struct sock *head; + struct l2cap_chan *head; rwlock_t lock; }; @@ -317,7 +324,7 @@ struct sock_del_list { #define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04 #define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08 -/* ----- L2CAP channel and socket info ----- */ +/* ----- L2CAP socket info ----- */ #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) #define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue) @@ -389,8 +396,7 @@ struct l2cap_pinfo { struct work_struct busy_work; struct srej_list srej_l; struct l2cap_conn *conn; - struct sock *next_c; - struct sock *prev_c; + struct l2cap_chan *chan; }; #define L2CAP_CONF_REQ_SENT 0x01 @@ -471,7 +477,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent); struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err); -void l2cap_chan_del(struct sock *sk, int err); +void l2cap_chan_del(struct l2cap_chan *chan, int err); int l2cap_do_connect(struct sock *sk); #endif /* __L2CAP_H */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c3cebed205c..e49d8f7b80a 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -74,58 +74,58 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); /* ---- L2CAP channels ---- */ -static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) +static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) { - struct sock *s; - for (s = l->head; s; s = l2cap_pi(s)->next_c) { - if (l2cap_pi(s)->dcid == cid) + struct l2cap_chan *c; + for (c = l->head; c; c = c->next_c) { + if (l2cap_pi(c->sk)->dcid == cid) break; } - return s; + return c; } -static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) +static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) { - struct sock *s; - for (s = l->head; s; s = l2cap_pi(s)->next_c) { - if (l2cap_pi(s)->scid == cid) + struct l2cap_chan *c; + for (c = l->head; c; c = c->next_c) { + if (l2cap_pi(c->sk)->scid == cid) break; } - return s; + return c; } /* Find channel with given SCID. * Returns locked socket */ -static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) +static inline struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) { - struct sock *s; + struct l2cap_chan *c; read_lock(&l->lock); - s = __l2cap_get_chan_by_scid(l, cid); - if (s) - bh_lock_sock(s); + c = __l2cap_get_chan_by_scid(l, cid); + if (c) + bh_lock_sock(c->sk); read_unlock(&l->lock); - return s; + return c; } -static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) +static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) { - struct sock *s; - for (s = l->head; s; s = l2cap_pi(s)->next_c) { - if (l2cap_pi(s)->ident == ident) + struct l2cap_chan *c; + for (c = l->head; c; c = c->next_c) { + if (l2cap_pi(c->sk)->ident == ident) break; } - return s; + return c; } -static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) +static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) { - struct sock *s; + struct l2cap_chan *c; read_lock(&l->lock); - s = __l2cap_get_chan_by_ident(l, ident); - if (s) - bh_lock_sock(s); + c = __l2cap_get_chan_by_ident(l, ident); + if (c) + bh_lock_sock(c->sk); read_unlock(&l->lock); - return s; + return c; } static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) @@ -140,38 +140,52 @@ static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) return 0; } -static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk) +static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) +{ + struct l2cap_chan *chan; + + chan = kzalloc(sizeof(*chan), GFP_ATOMIC); + if (!chan) + return NULL; + + chan->sk = sk; + + return chan; +} + +static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct l2cap_chan *chan) { - sock_hold(sk); + sock_hold(chan->sk); if (l->head) - l2cap_pi(l->head)->prev_c = sk; + l->head->prev_c = chan; - l2cap_pi(sk)->next_c = l->head; - l2cap_pi(sk)->prev_c = NULL; - l->head = sk; + chan->next_c = l->head; + chan->prev_c = NULL; + l->head = chan; } -static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk) +static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct l2cap_chan *chan) { - struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c; + struct l2cap_chan *next = chan->next_c, *prev = chan->prev_c; write_lock_bh(&l->lock); - if (sk == l->head) + if (chan == l->head) l->head = next; if (next) - l2cap_pi(next)->prev_c = prev; + next->prev_c = prev; if (prev) - l2cap_pi(prev)->next_c = next; + prev->next_c = next; write_unlock_bh(&l->lock); - __sock_put(sk); + __sock_put(chan->sk); } -static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) +static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) { struct l2cap_chan_list *l = &conn->chan_list; + struct sock *sk = chan->sk; BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid); @@ -203,13 +217,14 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; } - __l2cap_chan_link(l, sk); + __l2cap_chan_link(l, chan); } /* Delete channel. * Must be called on the locked socket. */ -void l2cap_chan_del(struct sock *sk, int err) +void l2cap_chan_del(struct l2cap_chan *chan, int err) { + struct sock *sk = chan->sk; struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct sock *parent = bt_sk(sk)->parent; @@ -219,7 +234,7 @@ void l2cap_chan_del(struct sock *sk, int err) if (conn) { /* Unlink from channel list */ - l2cap_chan_unlink(&conn->chan_list, sk); + l2cap_chan_unlink(&conn->chan_list, chan); l2cap_pi(sk)->conn = NULL; hci_conn_put(conn->hcon); } @@ -253,6 +268,8 @@ void l2cap_chan_del(struct sock *sk, int err) kfree(l); } } + + kfree(chan); } static inline u8 l2cap_get_auth_type(struct sock *sk) @@ -487,7 +504,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) { struct l2cap_chan_list *l = &conn->chan_list; struct sock_del_list del, *tmp1, *tmp2; - struct sock *sk; + struct l2cap_chan *chan; BT_DBG("conn %p", conn); @@ -495,7 +512,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) read_lock(&l->lock); - for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + for (chan = l->head; chan; chan = chan->next_c) { + struct sock *sk = chan->sk; bh_lock_sock(sk); if (sk->sk_type != SOCK_SEQPACKET && @@ -622,6 +640,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) { struct l2cap_chan_list *list = &conn->chan_list; struct sock *parent, *uninitialized_var(sk); + struct l2cap_chan *chan; BT_DBG(""); @@ -641,6 +660,12 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) if (!sk) goto clean; + chan = l2cap_chan_alloc(sk); + if (!chan) { + l2cap_sock_kill(sk); + goto clean; + } + write_lock_bh(&list->lock); hci_conn_hold(conn->hcon); @@ -651,7 +676,9 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) bt_accept_enqueue(parent, sk); - __l2cap_chan_add(conn, sk); + __l2cap_chan_add(conn, chan); + + l2cap_pi(sk)->chan = chan; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -667,7 +694,7 @@ clean: static void l2cap_conn_ready(struct l2cap_conn *conn) { struct l2cap_chan_list *l = &conn->chan_list; - struct sock *sk; + struct l2cap_chan *chan; BT_DBG("conn %p", conn); @@ -676,7 +703,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) read_lock(&l->lock); - for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + for (chan = l->head; chan; chan = chan->next_c) { + struct sock *sk = chan->sk; bh_lock_sock(sk); if (conn->hcon->type == LE_LINK) { @@ -703,13 +731,14 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) { struct l2cap_chan_list *l = &conn->chan_list; - struct sock *sk; + struct l2cap_chan *chan; BT_DBG("conn %p", conn); read_lock(&l->lock); - for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + for (chan = l->head; chan; chan = chan->next_c) { + struct sock *sk = chan->sk; if (l2cap_pi(sk)->force_reliable) sk->sk_err = err; } @@ -768,6 +797,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) static void l2cap_conn_del(struct hci_conn *hcon, int err) { struct l2cap_conn *conn = hcon->l2cap_data; + struct l2cap_chan *chan; struct sock *sk; if (!conn) @@ -778,9 +808,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) kfree_skb(conn->rx_skb); /* Kill channels */ - while ((sk = conn->chan_list.head)) { + while ((chan = conn->chan_list.head)) { + sk = chan->sk; bh_lock_sock(sk); - l2cap_chan_del(sk, err); + l2cap_chan_del(chan, err); bh_unlock_sock(sk); l2cap_sock_kill(sk); } @@ -792,11 +823,11 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) kfree(conn); } -static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) +static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) { struct l2cap_chan_list *l = &conn->chan_list; write_lock_bh(&l->lock); - __l2cap_chan_add(conn, sk); + __l2cap_chan_add(conn, chan); write_unlock_bh(&l->lock); } @@ -837,6 +868,7 @@ int l2cap_do_connect(struct sock *sk) bdaddr_t *src = &bt_sk(sk)->src; bdaddr_t *dst = &bt_sk(sk)->dst; struct l2cap_conn *conn; + struct l2cap_chan *chan; struct hci_conn *hcon; struct hci_dev *hdev; __u8 auth_type; @@ -872,10 +904,19 @@ int l2cap_do_connect(struct sock *sk) goto done; } + chan = l2cap_chan_alloc(sk); + if (!chan) { + hci_conn_put(hcon); + err = -ENOMEM; + goto done; + } + /* Update source addr of the socket */ bacpy(src, conn->src); - l2cap_chan_add(conn, sk); + l2cap_chan_add(conn, chan); + + l2cap_pi(sk)->chan = chan; sk->sk_state = BT_CONNECT; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -1387,12 +1428,13 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) { struct l2cap_chan_list *l = &conn->chan_list; struct sk_buff *nskb; - struct sock *sk; + struct l2cap_chan *chan; BT_DBG("conn %p", conn); read_lock(&l->lock); - for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + for (chan = l->head; chan; chan = chan->next_c) { + struct sock *sk = chan->sk; if (sk->sk_type != SOCK_RAW) continue; @@ -1976,6 +2018,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd struct l2cap_chan_list *list = &conn->chan_list; struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; struct l2cap_conn_rsp rsp; + struct l2cap_chan *chan; struct sock *parent, *sk = NULL; int result, status = L2CAP_CS_NO_INFO; @@ -2013,6 +2056,12 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd if (!sk) goto response; + chan = l2cap_chan_alloc(sk); + if (!chan) { + l2cap_sock_kill(sk); + goto response; + } + write_lock_bh(&list->lock); /* Check if we already have channel with that dcid */ @@ -2033,7 +2082,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd bt_accept_enqueue(parent, sk); - __l2cap_chan_add(conn, sk); + __l2cap_chan_add(conn, chan); + + l2cap_pi(sk)->chan = chan; + dcid = l2cap_pi(sk)->scid; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -2105,6 +2157,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd { struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; u16 scid, dcid, result, status; + struct l2cap_chan *chan; struct sock *sk; u8 req[128]; @@ -2116,15 +2169,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status); if (scid) { - sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); - if (!sk) + chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); + if (!chan) return -EFAULT; } else { - sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident); - if (!sk) + chan = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident); + if (!chan) return -EFAULT; } + sk = chan->sk; + switch (result) { case L2CAP_CR_SUCCESS: sk->sk_state = BT_CONFIG; @@ -2155,7 +2210,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd break; } - l2cap_chan_del(sk, ECONNREFUSED); + l2cap_chan_del(chan, ECONNREFUSED); break; } @@ -2179,6 +2234,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; u16 dcid, flags; u8 rsp[64]; + struct l2cap_chan *chan; struct sock *sk; int len; @@ -2187,10 +2243,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); - sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid); - if (!sk) + chan = l2cap_get_chan_by_scid(&conn->chan_list, dcid); + if (!chan) return -ENOENT; + sk = chan->sk; + if (sk->sk_state != BT_CONFIG) { struct l2cap_cmd_rej rej; @@ -2269,6 +2327,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr { struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; u16 scid, flags, result; + struct l2cap_chan *chan; struct sock *sk; int len = cmd->len - sizeof(*rsp); @@ -2279,10 +2338,12 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", scid, flags, result); - sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); - if (!sk) + chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); + if (!chan) return 0; + sk = chan->sk; + switch (result) { case L2CAP_CONF_SUCCESS: l2cap_conf_rfc_get(sk, rsp->data, len); @@ -2349,6 +2410,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; struct l2cap_disconn_rsp rsp; u16 dcid, scid; + struct l2cap_chan *chan; struct sock *sk; scid = __le16_to_cpu(req->scid); @@ -2356,10 +2418,12 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); - sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid); - if (!sk) + chan = l2cap_get_chan_by_scid(&conn->chan_list, dcid); + if (!chan) return 0; + sk = chan->sk; + rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); @@ -2375,7 +2439,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd return 0; } - l2cap_chan_del(sk, ECONNRESET); + l2cap_chan_del(chan, ECONNRESET); bh_unlock_sock(sk); l2cap_sock_kill(sk); @@ -2386,6 +2450,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd { struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; u16 dcid, scid; + struct l2cap_chan *chan; struct sock *sk; scid = __le16_to_cpu(rsp->scid); @@ -2393,10 +2458,12 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); - sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); - if (!sk) + chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); + if (!chan) return 0; + sk = chan->sk; + /* don't delete l2cap channel if sk is owned by user */ if (sock_owned_by_user(sk)) { sk->sk_state = BT_DISCONN; @@ -2406,7 +2473,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd return 0; } - l2cap_chan_del(sk, 0); + l2cap_chan_del(chan, 0); bh_unlock_sock(sk); l2cap_sock_kill(sk); @@ -3538,18 +3605,20 @@ drop: static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) { + struct l2cap_chan *chan; struct sock *sk; struct l2cap_pinfo *pi; u16 control; u8 tx_seq; int len; - sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); - if (!sk) { + chan = l2cap_get_chan_by_scid(&conn->chan_list, cid); + if (!chan) { BT_DBG("unknown cid 0x%4.4x", cid); goto drop; } + sk = chan->sk; pi = l2cap_pi(sk); BT_DBG("sk %p, len %d", sk, skb->len); @@ -3788,7 +3857,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) { struct l2cap_chan_list *l; struct l2cap_conn *conn = hcon->l2cap_data; - struct sock *sk; + struct l2cap_chan *chan; if (!conn) return 0; @@ -3799,7 +3868,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) read_lock(&l->lock); - for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + for (chan = l->head; chan; chan = chan->next_c) { + struct sock *sk = chan->sk; bh_lock_sock(sk); if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) { @@ -3872,7 +3942,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl if (!(flags & ACL_CONT)) { struct l2cap_hdr *hdr; - struct sock *sk; + struct l2cap_chan *chan; u16 cid; int len; @@ -3910,18 +3980,21 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl goto drop; } - sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); + chan = l2cap_get_chan_by_scid(&conn->chan_list, cid); - if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) { - BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)", - len, l2cap_pi(sk)->imtu); - bh_unlock_sock(sk); - l2cap_conn_unreliable(conn, ECOMM); - goto drop; - } + if (chan && chan->sk) { + struct sock *sk = chan->sk; - if (sk) + if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) { + BT_ERR("Frame exceeding recv MTU (len %d, " + "MTU %d)", len, + l2cap_pi(sk)->imtu); + bh_unlock_sock(sk); + l2cap_conn_unreliable(conn, ECOMM); + goto drop; + } bh_unlock_sock(sk); + } /* Allocate skb for the complete frame (with header) */ conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index f77308e63e5..7df81181a11 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -902,7 +902,7 @@ void __l2cap_sock_close(struct sock *sk, int reason) l2cap_sock_set_timer(sk, sk->sk_sndtimeo); l2cap_send_disconn_req(conn, sk, reason); } else - l2cap_chan_del(sk, reason); + l2cap_chan_del(l2cap_pi(sk)->chan, reason); break; case BT_CONNECT2: @@ -925,12 +925,12 @@ void __l2cap_sock_close(struct sock *sk, int reason) L2CAP_CONN_RSP, sizeof(rsp), &rsp); } - l2cap_chan_del(sk, reason); + l2cap_chan_del(l2cap_pi(sk)->chan, reason); break; case BT_CONNECT: case BT_DISCONN: - l2cap_chan_del(sk, reason); + l2cap_chan_del(l2cap_pi(sk)->chan, reason); break; default: -- cgit v1.2.3-70-g09d2 From fc7f8a7ed4543853a99852ca405ea71fabe78946 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 13:59:37 -0300 Subject: Bluetooth: Move ident to struct l2cap_chan ident is chan property, no need to reside on socket. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 4 ++-- net/bluetooth/l2cap_core.c | 38 +++++++++++++++++++------------------- net/bluetooth/l2cap_sock.c | 4 ++-- 3 files changed, 23 insertions(+), 23 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index d24b51c3ff8..81829e5c407 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -279,6 +279,8 @@ struct l2cap_conn_param_update_rsp { /* ----- L2CAP channels and connections ----- */ struct l2cap_chan { struct sock *sk; + __u8 ident; + struct list_head list; }; @@ -363,8 +365,6 @@ struct l2cap_pinfo { __u16 partial_sdu_len; struct sk_buff *sdu; - __u8 ident; - __u8 tx_win; __u8 max_tx; __u8 remote_tx_win; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b0aaaa9cf00..6020e1e2f50 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -118,8 +118,7 @@ static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 struct l2cap_chan *c; list_for_each_entry(c, &conn->chan_l, list) { - struct sock *s = c->sk; - if (l2cap_pi(s)->ident == ident) + if (c->ident == ident) return c; } return NULL; @@ -410,8 +409,9 @@ static inline int __l2cap_no_conn_pending(struct sock *sk) return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND); } -static void l2cap_do_start(struct sock *sk) +static void l2cap_do_start(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; struct l2cap_conn *conn = l2cap_pi(sk)->conn; if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { @@ -423,11 +423,11 @@ static void l2cap_do_start(struct sock *sk) req.scid = cpu_to_le16(l2cap_pi(sk)->scid); req.psm = l2cap_pi(sk)->psm; - l2cap_pi(sk)->ident = l2cap_get_ident(conn); + chan->ident = l2cap_get_ident(conn); l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; - l2cap_send_cmd(conn, l2cap_pi(sk)->ident, - L2CAP_CONN_REQ, sizeof(req), &req); + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, + sizeof(req), &req); } } else { struct l2cap_info_req req; @@ -529,11 +529,11 @@ static void l2cap_conn_start(struct l2cap_conn *conn) req.scid = cpu_to_le16(l2cap_pi(sk)->scid); req.psm = l2cap_pi(sk)->psm; - l2cap_pi(sk)->ident = l2cap_get_ident(conn); + chan->ident = l2cap_get_ident(conn); l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; - l2cap_send_cmd(conn, l2cap_pi(sk)->ident, - L2CAP_CONN_REQ, sizeof(req), &req); + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, + sizeof(req), &req); } else if (sk->sk_state == BT_CONNECT2) { struct l2cap_conn_rsp rsp; @@ -558,8 +558,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); } - l2cap_send_cmd(conn, l2cap_pi(sk)->ident, - L2CAP_CONN_RSP, sizeof(rsp), &rsp); + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, + sizeof(rsp), &rsp); if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT || rsp.result != L2CAP_CR_SUCCESS) { @@ -694,7 +694,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) sk->sk_state = BT_CONNECTED; sk->sk_state_change(sk); } else if (sk->sk_state == BT_CONNECT) - l2cap_do_start(sk); + l2cap_do_start(chan); bh_unlock_sock(sk); } @@ -904,7 +904,7 @@ int l2cap_do_connect(struct sock *sk) if (l2cap_check_security(sk)) sk->sk_state = BT_CONNECTED; } else - l2cap_do_start(sk); + l2cap_do_start(chan); } err = 0; @@ -2064,7 +2064,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd l2cap_sock_set_timer(sk, sk->sk_sndtimeo); - l2cap_pi(sk)->ident = cmd->ident; + chan->ident = cmd->ident; if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { if (l2cap_check_security(sk)) { @@ -2157,7 +2157,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd switch (result) { case L2CAP_CR_SUCCESS: sk->sk_state = BT_CONFIG; - l2cap_pi(sk)->ident = 0; + chan->ident = 0; l2cap_pi(sk)->dcid = dcid; l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND; @@ -3862,10 +3862,10 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) req.scid = cpu_to_le16(l2cap_pi(sk)->scid); req.psm = l2cap_pi(sk)->psm; - l2cap_pi(sk)->ident = l2cap_get_ident(conn); + chan->ident = l2cap_get_ident(conn); l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; - l2cap_send_cmd(conn, l2cap_pi(sk)->ident, + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); } else { l2cap_sock_clear_timer(sk); @@ -3888,8 +3888,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.result = cpu_to_le16(result); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); - l2cap_send_cmd(conn, l2cap_pi(sk)->ident, - L2CAP_CONN_RSP, sizeof(rsp), &rsp); + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, + sizeof(rsp), &rsp); } bh_unlock_sock(sk); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 7df81181a11..cad4bc7d36b 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -818,7 +818,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); - l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident, + l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) { @@ -921,7 +921,7 @@ void __l2cap_sock_close(struct sock *sk, int reason) rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.result = cpu_to_le16(result); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); - l2cap_send_cmd(conn, l2cap_pi(sk)->ident, + l2cap_send_cmd(conn, l2cap_pi(sk)->chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); } -- cgit v1.2.3-70-g09d2 From 73ffa904b78287f6acf8797e040150aa26a4af4a Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 14:16:54 -0300 Subject: Bluetooth: Move conf_{req,rsp} stuff to struct l2cap_chan They are also l2cap_chan specific. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 11 +++++---- net/bluetooth/l2cap_core.c | 55 ++++++++++++++++++++++--------------------- net/bluetooth/l2cap_sock.c | 8 +++---- 3 files changed, 38 insertions(+), 36 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 81829e5c407..bf918283712 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -281,6 +281,11 @@ struct l2cap_chan { struct sock *sk; __u8 ident; + __u8 conf_req[64]; + __u8 conf_len; + __u8 num_conf_req; + __u8 num_conf_rsp; + struct list_head list; }; @@ -337,8 +342,6 @@ struct l2cap_pinfo { __u16 omtu; __u16 flush_to; __u8 mode; - __u8 num_conf_req; - __u8 num_conf_rsp; __u8 fcs; __u8 sec_level; @@ -346,8 +349,6 @@ struct l2cap_pinfo { __u8 force_reliable; __u8 flushable; - __u8 conf_req[64]; - __u8 conf_len; __u8 conf_state; __u16 conn_state; @@ -447,7 +448,7 @@ void l2cap_cleanup_sockets(void); u8 l2cap_get_ident(struct l2cap_conn *conn); void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data); -int l2cap_build_conf_req(struct sock *sk, void *data); +int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); int __l2cap_wait_ack(struct sock *sk); struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 6020e1e2f50..cb849b51632 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -569,8 +569,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(sk, buf), buf); - l2cap_pi(sk)->num_conf_req++; + l2cap_build_conf_req(chan, buf), buf); + chan->num_conf_req++; } bh_unlock_sock(sk); @@ -1598,8 +1598,9 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) } } -int l2cap_build_conf_req(struct sock *sk, void *data) +int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); struct l2cap_conf_req *req = data; struct l2cap_conf_rfc rfc = { .mode = pi->mode }; @@ -1607,7 +1608,7 @@ int l2cap_build_conf_req(struct sock *sk, void *data) BT_DBG("sk %p", sk); - if (pi->num_conf_req || pi->num_conf_rsp) + if (chan->num_conf_req || chan->num_conf_rsp) goto done; switch (pi->mode) { @@ -1696,20 +1697,20 @@ done: return ptr - data; } -static int l2cap_parse_conf_req(struct sock *sk, void *data) +static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct l2cap_conf_rsp *rsp = data; void *ptr = rsp->data; - void *req = pi->conf_req; - int len = pi->conf_len; + void *req = chan->conf_req; + int len = chan->conf_len; int type, hint, olen; unsigned long val; struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; u16 mtu = L2CAP_DEFAULT_MTU; u16 result = L2CAP_CONF_SUCCESS; - BT_DBG("sk %p", sk); + BT_DBG("chan %p", chan); while (len >= L2CAP_CONF_OPT_SIZE) { len -= l2cap_get_conf_opt(&req, &type, &olen, &val); @@ -1750,7 +1751,7 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data) } } - if (pi->num_conf_rsp || pi->num_conf_req > 1) + if (chan->num_conf_rsp || chan->num_conf_req > 1) goto done; switch (pi->mode) { @@ -1773,7 +1774,7 @@ done: result = L2CAP_CONF_UNACCEPT; rfc.mode = pi->mode; - if (pi->num_conf_rsp == 1) + if (chan->num_conf_rsp == 1) return -ECONNREFUSED; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, @@ -1992,7 +1993,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd { struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; struct l2cap_conn_rsp rsp; - struct l2cap_chan *chan; + struct l2cap_chan *chan = NULL; struct sock *parent, *sk = NULL; int result, status = L2CAP_CS_NO_INFO; @@ -2115,13 +2116,13 @@ sendresp: L2CAP_INFO_REQ, sizeof(info), &info); } - if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) && + if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) && result == L2CAP_CR_SUCCESS) { u8 buf[128]; l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(sk, buf), buf); - l2cap_pi(sk)->num_conf_req++; + l2cap_build_conf_req(chan, buf), buf); + chan->num_conf_req++; } return 0; @@ -2167,8 +2168,8 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(sk, req), req); - l2cap_pi(sk)->num_conf_req++; + l2cap_build_conf_req(chan, req), req); + chan->num_conf_req++; break; case L2CAP_CR_PEND: @@ -2234,7 +2235,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr /* Reject if config buffer is too small. */ len = cmd_len - sizeof(*req); - if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) { + if (chan->conf_len + len > sizeof(chan->conf_req)) { l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_build_conf_rsp(sk, rsp, L2CAP_CONF_REJECT, flags), rsp); @@ -2242,8 +2243,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr } /* Store config. */ - memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len); - l2cap_pi(sk)->conf_len += len; + memcpy(chan->conf_req + chan->conf_len, req->data, len); + chan->conf_len += len; if (flags & 0x0001) { /* Incomplete config. Send empty response. */ @@ -2254,17 +2255,17 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr } /* Complete config. */ - len = l2cap_parse_conf_req(sk, rsp); + len = l2cap_parse_conf_req(chan, rsp); if (len < 0) { l2cap_send_disconn_req(conn, sk, ECONNRESET); goto unlock; } l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); - l2cap_pi(sk)->num_conf_rsp++; + chan->num_conf_rsp++; /* Reset config buffer. */ - l2cap_pi(sk)->conf_len = 0; + chan->conf_len = 0; if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE)) goto unlock; @@ -2288,8 +2289,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr u8 buf[64]; l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(sk, buf), buf); - l2cap_pi(sk)->num_conf_req++; + l2cap_build_conf_req(chan, buf), buf); + chan->num_conf_req++; } unlock: @@ -2324,7 +2325,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr break; case L2CAP_CONF_UNACCEPT: - if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { + if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { char req[64]; if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { @@ -2343,7 +2344,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, len, req); - l2cap_pi(sk)->num_conf_req++; + chan->num_conf_req++; if (result != L2CAP_CONF_SUCCESS) goto done; break; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index cad4bc7d36b..244475ea045 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -810,6 +810,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { struct l2cap_conn_rsp rsp; struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; u8 buf[128]; sk->sk_state = BT_CONFIG; @@ -818,7 +819,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); - l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->chan->ident, + l2cap_send_cmd(l2cap_pi(sk)->conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) { @@ -828,8 +829,8 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(sk, buf), buf); - l2cap_pi(sk)->num_conf_req++; + l2cap_build_conf_req(chan, buf), buf); + chan->num_conf_req++; release_sock(sk); return 0; @@ -1035,7 +1036,6 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) } /* Default config options */ - pi->conf_len = 0; pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; skb_queue_head_init(TX_QUEUE(sk)); skb_queue_head_init(SREJ_QUEUE(sk)); -- cgit v1.2.3-70-g09d2 From 710f9b0a423cad155144742f6497efe5163ed750 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 14:30:37 -0300 Subject: Bluetooth: clean up l2cap_sock_recvmsg() Move some channel specific stuff to l2cap_core.c, this will make things more clear. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 3 +-- net/bluetooth/l2cap_core.c | 28 +++++++++++++++++++++++++++- net/bluetooth/l2cap_sock.c | 25 +------------------------ 3 files changed, 29 insertions(+), 27 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index bf918283712..469241353d7 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -446,9 +446,8 @@ extern struct bt_sock_list l2cap_sk_list; int l2cap_init_sockets(void); void l2cap_cleanup_sockets(void); -u8 l2cap_get_ident(struct l2cap_conn *conn); void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data); -int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); +void __l2cap_connect_rsp_defer(struct sock *sk); int __l2cap_wait_ack(struct sock *sk); struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index cb849b51632..b41e21f4623 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -70,6 +70,7 @@ static void l2cap_busy_work(struct work_struct *work); static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, u8 ident, u16 dlen, void *data); +static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); @@ -1598,7 +1599,7 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) } } -int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) +static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) { struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); @@ -1934,6 +1935,31 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 fla return ptr - data; } +void __l2cap_connect_rsp_defer(struct sock *sk) +{ + struct l2cap_conn_rsp rsp; + struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + u8 buf[128]; + + sk->sk_state = BT_CONFIG; + + rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); + rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); + rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); + rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); + l2cap_send_cmd(conn, chan->ident, + L2CAP_CONN_RSP, sizeof(rsp), &rsp); + + if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) + return; + + l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; + l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, + l2cap_build_conf_req(chan, buf), buf); + chan->num_conf_req++; +} + static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len) { struct l2cap_pinfo *pi = l2cap_pi(sk); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 244475ea045..450f57b106b 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -808,30 +808,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms lock_sock(sk); if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { - struct l2cap_conn_rsp rsp; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; - struct l2cap_chan *chan = l2cap_pi(sk)->chan; - u8 buf[128]; - - sk->sk_state = BT_CONFIG; - - rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); - rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); - rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); - rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); - l2cap_send_cmd(l2cap_pi(sk)->conn, chan->ident, - L2CAP_CONN_RSP, sizeof(rsp), &rsp); - - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) { - release_sock(sk); - return 0; - } - - l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; - l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, - l2cap_build_conf_req(chan, buf), buf); - chan->num_conf_req++; - + __l2cap_connect_rsp_defer(sk); release_sock(sk); return 0; } -- cgit v1.2.3-70-g09d2 From 525cd1851b9faaadf5ea33e05192b8d22f42487e Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 19:43:39 -0300 Subject: Bluetooth: Move conn_state to struct l2cap_chan This is part of "moving things to l2cap_chan". As one the first move it triggered a big number of changes in the funcions parameters, basically changing the struct sock param to struct l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 5 +- net/bluetooth/l2cap_core.c | 391 ++++++++++++++++++++++-------------------- net/bluetooth/l2cap_sock.c | 16 +- 3 files changed, 217 insertions(+), 195 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 469241353d7..82d5b81a779 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -286,6 +286,8 @@ struct l2cap_chan { __u8 num_conf_req; __u8 num_conf_rsp; + __u16 conn_state; + struct list_head list; }; @@ -350,7 +352,6 @@ struct l2cap_pinfo { __u8 flushable; __u8 conf_state; - __u16 conn_state; __u8 next_tx_seq; __u8 expected_ack_seq; @@ -456,7 +457,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len); void l2cap_do_send(struct sock *sk, struct sk_buff *skb); void l2cap_streaming_send(struct sock *sk); -int l2cap_ertm_send(struct sock *sk); +int l2cap_ertm_send(struct l2cap_chan *chan); void l2cap_sock_set_timer(struct sock *sk, long timeout); void l2cap_sock_clear_timer(struct sock *sk); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b41e21f4623..b5435cd74f9 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -340,10 +340,11 @@ void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *d hci_send_acl(conn->hcon, skb, flags); } -static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) +static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) { struct sk_buff *skb; struct l2cap_hdr *lh; + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct l2cap_conn *conn = pi->conn; struct sock *sk = (struct sock *)pi; int count, hlen = L2CAP_HDR_SIZE + 2; @@ -360,14 +361,14 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) count = min_t(unsigned int, conn->mtu, hlen); control |= L2CAP_CTRL_FRAME_TYPE; - if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { + if (chan->conn_state & L2CAP_CONN_SEND_FBIT) { control |= L2CAP_CTRL_FINAL; - pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + chan->conn_state &= ~L2CAP_CONN_SEND_FBIT; } - if (pi->conn_state & L2CAP_CONN_SEND_PBIT) { + if (chan->conn_state & L2CAP_CONN_SEND_PBIT) { control |= L2CAP_CTRL_POLL; - pi->conn_state &= ~L2CAP_CONN_SEND_PBIT; + chan->conn_state &= ~L2CAP_CONN_SEND_PBIT; } skb = bt_skb_alloc(count, GFP_ATOMIC); @@ -392,17 +393,19 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) hci_send_acl(pi->conn->hcon, skb, flags); } -static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) +static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control) { - if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); + + if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; - pi->conn_state |= L2CAP_CONN_RNR_SENT; + chan->conn_state |= L2CAP_CONN_RNR_SENT; } else control |= L2CAP_SUPER_RCV_READY; control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; - l2cap_send_sframe(pi, control); + l2cap_send_sframe(chan, control); } static inline int __l2cap_no_conn_pending(struct sock *sk) @@ -949,9 +952,10 @@ int __l2cap_wait_ack(struct sock *sk) static void l2cap_monitor_timeout(unsigned long arg) { - struct sock *sk = (void *) arg; + struct l2cap_chan *chan = (void *) arg; + struct sock *sk = chan->sk; - BT_DBG("sk %p", sk); + BT_DBG("chan %p", chan); bh_lock_sock(sk); if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) { @@ -963,13 +967,14 @@ static void l2cap_monitor_timeout(unsigned long arg) l2cap_pi(sk)->retry_count++; __mod_monitor_timer(); - l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL); + l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); bh_unlock_sock(sk); } static void l2cap_retrans_timeout(unsigned long arg) { - struct sock *sk = (void *) arg; + struct l2cap_chan *chan = (void *) arg; + struct sock *sk = chan->sk; BT_DBG("sk %p", sk); @@ -977,9 +982,9 @@ static void l2cap_retrans_timeout(unsigned long arg) l2cap_pi(sk)->retry_count = 1; __mod_monitor_timer(); - l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; + chan->conn_state |= L2CAP_CONN_WAIT_F; - l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL); + l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); bh_unlock_sock(sk); } @@ -1040,8 +1045,9 @@ void l2cap_streaming_send(struct sock *sk) } } -static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq) +static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *skb, *tx_skb; u16 control, fcs; @@ -1069,9 +1075,9 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq) bt_cb(skb)->retries++; control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); - if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { + if (chan->conn_state & L2CAP_CONN_SEND_FBIT) { control |= L2CAP_CTRL_FINAL; - pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + chan->conn_state &= ~L2CAP_CONN_SEND_FBIT; } control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) @@ -1087,9 +1093,10 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq) l2cap_do_send(sk, tx_skb); } -int l2cap_ertm_send(struct sock *sk) +int l2cap_ertm_send(struct l2cap_chan *chan) { struct sk_buff *skb, *tx_skb; + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; int nsent = 0; @@ -1112,9 +1119,9 @@ int l2cap_ertm_send(struct sock *sk) control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); control &= L2CAP_CTRL_SAR; - if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { + if (chan->conn_state & L2CAP_CONN_SEND_FBIT) { control |= L2CAP_CTRL_FINAL; - pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; + chan->conn_state &= ~L2CAP_CONN_SEND_FBIT; } control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); @@ -1149,8 +1156,9 @@ int l2cap_ertm_send(struct sock *sk) return nsent; } -static int l2cap_retransmit_frames(struct sock *sk) +static int l2cap_retransmit_frames(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); int ret; @@ -1158,32 +1166,32 @@ static int l2cap_retransmit_frames(struct sock *sk) sk->sk_send_head = TX_QUEUE(sk)->next; pi->next_tx_seq = pi->expected_ack_seq; - ret = l2cap_ertm_send(sk); + ret = l2cap_ertm_send(chan); return ret; } -static void l2cap_send_ack(struct l2cap_pinfo *pi) +static void l2cap_send_ack(struct l2cap_chan *chan) { - struct sock *sk = (struct sock *)pi; + struct sock *sk = chan->sk; u16 control = 0; - control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control |= l2cap_pi(sk)->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; - if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; - pi->conn_state |= L2CAP_CONN_RNR_SENT; - l2cap_send_sframe(pi, control); + chan->conn_state |= L2CAP_CONN_RNR_SENT; + l2cap_send_sframe(chan, control); return; } - if (l2cap_ertm_send(sk) > 0) + if (l2cap_ertm_send(chan) > 0) return; control |= L2CAP_SUPER_RCV_READY; - l2cap_send_sframe(pi, control); + l2cap_send_sframe(chan, control); } -static void l2cap_send_srejtail(struct sock *sk) +static void l2cap_send_srejtail(struct l2cap_chan *chan) { struct srej_list *tail; u16 control; @@ -1191,10 +1199,10 @@ static void l2cap_send_srejtail(struct sock *sk) control = L2CAP_SUPER_SELECT_REJECT; control |= L2CAP_CTRL_FINAL; - tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list); + tail = list_entry(SREJ_LIST(chan->sk)->prev, struct srej_list, list); control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; - l2cap_send_sframe(l2cap_pi(sk), control); + l2cap_send_sframe(chan, control); } static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb) @@ -1556,15 +1564,17 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) static void l2cap_ack_timeout(unsigned long arg) { - struct sock *sk = (void *) arg; + struct l2cap_chan *chan = (void *) arg; - bh_lock_sock(sk); - l2cap_send_ack(l2cap_pi(sk)); - bh_unlock_sock(sk); + bh_lock_sock(chan->sk); + l2cap_send_ack(chan); + bh_unlock_sock(chan->sk); } -static inline void l2cap_ertm_init(struct sock *sk) +static inline void l2cap_ertm_init(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; + l2cap_pi(sk)->expected_ack_seq = 0; l2cap_pi(sk)->unacked_frames = 0; l2cap_pi(sk)->buffer_seq = 0; @@ -1572,11 +1582,11 @@ static inline void l2cap_ertm_init(struct sock *sk) l2cap_pi(sk)->frames_sent = 0; setup_timer(&l2cap_pi(sk)->retrans_timer, - l2cap_retrans_timeout, (unsigned long) sk); + l2cap_retrans_timeout, (unsigned long) chan); setup_timer(&l2cap_pi(sk)->monitor_timer, - l2cap_monitor_timeout, (unsigned long) sk); + l2cap_monitor_timeout, (unsigned long) chan); setup_timer(&l2cap_pi(sk)->ack_timer, - l2cap_ack_timeout, (unsigned long) sk); + l2cap_ack_timeout, (unsigned long) chan); __skb_queue_head_init(SREJ_QUEUE(sk)); __skb_queue_head_init(BUSY_QUEUE(sk)); @@ -2305,7 +2315,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr l2cap_pi(sk)->expected_tx_seq = 0; __skb_queue_head_init(TX_QUEUE(sk)); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) - l2cap_ertm_init(sk); + l2cap_ertm_init(chan); l2cap_chan_ready(sk); goto unlock; @@ -2396,7 +2406,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr l2cap_pi(sk)->expected_tx_seq = 0; __skb_queue_head_init(TX_QUEUE(sk)); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) - l2cap_ertm_init(sk); + l2cap_ertm_init(chan); l2cap_chan_ready(sk); } @@ -2777,30 +2787,30 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb) return 0; } -static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk) +static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u16 control = 0; pi->frames_sent = 0; control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; - if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; - l2cap_send_sframe(pi, control); - pi->conn_state |= L2CAP_CONN_RNR_SENT; + l2cap_send_sframe(chan, control); + chan->conn_state |= L2CAP_CONN_RNR_SENT; } - if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY) - l2cap_retransmit_frames(sk); + if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY) + l2cap_retransmit_frames(chan); - l2cap_ertm_send(sk); + l2cap_ertm_send(chan); - if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) && + if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) && pi->frames_sent == 0) { control |= L2CAP_SUPER_RCV_READY; - l2cap_send_sframe(pi, control); + l2cap_send_sframe(chan, control); } } @@ -2847,25 +2857,25 @@ static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_s return 0; } -static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) +static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct sk_buff *_skb; int err; switch (control & L2CAP_CTRL_SAR) { case L2CAP_SDU_UNSEGMENTED: - if (pi->conn_state & L2CAP_CONN_SAR_SDU) + if (chan->conn_state & L2CAP_CONN_SAR_SDU) goto drop; - err = sock_queue_rcv_skb(sk, skb); + err = sock_queue_rcv_skb(chan->sk, skb); if (!err) return err; break; case L2CAP_SDU_START: - if (pi->conn_state & L2CAP_CONN_SAR_SDU) + if (chan->conn_state & L2CAP_CONN_SAR_SDU) goto drop; pi->sdu_len = get_unaligned_le16(skb->data); @@ -2884,12 +2894,12 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); - pi->conn_state |= L2CAP_CONN_SAR_SDU; + chan->conn_state |= L2CAP_CONN_SAR_SDU; pi->partial_sdu_len = skb->len; break; case L2CAP_SDU_CONTINUE: - if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) + if (!(chan->conn_state & L2CAP_CONN_SAR_SDU)) goto disconnect; if (!pi->sdu) @@ -2904,13 +2914,13 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c break; case L2CAP_SDU_END: - if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) + if (!(chan->conn_state & L2CAP_CONN_SAR_SDU)) goto disconnect; if (!pi->sdu) goto disconnect; - if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) { + if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) { pi->partial_sdu_len += skb->len; if (pi->partial_sdu_len > pi->imtu) @@ -2924,19 +2934,19 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c _skb = skb_clone(pi->sdu, GFP_ATOMIC); if (!_skb) { - pi->conn_state |= L2CAP_CONN_SAR_RETRY; + chan->conn_state |= L2CAP_CONN_SAR_RETRY; return -ENOMEM; } - err = sock_queue_rcv_skb(sk, _skb); + err = sock_queue_rcv_skb(chan->sk, _skb); if (err < 0) { kfree_skb(_skb); - pi->conn_state |= L2CAP_CONN_SAR_RETRY; + chan->conn_state |= L2CAP_CONN_SAR_RETRY; return err; } - pi->conn_state &= ~L2CAP_CONN_SAR_RETRY; - pi->conn_state &= ~L2CAP_CONN_SAR_SDU; + chan->conn_state &= ~L2CAP_CONN_SAR_RETRY; + chan->conn_state &= ~L2CAP_CONN_SAR_SDU; kfree_skb(pi->sdu); break; @@ -2950,13 +2960,14 @@ drop: pi->sdu = NULL; disconnect: - l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan->sk, ECONNRESET); kfree_skb(skb); return 0; } -static int l2cap_try_push_rx_skb(struct sock *sk) +static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *skb; u16 control; @@ -2964,7 +2975,7 @@ static int l2cap_try_push_rx_skb(struct sock *sk) while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) { control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; - err = l2cap_ertm_reassembly_sdu(sk, skb, control); + err = l2cap_ertm_reassembly_sdu(chan, skb, control); if (err < 0) { skb_queue_head(BUSY_QUEUE(sk), skb); return -EBUSY; @@ -2973,22 +2984,22 @@ static int l2cap_try_push_rx_skb(struct sock *sk) pi->buffer_seq = (pi->buffer_seq + 1) % 64; } - if (!(pi->conn_state & L2CAP_CONN_RNR_SENT)) + if (!(chan->conn_state & L2CAP_CONN_RNR_SENT)) goto done; control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL; - l2cap_send_sframe(pi, control); + l2cap_send_sframe(chan, control); l2cap_pi(sk)->retry_count = 1; del_timer(&pi->retrans_timer); __mod_monitor_timer(); - l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; + chan->conn_state |= L2CAP_CONN_WAIT_F; done: - pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY; - pi->conn_state &= ~L2CAP_CONN_RNR_SENT; + chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY; + chan->conn_state &= ~L2CAP_CONN_RNR_SENT; BT_DBG("sk %p, Exit local busy", sk); @@ -3032,7 +3043,7 @@ static void l2cap_busy_work(struct work_struct *work) if (err) break; - if (l2cap_try_push_rx_skb(sk) == 0) + if (l2cap_try_push_rx_skb(l2cap_pi(sk)->chan) == 0) break; } @@ -3042,20 +3053,21 @@ static void l2cap_busy_work(struct work_struct *work) release_sock(sk); } -static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control) +static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); int sctrl, err; - if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { + if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; __skb_queue_tail(BUSY_QUEUE(sk), skb); - return l2cap_try_push_rx_skb(sk); + return l2cap_try_push_rx_skb(chan); } - err = l2cap_ertm_reassembly_sdu(sk, skb, control); + err = l2cap_ertm_reassembly_sdu(chan, skb, control); if (err >= 0) { pi->buffer_seq = (pi->buffer_seq + 1) % 64; return err; @@ -3064,15 +3076,15 @@ static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control) /* Busy Condition */ BT_DBG("sk %p, Enter local busy", sk); - pi->conn_state |= L2CAP_CONN_LOCAL_BUSY; + chan->conn_state |= L2CAP_CONN_LOCAL_BUSY; bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; __skb_queue_tail(BUSY_QUEUE(sk), skb); sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; sctrl |= L2CAP_SUPER_RCV_NOT_READY; - l2cap_send_sframe(pi, sctrl); + l2cap_send_sframe(chan, sctrl); - pi->conn_state |= L2CAP_CONN_RNR_SENT; + chan->conn_state |= L2CAP_CONN_RNR_SENT; del_timer(&pi->ack_timer); @@ -3081,9 +3093,9 @@ static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control) return err; } -static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) +static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct sk_buff *_skb; int err = -EINVAL; @@ -3094,19 +3106,19 @@ static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, switch (control & L2CAP_CTRL_SAR) { case L2CAP_SDU_UNSEGMENTED: - if (pi->conn_state & L2CAP_CONN_SAR_SDU) { + if (chan->conn_state & L2CAP_CONN_SAR_SDU) { kfree_skb(pi->sdu); break; } - err = sock_queue_rcv_skb(sk, skb); + err = sock_queue_rcv_skb(chan->sk, skb); if (!err) return 0; break; case L2CAP_SDU_START: - if (pi->conn_state & L2CAP_CONN_SAR_SDU) { + if (chan->conn_state & L2CAP_CONN_SAR_SDU) { kfree_skb(pi->sdu); break; } @@ -3127,13 +3139,13 @@ static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); - pi->conn_state |= L2CAP_CONN_SAR_SDU; + chan->conn_state |= L2CAP_CONN_SAR_SDU; pi->partial_sdu_len = skb->len; err = 0; break; case L2CAP_SDU_CONTINUE: - if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) + if (!(chan->conn_state & L2CAP_CONN_SAR_SDU)) break; memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); @@ -3147,12 +3159,12 @@ static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, break; case L2CAP_SDU_END: - if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) + if (!(chan->conn_state & L2CAP_CONN_SAR_SDU)) break; memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); - pi->conn_state &= ~L2CAP_CONN_SAR_SDU; + chan->conn_state &= ~L2CAP_CONN_SAR_SDU; pi->partial_sdu_len += skb->len; if (pi->partial_sdu_len > pi->imtu) @@ -3160,7 +3172,7 @@ static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, if (pi->partial_sdu_len == pi->sdu_len) { _skb = skb_clone(pi->sdu, GFP_ATOMIC); - err = sock_queue_rcv_skb(sk, _skb); + err = sock_queue_rcv_skb(chan->sk, _skb); if (err < 0) kfree_skb(_skb); } @@ -3175,8 +3187,9 @@ drop: return err; } -static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq) +static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq) { + struct sock *sk = chan->sk; struct sk_buff *skb; u16 control; @@ -3186,16 +3199,16 @@ static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq) skb = skb_dequeue(SREJ_QUEUE(sk)); control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; - l2cap_ertm_reassembly_sdu(sk, skb, control); + l2cap_ertm_reassembly_sdu(chan, skb, control); l2cap_pi(sk)->buffer_seq_srej = (l2cap_pi(sk)->buffer_seq_srej + 1) % 64; tx_seq = (tx_seq + 1) % 64; } } -static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq) +static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct sock *sk = chan->sk; struct srej_list *l, *tmp; u16 control; @@ -3207,14 +3220,15 @@ static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq) } control = L2CAP_SUPER_SELECT_REJECT; control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; - l2cap_send_sframe(pi, control); + l2cap_send_sframe(chan, control); list_del(&l->list); list_add_tail(&l->list, SREJ_LIST(sk)); } } -static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq) +static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); struct srej_list *new; u16 control; @@ -3222,7 +3236,7 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq) while (tx_seq != pi->expected_tx_seq) { control = L2CAP_SUPER_SELECT_REJECT; control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; - l2cap_send_sframe(pi, control); + l2cap_send_sframe(chan, control); new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); new->tx_seq = pi->expected_tx_seq; @@ -3232,8 +3246,9 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq) pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; } -static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) +static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); u8 tx_seq = __get_txseq(rx_control); u8 req_seq = __get_reqseq(rx_control); @@ -3242,15 +3257,15 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str int num_to_ack = (pi->tx_win/6) + 1; int err = 0; - BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq, - rx_control); + BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len, + tx_seq, rx_control); if (L2CAP_CTRL_FINAL & rx_control && - l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) { + chan->conn_state & L2CAP_CONN_WAIT_F) { del_timer(&pi->monitor_timer); if (pi->unacked_frames > 0) __mod_retrans_timer(); - pi->conn_state &= ~L2CAP_CONN_WAIT_F; + chan->conn_state &= ~L2CAP_CONN_WAIT_F; } pi->expected_ack_seq = req_seq; @@ -3269,25 +3284,25 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str goto drop; } - if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY) + if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY) goto drop; - if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { + if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { struct srej_list *first; first = list_first_entry(SREJ_LIST(sk), struct srej_list, list); if (tx_seq == first->tx_seq) { l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); - l2cap_check_srej_gap(sk, tx_seq); + l2cap_check_srej_gap(chan, tx_seq); list_del(&first->list); kfree(first); if (list_empty(SREJ_LIST(sk))) { pi->buffer_seq = pi->buffer_seq_srej; - pi->conn_state &= ~L2CAP_CONN_SREJ_SENT; - l2cap_send_ack(pi); + chan->conn_state &= ~L2CAP_CONN_SREJ_SENT; + l2cap_send_ack(chan); BT_DBG("sk %p, Exit SREJ_SENT", sk); } } else { @@ -3299,11 +3314,11 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str list_for_each_entry(l, SREJ_LIST(sk), list) { if (l->tx_seq == tx_seq) { - l2cap_resend_srejframe(sk, tx_seq); + l2cap_resend_srejframe(chan, tx_seq); return 0; } } - l2cap_send_srejframe(sk, tx_seq); + l2cap_send_srejframe(chan, tx_seq); } } else { expected_tx_seq_offset = @@ -3315,7 +3330,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str if (tx_seq_offset < expected_tx_seq_offset) goto drop; - pi->conn_state |= L2CAP_CONN_SREJ_SENT; + chan->conn_state |= L2CAP_CONN_SREJ_SENT; BT_DBG("sk %p, Enter SREJ", sk); @@ -3326,9 +3341,9 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str __skb_queue_head_init(BUSY_QUEUE(sk)); l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); - pi->conn_state |= L2CAP_CONN_SEND_PBIT; + chan->conn_state |= L2CAP_CONN_SEND_PBIT; - l2cap_send_srejframe(sk, tx_seq); + l2cap_send_srejframe(chan, tx_seq); del_timer(&pi->ack_timer); } @@ -3337,29 +3352,29 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str expected: pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; - if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { + if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { bt_cb(skb)->tx_seq = tx_seq; bt_cb(skb)->sar = sar; __skb_queue_tail(SREJ_QUEUE(sk), skb); return 0; } - err = l2cap_push_rx_skb(sk, skb, rx_control); + err = l2cap_push_rx_skb(chan, skb, rx_control); if (err < 0) return 0; if (rx_control & L2CAP_CTRL_FINAL) { - if (pi->conn_state & L2CAP_CONN_REJ_ACT) - pi->conn_state &= ~L2CAP_CONN_REJ_ACT; + if (chan->conn_state & L2CAP_CONN_REJ_ACT) + chan->conn_state &= ~L2CAP_CONN_REJ_ACT; else - l2cap_retransmit_frames(sk); + l2cap_retransmit_frames(chan); } __mod_ack_timer(); pi->num_acked = (pi->num_acked + 1) % num_to_ack; if (pi->num_acked == num_to_ack - 1) - l2cap_send_ack(pi); + l2cap_send_ack(chan); return 0; @@ -3368,8 +3383,9 @@ drop: return 0; } -static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) +static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control), @@ -3379,154 +3395,156 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) l2cap_drop_acked_frames(sk); if (rx_control & L2CAP_CTRL_POLL) { - pi->conn_state |= L2CAP_CONN_SEND_FBIT; - if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { - if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && + chan->conn_state |= L2CAP_CONN_SEND_FBIT; + if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { + if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && (pi->unacked_frames > 0)) __mod_retrans_timer(); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - l2cap_send_srejtail(sk); + chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + l2cap_send_srejtail(chan); } else { - l2cap_send_i_or_rr_or_rnr(sk); + l2cap_send_i_or_rr_or_rnr(chan); } } else if (rx_control & L2CAP_CTRL_FINAL) { - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - if (pi->conn_state & L2CAP_CONN_REJ_ACT) - pi->conn_state &= ~L2CAP_CONN_REJ_ACT; + if (chan->conn_state & L2CAP_CONN_REJ_ACT) + chan->conn_state &= ~L2CAP_CONN_REJ_ACT; else - l2cap_retransmit_frames(sk); + l2cap_retransmit_frames(chan); } else { - if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && + if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && (pi->unacked_frames > 0)) __mod_retrans_timer(); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - if (pi->conn_state & L2CAP_CONN_SREJ_SENT) - l2cap_send_ack(pi); + chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + if (chan->conn_state & L2CAP_CONN_SREJ_SENT) + l2cap_send_ack(chan); else - l2cap_ertm_send(sk); + l2cap_ertm_send(chan); } } -static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control) +static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_reqseq(rx_control); - BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control); + BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); + l2cap_drop_acked_frames(chan->sk); if (rx_control & L2CAP_CTRL_FINAL) { - if (pi->conn_state & L2CAP_CONN_REJ_ACT) - pi->conn_state &= ~L2CAP_CONN_REJ_ACT; + if (chan->conn_state & L2CAP_CONN_REJ_ACT) + chan->conn_state &= ~L2CAP_CONN_REJ_ACT; else - l2cap_retransmit_frames(sk); + l2cap_retransmit_frames(chan); } else { - l2cap_retransmit_frames(sk); + l2cap_retransmit_frames(chan); - if (pi->conn_state & L2CAP_CONN_WAIT_F) - pi->conn_state |= L2CAP_CONN_REJ_ACT; + if (chan->conn_state & L2CAP_CONN_WAIT_F) + chan->conn_state |= L2CAP_CONN_REJ_ACT; } } -static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control) +static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_reqseq(rx_control); - BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control); + BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); - pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; if (rx_control & L2CAP_CTRL_POLL) { pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); + l2cap_drop_acked_frames(chan->sk); - pi->conn_state |= L2CAP_CONN_SEND_FBIT; - l2cap_retransmit_one_frame(sk, tx_seq); + chan->conn_state |= L2CAP_CONN_SEND_FBIT; + l2cap_retransmit_one_frame(chan, tx_seq); - l2cap_ertm_send(sk); + l2cap_ertm_send(chan); - if (pi->conn_state & L2CAP_CONN_WAIT_F) { + if (chan->conn_state & L2CAP_CONN_WAIT_F) { pi->srej_save_reqseq = tx_seq; - pi->conn_state |= L2CAP_CONN_SREJ_ACT; + chan->conn_state |= L2CAP_CONN_SREJ_ACT; } } else if (rx_control & L2CAP_CTRL_FINAL) { - if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) && + if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) && pi->srej_save_reqseq == tx_seq) - pi->conn_state &= ~L2CAP_CONN_SREJ_ACT; + chan->conn_state &= ~L2CAP_CONN_SREJ_ACT; else - l2cap_retransmit_one_frame(sk, tx_seq); + l2cap_retransmit_one_frame(chan, tx_seq); } else { - l2cap_retransmit_one_frame(sk, tx_seq); - if (pi->conn_state & L2CAP_CONN_WAIT_F) { + l2cap_retransmit_one_frame(chan, tx_seq); + if (chan->conn_state & L2CAP_CONN_WAIT_F) { pi->srej_save_reqseq = tx_seq; - pi->conn_state |= L2CAP_CONN_SREJ_ACT; + chan->conn_state |= L2CAP_CONN_SREJ_ACT; } } } -static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control) +static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_reqseq(rx_control); - BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control); + BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); - pi->conn_state |= L2CAP_CONN_REMOTE_BUSY; + chan->conn_state |= L2CAP_CONN_REMOTE_BUSY; pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(sk); + l2cap_drop_acked_frames(chan->sk); if (rx_control & L2CAP_CTRL_POLL) - pi->conn_state |= L2CAP_CONN_SEND_FBIT; + chan->conn_state |= L2CAP_CONN_SEND_FBIT; - if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) { + if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) { del_timer(&pi->retrans_timer); if (rx_control & L2CAP_CTRL_POLL) - l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL); + l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL); return; } if (rx_control & L2CAP_CTRL_POLL) - l2cap_send_srejtail(sk); + l2cap_send_srejtail(chan); else - l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY); + l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY); } -static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) +static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) { - BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); + struct sock *sk = chan->sk; + + BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len); if (L2CAP_CTRL_FINAL & rx_control && - l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) { + chan->conn_state & L2CAP_CONN_WAIT_F) { del_timer(&l2cap_pi(sk)->monitor_timer); if (l2cap_pi(sk)->unacked_frames > 0) __mod_retrans_timer(); - l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F; + chan->conn_state &= ~L2CAP_CONN_WAIT_F; } switch (rx_control & L2CAP_CTRL_SUPERVISE) { case L2CAP_SUPER_RCV_READY: - l2cap_data_channel_rrframe(sk, rx_control); + l2cap_data_channel_rrframe(chan, rx_control); break; case L2CAP_SUPER_REJECT: - l2cap_data_channel_rejframe(sk, rx_control); + l2cap_data_channel_rejframe(chan, rx_control); break; case L2CAP_SUPER_SELECT_REJECT: - l2cap_data_channel_srejframe(sk, rx_control); + l2cap_data_channel_srejframe(chan, rx_control); break; case L2CAP_SUPER_RCV_NOT_READY: - l2cap_data_channel_rnrframe(sk, rx_control); + l2cap_data_channel_rnrframe(chan, rx_control); break; } @@ -3536,6 +3554,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control; u8 req_seq; @@ -3586,7 +3605,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) goto drop; } - l2cap_data_channel_iframe(sk, control, skb); + l2cap_data_channel_iframe(chan, control, skb); } else { if (len != 0) { BT_ERR("%d", len); @@ -3594,7 +3613,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) goto drop; } - l2cap_data_channel_sframe(sk, control, skb); + l2cap_data_channel_sframe(chan, control, skb); } return 0; @@ -3675,7 +3694,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk else pi->expected_tx_seq = (tx_seq + 1) % 64; - l2cap_streaming_reassembly_sdu(sk, skb, control); + l2cap_streaming_reassembly_sdu(chan, skb, control); goto done; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 450f57b106b..66ec966ffc1 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -778,14 +778,16 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms if (pi->mode == L2CAP_MODE_STREAMING) { l2cap_streaming_send(sk); - } else { - if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && - (pi->conn_state & L2CAP_CONN_WAIT_F)) { - err = len; - break; - } - err = l2cap_ertm_send(sk); + err = len; + break; + } + + if ((pi->chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && + (pi->chan->conn_state & L2CAP_CONN_WAIT_F)) { + err = len; + break; } + err = l2cap_ertm_send(pi->chan); if (err >= 0) err = len; -- cgit v1.2.3-70-g09d2 From 42e5c8027bad6f1591032941f0ebf4fc079405c8 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 19:58:34 -0300 Subject: Bluetooth: Move of ERTM *_seq vars to struct l2cap_chan As part of the moving channel to stuff to struct l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 20 +++---- net/bluetooth/l2cap_core.c | 128 ++++++++++++++++++++---------------------- net/bluetooth/l2cap_sock.c | 2 +- 3 files changed, 73 insertions(+), 77 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 82d5b81a779..9b43874ca6e 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -288,6 +288,12 @@ struct l2cap_chan { __u16 conn_state; + __u8 next_tx_seq; + __u8 expected_ack_seq; + __u8 expected_tx_seq; + __u8 buffer_seq; + __u8 buffer_seq_srej; + struct list_head list; }; @@ -353,11 +359,6 @@ struct l2cap_pinfo { __u8 conf_state; - __u8 next_tx_seq; - __u8 expected_ack_seq; - __u8 expected_tx_seq; - __u8 buffer_seq; - __u8 buffer_seq_srej; __u8 srej_save_reqseq; __u8 frames_sent; __u8 unacked_frames; @@ -421,17 +422,16 @@ struct l2cap_pinfo { #define __mod_ack_timer() mod_timer(&l2cap_pi(sk)->ack_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); -static inline int l2cap_tx_window_full(struct sock *sk) +static inline int l2cap_tx_window_full(struct l2cap_chan *ch) { - struct l2cap_pinfo *pi = l2cap_pi(sk); int sub; - sub = (pi->next_tx_seq - pi->expected_ack_seq) % 64; + sub = (ch->next_tx_seq - ch->expected_ack_seq) % 64; if (sub < 0) sub += 64; - return sub == pi->remote_tx_win; + return sub == l2cap_pi(ch->sk)->remote_tx_win; } #define __get_txseq(ctrl) (((ctrl) & L2CAP_CTRL_TXSEQ) >> 1) @@ -456,7 +456,7 @@ struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen); int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len); void l2cap_do_send(struct sock *sk, struct sk_buff *skb); -void l2cap_streaming_send(struct sock *sk); +void l2cap_streaming_send(struct l2cap_chan *chan); int l2cap_ertm_send(struct l2cap_chan *chan); void l2cap_sock_set_timer(struct sock *sk, long timeout); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b5435cd74f9..d975092904c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -395,15 +395,13 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); - if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; chan->conn_state |= L2CAP_CONN_RNR_SENT; } else control |= L2CAP_SUPER_RCV_READY; - control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; l2cap_send_sframe(chan, control); } @@ -988,13 +986,14 @@ static void l2cap_retrans_timeout(unsigned long arg) bh_unlock_sock(sk); } -static void l2cap_drop_acked_frames(struct sock *sk) +static void l2cap_drop_acked_frames(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; struct sk_buff *skb; while ((skb = skb_peek(TX_QUEUE(sk))) && l2cap_pi(sk)->unacked_frames) { - if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq) + if (bt_cb(skb)->tx_seq == chan->expected_ack_seq) break; skb = skb_dequeue(TX_QUEUE(sk)); @@ -1023,15 +1022,16 @@ void l2cap_do_send(struct sock *sk, struct sk_buff *skb) hci_send_acl(hcon, skb, flags); } -void l2cap_streaming_send(struct sock *sk) +void l2cap_streaming_send(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; struct sk_buff *skb; struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; while ((skb = skb_dequeue(TX_QUEUE(sk)))) { control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE); - control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; + control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE); if (pi->fcs == L2CAP_FCS_CRC16) { @@ -1041,7 +1041,7 @@ void l2cap_streaming_send(struct sock *sk) l2cap_do_send(sk, skb); - pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; + chan->next_tx_seq = (chan->next_tx_seq + 1) % 64; } } @@ -1080,7 +1080,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) chan->conn_state &= ~L2CAP_CONN_SEND_FBIT; } - control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) + control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); @@ -1104,7 +1104,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan) if (sk->sk_state != BT_CONNECTED) return -ENOTCONN; - while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) { + while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(chan))) { if (pi->remote_max_tx && bt_cb(skb)->retries == pi->remote_max_tx) { @@ -1123,8 +1123,8 @@ int l2cap_ertm_send(struct l2cap_chan *chan) control |= L2CAP_CTRL_FINAL; chan->conn_state &= ~L2CAP_CONN_SEND_FBIT; } - control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) - | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); + control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) + | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); @@ -1137,8 +1137,8 @@ int l2cap_ertm_send(struct l2cap_chan *chan) __mod_retrans_timer(); - bt_cb(skb)->tx_seq = pi->next_tx_seq; - pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; + bt_cb(skb)->tx_seq = chan->next_tx_seq; + chan->next_tx_seq = (chan->next_tx_seq + 1) % 64; if (bt_cb(skb)->retries == 1) pi->unacked_frames++; @@ -1159,23 +1159,21 @@ int l2cap_ertm_send(struct l2cap_chan *chan) static int l2cap_retransmit_frames(struct l2cap_chan *chan) { struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); int ret; if (!skb_queue_empty(TX_QUEUE(sk))) sk->sk_send_head = TX_QUEUE(sk)->next; - pi->next_tx_seq = pi->expected_ack_seq; + chan->next_tx_seq = chan->expected_ack_seq; ret = l2cap_ertm_send(chan); return ret; } static void l2cap_send_ack(struct l2cap_chan *chan) { - struct sock *sk = chan->sk; u16 control = 0; - control |= l2cap_pi(sk)->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; @@ -1575,9 +1573,9 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan) { struct sock *sk = chan->sk; - l2cap_pi(sk)->expected_ack_seq = 0; + chan->expected_ack_seq = 0; l2cap_pi(sk)->unacked_frames = 0; - l2cap_pi(sk)->buffer_seq = 0; + chan->buffer_seq = 0; l2cap_pi(sk)->num_acked = 0; l2cap_pi(sk)->frames_sent = 0; @@ -2311,8 +2309,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr sk->sk_state = BT_CONNECTED; - l2cap_pi(sk)->next_tx_seq = 0; - l2cap_pi(sk)->expected_tx_seq = 0; + chan->next_tx_seq = 0; + chan->expected_tx_seq = 0; __skb_queue_head_init(TX_QUEUE(sk)); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) l2cap_ertm_init(chan); @@ -2402,8 +2400,8 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr set_default_fcs(l2cap_pi(sk)); sk->sk_state = BT_CONNECTED; - l2cap_pi(sk)->next_tx_seq = 0; - l2cap_pi(sk)->expected_tx_seq = 0; + chan->next_tx_seq = 0; + chan->expected_tx_seq = 0; __skb_queue_head_init(TX_QUEUE(sk)); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) l2cap_ertm_init(chan); @@ -2794,7 +2792,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) pi->frames_sent = 0; - control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; @@ -2814,10 +2812,10 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) } } -static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar) +static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar) { + struct sock *sk = chan->sk; struct sk_buff *next_skb; - struct l2cap_pinfo *pi = l2cap_pi(sk); int tx_seq_offset, next_tx_seq_offset; bt_cb(skb)->tx_seq = tx_seq; @@ -2829,7 +2827,7 @@ static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_s return 0; } - tx_seq_offset = (tx_seq - pi->buffer_seq) % 64; + tx_seq_offset = (tx_seq - chan->buffer_seq) % 64; if (tx_seq_offset < 0) tx_seq_offset += 64; @@ -2838,7 +2836,7 @@ static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_s return -EINVAL; next_tx_seq_offset = (bt_cb(next_skb)->tx_seq - - pi->buffer_seq) % 64; + chan->buffer_seq) % 64; if (next_tx_seq_offset < 0) next_tx_seq_offset += 64; @@ -2981,13 +2979,13 @@ static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) return -EBUSY; } - pi->buffer_seq = (pi->buffer_seq + 1) % 64; + chan->buffer_seq = (chan->buffer_seq + 1) % 64; } if (!(chan->conn_state & L2CAP_CONN_RNR_SENT)) goto done; - control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL; l2cap_send_sframe(chan, control); l2cap_pi(sk)->retry_count = 1; @@ -3069,7 +3067,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c err = l2cap_ertm_reassembly_sdu(chan, skb, control); if (err >= 0) { - pi->buffer_seq = (pi->buffer_seq + 1) % 64; + chan->buffer_seq = (chan->buffer_seq + 1) % 64; return err; } @@ -3080,7 +3078,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; __skb_queue_tail(BUSY_QUEUE(sk), skb); - sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; + sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; sctrl |= L2CAP_SUPER_RCV_NOT_READY; l2cap_send_sframe(chan, sctrl); @@ -3200,8 +3198,8 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq) skb = skb_dequeue(SREJ_QUEUE(sk)); control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; l2cap_ertm_reassembly_sdu(chan, skb, control); - l2cap_pi(sk)->buffer_seq_srej = - (l2cap_pi(sk)->buffer_seq_srej + 1) % 64; + chan->buffer_seq_srej = + (chan->buffer_seq_srej + 1) % 64; tx_seq = (tx_seq + 1) % 64; } } @@ -3229,21 +3227,20 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq) static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) { struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); struct srej_list *new; u16 control; - while (tx_seq != pi->expected_tx_seq) { + while (tx_seq != chan->expected_tx_seq) { control = L2CAP_SUPER_SELECT_REJECT; - control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; + control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; l2cap_send_sframe(chan, control); new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); - new->tx_seq = pi->expected_tx_seq; - pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; + new->tx_seq = chan->expected_tx_seq; + chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; list_add_tail(&new->list, SREJ_LIST(sk)); } - pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; + chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; } static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) @@ -3268,13 +3265,13 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont chan->conn_state &= ~L2CAP_CONN_WAIT_F; } - pi->expected_ack_seq = req_seq; - l2cap_drop_acked_frames(sk); + chan->expected_ack_seq = req_seq; + l2cap_drop_acked_frames(chan); - if (tx_seq == pi->expected_tx_seq) + if (tx_seq == chan->expected_tx_seq) goto expected; - tx_seq_offset = (tx_seq - pi->buffer_seq) % 64; + tx_seq_offset = (tx_seq - chan->buffer_seq) % 64; if (tx_seq_offset < 0) tx_seq_offset += 64; @@ -3293,14 +3290,14 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont first = list_first_entry(SREJ_LIST(sk), struct srej_list, list); if (tx_seq == first->tx_seq) { - l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); + l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); l2cap_check_srej_gap(chan, tx_seq); list_del(&first->list); kfree(first); if (list_empty(SREJ_LIST(sk))) { - pi->buffer_seq = pi->buffer_seq_srej; + chan->buffer_seq = chan->buffer_seq_srej; chan->conn_state &= ~L2CAP_CONN_SREJ_SENT; l2cap_send_ack(chan); BT_DBG("sk %p, Exit SREJ_SENT", sk); @@ -3309,7 +3306,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont struct srej_list *l; /* duplicated tx_seq */ - if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0) + if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0) goto drop; list_for_each_entry(l, SREJ_LIST(sk), list) { @@ -3322,7 +3319,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont } } else { expected_tx_seq_offset = - (pi->expected_tx_seq - pi->buffer_seq) % 64; + (chan->expected_tx_seq - chan->buffer_seq) % 64; if (expected_tx_seq_offset < 0) expected_tx_seq_offset += 64; @@ -3335,11 +3332,11 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont BT_DBG("sk %p, Enter SREJ", sk); INIT_LIST_HEAD(SREJ_LIST(sk)); - pi->buffer_seq_srej = pi->buffer_seq; + chan->buffer_seq_srej = chan->buffer_seq; __skb_queue_head_init(SREJ_QUEUE(sk)); __skb_queue_head_init(BUSY_QUEUE(sk)); - l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); + l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); chan->conn_state |= L2CAP_CONN_SEND_PBIT; @@ -3350,7 +3347,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont return 0; expected: - pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; + chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { bt_cb(skb)->tx_seq = tx_seq; @@ -3391,8 +3388,8 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control), rx_control); - pi->expected_ack_seq = __get_reqseq(rx_control); - l2cap_drop_acked_frames(sk); + chan->expected_ack_seq = __get_reqseq(rx_control); + l2cap_drop_acked_frames(chan); if (rx_control & L2CAP_CTRL_POLL) { chan->conn_state |= L2CAP_CONN_SEND_FBIT; @@ -3430,15 +3427,14 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_reqseq(rx_control); BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(chan->sk); + chan->expected_ack_seq = tx_seq; + l2cap_drop_acked_frames(chan); if (rx_control & L2CAP_CTRL_FINAL) { if (chan->conn_state & L2CAP_CONN_REJ_ACT) @@ -3462,8 +3458,8 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_ chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; if (rx_control & L2CAP_CTRL_POLL) { - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(chan->sk); + chan->expected_ack_seq = tx_seq; + l2cap_drop_acked_frames(chan); chan->conn_state |= L2CAP_CONN_SEND_FBIT; l2cap_retransmit_one_frame(chan, tx_seq); @@ -3497,8 +3493,8 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_c BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); chan->conn_state |= L2CAP_CONN_REMOTE_BUSY; - pi->expected_ack_seq = tx_seq; - l2cap_drop_acked_frames(chan->sk); + chan->expected_ack_seq = tx_seq; + l2cap_drop_acked_frames(chan); if (rx_control & L2CAP_CTRL_POLL) chan->conn_state |= L2CAP_CONN_SEND_FBIT; @@ -3584,12 +3580,12 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) } req_seq = __get_reqseq(control); - req_seq_offset = (req_seq - pi->expected_ack_seq) % 64; + req_seq_offset = (req_seq - chan->expected_ack_seq) % 64; if (req_seq_offset < 0) req_seq_offset += 64; next_tx_seq_offset = - (pi->next_tx_seq - pi->expected_ack_seq) % 64; + (chan->next_tx_seq - chan->expected_ack_seq) % 64; if (next_tx_seq_offset < 0) next_tx_seq_offset += 64; @@ -3689,10 +3685,10 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk tx_seq = __get_txseq(control); - if (pi->expected_tx_seq == tx_seq) - pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; + if (chan->expected_tx_seq == tx_seq) + chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; else - pi->expected_tx_seq = (tx_seq + 1) % 64; + chan->expected_tx_seq = (tx_seq + 1) % 64; l2cap_streaming_reassembly_sdu(chan, skb, control); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 66ec966ffc1..19574e43226 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -777,7 +777,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms } if (pi->mode == L2CAP_MODE_STREAMING) { - l2cap_streaming_send(sk); + l2cap_streaming_send(pi->chan); err = len; break; } -- cgit v1.2.3-70-g09d2 From 2c03a7a49e0831646bd35d0877ec7d051d8f174b Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 20:15:28 -0300 Subject: Bluetooth: Move remote info to struct l2cap_chan As part of the moving channel stuff to l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 10 +++++----- net/bluetooth/l2cap_core.c | 32 ++++++++++++++++---------------- net/bluetooth/l2cap_sock.c | 4 ++-- 3 files changed, 23 insertions(+), 23 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 19d613bbcf0..11c53cb4a11 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -302,6 +302,9 @@ struct l2cap_chan { __u16 partial_sdu_len; struct sk_buff *sdu; + __u8 remote_tx_win; + __u8 remote_max_tx; + __u16 remote_mps; struct list_head list; }; @@ -370,11 +373,8 @@ struct l2cap_pinfo { __u8 tx_win; __u8 max_tx; - __u8 remote_tx_win; - __u8 remote_max_tx; __u16 retrans_timeout; __u16 monitor_timeout; - __u16 remote_mps; __u16 mps; __le16 sport; @@ -431,7 +431,7 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch) if (sub < 0) sub += 64; - return sub == l2cap_pi(ch->sk)->remote_tx_win; + return sub == ch->remote_tx_win; } #define __get_txseq(ctrl) (((ctrl) & L2CAP_CTRL_TXSEQ) >> 1) @@ -454,7 +454,7 @@ int __l2cap_wait_ack(struct sock *sk); struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len); struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len); struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen); -int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len); +int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); void l2cap_do_send(struct sock *sk, struct sk_buff *skb); void l2cap_streaming_send(struct l2cap_chan *chan); int l2cap_ertm_send(struct l2cap_chan *chan); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8ccfcdf3e08..2176a003087 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -956,7 +956,7 @@ static void l2cap_monitor_timeout(unsigned long arg) BT_DBG("chan %p", chan); bh_lock_sock(sk); - if (chan->retry_count >= l2cap_pi(sk)->remote_max_tx) { + if (chan->retry_count >= chan->remote_max_tx) { l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED); bh_unlock_sock(sk); return; @@ -1065,8 +1065,8 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) } while ((skb = skb_queue_next(TX_QUEUE(sk), skb))); - if (pi->remote_max_tx && - bt_cb(skb)->retries == pi->remote_max_tx) { + if (chan->remote_max_tx && + bt_cb(skb)->retries == chan->remote_max_tx) { l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED); return; } @@ -1106,8 +1106,8 @@ int l2cap_ertm_send(struct l2cap_chan *chan) while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(chan))) { - if (pi->remote_max_tx && - bt_cb(skb)->retries == pi->remote_max_tx) { + if (chan->remote_max_tx && + bt_cb(skb)->retries == chan->remote_max_tx) { l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED); break; } @@ -1337,9 +1337,9 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz return skb; } -int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len) +int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct sock *sk = chan->sk; struct sk_buff *skb; struct sk_buff_head sar_queue; u16 control; @@ -1347,20 +1347,20 @@ int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len) skb_queue_head_init(&sar_queue); control = L2CAP_SDU_START; - skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len); + skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len); if (IS_ERR(skb)) return PTR_ERR(skb); __skb_queue_tail(&sar_queue, skb); - len -= pi->remote_mps; - size += pi->remote_mps; + len -= chan->remote_mps; + size += chan->remote_mps; while (len > 0) { size_t buflen; - if (len > pi->remote_mps) { + if (len > chan->remote_mps) { control = L2CAP_SDU_CONTINUE; - buflen = pi->remote_mps; + buflen = chan->remote_mps; } else { control = L2CAP_SDU_END; buflen = len; @@ -1810,13 +1810,13 @@ done: break; case L2CAP_MODE_ERTM: - pi->remote_tx_win = rfc.txwin_size; - pi->remote_max_tx = rfc.max_transmit; + chan->remote_tx_win = rfc.txwin_size; + chan->remote_max_tx = rfc.max_transmit; if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10) rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); - pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); + chan->remote_mps = le16_to_cpu(rfc.max_pdu_size); rfc.retrans_timeout = le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO); @@ -1834,7 +1834,7 @@ done: if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10) rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); - pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); + chan->remote_mps = le16_to_cpu(rfc.max_pdu_size); pi->conf_state |= L2CAP_CONF_MODE_DONE; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 19574e43226..f90ca2586ea 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -757,7 +757,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms case L2CAP_MODE_ERTM: case L2CAP_MODE_STREAMING: /* Entire SDU fits into one PDU */ - if (len <= pi->remote_mps) { + if (len <= pi->chan->remote_mps) { control = L2CAP_SDU_UNSEGMENTED; skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0); if (IS_ERR(skb)) { @@ -771,7 +771,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms } else { /* Segment SDU into multiples PDUs */ - err = l2cap_sar_segment_sdu(sk, msg, len); + err = l2cap_sar_segment_sdu(pi->chan, msg, len); if (err < 0) goto done; } -- cgit v1.2.3-70-g09d2 From e92c8e70faf5e3cc22979daba2a895359aa1eab2 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 1 Apr 2011 00:53:45 -0300 Subject: Bluetooth: Move ERTM timers to struct l2cap_chan This also triggered a change in l2cap_send_disconn_req() parameters. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 15 +++++---- net/bluetooth/l2cap_core.c | 74 +++++++++++++++++++++---------------------- net/bluetooth/l2cap_sock.c | 13 ++++---- 3 files changed, 51 insertions(+), 51 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 11c53cb4a11..5f4abea313a 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -306,6 +306,10 @@ struct l2cap_chan { __u8 remote_max_tx; __u16 remote_mps; + struct timer_list retrans_timer; + struct timer_list monitor_timer; + struct timer_list ack_timer; + struct list_head list; }; @@ -379,9 +383,6 @@ struct l2cap_pinfo { __le16 sport; - struct timer_list retrans_timer; - struct timer_list monitor_timer; - struct timer_list ack_timer; struct sk_buff_head tx_queue; struct sk_buff_head srej_queue; struct sk_buff_head busy_queue; @@ -415,11 +416,11 @@ struct l2cap_pinfo { #define L2CAP_CONN_RNR_SENT 0x0200 #define L2CAP_CONN_SAR_RETRY 0x0400 -#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ +#define __mod_retrans_timer() mod_timer(&chan->retrans_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); -#define __mod_monitor_timer() mod_timer(&l2cap_pi(sk)->monitor_timer, \ +#define __mod_monitor_timer() mod_timer(&chan->monitor_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO)); -#define __mod_ack_timer() mod_timer(&l2cap_pi(sk)->ack_timer, \ +#define __mod_ack_timer() mod_timer(&chan->ack_timer, \ jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); static inline int l2cap_tx_window_full(struct l2cap_chan *ch) @@ -466,7 +467,7 @@ void l2cap_sock_kill(struct sock *sk); void l2cap_sock_init(struct sock *sk, struct sock *parent); struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); -void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err); +void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); void l2cap_chan_del(struct l2cap_chan *chan, int err); int l2cap_do_connect(struct sock *sk); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 2176a003087..eaac13cb793 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -241,9 +241,9 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { struct srej_list *l, *tmp; - del_timer(&l2cap_pi(sk)->retrans_timer); - del_timer(&l2cap_pi(sk)->monitor_timer); - del_timer(&l2cap_pi(sk)->ack_timer); + del_timer(&chan->retrans_timer); + del_timer(&chan->monitor_timer); + del_timer(&chan->ack_timer); skb_queue_purge(SREJ_QUEUE(sk)); skb_queue_purge(BUSY_QUEUE(sk)); @@ -462,19 +462,22 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) } } -void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err) +void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) { + struct sock *sk; struct l2cap_disconn_req req; if (!conn) return; + sk = chan->sk; + skb_queue_purge(TX_QUEUE(sk)); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { - del_timer(&l2cap_pi(sk)->retrans_timer); - del_timer(&l2cap_pi(sk)->monitor_timer); - del_timer(&l2cap_pi(sk)->ack_timer); + del_timer(&chan->retrans_timer); + del_timer(&chan->monitor_timer); + del_timer(&chan->ack_timer); } req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid); @@ -957,7 +960,7 @@ static void l2cap_monitor_timeout(unsigned long arg) bh_lock_sock(sk); if (chan->retry_count >= chan->remote_max_tx) { - l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED); + l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED); bh_unlock_sock(sk); return; } @@ -1003,7 +1006,7 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan) } if (!chan->unacked_frames) - del_timer(&l2cap_pi(sk)->retrans_timer); + del_timer(&chan->retrans_timer); } void l2cap_do_send(struct sock *sk, struct sk_buff *skb) @@ -1067,7 +1070,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { - l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED); + l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED); return; } @@ -1108,7 +1111,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan) if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { - l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED); + l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED); break; } @@ -1579,12 +1582,11 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan) chan->num_acked = 0; chan->frames_sent = 0; - setup_timer(&l2cap_pi(sk)->retrans_timer, - l2cap_retrans_timeout, (unsigned long) chan); - setup_timer(&l2cap_pi(sk)->monitor_timer, - l2cap_monitor_timeout, (unsigned long) chan); - setup_timer(&l2cap_pi(sk)->ack_timer, - l2cap_ack_timeout, (unsigned long) chan); + setup_timer(&chan->retrans_timer, l2cap_retrans_timeout, + (unsigned long) chan); + setup_timer(&chan->monitor_timer, l2cap_monitor_timeout, + (unsigned long) chan); + setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan); __skb_queue_head_init(SREJ_QUEUE(sk)); __skb_queue_head_init(BUSY_QUEUE(sk)); @@ -2291,7 +2293,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr /* Complete config. */ len = l2cap_parse_conf_req(chan, rsp); if (len < 0) { - l2cap_send_disconn_req(conn, sk, ECONNRESET); + l2cap_send_disconn_req(conn, chan, ECONNRESET); goto unlock; } @@ -2363,7 +2365,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr char req[64]; if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { - l2cap_send_disconn_req(conn, sk, ECONNRESET); + l2cap_send_disconn_req(conn, chan, ECONNRESET); goto done; } @@ -2372,7 +2374,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr len = l2cap_parse_conf_rsp(sk, rsp->data, len, req, &result); if (len < 0) { - l2cap_send_disconn_req(conn, sk, ECONNRESET); + l2cap_send_disconn_req(conn, chan, ECONNRESET); goto done; } @@ -2387,7 +2389,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr default: sk->sk_err = ECONNRESET; l2cap_sock_set_timer(sk, HZ * 5); - l2cap_send_disconn_req(conn, sk, ECONNRESET); + l2cap_send_disconn_req(conn, chan, ECONNRESET); goto done; } @@ -2957,7 +2959,7 @@ drop: chan->sdu = NULL; disconnect: - l2cap_send_disconn_req(pi->conn, chan->sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); kfree_skb(skb); return 0; } @@ -2965,7 +2967,6 @@ disconnect: static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) { struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *skb; u16 control; int err; @@ -2989,7 +2990,7 @@ static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) l2cap_send_sframe(chan, control); chan->retry_count = 1; - del_timer(&pi->retrans_timer); + del_timer(&chan->retrans_timer); __mod_monitor_timer(); chan->conn_state |= L2CAP_CONN_WAIT_F; @@ -3020,7 +3021,7 @@ static void l2cap_busy_work(struct work_struct *work) if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) { err = -EBUSY; - l2cap_send_disconn_req(pi->conn, sk, EBUSY); + l2cap_send_disconn_req(pi->conn, pi->chan, EBUSY); break; } @@ -3083,7 +3084,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c chan->conn_state |= L2CAP_CONN_RNR_SENT; - del_timer(&pi->ack_timer); + del_timer(&chan->ack_timer); queue_work(_busy_wq, &pi->busy_work); @@ -3258,7 +3259,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont if (L2CAP_CTRL_FINAL & rx_control && chan->conn_state & L2CAP_CONN_WAIT_F) { - del_timer(&pi->monitor_timer); + del_timer(&chan->monitor_timer); if (chan->unacked_frames > 0) __mod_retrans_timer(); chan->conn_state &= ~L2CAP_CONN_WAIT_F; @@ -3276,7 +3277,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont /* invalid tx_seq */ if (tx_seq_offset >= pi->tx_win) { - l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } @@ -3341,7 +3342,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont l2cap_send_srejframe(chan, tx_seq); - del_timer(&pi->ack_timer); + del_timer(&chan->ack_timer); } return 0; @@ -3484,7 +3485,6 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_reqseq(rx_control); BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); @@ -3497,7 +3497,7 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_c chan->conn_state |= L2CAP_CONN_SEND_FBIT; if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) { - del_timer(&pi->retrans_timer); + del_timer(&chan->retrans_timer); if (rx_control & L2CAP_CTRL_POLL) l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL); return; @@ -3511,13 +3511,11 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_c static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) { - struct sock *sk = chan->sk; - BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len); if (L2CAP_CTRL_FINAL & rx_control && chan->conn_state & L2CAP_CONN_WAIT_F) { - del_timer(&l2cap_pi(sk)->monitor_timer); + del_timer(&chan->monitor_timer); if (chan->unacked_frames > 0) __mod_retrans_timer(); chan->conn_state &= ~L2CAP_CONN_WAIT_F; @@ -3572,7 +3570,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) len -= 2; if (len > pi->mps) { - l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } @@ -3588,13 +3586,13 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) /* check for invalid req-seq */ if (req_seq_offset > next_tx_seq_offset) { - l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } if (__is_iframe(control)) { if (len < 0) { - l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } @@ -3602,7 +3600,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) } else { if (len != 0) { BT_ERR("%d", len); - l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); + l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index f90ca2586ea..d66886f7ecc 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -866,6 +866,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent) void __l2cap_sock_close(struct sock *sk, int reason) { struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket); @@ -880,9 +881,9 @@ void __l2cap_sock_close(struct sock *sk, int reason) sk->sk_type == SOCK_STREAM) && conn->hcon->type == ACL_LINK) { l2cap_sock_set_timer(sk, sk->sk_sndtimeo); - l2cap_send_disconn_req(conn, sk, reason); + l2cap_send_disconn_req(conn, chan, reason); } else - l2cap_chan_del(l2cap_pi(sk)->chan, reason); + l2cap_chan_del(chan, reason); break; case BT_CONNECT2: @@ -901,16 +902,16 @@ void __l2cap_sock_close(struct sock *sk, int reason) rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.result = cpu_to_le16(result); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); - l2cap_send_cmd(conn, l2cap_pi(sk)->chan->ident, - L2CAP_CONN_RSP, sizeof(rsp), &rsp); + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, + sizeof(rsp), &rsp); } - l2cap_chan_del(l2cap_pi(sk)->chan, reason); + l2cap_chan_del(chan, reason); break; case BT_CONNECT: case BT_DISCONN: - l2cap_chan_del(l2cap_pi(sk)->chan, reason); + l2cap_chan_del(chan, reason); break; default: -- cgit v1.2.3-70-g09d2 From f1c6775be6fc944e32e0150305d9753b9a846519 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 25 Mar 2011 20:36:10 -0300 Subject: Bluetooth: Move srej and busy queues to struct l2cap_chan As part of the moving channel stuff to l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 6 ++---- net/bluetooth/l2cap_core.c | 42 ++++++++++++++++++++---------------------- net/bluetooth/l2cap_sock.c | 2 -- 3 files changed, 22 insertions(+), 28 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 5f4abea313a..09f4a2fc2e2 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -309,6 +309,8 @@ struct l2cap_chan { struct timer_list retrans_timer; struct timer_list monitor_timer; struct timer_list ack_timer; + struct sk_buff_head srej_q; + struct sk_buff_head busy_q; struct list_head list; }; @@ -347,8 +349,6 @@ struct l2cap_conn { /* ----- L2CAP socket info ----- */ #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) -#define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue) -#define BUSY_QUEUE(sk) (&l2cap_pi(sk)->busy_queue) #define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list) struct srej_list { @@ -384,8 +384,6 @@ struct l2cap_pinfo { __le16 sport; struct sk_buff_head tx_queue; - struct sk_buff_head srej_queue; - struct sk_buff_head busy_queue; struct work_struct busy_work; struct srej_list srej_l; struct l2cap_conn *conn; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index eaac13cb793..06c505b1476 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -245,8 +245,8 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) del_timer(&chan->monitor_timer); del_timer(&chan->ack_timer); - skb_queue_purge(SREJ_QUEUE(sk)); - skb_queue_purge(BUSY_QUEUE(sk)); + skb_queue_purge(&chan->srej_q); + skb_queue_purge(&chan->busy_q); list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { list_del(&l->list); @@ -1588,8 +1588,8 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan) (unsigned long) chan); setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan); - __skb_queue_head_init(SREJ_QUEUE(sk)); - __skb_queue_head_init(BUSY_QUEUE(sk)); + skb_queue_head_init(&chan->srej_q); + skb_queue_head_init(&chan->busy_q); INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work); @@ -2815,16 +2815,15 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar) { - struct sock *sk = chan->sk; struct sk_buff *next_skb; int tx_seq_offset, next_tx_seq_offset; bt_cb(skb)->tx_seq = tx_seq; bt_cb(skb)->sar = sar; - next_skb = skb_peek(SREJ_QUEUE(sk)); + next_skb = skb_peek(&chan->srej_q); if (!next_skb) { - __skb_queue_tail(SREJ_QUEUE(sk), skb); + __skb_queue_tail(&chan->srej_q, skb); return 0; } @@ -2842,16 +2841,16 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, next_tx_seq_offset += 64; if (next_tx_seq_offset > tx_seq_offset) { - __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb); + __skb_queue_before(&chan->srej_q, next_skb, skb); return 0; } - if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb)) + if (skb_queue_is_last(&chan->srej_q, next_skb)) break; - } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb))); + } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb))); - __skb_queue_tail(SREJ_QUEUE(sk), skb); + __skb_queue_tail(&chan->srej_q, skb); return 0; } @@ -2971,11 +2970,11 @@ static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) u16 control; int err; - while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) { + while ((skb = skb_dequeue(&chan->busy_q))) { control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; err = l2cap_ertm_reassembly_sdu(chan, skb, control); if (err < 0) { - skb_queue_head(BUSY_QUEUE(sk), skb); + skb_queue_head(&chan->busy_q, skb); return -EBUSY; } @@ -3016,7 +3015,7 @@ static void l2cap_busy_work(struct work_struct *work) lock_sock(sk); add_wait_queue(sk_sleep(sk), &wait); - while ((skb = skb_peek(BUSY_QUEUE(sk)))) { + while ((skb = skb_peek(&pi->chan->busy_q))) { set_current_state(TASK_INTERRUPTIBLE); if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) { @@ -3059,7 +3058,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) { bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; - __skb_queue_tail(BUSY_QUEUE(sk), skb); + __skb_queue_tail(&chan->busy_q, skb); return l2cap_try_push_rx_skb(chan); @@ -3076,7 +3075,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c chan->conn_state |= L2CAP_CONN_LOCAL_BUSY; bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; - __skb_queue_tail(BUSY_QUEUE(sk), skb); + __skb_queue_tail(&chan->busy_q, skb); sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; sctrl |= L2CAP_SUPER_RCV_NOT_READY; @@ -3187,15 +3186,14 @@ drop: static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq) { - struct sock *sk = chan->sk; struct sk_buff *skb; u16 control; - while ((skb = skb_peek(SREJ_QUEUE(sk)))) { + while ((skb = skb_peek(&chan->srej_q))) { if (bt_cb(skb)->tx_seq != tx_seq) break; - skb = skb_dequeue(SREJ_QUEUE(sk)); + skb = skb_dequeue(&chan->srej_q); control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; l2cap_ertm_reassembly_sdu(chan, skb, control); chan->buffer_seq_srej = @@ -3334,8 +3332,8 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont INIT_LIST_HEAD(SREJ_LIST(sk)); chan->buffer_seq_srej = chan->buffer_seq; - __skb_queue_head_init(SREJ_QUEUE(sk)); - __skb_queue_head_init(BUSY_QUEUE(sk)); + __skb_queue_head_init(&chan->srej_q); + __skb_queue_head_init(&chan->busy_q); l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); chan->conn_state |= L2CAP_CONN_SEND_PBIT; @@ -3352,7 +3350,7 @@ expected: if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { bt_cb(skb)->tx_seq = tx_seq; bt_cb(skb)->sar = sar; - __skb_queue_tail(SREJ_QUEUE(sk), skb); + __skb_queue_tail(&chan->srej_q, skb); return 0; } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index d66886f7ecc..55dee999af9 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1018,8 +1018,6 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) /* Default config options */ pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; skb_queue_head_init(TX_QUEUE(sk)); - skb_queue_head_init(SREJ_QUEUE(sk)); - skb_queue_head_init(BUSY_QUEUE(sk)); INIT_LIST_HEAD(SREJ_LIST(sk)); } -- cgit v1.2.3-70-g09d2 From 39d5a3ee355fa903ef4609402c79f570eb9fc4d2 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 4 Apr 2011 15:40:12 -0300 Subject: Bluetooth: Move SREJ list to struct l2cap_chan As part of moving all the Channel related operation to struct l2cap_chan. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 13 ++++++------- net/bluetooth/l2cap_core.c | 22 +++++++++++----------- net/bluetooth/l2cap_sock.c | 1 - 3 files changed, 17 insertions(+), 19 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index d05d91f2fd3..ec56d8861a4 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -277,6 +277,11 @@ struct l2cap_conn_param_update_rsp { #define L2CAP_CONN_PARAM_REJECTED 0x0001 /* ----- L2CAP channels and connections ----- */ +struct srej_list { + __u8 tx_seq; + struct list_head list; +}; + struct l2cap_chan { struct sock *sk; __u8 ident; @@ -312,6 +317,7 @@ struct l2cap_chan { struct sk_buff_head srej_q; struct sk_buff_head busy_q; struct work_struct busy_work; + struct list_head srej_l; struct list_head list; }; @@ -350,12 +356,6 @@ struct l2cap_conn { /* ----- L2CAP socket info ----- */ #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) -#define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list) - -struct srej_list { - __u8 tx_seq; - struct list_head list; -}; struct l2cap_pinfo { struct bt_sock bt; @@ -385,7 +385,6 @@ struct l2cap_pinfo { __le16 sport; struct sk_buff_head tx_queue; - struct srej_list srej_l; struct l2cap_conn *conn; struct l2cap_chan *chan; }; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 7264119b64a..9580d6cd55d 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -252,7 +252,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) skb_queue_purge(&chan->srej_q); skb_queue_purge(&chan->busy_q); - list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { + list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { list_del(&l->list); kfree(l); } @@ -1205,7 +1205,7 @@ static void l2cap_send_srejtail(struct l2cap_chan *chan) control = L2CAP_SUPER_SELECT_REJECT; control |= L2CAP_CTRL_FINAL; - tail = list_entry(SREJ_LIST(chan->sk)->prev, struct srej_list, list); + tail = list_entry((&chan->srej_l)->prev, struct srej_list, list); control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; l2cap_send_sframe(chan, control); @@ -1596,6 +1596,8 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan) skb_queue_head_init(&chan->srej_q); skb_queue_head_init(&chan->busy_q); + INIT_LIST_HEAD(&chan->srej_l); + INIT_WORK(&chan->busy_work, l2cap_busy_work); sk->sk_backlog_rcv = l2cap_ertm_data_rcv; @@ -3207,11 +3209,10 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq) static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq) { - struct sock *sk = chan->sk; struct srej_list *l, *tmp; u16 control; - list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { + list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { if (l->tx_seq == tx_seq) { list_del(&l->list); kfree(l); @@ -3221,13 +3222,12 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq) control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; l2cap_send_sframe(chan, control); list_del(&l->list); - list_add_tail(&l->list, SREJ_LIST(sk)); + list_add_tail(&l->list, &chan->srej_l); } } static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) { - struct sock *sk = chan->sk; struct srej_list *new; u16 control; @@ -3239,7 +3239,7 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); new->tx_seq = chan->expected_tx_seq; chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; - list_add_tail(&new->list, SREJ_LIST(sk)); + list_add_tail(&new->list, &chan->srej_l); } chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; } @@ -3288,7 +3288,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { struct srej_list *first; - first = list_first_entry(SREJ_LIST(sk), + first = list_first_entry(&chan->srej_l, struct srej_list, list); if (tx_seq == first->tx_seq) { l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); @@ -3297,7 +3297,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont list_del(&first->list); kfree(first); - if (list_empty(SREJ_LIST(sk))) { + if (list_empty(&chan->srej_l)) { chan->buffer_seq = chan->buffer_seq_srej; chan->conn_state &= ~L2CAP_CONN_SREJ_SENT; l2cap_send_ack(chan); @@ -3310,7 +3310,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0) goto drop; - list_for_each_entry(l, SREJ_LIST(sk), list) { + list_for_each_entry(l, &chan->srej_l, list) { if (l->tx_seq == tx_seq) { l2cap_resend_srejframe(chan, tx_seq); return 0; @@ -3332,7 +3332,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont BT_DBG("sk %p, Enter SREJ", sk); - INIT_LIST_HEAD(SREJ_LIST(sk)); + INIT_LIST_HEAD(&chan->srej_l); chan->buffer_seq_srej = chan->buffer_seq; __skb_queue_head_init(&chan->srej_q); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 55dee999af9..16a223bfa8f 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1018,7 +1018,6 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) /* Default config options */ pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; skb_queue_head_init(TX_QUEUE(sk)); - INIT_LIST_HEAD(SREJ_LIST(sk)); } static struct proto l2cap_proto = { -- cgit v1.2.3-70-g09d2 From 58d35f87effa0235181a24d55576aaa756ef7312 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 4 Apr 2011 16:16:44 -0300 Subject: Bluetooth: Move tx queue to struct l2cap_chan tx_q is the queue used by ERTM mode. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 4 ++-- net/bluetooth/l2cap_core.c | 40 +++++++++++++++++++--------------------- net/bluetooth/l2cap_sock.c | 7 +++---- 3 files changed, 24 insertions(+), 27 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index ec56d8861a4..7a215a7f9e3 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -314,6 +314,8 @@ struct l2cap_chan { struct timer_list retrans_timer; struct timer_list monitor_timer; struct timer_list ack_timer; + struct sk_buff *tx_send_head; + struct sk_buff_head tx_q; struct sk_buff_head srej_q; struct sk_buff_head busy_q; struct work_struct busy_work; @@ -355,7 +357,6 @@ struct l2cap_conn { /* ----- L2CAP socket info ----- */ #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) -#define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) struct l2cap_pinfo { struct bt_sock bt; @@ -384,7 +385,6 @@ struct l2cap_pinfo { __le16 sport; - struct sk_buff_head tx_queue; struct l2cap_conn *conn; struct l2cap_chan *chan; }; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 5fc852a9ae5..97827506dc9 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -240,7 +240,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE)) goto free; - skb_queue_purge(TX_QUEUE(sk)); + skb_queue_purge(&chan->tx_q); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { struct srej_list *l, *tmp; @@ -477,7 +477,7 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in sk = chan->sk; - skb_queue_purge(TX_QUEUE(sk)); + skb_queue_purge(&chan->tx_q); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { del_timer(&chan->retrans_timer); @@ -996,15 +996,14 @@ static void l2cap_retrans_timeout(unsigned long arg) static void l2cap_drop_acked_frames(struct l2cap_chan *chan) { - struct sock *sk = chan->sk; struct sk_buff *skb; - while ((skb = skb_peek(TX_QUEUE(sk))) && + while ((skb = skb_peek(&chan->tx_q)) && chan->unacked_frames) { if (bt_cb(skb)->tx_seq == chan->expected_ack_seq) break; - skb = skb_dequeue(TX_QUEUE(sk)); + skb = skb_dequeue(&chan->tx_q); kfree_skb(skb); chan->unacked_frames--; @@ -1037,7 +1036,7 @@ void l2cap_streaming_send(struct l2cap_chan *chan) struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; - while ((skb = skb_dequeue(TX_QUEUE(sk)))) { + while ((skb = skb_dequeue(&chan->tx_q))) { control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE); control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE); @@ -1060,7 +1059,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) struct sk_buff *skb, *tx_skb; u16 control, fcs; - skb = skb_peek(TX_QUEUE(sk)); + skb = skb_peek(&chan->tx_q); if (!skb) return; @@ -1068,10 +1067,10 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) if (bt_cb(skb)->tx_seq == tx_seq) break; - if (skb_queue_is_last(TX_QUEUE(sk), skb)) + if (skb_queue_is_last(&chan->tx_q, skb)) return; - } while ((skb = skb_queue_next(TX_QUEUE(sk), skb))); + } while ((skb = skb_queue_next(&chan->tx_q, skb))); if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { @@ -1112,7 +1111,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan) if (sk->sk_state != BT_CONNECTED) return -ENOTCONN; - while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(chan))) { + while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) { if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { @@ -1153,10 +1152,10 @@ int l2cap_ertm_send(struct l2cap_chan *chan) chan->frames_sent++; - if (skb_queue_is_last(TX_QUEUE(sk), skb)) - sk->sk_send_head = NULL; + if (skb_queue_is_last(&chan->tx_q, skb)) + chan->tx_send_head = NULL; else - sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb); + chan->tx_send_head = skb_queue_next(&chan->tx_q, skb); nsent++; } @@ -1166,11 +1165,10 @@ int l2cap_ertm_send(struct l2cap_chan *chan) static int l2cap_retransmit_frames(struct l2cap_chan *chan) { - struct sock *sk = chan->sk; int ret; - if (!skb_queue_empty(TX_QUEUE(sk))) - sk->sk_send_head = TX_QUEUE(sk)->next; + if (!skb_queue_empty(&chan->tx_q)) + chan->tx_send_head = chan->tx_q.next; chan->next_tx_seq = chan->expected_ack_seq; ret = l2cap_ertm_send(chan); @@ -1384,9 +1382,9 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le len -= buflen; size += buflen; } - skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk)); - if (sk->sk_send_head == NULL) - sk->sk_send_head = sar_queue.next; + skb_queue_splice_tail(&sar_queue, &chan->tx_q); + if (chan->tx_send_head == NULL) + chan->tx_send_head = sar_queue.next; return size; } @@ -2319,7 +2317,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr chan->next_tx_seq = 0; chan->expected_tx_seq = 0; - __skb_queue_head_init(TX_QUEUE(sk)); + skb_queue_head_init(&chan->tx_q); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) l2cap_ertm_init(chan); @@ -2410,7 +2408,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr sk->sk_state = BT_CONNECTED; chan->next_tx_seq = 0; chan->expected_tx_seq = 0; - __skb_queue_head_init(TX_QUEUE(sk)); + skb_queue_head_init(&chan->tx_q); if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) l2cap_ertm_init(chan); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 16a223bfa8f..b2bfa1e0d74 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -764,10 +764,10 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms err = PTR_ERR(skb); goto done; } - __skb_queue_tail(TX_QUEUE(sk), skb); + __skb_queue_tail(&pi->chan->tx_q, skb); - if (sk->sk_send_head == NULL) - sk->sk_send_head = skb; + if (pi->chan->tx_send_head == NULL) + pi->chan->tx_send_head = skb; } else { /* Segment SDU into multiples PDUs */ @@ -1017,7 +1017,6 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) /* Default config options */ pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; - skb_queue_head_init(TX_QUEUE(sk)); } static struct proto l2cap_proto = { -- cgit v1.2.3-70-g09d2 From cd69a03af1106c486033df600c7945957ea5abeb Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 5 Apr 2011 15:24:40 -0300 Subject: Bluetooth: Fix wrong comparison in listen() We should check for the pi->scid there. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index b2bfa1e0d74..473e5973d8f 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -269,7 +269,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) goto done; } - if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->dcid) { + if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->scid) { bdaddr_t *src = &bt_sk(sk)->src; u16 psm; -- cgit v1.2.3-70-g09d2 From 5d41ce1dd91bce01d50aff79786dc5d5eedcfab7 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 8 Apr 2011 15:40:02 -0300 Subject: Bluetooth: Refactor L2CAP channel allocation If the allocation happens at l2cap_sock_create() will be able to use the struct l2cap_chan to store channel info that comes from the user via setsockopt. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 3 ++- net/bluetooth/l2cap_core.c | 23 +++++++---------------- net/bluetooth/l2cap_sock.c | 11 ++++++++++- 3 files changed, 19 insertions(+), 18 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 7a215a7f9e3..537e3c16339 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -465,7 +465,8 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent); struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); +struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); void l2cap_chan_del(struct l2cap_chan *chan, int err); -int l2cap_do_connect(struct sock *sk); +int l2cap_do_connect(struct l2cap_chan *chan); #endif /* __L2CAP_H */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9e8dc136ef1..4b857adc536 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -149,7 +149,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) return 0; } -static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) +struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) { struct l2cap_chan *chan; @@ -648,6 +648,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) goto clean; } + l2cap_pi(sk)->chan = chan; + write_lock_bh(&conn->chan_lock); hci_conn_hold(conn->hcon); @@ -661,8 +663,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) __l2cap_chan_add(conn, chan); - l2cap_pi(sk)->chan = chan; - l2cap_sock_set_timer(sk, sk->sk_sndtimeo); sk->sk_state = BT_CONNECTED; @@ -847,12 +847,12 @@ static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) return node ? sk : sk1; } -int l2cap_do_connect(struct sock *sk) +int l2cap_do_connect(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; bdaddr_t *src = &bt_sk(sk)->src; bdaddr_t *dst = &bt_sk(sk)->dst; struct l2cap_conn *conn; - struct l2cap_chan *chan; struct hci_conn *hcon; struct hci_dev *hdev; __u8 auth_type; @@ -888,20 +888,11 @@ int l2cap_do_connect(struct sock *sk) goto done; } - chan = l2cap_chan_alloc(sk); - if (!chan) { - hci_conn_put(hcon); - err = -ENOMEM; - goto done; - } - /* Update source addr of the socket */ bacpy(src, conn->src); l2cap_chan_add(conn, chan); - l2cap_pi(sk)->chan = chan; - sk->sk_state = BT_CONNECT; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -2076,6 +2067,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd goto response; } + l2cap_pi(sk)->chan = chan; + write_lock_bh(&conn->chan_lock); /* Check if we already have channel with that dcid */ @@ -2098,8 +2091,6 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd __l2cap_chan_add(conn, chan); - l2cap_pi(sk)->chan = chan; - dcid = l2cap_pi(sk)->scid; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 473e5973d8f..e3724572c44 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -229,7 +229,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al l2cap_pi(sk)->psm = la.l2_psm; l2cap_pi(sk)->dcid = la.l2_cid; - err = l2cap_do_connect(sk); + err = l2cap_do_connect(l2cap_pi(sk)->chan); if (err) goto done; @@ -1054,6 +1054,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, int kern) { struct sock *sk; + struct l2cap_chan *chan; BT_DBG("sock %p", sock); @@ -1072,6 +1073,14 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, if (!sk) return -ENOMEM; + chan = l2cap_chan_alloc(sk); + if (!chan) { + l2cap_sock_kill(sk); + return -ENOMEM; + } + + l2cap_pi(sk)->chan = chan; + l2cap_sock_init(sk, NULL); return 0; } -- cgit v1.2.3-70-g09d2 From b44500351845e4f6df0d752a8870da246be8216f Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 12 Apr 2011 18:15:09 -0300 Subject: Bluetooth: Move conf_state to struct l2cap_chan First move of elements depending on user data. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 3 +- net/bluetooth/l2cap_core.c | 88 ++++++++++++++++++++++--------------------- net/bluetooth/l2cap_sock.c | 10 +++-- 3 files changed, 53 insertions(+), 48 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 537e3c16339..b3bb3d492ff 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -291,6 +291,7 @@ struct l2cap_chan { __u8 num_conf_req; __u8 num_conf_rsp; + __u8 conf_state; __u16 conn_state; __u8 next_tx_seq; @@ -375,8 +376,6 @@ struct l2cap_pinfo { __u8 force_reliable; __u8 flushable; - __u8 conf_state; - __u8 tx_win; __u8 max_tx; __u16 retrans_timeout; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 4b857adc536..190b04960da 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -236,8 +236,8 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) } else sk->sk_state_change(sk); - if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE && - l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE)) + if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE && + chan->conf_state & L2CAP_CONF_INPUT_DONE)) goto free; skb_queue_purge(&chan->tx_q); @@ -411,9 +411,9 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control) l2cap_send_sframe(chan, control); } -static inline int __l2cap_no_conn_pending(struct sock *sk) +static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) { - return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND); + return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND); } static void l2cap_do_start(struct l2cap_chan *chan) @@ -425,13 +425,13 @@ static void l2cap_do_start(struct l2cap_chan *chan) if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) return; - if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) { + if (l2cap_check_security(sk) && __l2cap_no_conn_pending(chan)) { struct l2cap_conn_req req; req.scid = cpu_to_le16(l2cap_pi(sk)->scid); req.psm = l2cap_pi(sk)->psm; chan->ident = l2cap_get_ident(conn); - l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; + chan->conf_state |= L2CAP_CONF_CONNECT_PEND; l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); @@ -516,14 +516,14 @@ static void l2cap_conn_start(struct l2cap_conn *conn) struct l2cap_conn_req req; if (!l2cap_check_security(sk) || - !__l2cap_no_conn_pending(sk)) { + !__l2cap_no_conn_pending(chan)) { bh_unlock_sock(sk); continue; } if (!l2cap_mode_supported(l2cap_pi(sk)->mode, conn->feat_mask) - && l2cap_pi(sk)->conf_state & + && chan->conf_state & L2CAP_CONF_STATE2_DEVICE) { /* __l2cap_sock_close() calls list_del(chan) * so release the lock */ @@ -538,7 +538,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) req.psm = l2cap_pi(sk)->psm; chan->ident = l2cap_get_ident(conn); - l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; + chan->conf_state |= L2CAP_CONF_CONNECT_PEND; l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); @@ -569,13 +569,13 @@ static void l2cap_conn_start(struct l2cap_conn *conn) l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT || + if (chan->conf_state & L2CAP_CONF_REQ_SENT || rsp.result != L2CAP_CR_SUCCESS) { bh_unlock_sock(sk); continue; } - l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; + chan->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; @@ -1382,10 +1382,11 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le static void l2cap_chan_ready(struct sock *sk) { struct sock *parent = bt_sk(sk)->parent; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; BT_DBG("sk %p, parent %p", sk, parent); - l2cap_pi(sk)->conf_state = 0; + chan->conf_state = 0; l2cap_sock_clear_timer(sk); if (!parent) { @@ -1619,7 +1620,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) switch (pi->mode) { case L2CAP_MODE_STREAMING: case L2CAP_MODE_ERTM: - if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE) + if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE) break; /* fall through */ @@ -1666,7 +1667,7 @@ done: break; if (pi->fcs == L2CAP_FCS_NONE || - pi->conf_state & L2CAP_CONF_NO_FCS_RECV) { + chan->conf_state & L2CAP_CONF_NO_FCS_RECV) { pi->fcs = L2CAP_FCS_NONE; l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs); } @@ -1689,7 +1690,7 @@ done: break; if (pi->fcs == L2CAP_FCS_NONE || - pi->conf_state & L2CAP_CONF_NO_FCS_RECV) { + chan->conf_state & L2CAP_CONF_NO_FCS_RECV) { pi->fcs = L2CAP_FCS_NONE; l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs); } @@ -1742,7 +1743,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) case L2CAP_CONF_FCS: if (val == L2CAP_FCS_NONE) - pi->conf_state |= L2CAP_CONF_NO_FCS_RECV; + chan->conf_state |= L2CAP_CONF_NO_FCS_RECV; break; @@ -1762,7 +1763,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) switch (pi->mode) { case L2CAP_MODE_STREAMING: case L2CAP_MODE_ERTM: - if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) { + if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) { pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); break; @@ -1795,14 +1796,14 @@ done: result = L2CAP_CONF_UNACCEPT; else { pi->omtu = mtu; - pi->conf_state |= L2CAP_CONF_MTU_DONE; + chan->conf_state |= L2CAP_CONF_MTU_DONE; } l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu); switch (rfc.mode) { case L2CAP_MODE_BASIC: pi->fcs = L2CAP_FCS_NONE; - pi->conf_state |= L2CAP_CONF_MODE_DONE; + chan->conf_state |= L2CAP_CONF_MODE_DONE; break; case L2CAP_MODE_ERTM: @@ -1819,7 +1820,7 @@ done: rfc.monitor_timeout = le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO); - pi->conf_state |= L2CAP_CONF_MODE_DONE; + chan->conf_state |= L2CAP_CONF_MODE_DONE; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); @@ -1832,7 +1833,7 @@ done: chan->remote_mps = le16_to_cpu(rfc.max_pdu_size); - pi->conf_state |= L2CAP_CONF_MODE_DONE; + chan->conf_state |= L2CAP_CONF_MODE_DONE; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); @@ -1847,7 +1848,7 @@ done: } if (result == L2CAP_CONF_SUCCESS) - pi->conf_state |= L2CAP_CONF_OUTPUT_DONE; + chan->conf_state |= L2CAP_CONF_OUTPUT_DONE; } rsp->scid = cpu_to_le16(pi->dcid); rsp->result = cpu_to_le16(result); @@ -1856,8 +1857,9 @@ done: return ptr - data; } -static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result) +static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) { + struct sock *sk = chan->sk; struct l2cap_pinfo *pi = l2cap_pi(sk); struct l2cap_conf_req *req = data; void *ptr = req->data; @@ -1890,7 +1892,7 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, if (olen == sizeof(rfc)) memcpy(&rfc, (void *)val, olen); - if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) && + if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) && rfc.mode != pi->mode) return -ECONNREFUSED; @@ -1955,10 +1957,10 @@ void __l2cap_connect_rsp_defer(struct sock *sk) l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) + if (chan->conf_state & L2CAP_CONF_REQ_SENT) return; - l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; + chan->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; @@ -2146,10 +2148,10 @@ sendresp: L2CAP_INFO_REQ, sizeof(info), &info); } - if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) && + if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) && result == L2CAP_CR_SUCCESS) { u8 buf[128]; - l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; + chan->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; @@ -2190,12 +2192,12 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd sk->sk_state = BT_CONFIG; chan->ident = 0; l2cap_pi(sk)->dcid = dcid; - l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND; + chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND; - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) + if (chan->conf_state & L2CAP_CONF_REQ_SENT) break; - l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; + chan->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, l2cap_build_conf_req(chan, req), req); @@ -2203,7 +2205,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd break; case L2CAP_CR_PEND: - l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; + chan->conf_state |= L2CAP_CONF_CONNECT_PEND; break; default: @@ -2230,7 +2232,7 @@ static inline void set_default_fcs(struct l2cap_pinfo *pi) */ if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING) pi->fcs = L2CAP_FCS_NONE; - else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV)) + else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV)) pi->fcs = L2CAP_FCS_CRC16; } @@ -2297,10 +2299,10 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr /* Reset config buffer. */ chan->conf_len = 0; - if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE)) + if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE)) goto unlock; - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) { + if (chan->conf_state & L2CAP_CONF_INPUT_DONE) { set_default_fcs(l2cap_pi(sk)); sk->sk_state = BT_CONNECTED; @@ -2315,9 +2317,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr goto unlock; } - if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) { + if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) { u8 buf[64]; - l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; + chan->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, l2cap_build_conf_req(chan, buf), buf); chan->num_conf_req++; @@ -2365,8 +2367,8 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr /* throw out any old stored conf requests */ result = L2CAP_CONF_SUCCESS; - len = l2cap_parse_conf_rsp(sk, rsp->data, - len, req, &result); + len = l2cap_parse_conf_rsp(chan, rsp->data, len, + req, &result); if (len < 0) { l2cap_send_disconn_req(conn, chan, ECONNRESET); goto done; @@ -2390,9 +2392,9 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr if (flags & 0x01) goto done; - l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE; + chan->conf_state |= L2CAP_CONF_INPUT_DONE; - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) { + if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) { set_default_fcs(l2cap_pi(sk)); sk->sk_state = BT_CONNECTED; @@ -3899,7 +3901,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) bh_lock_sock(sk); - if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) { + if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) { bh_unlock_sock(sk); continue; } @@ -3918,7 +3920,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) req.psm = l2cap_pi(sk)->psm; chan->ident = l2cap_get_ident(conn); - l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; + chan->conf_state |= L2CAP_CONF_CONNECT_PEND; l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index e3724572c44..a29782a0083 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -528,6 +528,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct l2cap_options opts; int len, err = 0; u32 opt; @@ -565,7 +566,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us l2cap_pi(sk)->mode = opts.mode; switch (l2cap_pi(sk)->mode) { case L2CAP_MODE_BASIC: - l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE; + chan->conf_state &= ~L2CAP_CONF_STATE2_DEVICE; break; case L2CAP_MODE_ERTM: case L2CAP_MODE_STREAMING: @@ -979,16 +980,19 @@ static void l2cap_sock_destruct(struct sock *sk) void l2cap_sock_init(struct sock *sk, struct sock *parent) { struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_chan *chan = pi->chan; BT_DBG("sk %p", sk); if (parent) { + struct l2cap_chan *pchan = l2cap_pi(parent)->chan; + sk->sk_type = parent->sk_type; bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup; pi->imtu = l2cap_pi(parent)->imtu; pi->omtu = l2cap_pi(parent)->omtu; - pi->conf_state = l2cap_pi(parent)->conf_state; + chan->conf_state = pchan->conf_state; pi->mode = l2cap_pi(parent)->mode; pi->fcs = l2cap_pi(parent)->fcs; pi->max_tx = l2cap_pi(parent)->max_tx; @@ -1002,7 +1006,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->omtu = 0; if (!disable_ertm && sk->sk_type == SOCK_STREAM) { pi->mode = L2CAP_MODE_ERTM; - pi->conf_state |= L2CAP_CONF_STATE2_DEVICE; + chan->conf_state |= L2CAP_CONF_STATE2_DEVICE; } else { pi->mode = L2CAP_MODE_BASIC; } -- cgit v1.2.3-70-g09d2 From 77a74c7e0861e6ebac7effe233fd7e83f1ad9ecc Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 12 Apr 2011 18:17:14 -0300 Subject: Bluetooth: Rename l2cap_do_connect() to l2cap_chan_connect() l2cap_chan_connect() is a much better name and reflects what this functions is doing (or will do once socket dependence is removed from the core). Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 2 +- net/bluetooth/l2cap_core.c | 2 +- net/bluetooth/l2cap_sock.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index b3bb3d492ff..f7093500034 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -466,6 +466,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); void l2cap_chan_del(struct l2cap_chan *chan, int err); -int l2cap_do_connect(struct l2cap_chan *chan); +int l2cap_chan_connect(struct l2cap_chan *chan); #endif /* __L2CAP_H */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 190b04960da..29742d875e6 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -847,7 +847,7 @@ static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) return node ? sk : sk1; } -int l2cap_do_connect(struct l2cap_chan *chan) +int l2cap_chan_connect(struct l2cap_chan *chan) { struct sock *sk = chan->sk; bdaddr_t *src = &bt_sk(sk)->src; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index a29782a0083..50437c665d1 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -229,7 +229,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al l2cap_pi(sk)->psm = la.l2_psm; l2cap_pi(sk)->dcid = la.l2_cid; - err = l2cap_do_connect(l2cap_pi(sk)->chan); + err = l2cap_chan_connect(l2cap_pi(sk)->chan); if (err) goto done; -- cgit v1.2.3-70-g09d2 From 4343478f3a4806394136d8141b2e451aa5443f03 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 12 Apr 2011 18:31:57 -0300 Subject: Bluetooth: Move some more elements to struct l2cap_chan In this commit sec_level, force_reliable, role_switch and flushable. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 12 ++++--- net/bluetooth/l2cap_core.c | 78 +++++++++++++++++++++++-------------------- net/bluetooth/l2cap_sock.c | 52 ++++++++++++++++------------- 3 files changed, 77 insertions(+), 65 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index f7093500034..684deee6ec5 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -284,6 +284,12 @@ struct srej_list { struct l2cap_chan { struct sock *sk; + + __u8 sec_level; + __u8 role_switch; + __u8 force_reliable; + __u8 flushable; + __u8 ident; __u8 conf_req[64]; @@ -371,10 +377,6 @@ struct l2cap_pinfo { __u8 mode; __u8 fcs; - __u8 sec_level; - __u8 role_switch; - __u8 force_reliable; - __u8 flushable; __u8 tx_win; __u8 max_tx; @@ -452,7 +454,7 @@ struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, s struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len); struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen); int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); -void l2cap_do_send(struct sock *sk, struct sk_buff *skb); +void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); void l2cap_streaming_send(struct l2cap_chan *chan); int l2cap_ertm_send(struct l2cap_chan *chan); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 29742d875e6..0fc6bbe85d4 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -262,10 +262,12 @@ free: kfree(chan); } -static inline u8 l2cap_get_auth_type(struct sock *sk) +static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) { + struct sock *sk = chan->sk; + if (sk->sk_type == SOCK_RAW) { - switch (l2cap_pi(sk)->sec_level) { + switch (chan->sec_level) { case BT_SECURITY_HIGH: return HCI_AT_DEDICATED_BONDING_MITM; case BT_SECURITY_MEDIUM: @@ -274,15 +276,15 @@ static inline u8 l2cap_get_auth_type(struct sock *sk) return HCI_AT_NO_BONDING; } } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) { - if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW) - l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; + if (chan->sec_level == BT_SECURITY_LOW) + chan->sec_level = BT_SECURITY_SDP; - if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH) + if (chan->sec_level == BT_SECURITY_HIGH) return HCI_AT_NO_BONDING_MITM; else return HCI_AT_NO_BONDING; } else { - switch (l2cap_pi(sk)->sec_level) { + switch (chan->sec_level) { case BT_SECURITY_HIGH: return HCI_AT_GENERAL_BONDING_MITM; case BT_SECURITY_MEDIUM: @@ -294,15 +296,14 @@ static inline u8 l2cap_get_auth_type(struct sock *sk) } /* Service level security */ -static inline int l2cap_check_security(struct sock *sk) +static inline int l2cap_check_security(struct l2cap_chan *chan) { - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = l2cap_pi(chan->sk)->conn; __u8 auth_type; - auth_type = l2cap_get_auth_type(sk); + auth_type = l2cap_get_auth_type(chan); - return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level, - auth_type); + return hci_conn_security(conn->hcon, chan->sec_level, auth_type); } u8 l2cap_get_ident(struct l2cap_conn *conn) @@ -425,7 +426,8 @@ static void l2cap_do_start(struct l2cap_chan *chan) if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) return; - if (l2cap_check_security(sk) && __l2cap_no_conn_pending(chan)) { + if (l2cap_check_security(chan) && + __l2cap_no_conn_pending(chan)) { struct l2cap_conn_req req; req.scid = cpu_to_le16(l2cap_pi(sk)->scid); req.psm = l2cap_pi(sk)->psm; @@ -515,7 +517,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) if (sk->sk_state == BT_CONNECT) { struct l2cap_conn_req req; - if (!l2cap_check_security(sk) || + if (!l2cap_check_security(chan) || !__l2cap_no_conn_pending(chan)) { bh_unlock_sock(sk); continue; @@ -549,7 +551,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); - if (l2cap_check_security(sk)) { + if (l2cap_check_security(chan)) { if (bt_sk(sk)->defer_setup) { struct sock *parent = bt_sk(sk)->parent; rsp.result = cpu_to_le16(L2CAP_CR_PEND); @@ -722,7 +724,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) list_for_each_entry(chan, &conn->chan_l, list) { struct sock *sk = chan->sk; - if (l2cap_pi(sk)->force_reliable) + if (chan->force_reliable) sk->sk_err = err; } @@ -867,14 +869,14 @@ int l2cap_chan_connect(struct l2cap_chan *chan) hci_dev_lock_bh(hdev); - auth_type = l2cap_get_auth_type(sk); + auth_type = l2cap_get_auth_type(chan); if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA) hcon = hci_connect(hdev, LE_LINK, dst, - l2cap_pi(sk)->sec_level, auth_type); + chan->sec_level, auth_type); else hcon = hci_connect(hdev, ACL_LINK, dst, - l2cap_pi(sk)->sec_level, auth_type); + chan->sec_level, auth_type); if (IS_ERR(hcon)) { err = PTR_ERR(hcon); @@ -900,7 +902,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan) if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM) { l2cap_sock_clear_timer(sk); - if (l2cap_check_security(sk)) + if (l2cap_check_security(chan)) sk->sk_state = BT_CONNECTED; } else l2cap_do_start(chan); @@ -1002,15 +1004,15 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan) del_timer(&chan->retrans_timer); } -void l2cap_do_send(struct sock *sk, struct sk_buff *skb) +void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) { - struct l2cap_pinfo *pi = l2cap_pi(sk); - struct hci_conn *hcon = pi->conn->hcon; + struct sock *sk = chan->sk; + struct hci_conn *hcon = l2cap_pi(sk)->conn->hcon; u16 flags; - BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len); + BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len); - if (!pi->flushable && lmp_no_flush_capable(hcon->hdev)) + if (!chan->flushable && lmp_no_flush_capable(hcon->hdev)) flags = ACL_START_NO_FLUSH; else flags = ACL_START; @@ -1035,7 +1037,7 @@ void l2cap_streaming_send(struct l2cap_chan *chan) put_unaligned_le16(fcs, skb->data + skb->len - 2); } - l2cap_do_send(sk, skb); + l2cap_do_send(chan, skb); chan->next_tx_seq = (chan->next_tx_seq + 1) % 64; } @@ -1087,7 +1089,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); } - l2cap_do_send(sk, tx_skb); + l2cap_do_send(chan, tx_skb); } int l2cap_ertm_send(struct l2cap_chan *chan) @@ -1130,7 +1132,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan) put_unaligned_le16(fcs, skb->data + tx_skb->len - 2); } - l2cap_do_send(sk, tx_skb); + l2cap_do_send(chan, tx_skb); __mod_retrans_timer(); @@ -2100,7 +2102,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd chan->ident = cmd->ident; if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { - if (l2cap_check_security(sk)) { + if (l2cap_check_security(chan)) { if (bt_sk(sk)->defer_setup) { sk->sk_state = BT_CONNECT2; result = L2CAP_CR_PEND; @@ -3805,17 +3807,19 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) /* Find listening sockets and check their link_mode */ read_lock(&l2cap_sk_list.lock); sk_for_each(sk, node, &l2cap_sk_list.head) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + if (sk->sk_state != BT_LISTEN) continue; if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { lm1 |= HCI_LM_ACCEPT; - if (l2cap_pi(sk)->role_switch) + if (chan->role_switch) lm1 |= HCI_LM_MASTER; exact++; } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { lm2 |= HCI_LM_ACCEPT; - if (l2cap_pi(sk)->role_switch) + if (chan->role_switch) lm2 |= HCI_LM_MASTER; } } @@ -3867,19 +3871,21 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) return 0; } -static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt) +static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) { + struct sock *sk = chan->sk; + if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM) return; if (encrypt == 0x00) { - if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) { + if (chan->sec_level == BT_SECURITY_MEDIUM) { l2cap_sock_clear_timer(sk); l2cap_sock_set_timer(sk, HZ * 5); - } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH) + } else if (chan->sec_level == BT_SECURITY_HIGH) __l2cap_sock_close(sk, ECONNREFUSED); } else { - if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) + if (chan->sec_level == BT_SECURITY_MEDIUM) l2cap_sock_clear_timer(sk); } } @@ -3908,7 +3914,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) if (!status && (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)) { - l2cap_check_encryption(sk, encrypt); + l2cap_check_encryption(chan, encrypt); bh_unlock_sock(sk); continue; } @@ -4083,7 +4089,7 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) batostr(&bt_sk(sk)->dst), sk->sk_state, __le16_to_cpu(pi->psm), pi->scid, pi->dcid, - pi->imtu, pi->omtu, pi->sec_level, + pi->imtu, pi->omtu, pi->chan->sec_level, pi->mode); } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 50437c665d1..612955679b3 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -51,7 +51,7 @@ static void l2cap_sock_timeout(unsigned long arg) if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) reason = ECONNREFUSED; else if (sk->sk_state == BT_CONNECT && - l2cap_pi(sk)->sec_level != BT_SECURITY_SDP) + l2cap_pi(sk)->chan->sec_level != BT_SECURITY_SDP) reason = ECONNREFUSED; else reason = ETIMEDOUT; @@ -91,6 +91,7 @@ found: static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct sockaddr_l2 la; int len, err = 0; @@ -142,7 +143,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) if (__le16_to_cpu(la.l2_psm) == 0x0001 || __le16_to_cpu(la.l2_psm) == 0x0003) - l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; + chan->sec_level = BT_SECURITY_SDP; } if (la.l2_cid) @@ -382,6 +383,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct l2cap_options opts; struct l2cap_conninfo cinfo; int len, err = 0; @@ -412,7 +414,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us break; case L2CAP_LM: - switch (l2cap_pi(sk)->sec_level) { + switch (chan->sec_level) { case BT_SECURITY_LOW: opt = L2CAP_LM_AUTH; break; @@ -428,10 +430,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us break; } - if (l2cap_pi(sk)->role_switch) + if (chan->role_switch) opt |= L2CAP_LM_MASTER; - if (l2cap_pi(sk)->force_reliable) + if (chan->force_reliable) opt |= L2CAP_LM_RELIABLE; if (put_user(opt, (u32 __user *) optval)) @@ -467,6 +469,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct bt_security sec; int len, err = 0; @@ -491,7 +494,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch break; } - sec.level = l2cap_pi(sk)->sec_level; + sec.level = chan->sec_level; len = min_t(unsigned int, len, sizeof(sec)); if (copy_to_user(optval, (char *) &sec, len)) @@ -511,7 +514,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch break; case BT_FLUSHABLE: - if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval)) + if (put_user(chan->flushable, (u32 __user *) optval)) err = -EFAULT; break; @@ -592,14 +595,14 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us } if (opt & L2CAP_LM_AUTH) - l2cap_pi(sk)->sec_level = BT_SECURITY_LOW; + chan->sec_level = BT_SECURITY_LOW; if (opt & L2CAP_LM_ENCRYPT) - l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM; + chan->sec_level = BT_SECURITY_MEDIUM; if (opt & L2CAP_LM_SECURE) - l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH; + chan->sec_level = BT_SECURITY_HIGH; - l2cap_pi(sk)->role_switch = (opt & L2CAP_LM_MASTER); - l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE); + chan->role_switch = (opt & L2CAP_LM_MASTER); + chan->force_reliable = (opt & L2CAP_LM_RELIABLE); break; default: @@ -614,6 +617,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct bt_security sec; int len, err = 0; u32 opt; @@ -650,7 +654,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch break; } - l2cap_pi(sk)->sec_level = sec.level; + chan->sec_level = sec.level; break; case BT_DEFER_SETUP: @@ -688,7 +692,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch } } - l2cap_pi(sk)->flushable = opt; + chan->flushable = opt; break; default: @@ -730,7 +734,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms if (IS_ERR(skb)) { err = PTR_ERR(skb); } else { - l2cap_do_send(sk, skb); + l2cap_do_send(pi->chan, skb); err = len; } goto done; @@ -751,7 +755,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms goto done; } - l2cap_do_send(sk, skb); + l2cap_do_send(pi->chan, skb); err = len; break; @@ -997,10 +1001,10 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->fcs = l2cap_pi(parent)->fcs; pi->max_tx = l2cap_pi(parent)->max_tx; pi->tx_win = l2cap_pi(parent)->tx_win; - pi->sec_level = l2cap_pi(parent)->sec_level; - pi->role_switch = l2cap_pi(parent)->role_switch; - pi->force_reliable = l2cap_pi(parent)->force_reliable; - pi->flushable = l2cap_pi(parent)->flushable; + chan->sec_level = pchan->sec_level; + chan->role_switch = pchan->role_switch; + chan->force_reliable = pchan->force_reliable; + chan->flushable = pchan->flushable; } else { pi->imtu = L2CAP_DEFAULT_MTU; pi->omtu = 0; @@ -1013,10 +1017,10 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->max_tx = L2CAP_DEFAULT_MAX_TX; pi->fcs = L2CAP_FCS_CRC16; pi->tx_win = L2CAP_DEFAULT_TX_WINDOW; - pi->sec_level = BT_SECURITY_LOW; - pi->role_switch = 0; - pi->force_reliable = 0; - pi->flushable = BT_FLUSHABLE_OFF; + chan->sec_level = BT_SECURITY_LOW; + chan->role_switch = 0; + chan->force_reliable = 0; + chan->flushable = BT_FLUSHABLE_OFF; } /* Default config options */ -- cgit v1.2.3-70-g09d2 From 47d1ec6161da2c7b9dbc56a5200fa26b17d5fdc1 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 13 Apr 2011 15:57:03 -0300 Subject: Bluetooth: Move more vars to struct l2cap_chan In this commit all ERTM and Streaming Mode specific vars. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 18 ++++---- net/bluetooth/l2cap_core.c | 100 +++++++++++++++++++++--------------------- net/bluetooth/l2cap_sock.c | 33 +++++++------- net/bluetooth/rfcomm/core.c | 2 +- 4 files changed, 77 insertions(+), 76 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 684deee6ec5..02db90210f8 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -297,6 +297,14 @@ struct l2cap_chan { __u8 num_conf_req; __u8 num_conf_rsp; + __u8 fcs; + + __u8 tx_win; + __u8 max_tx; + __u16 retrans_timeout; + __u16 monitor_timeout; + __u16 mps; + __u8 conf_state; __u16 conn_state; @@ -376,14 +384,6 @@ struct l2cap_pinfo { __u16 flush_to; __u8 mode; - __u8 fcs; - - __u8 tx_win; - __u8 max_tx; - __u16 retrans_timeout; - __u16 monitor_timeout; - __u16 mps; - __le16 sport; struct l2cap_conn *conn; @@ -452,7 +452,7 @@ int __l2cap_wait_ack(struct sock *sk); struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len); struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len); -struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen); +struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen); int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); void l2cap_streaming_send(struct l2cap_chan *chan); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 0fc6bbe85d4..cb3c4ed47ae 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -359,7 +359,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) if (sk->sk_state != BT_CONNECTED) return; - if (pi->fcs == L2CAP_FCS_CRC16) + if (chan->fcs == L2CAP_FCS_CRC16) hlen += 2; BT_DBG("chan %p, control 0x%2.2x", chan, control); @@ -386,7 +386,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) lh->cid = cpu_to_le16(pi->dcid); put_unaligned_le16(control, skb_put(skb, 2)); - if (pi->fcs == L2CAP_FCS_CRC16) { + if (chan->fcs == L2CAP_FCS_CRC16) { u16 fcs = crc16(0, (u8 *)lh, count - 2); put_unaligned_le16(fcs, skb_put(skb, 2)); } @@ -1022,9 +1022,7 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) void l2cap_streaming_send(struct l2cap_chan *chan) { - struct sock *sk = chan->sk; struct sk_buff *skb; - struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; while ((skb = skb_dequeue(&chan->tx_q))) { @@ -1032,7 +1030,7 @@ void l2cap_streaming_send(struct l2cap_chan *chan) control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE); - if (pi->fcs == L2CAP_FCS_CRC16) { + if (chan->fcs == L2CAP_FCS_CRC16) { fcs = crc16(0, (u8 *)skb->data, skb->len - 2); put_unaligned_le16(fcs, skb->data + skb->len - 2); } @@ -1084,7 +1082,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); - if (pi->fcs == L2CAP_FCS_CRC16) { + if (chan->fcs == L2CAP_FCS_CRC16) { fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); } @@ -1127,7 +1125,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan) put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); - if (pi->fcs == L2CAP_FCS_CRC16) { + if (chan->fcs == L2CAP_FCS_CRC16) { fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2); put_unaligned_le16(fcs, skb->data + tx_skb->len - 2); } @@ -1290,8 +1288,9 @@ struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size return skb; } -struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen) +struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen) { + struct sock *sk = chan->sk; struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct sk_buff *skb; int err, count, hlen = L2CAP_HDR_SIZE + 2; @@ -1305,7 +1304,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz if (sdulen) hlen += 2; - if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) + if (chan->fcs == L2CAP_FCS_CRC16) hlen += 2; count = min_t(unsigned int, (conn->mtu - hlen), len); @@ -1328,7 +1327,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz return ERR_PTR(err); } - if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) + if (chan->fcs == L2CAP_FCS_CRC16) put_unaligned_le16(0, skb_put(skb, 2)); bt_cb(skb)->retries = 0; @@ -1337,7 +1336,6 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) { - struct sock *sk = chan->sk; struct sk_buff *skb; struct sk_buff_head sar_queue; u16 control; @@ -1345,7 +1343,7 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le skb_queue_head_init(&sar_queue); control = L2CAP_SDU_START; - skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len); + skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -1364,7 +1362,7 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le buflen = len; } - skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0); + skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0); if (IS_ERR(skb)) { skb_queue_purge(&sar_queue); return PTR_ERR(skb); @@ -1654,8 +1652,8 @@ done: case L2CAP_MODE_ERTM: rfc.mode = L2CAP_MODE_ERTM; - rfc.txwin_size = pi->tx_win; - rfc.max_transmit = pi->max_tx; + rfc.txwin_size = chan->tx_win; + rfc.max_transmit = chan->max_tx; rfc.retrans_timeout = 0; rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); @@ -1668,10 +1666,10 @@ done: if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS)) break; - if (pi->fcs == L2CAP_FCS_NONE || + if (chan->fcs == L2CAP_FCS_NONE || chan->conf_state & L2CAP_CONF_NO_FCS_RECV) { - pi->fcs = L2CAP_FCS_NONE; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs); + chan->fcs = L2CAP_FCS_NONE; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); } break; @@ -1691,10 +1689,10 @@ done: if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS)) break; - if (pi->fcs == L2CAP_FCS_NONE || + if (chan->fcs == L2CAP_FCS_NONE || chan->conf_state & L2CAP_CONF_NO_FCS_RECV) { - pi->fcs = L2CAP_FCS_NONE; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs); + chan->fcs = L2CAP_FCS_NONE; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); } break; } @@ -1804,7 +1802,7 @@ done: switch (rfc.mode) { case L2CAP_MODE_BASIC: - pi->fcs = L2CAP_FCS_NONE; + chan->fcs = L2CAP_FCS_NONE; chan->conf_state |= L2CAP_CONF_MODE_DONE; break; @@ -1898,7 +1896,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi rfc.mode != pi->mode) return -ECONNREFUSED; - pi->fcs = 0; + chan->fcs = 0; l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); @@ -1914,12 +1912,12 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi if (*result == L2CAP_CONF_SUCCESS) { switch (rfc.mode) { case L2CAP_MODE_ERTM: - pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); - pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); - pi->mps = le16_to_cpu(rfc.max_pdu_size); + chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); + chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); + chan->mps = le16_to_cpu(rfc.max_pdu_size); break; case L2CAP_MODE_STREAMING: - pi->mps = le16_to_cpu(rfc.max_pdu_size); + chan->mps = le16_to_cpu(rfc.max_pdu_size); } } @@ -1968,14 +1966,14 @@ void __l2cap_connect_rsp_defer(struct sock *sk) chan->num_conf_req++; } -static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len) +static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) { - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); int type, olen; unsigned long val; struct l2cap_conf_rfc rfc; - BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len); + BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING)) return; @@ -1994,12 +1992,12 @@ static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len) done: switch (rfc.mode) { case L2CAP_MODE_ERTM: - pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); - pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); - pi->mps = le16_to_cpu(rfc.max_pdu_size); + chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); + chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); + chan->mps = le16_to_cpu(rfc.max_pdu_size); break; case L2CAP_MODE_STREAMING: - pi->mps = le16_to_cpu(rfc.max_pdu_size); + chan->mps = le16_to_cpu(rfc.max_pdu_size); } } @@ -2227,15 +2225,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd return 0; } -static inline void set_default_fcs(struct l2cap_pinfo *pi) +static inline void set_default_fcs(struct l2cap_chan *chan) { + struct l2cap_pinfo *pi = l2cap_pi(chan->sk); + /* FCS is enabled only in ERTM or streaming mode, if one or both * sides request it. */ if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING) - pi->fcs = L2CAP_FCS_NONE; + chan->fcs = L2CAP_FCS_NONE; else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV)) - pi->fcs = L2CAP_FCS_CRC16; + chan->fcs = L2CAP_FCS_CRC16; } static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) @@ -2305,7 +2305,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr goto unlock; if (chan->conf_state & L2CAP_CONF_INPUT_DONE) { - set_default_fcs(l2cap_pi(sk)); + set_default_fcs(chan); sk->sk_state = BT_CONNECTED; @@ -2355,7 +2355,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr switch (result) { case L2CAP_CONF_SUCCESS: - l2cap_conf_rfc_get(sk, rsp->data, len); + l2cap_conf_rfc_get(chan, rsp->data, len); break; case L2CAP_CONF_UNACCEPT: @@ -2397,7 +2397,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr chan->conf_state |= L2CAP_CONF_INPUT_DONE; if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) { - set_default_fcs(l2cap_pi(sk)); + set_default_fcs(chan); sk->sk_state = BT_CONNECTED; chan->next_tx_seq = 0; @@ -2769,12 +2769,12 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, kfree_skb(skb); } -static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb) +static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) { u16 our_fcs, rcv_fcs; int hdr_size = L2CAP_HDR_SIZE + 2; - if (pi->fcs == L2CAP_FCS_CRC16) { + if (chan->fcs == L2CAP_FCS_CRC16) { skb_trim(skb, skb->len - 2); rcv_fcs = get_unaligned_le16(skb->data + skb->len); our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); @@ -3241,7 +3241,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont u8 req_seq = __get_reqseq(rx_control); u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; int tx_seq_offset, expected_tx_seq_offset; - int num_to_ack = (pi->tx_win/6) + 1; + int num_to_ack = (chan->tx_win/6) + 1; int err = 0; BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len, @@ -3266,7 +3266,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont tx_seq_offset += 64; /* invalid tx_seq */ - if (tx_seq_offset >= pi->tx_win) { + if (tx_seq_offset >= chan->tx_win) { l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } @@ -3548,16 +3548,16 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) * Receiver will miss it and start proper recovery * procedures and ask retransmission. */ - if (l2cap_check_fcs(pi, skb)) + if (l2cap_check_fcs(chan, skb)) goto drop; if (__is_sar_start(control) && __is_iframe(control)) len -= 2; - if (pi->fcs == L2CAP_FCS_CRC16) + if (chan->fcs == L2CAP_FCS_CRC16) len -= 2; - if (len > pi->mps) { + if (len > chan->mps) { l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); goto drop; } @@ -3654,16 +3654,16 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk skb_pull(skb, 2); len = skb->len; - if (l2cap_check_fcs(pi, skb)) + if (l2cap_check_fcs(chan, skb)) goto drop; if (__is_sar_start(control)) len -= 2; - if (pi->fcs == L2CAP_FCS_CRC16) + if (chan->fcs == L2CAP_FCS_CRC16) len -= 2; - if (len > pi->mps || len < 0 || __is_sframe(control)) + if (len > chan->mps || len < 0 || __is_sframe(control)) goto drop; tx_seq = __get_txseq(control); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 612955679b3..4ba15b3b2e6 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -403,9 +403,9 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us opts.omtu = l2cap_pi(sk)->omtu; opts.flush_to = l2cap_pi(sk)->flush_to; opts.mode = l2cap_pi(sk)->mode; - opts.fcs = l2cap_pi(sk)->fcs; - opts.max_tx = l2cap_pi(sk)->max_tx; - opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; + opts.fcs = chan->fcs; + opts.max_tx = chan->max_tx; + opts.txwin_size = (__u16)chan->tx_win; len = min_t(unsigned int, len, sizeof(opts)); if (copy_to_user(optval, (char *) &opts, len)) @@ -551,9 +551,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us opts.omtu = l2cap_pi(sk)->omtu; opts.flush_to = l2cap_pi(sk)->flush_to; opts.mode = l2cap_pi(sk)->mode; - opts.fcs = l2cap_pi(sk)->fcs; - opts.max_tx = l2cap_pi(sk)->max_tx; - opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; + opts.fcs = chan->fcs; + opts.max_tx = chan->max_tx; + opts.txwin_size = (__u16)chan->tx_win; len = min_t(unsigned int, sizeof(opts), optlen); if (copy_from_user((char *) &opts, optval, len)) { @@ -583,9 +583,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us l2cap_pi(sk)->imtu = opts.imtu; l2cap_pi(sk)->omtu = opts.omtu; - l2cap_pi(sk)->fcs = opts.fcs; - l2cap_pi(sk)->max_tx = opts.max_tx; - l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size; + chan->fcs = opts.fcs; + chan->max_tx = opts.max_tx; + chan->tx_win = (__u8)opts.txwin_size; break; case L2CAP_LM: @@ -764,7 +764,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms /* Entire SDU fits into one PDU */ if (len <= pi->chan->remote_mps) { control = L2CAP_SDU_UNSEGMENTED; - skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0); + skb = l2cap_create_iframe_pdu(pi->chan, msg, len, + control, 0); if (IS_ERR(skb)) { err = PTR_ERR(skb); goto done; @@ -998,9 +999,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) pi->omtu = l2cap_pi(parent)->omtu; chan->conf_state = pchan->conf_state; pi->mode = l2cap_pi(parent)->mode; - pi->fcs = l2cap_pi(parent)->fcs; - pi->max_tx = l2cap_pi(parent)->max_tx; - pi->tx_win = l2cap_pi(parent)->tx_win; + chan->fcs = pchan->fcs; + chan->max_tx = pchan->max_tx; + chan->tx_win = pchan->tx_win; chan->sec_level = pchan->sec_level; chan->role_switch = pchan->role_switch; chan->force_reliable = pchan->force_reliable; @@ -1014,9 +1015,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) } else { pi->mode = L2CAP_MODE_BASIC; } - pi->max_tx = L2CAP_DEFAULT_MAX_TX; - pi->fcs = L2CAP_FCS_CRC16; - pi->tx_win = L2CAP_DEFAULT_TX_WINDOW; + chan->max_tx = L2CAP_DEFAULT_MAX_TX; + chan->fcs = L2CAP_FCS_CRC16; + chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; chan->sec_level = BT_SECURITY_LOW; chan->role_switch = 0; chan->force_reliable = 0; diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index c9973932456..4f728a4f717 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -711,7 +711,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, sk = sock->sk; lock_sock(sk); l2cap_pi(sk)->imtu = l2cap_mtu; - l2cap_pi(sk)->sec_level = sec_level; + l2cap_pi(sk)->chan->sec_level = sec_level; if (l2cap_ertm) l2cap_pi(sk)->mode = L2CAP_MODE_ERTM; release_sock(sk); -- cgit v1.2.3-70-g09d2 From 0c1bc5c626e9783034264ccca4b262b3acc628f1 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 13 Apr 2011 17:20:49 -0300 Subject: Bluetooth: Move more channel info to struct l2cap_chan In this commit, omtu, imtu, flush_to, mode and sport. It also remove the pi var from l2cap_sock_sendmsg(). Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 14 +++--- net/bluetooth/cmtp/core.c | 3 +- net/bluetooth/hidp/core.c | 6 ++- net/bluetooth/l2cap_core.c | 97 ++++++++++++++++++++-------------------- net/bluetooth/l2cap_sock.c | 100 +++++++++++++++++++++++------------------- net/bluetooth/rfcomm/core.c | 11 ++--- 6 files changed, 121 insertions(+), 110 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 02db90210f8..7522835c24e 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -285,6 +285,13 @@ struct srej_list { struct l2cap_chan { struct sock *sk; + __u16 imtu; + __u16 omtu; + __u16 flush_to; + __u8 mode; + + __le16 sport; + __u8 sec_level; __u8 role_switch; __u8 force_reliable; @@ -379,13 +386,6 @@ struct l2cap_pinfo { __u16 dcid; __u16 scid; - __u16 imtu; - __u16 omtu; - __u16 flush_to; - __u8 mode; - - __le16 sport; - struct l2cap_conn *conn; struct l2cap_chan *chan; }; diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index cce99b0919f..c5b11af908b 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -346,7 +346,8 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) bacpy(&session->bdaddr, &bt_sk(sock->sk)->dst); - session->mtu = min_t(uint, l2cap_pi(sock->sk)->omtu, l2cap_pi(sock->sk)->imtu); + session->mtu = min_t(uint, l2cap_pi(sock->sk)->chan->omtu, + l2cap_pi(sock->sk)->chan->imtu); BT_DBG("mtu %d", session->mtu); diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index ae6ebc6c348..c405a954a60 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -979,8 +979,10 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst); - session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu); - session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu); + session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu, + l2cap_pi(ctrl_sock->sk)->chan->imtu); + session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->chan->omtu, + l2cap_pi(intr_sock->sk)->chan->imtu); BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index cb3c4ed47ae..7b06375d05a 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -176,24 +176,24 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) { if (conn->hcon->type == LE_LINK) { /* LE connection */ - l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU; + chan->omtu = L2CAP_LE_DEFAULT_MTU; l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA; l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA; } else { /* Alloc CID for connection-oriented socket */ l2cap_pi(sk)->scid = l2cap_alloc_cid(conn); - l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; + chan->omtu = L2CAP_DEFAULT_MTU; } } else if (sk->sk_type == SOCK_DGRAM) { /* Connectionless socket */ l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS; l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS; - l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; + chan->omtu = L2CAP_DEFAULT_MTU; } else { /* Raw socket can send/recv signalling messages only */ l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING; l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING; - l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; + chan->omtu = L2CAP_DEFAULT_MTU; } sock_hold(sk); @@ -242,7 +242,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) skb_queue_purge(&chan->tx_q); - if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { + if (chan->mode == L2CAP_MODE_ERTM) { struct srej_list *l, *tmp; del_timer(&chan->retrans_timer); @@ -479,7 +479,7 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in sk = chan->sk; - if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { + if (chan->mode == L2CAP_MODE_ERTM) { del_timer(&chan->retrans_timer); del_timer(&chan->monitor_timer); del_timer(&chan->ack_timer); @@ -523,7 +523,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) continue; } - if (!l2cap_mode_supported(l2cap_pi(sk)->mode, + if (!l2cap_mode_supported(chan->mode, conn->feat_mask) && chan->conf_state & L2CAP_CONF_STATE2_DEVICE) { @@ -1609,7 +1609,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) { struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct l2cap_conf_req *req = data; - struct l2cap_conf_rfc rfc = { .mode = pi->mode }; + struct l2cap_conf_rfc rfc = { .mode = chan->mode }; void *ptr = req->data; BT_DBG("chan %p", chan); @@ -1617,7 +1617,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) if (chan->num_conf_req || chan->num_conf_rsp) goto done; - switch (pi->mode) { + switch (chan->mode) { case L2CAP_MODE_STREAMING: case L2CAP_MODE_ERTM: if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE) @@ -1625,15 +1625,15 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) /* fall through */ default: - pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); + chan->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); break; } done: - if (pi->imtu != L2CAP_DEFAULT_MTU) - l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu); + if (chan->imtu != L2CAP_DEFAULT_MTU) + l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); - switch (pi->mode) { + switch (chan->mode) { case L2CAP_MODE_BASIC: if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) && !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING)) @@ -1730,7 +1730,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) break; case L2CAP_CONF_FLUSH_TO: - pi->flush_to = val; + chan->flush_to = val; break; case L2CAP_CONF_QOS: @@ -1760,25 +1760,25 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) if (chan->num_conf_rsp || chan->num_conf_req > 1) goto done; - switch (pi->mode) { + switch (chan->mode) { case L2CAP_MODE_STREAMING: case L2CAP_MODE_ERTM: if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) { - pi->mode = l2cap_select_mode(rfc.mode, + chan->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); break; } - if (pi->mode != rfc.mode) + if (chan->mode != rfc.mode) return -ECONNREFUSED; break; } done: - if (pi->mode != rfc.mode) { + if (chan->mode != rfc.mode) { result = L2CAP_CONF_UNACCEPT; - rfc.mode = pi->mode; + rfc.mode = chan->mode; if (chan->num_conf_rsp == 1) return -ECONNREFUSED; @@ -1795,10 +1795,10 @@ done: if (mtu < L2CAP_DEFAULT_MIN_MTU) result = L2CAP_CONF_UNACCEPT; else { - pi->omtu = mtu; + chan->omtu = mtu; chan->conf_state |= L2CAP_CONF_MTU_DONE; } - l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu); + l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); switch (rfc.mode) { case L2CAP_MODE_BASIC: @@ -1844,7 +1844,7 @@ done: result = L2CAP_CONF_UNACCEPT; memset(&rfc, 0, sizeof(rfc)); - rfc.mode = pi->mode; + rfc.mode = chan->mode; } if (result == L2CAP_CONF_SUCCESS) @@ -1876,16 +1876,16 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi case L2CAP_CONF_MTU: if (val < L2CAP_DEFAULT_MIN_MTU) { *result = L2CAP_CONF_UNACCEPT; - pi->imtu = L2CAP_DEFAULT_MIN_MTU; + chan->imtu = L2CAP_DEFAULT_MIN_MTU; } else - pi->imtu = val; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu); + chan->imtu = val; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); break; case L2CAP_CONF_FLUSH_TO: - pi->flush_to = val; + chan->flush_to = val; l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, - 2, pi->flush_to); + 2, chan->flush_to); break; case L2CAP_CONF_RFC: @@ -1893,7 +1893,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi memcpy(&rfc, (void *)val, olen); if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) && - rfc.mode != pi->mode) + rfc.mode != chan->mode) return -ECONNREFUSED; chan->fcs = 0; @@ -1904,10 +1904,10 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi } } - if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode) + if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) return -ECONNREFUSED; - pi->mode = rfc.mode; + chan->mode = rfc.mode; if (*result == L2CAP_CONF_SUCCESS) { switch (rfc.mode) { @@ -1968,14 +1968,13 @@ void __l2cap_connect_rsp_defer(struct sock *sk) static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); int type, olen; unsigned long val; struct l2cap_conf_rfc rfc; BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); - if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING)) + if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) return; while (len >= L2CAP_CONF_OPT_SIZE) { @@ -2232,7 +2231,7 @@ static inline void set_default_fcs(struct l2cap_chan *chan) /* FCS is enabled only in ERTM or streaming mode, if one or both * sides request it. */ - if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING) + if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) chan->fcs = L2CAP_FCS_NONE; else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV)) chan->fcs = L2CAP_FCS_CRC16; @@ -2312,7 +2311,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr chan->next_tx_seq = 0; chan->expected_tx_seq = 0; skb_queue_head_init(&chan->tx_q); - if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) + if (chan->mode == L2CAP_MODE_ERTM) l2cap_ertm_init(chan); l2cap_chan_ready(sk); @@ -2403,7 +2402,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr chan->next_tx_seq = 0; chan->expected_tx_seq = 0; skb_queue_head_init(&chan->tx_q); - if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) + if (chan->mode == L2CAP_MODE_ERTM) l2cap_ertm_init(chan); l2cap_chan_ready(sk); @@ -2876,7 +2875,7 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk chan->sdu_len = get_unaligned_le16(skb->data); - if (chan->sdu_len > pi->imtu) + if (chan->sdu_len > chan->imtu) goto disconnect; chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC); @@ -2919,7 +2918,7 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) { chan->partial_sdu_len += skb->len; - if (chan->partial_sdu_len > pi->imtu) + if (chan->partial_sdu_len > chan->imtu) goto drop; if (chan->partial_sdu_len != chan->sdu_len) @@ -3087,7 +3086,6 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct sk_buff *_skb; int err = -EINVAL; @@ -3118,7 +3116,7 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf chan->sdu_len = get_unaligned_le16(skb->data); skb_pull(skb, 2); - if (chan->sdu_len > pi->imtu) { + if (chan->sdu_len > chan->imtu) { err = -EMSGSIZE; break; } @@ -3159,7 +3157,7 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf chan->conn_state &= ~L2CAP_CONN_SAR_SDU; chan->partial_sdu_len += skb->len; - if (chan->partial_sdu_len > pi->imtu) + if (chan->partial_sdu_len > chan->imtu) goto drop; if (chan->partial_sdu_len == chan->sdu_len) { @@ -3625,14 +3623,14 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk if (sk->sk_state != BT_CONNECTED) goto drop; - switch (pi->mode) { + switch (chan->mode) { case L2CAP_MODE_BASIC: /* If socket recv buffers overflows we drop data here * which is *bad* because L2CAP has to be reliable. * But we don't have any other choice. L2CAP doesn't * provide flow control mechanism. */ - if (pi->imtu < skb->len) + if (chan->imtu < skb->len) goto drop; if (!sock_queue_rcv_skb(sk, skb)) @@ -3678,7 +3676,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk goto done; default: - BT_DBG("chan %p: bad mode 0x%2.2x", chan, pi->mode); + BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode); break; } @@ -3707,7 +3705,7 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) goto drop; - if (l2cap_pi(sk)->imtu < skb->len) + if (l2cap_pi(sk)->chan->imtu < skb->len) goto drop; if (!sock_queue_rcv_skb(sk, skb)) @@ -3737,7 +3735,7 @@ static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) goto drop; - if (l2cap_pi(sk)->imtu < skb->len) + if (l2cap_pi(sk)->chan->imtu < skb->len) goto drop; if (!sock_queue_rcv_skb(sk, skb)) @@ -4020,10 +4018,10 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl if (chan && chan->sk) { struct sock *sk = chan->sk; - if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) { + if (chan->imtu < len - L2CAP_HDR_SIZE) { BT_ERR("Frame exceeding recv MTU (len %d, " "MTU %d)", len, - l2cap_pi(sk)->imtu); + chan->imtu); bh_unlock_sock(sk); l2cap_conn_unreliable(conn, ECOMM); goto drop; @@ -4083,14 +4081,15 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) sk_for_each(sk, node, &l2cap_sk_list.head) { struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_chan *chan = pi->chan; seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), sk->sk_state, __le16_to_cpu(pi->psm), pi->scid, pi->dcid, - pi->imtu, pi->omtu, pi->chan->sec_level, - pi->mode); + chan->imtu, chan->omtu, chan->sec_level, + chan->mode); } read_unlock_bh(&l2cap_sk_list.lock); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 4ba15b3b2e6..eef33b179f0 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -80,9 +80,13 @@ static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) { struct sock *sk; struct hlist_node *node; - sk_for_each(sk, node, &l2cap_sk_list.head) - if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src)) + sk_for_each(sk, node, &l2cap_sk_list.head) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + + if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src)) goto found; + } + sk = NULL; found: return sk; @@ -138,7 +142,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) /* Save source address */ bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); l2cap_pi(sk)->psm = la.l2_psm; - l2cap_pi(sk)->sport = la.l2_psm; + chan->sport = la.l2_psm; sk->sk_state = BT_BOUND; if (__le16_to_cpu(la.l2_psm) == 0x0001 || @@ -159,6 +163,7 @@ done: static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct sockaddr_l2 la; int len, err = 0; @@ -183,7 +188,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al goto done; } - switch (l2cap_pi(sk)->mode) { + switch (chan->mode) { case L2CAP_MODE_BASIC: break; case L2CAP_MODE_ERTM: @@ -245,6 +250,7 @@ done: static int l2cap_sock_listen(struct socket *sock, int backlog) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; int err = 0; BT_DBG("sk %p backlog %d", sk, backlog); @@ -257,7 +263,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) goto done; } - switch (l2cap_pi(sk)->mode) { + switch (chan->mode) { case L2CAP_MODE_BASIC: break; case L2CAP_MODE_ERTM: @@ -281,7 +287,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) for (psm = 0x1001; psm < 0x1100; psm += 2) if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) { l2cap_pi(sk)->psm = cpu_to_le16(psm); - l2cap_pi(sk)->sport = cpu_to_le16(psm); + chan->sport = cpu_to_le16(psm); err = 0; break; } @@ -361,6 +367,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l { struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr; struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; BT_DBG("sock %p, sk %p", sock, sk); @@ -372,7 +379,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst); la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid); } else { - la->l2_psm = l2cap_pi(sk)->sport; + la->l2_psm = chan->sport; bacpy(&la->l2_bdaddr, &bt_sk(sk)->src); la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid); } @@ -399,10 +406,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us switch (optname) { case L2CAP_OPTIONS: memset(&opts, 0, sizeof(opts)); - opts.imtu = l2cap_pi(sk)->imtu; - opts.omtu = l2cap_pi(sk)->omtu; - opts.flush_to = l2cap_pi(sk)->flush_to; - opts.mode = l2cap_pi(sk)->mode; + opts.imtu = chan->imtu; + opts.omtu = chan->omtu; + opts.flush_to = chan->flush_to; + opts.mode = chan->mode; opts.fcs = chan->fcs; opts.max_tx = chan->max_tx; opts.txwin_size = (__u16)chan->tx_win; @@ -547,10 +554,10 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us break; } - opts.imtu = l2cap_pi(sk)->imtu; - opts.omtu = l2cap_pi(sk)->omtu; - opts.flush_to = l2cap_pi(sk)->flush_to; - opts.mode = l2cap_pi(sk)->mode; + opts.imtu = chan->imtu; + opts.omtu = chan->omtu; + opts.flush_to = chan->flush_to; + opts.mode = chan->mode; opts.fcs = chan->fcs; opts.max_tx = chan->max_tx; opts.txwin_size = (__u16)chan->tx_win; @@ -566,8 +573,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us break; } - l2cap_pi(sk)->mode = opts.mode; - switch (l2cap_pi(sk)->mode) { + chan->mode = opts.mode; + switch (chan->mode) { case L2CAP_MODE_BASIC: chan->conf_state &= ~L2CAP_CONF_STATE2_DEVICE; break; @@ -581,8 +588,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us break; } - l2cap_pi(sk)->imtu = opts.imtu; - l2cap_pi(sk)->omtu = opts.omtu; + chan->imtu = opts.imtu; + chan->omtu = opts.omtu; chan->fcs = opts.fcs; chan->max_tx = opts.max_tx; chan->tx_win = (__u8)opts.txwin_size; @@ -707,7 +714,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { struct sock *sk = sock->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); + struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct sk_buff *skb; u16 control; int err; @@ -734,16 +741,16 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms if (IS_ERR(skb)) { err = PTR_ERR(skb); } else { - l2cap_do_send(pi->chan, skb); + l2cap_do_send(chan, skb); err = len; } goto done; } - switch (pi->mode) { + switch (chan->mode) { case L2CAP_MODE_BASIC: /* Check outgoing MTU */ - if (len > pi->omtu) { + if (len > chan->omtu) { err = -EMSGSIZE; goto done; } @@ -755,52 +762,52 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms goto done; } - l2cap_do_send(pi->chan, skb); + l2cap_do_send(chan, skb); err = len; break; case L2CAP_MODE_ERTM: case L2CAP_MODE_STREAMING: /* Entire SDU fits into one PDU */ - if (len <= pi->chan->remote_mps) { + if (len <= chan->remote_mps) { control = L2CAP_SDU_UNSEGMENTED; - skb = l2cap_create_iframe_pdu(pi->chan, msg, len, - control, 0); + skb = l2cap_create_iframe_pdu(chan, msg, len, control, + 0); if (IS_ERR(skb)) { err = PTR_ERR(skb); goto done; } - __skb_queue_tail(&pi->chan->tx_q, skb); + __skb_queue_tail(&chan->tx_q, skb); - if (pi->chan->tx_send_head == NULL) - pi->chan->tx_send_head = skb; + if (chan->tx_send_head == NULL) + chan->tx_send_head = skb; } else { /* Segment SDU into multiples PDUs */ - err = l2cap_sar_segment_sdu(pi->chan, msg, len); + err = l2cap_sar_segment_sdu(chan, msg, len); if (err < 0) goto done; } - if (pi->mode == L2CAP_MODE_STREAMING) { - l2cap_streaming_send(pi->chan); + if (chan->mode == L2CAP_MODE_STREAMING) { + l2cap_streaming_send(chan); err = len; break; } - if ((pi->chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && - (pi->chan->conn_state & L2CAP_CONN_WAIT_F)) { + if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && + (chan->conn_state & L2CAP_CONN_WAIT_F)) { err = len; break; } - err = l2cap_ertm_send(pi->chan); + err = l2cap_ertm_send(chan); if (err >= 0) err = len; break; default: - BT_DBG("bad state %1.1x", pi->mode); + BT_DBG("bad state %1.1x", chan->mode); err = -EBADFD; } @@ -929,6 +936,7 @@ void __l2cap_sock_close(struct sock *sk, int reason) static int l2cap_sock_shutdown(struct socket *sock, int how) { struct sock *sk = sock->sk; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; int err = 0; BT_DBG("sock %p, sk %p", sock, sk); @@ -938,7 +946,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) lock_sock(sk); if (!sk->sk_shutdown) { - if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) + if (chan->mode == L2CAP_MODE_ERTM) err = __l2cap_wait_ack(sk); sk->sk_shutdown = SHUTDOWN_MASK; @@ -995,10 +1003,10 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) sk->sk_type = parent->sk_type; bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup; - pi->imtu = l2cap_pi(parent)->imtu; - pi->omtu = l2cap_pi(parent)->omtu; + chan->imtu = pchan->imtu; + chan->omtu = pchan->omtu; chan->conf_state = pchan->conf_state; - pi->mode = l2cap_pi(parent)->mode; + chan->mode = pchan->mode; chan->fcs = pchan->fcs; chan->max_tx = pchan->max_tx; chan->tx_win = pchan->tx_win; @@ -1007,13 +1015,13 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) chan->force_reliable = pchan->force_reliable; chan->flushable = pchan->flushable; } else { - pi->imtu = L2CAP_DEFAULT_MTU; - pi->omtu = 0; + chan->imtu = L2CAP_DEFAULT_MTU; + chan->omtu = 0; if (!disable_ertm && sk->sk_type == SOCK_STREAM) { - pi->mode = L2CAP_MODE_ERTM; + chan->mode = L2CAP_MODE_ERTM; chan->conf_state |= L2CAP_CONF_STATE2_DEVICE; } else { - pi->mode = L2CAP_MODE_BASIC; + chan->mode = L2CAP_MODE_BASIC; } chan->max_tx = L2CAP_DEFAULT_MAX_TX; chan->fcs = L2CAP_FCS_CRC16; @@ -1025,7 +1033,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent) } /* Default config options */ - pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; + chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; } static struct proto l2cap_proto = { diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 4f728a4f717..fdd8f5ab18c 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -710,10 +710,10 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, /* Set L2CAP options */ sk = sock->sk; lock_sock(sk); - l2cap_pi(sk)->imtu = l2cap_mtu; + l2cap_pi(sk)->chan->imtu = l2cap_mtu; l2cap_pi(sk)->chan->sec_level = sec_level; if (l2cap_ertm) - l2cap_pi(sk)->mode = L2CAP_MODE_ERTM; + l2cap_pi(sk)->chan->mode = L2CAP_MODE_ERTM; release_sock(sk); s = rfcomm_session_add(sock, BT_BOUND); @@ -1890,7 +1890,8 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s) /* We should adjust MTU on incoming sessions. * L2CAP MTU minus UIH header and FCS. */ - s->mtu = min(l2cap_pi(nsock->sk)->omtu, l2cap_pi(nsock->sk)->imtu) - 5; + s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu, + l2cap_pi(nsock->sk)->chan->imtu) - 5; rfcomm_schedule(); } else @@ -1909,7 +1910,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s) /* We can adjust MTU on outgoing sessions. * L2CAP MTU minus UIH header and FCS. */ - s->mtu = min(l2cap_pi(sk)->omtu, l2cap_pi(sk)->imtu) - 5; + s->mtu = min(l2cap_pi(sk)->chan->omtu, l2cap_pi(sk)->chan->imtu) - 5; rfcomm_send_sabm(s, 0); break; @@ -1992,7 +1993,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) /* Set L2CAP options */ sk = sock->sk; lock_sock(sk); - l2cap_pi(sk)->imtu = l2cap_mtu; + l2cap_pi(sk)->chan->imtu = l2cap_mtu; release_sock(sk); /* Start listening on the socket */ -- cgit v1.2.3-70-g09d2 From fe4128e0aabc3c748786c00da21e6eff9d3aeddb Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 13 Apr 2011 19:50:45 -0300 Subject: Bluetooth: Move more vars to struct l2cap_chan In this commit, psm, scid and dcid. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 10 ++-- net/bluetooth/l2cap_core.c | 116 +++++++++++++++++++++--------------------- net/bluetooth/l2cap_sock.c | 26 +++++----- 3 files changed, 77 insertions(+), 75 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 7522835c24e..fd199cda752 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -284,6 +284,9 @@ struct srej_list { struct l2cap_chan { struct sock *sk; + __le16 psm; + __u16 dcid; + __u16 scid; __u16 imtu; __u16 omtu; @@ -382,9 +385,6 @@ struct l2cap_conn { struct l2cap_pinfo { struct bt_sock bt; - __le16 psm; - __u16 dcid; - __u16 scid; struct l2cap_conn *conn; struct l2cap_chan *chan; @@ -450,8 +450,8 @@ void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *d void __l2cap_connect_rsp_defer(struct sock *sk); int __l2cap_wait_ack(struct sock *sk); -struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len); -struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len); +struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); +struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen); int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 7b06375d05a..dd726bdd6e0 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -80,8 +80,7 @@ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 struct l2cap_chan *c; list_for_each_entry(c, &conn->chan_l, list) { - struct sock *s = c->sk; - if (l2cap_pi(s)->dcid == cid) + if (c->dcid == cid) return c; } return NULL; @@ -93,8 +92,7 @@ static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 struct l2cap_chan *c; list_for_each_entry(c, &conn->chan_l, list) { - struct sock *s = c->sk; - if (l2cap_pi(s)->scid == cid) + if (c->scid == cid) return c; } return NULL; @@ -167,7 +165,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) struct sock *sk = chan->sk; BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, - l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid); + chan->psm, chan->dcid); conn->disc_reason = 0x13; @@ -177,22 +175,22 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) if (conn->hcon->type == LE_LINK) { /* LE connection */ chan->omtu = L2CAP_LE_DEFAULT_MTU; - l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA; - l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA; + chan->scid = L2CAP_CID_LE_DATA; + chan->dcid = L2CAP_CID_LE_DATA; } else { /* Alloc CID for connection-oriented socket */ - l2cap_pi(sk)->scid = l2cap_alloc_cid(conn); + chan->scid = l2cap_alloc_cid(conn); chan->omtu = L2CAP_DEFAULT_MTU; } } else if (sk->sk_type == SOCK_DGRAM) { /* Connectionless socket */ - l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS; - l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS; + chan->scid = L2CAP_CID_CONN_LESS; + chan->dcid = L2CAP_CID_CONN_LESS; chan->omtu = L2CAP_DEFAULT_MTU; } else { /* Raw socket can send/recv signalling messages only */ - l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING; - l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING; + chan->scid = L2CAP_CID_SIGNALING; + chan->dcid = L2CAP_CID_SIGNALING; chan->omtu = L2CAP_DEFAULT_MTU; } @@ -275,7 +273,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) default: return HCI_AT_NO_BONDING; } - } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) { + } else if (chan->psm == cpu_to_le16(0x0001)) { if (chan->sec_level == BT_SECURITY_LOW) chan->sec_level = BT_SECURITY_SDP; @@ -383,7 +381,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); - lh->cid = cpu_to_le16(pi->dcid); + lh->cid = cpu_to_le16(chan->dcid); put_unaligned_le16(control, skb_put(skb, 2)); if (chan->fcs == L2CAP_FCS_CRC16) { @@ -429,8 +427,8 @@ static void l2cap_do_start(struct l2cap_chan *chan) if (l2cap_check_security(chan) && __l2cap_no_conn_pending(chan)) { struct l2cap_conn_req req; - req.scid = cpu_to_le16(l2cap_pi(sk)->scid); - req.psm = l2cap_pi(sk)->psm; + req.scid = cpu_to_le16(chan->scid); + req.psm = chan->psm; chan->ident = l2cap_get_ident(conn); chan->conf_state |= L2CAP_CONF_CONNECT_PEND; @@ -485,8 +483,8 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in del_timer(&chan->ack_timer); } - req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid); - req.scid = cpu_to_le16(l2cap_pi(sk)->scid); + req.dcid = cpu_to_le16(chan->dcid); + req.scid = cpu_to_le16(chan->scid); l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, sizeof(req), &req); @@ -536,8 +534,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) continue; } - req.scid = cpu_to_le16(l2cap_pi(sk)->scid); - req.psm = l2cap_pi(sk)->psm; + req.scid = cpu_to_le16(chan->scid); + req.psm = chan->psm; chan->ident = l2cap_get_ident(conn); chan->conf_state |= L2CAP_CONF_CONNECT_PEND; @@ -548,8 +546,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) } else if (sk->sk_state == BT_CONNECT2) { struct l2cap_conn_rsp rsp; char buf[128]; - rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); - rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); + rsp.scid = cpu_to_le16(chan->dcid); + rsp.dcid = cpu_to_le16(chan->scid); if (l2cap_check_security(chan)) { if (bt_sk(sk)->defer_setup) { @@ -600,10 +598,12 @@ static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src) read_lock(&l2cap_sk_list.lock); sk_for_each(sk, node, &l2cap_sk_list.head) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + if (state && sk->sk_state != state) continue; - if (l2cap_pi(sk)->scid == cid) { + if (chan->scid == cid) { /* Exact match. */ if (!bacmp(&bt_sk(sk)->src, src)) break; @@ -830,10 +830,12 @@ static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) read_lock(&l2cap_sk_list.lock); sk_for_each(sk, node, &l2cap_sk_list.head) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + if (state && sk->sk_state != state) continue; - if (l2cap_pi(sk)->psm == psm) { + if (chan->psm == psm) { /* Exact match. */ if (!bacmp(&bt_sk(sk)->src, src)) break; @@ -861,7 +863,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan) int err; BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), - l2cap_pi(sk)->psm); + chan->psm); hdev = hci_get_route(dst, src); if (!hdev) @@ -871,7 +873,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan) auth_type = l2cap_get_auth_type(chan); - if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA) + if (chan->dcid == L2CAP_CID_LE_DATA) hcon = hci_connect(hdev, LE_LINK, dst, chan->sec_level, auth_type); else @@ -1231,8 +1233,9 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in return sent; } -struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len) +struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) { + struct sock *sk = chan->sk; struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct sk_buff *skb; int err, count, hlen = L2CAP_HDR_SIZE + 2; @@ -1248,9 +1251,9 @@ struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, s /* Create L2CAP header */ lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); - lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid); + lh->cid = cpu_to_le16(chan->dcid); lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); - put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2)); + put_unaligned_le16(chan->psm, skb_put(skb, 2)); err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb); if (unlikely(err < 0)) { @@ -1260,8 +1263,9 @@ struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, s return skb; } -struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len) +struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) { + struct sock *sk = chan->sk; struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct sk_buff *skb; int err, count, hlen = L2CAP_HDR_SIZE; @@ -1277,7 +1281,7 @@ struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size /* Create L2CAP header */ lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); - lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid); + lh->cid = cpu_to_le16(chan->dcid); lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb); @@ -1315,7 +1319,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr * /* Create L2CAP header */ lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); - lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid); + lh->cid = cpu_to_le16(chan->dcid); lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); put_unaligned_le16(control, skb_put(skb, 2)); if (sdulen) @@ -1697,7 +1701,7 @@ done: break; } - req->dcid = cpu_to_le16(pi->dcid); + req->dcid = cpu_to_le16(chan->dcid); req->flags = cpu_to_le16(0); return ptr - data; @@ -1850,7 +1854,7 @@ done: if (result == L2CAP_CONF_SUCCESS) chan->conf_state |= L2CAP_CONF_OUTPUT_DONE; } - rsp->scid = cpu_to_le16(pi->dcid); + rsp->scid = cpu_to_le16(chan->dcid); rsp->result = cpu_to_le16(result); rsp->flags = cpu_to_le16(0x0000); @@ -1859,15 +1863,13 @@ done: static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) { - struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); struct l2cap_conf_req *req = data; void *ptr = req->data; int type, olen; unsigned long val; struct l2cap_conf_rfc rfc; - BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data); + BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); while (len >= L2CAP_CONF_OPT_SIZE) { len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); @@ -1921,20 +1923,20 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi } } - req->dcid = cpu_to_le16(pi->dcid); + req->dcid = cpu_to_le16(chan->dcid); req->flags = cpu_to_le16(0x0000); return ptr - data; } -static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags) +static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) { struct l2cap_conf_rsp *rsp = data; void *ptr = rsp->data; - BT_DBG("sk %p", sk); + BT_DBG("chan %p", chan); - rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid); + rsp->scid = cpu_to_le16(chan->dcid); rsp->result = cpu_to_le16(result); rsp->flags = cpu_to_le16(flags); @@ -1950,8 +1952,8 @@ void __l2cap_connect_rsp_defer(struct sock *sk) sk->sk_state = BT_CONFIG; - rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); - rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); + rsp.scid = cpu_to_le16(chan->dcid); + rsp.dcid = cpu_to_le16(chan->scid); rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); l2cap_send_cmd(conn, chan->ident, @@ -2085,14 +2087,14 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd l2cap_sock_init(sk, parent); bacpy(&bt_sk(sk)->src, conn->src); bacpy(&bt_sk(sk)->dst, conn->dst); - l2cap_pi(sk)->psm = psm; - l2cap_pi(sk)->dcid = scid; + chan->psm = psm; + chan->dcid = scid; bt_accept_enqueue(parent, sk); __l2cap_chan_add(conn, chan); - dcid = l2cap_pi(sk)->scid; + dcid = chan->scid; l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -2190,7 +2192,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd case L2CAP_CR_SUCCESS: sk->sk_state = BT_CONFIG; chan->ident = 0; - l2cap_pi(sk)->dcid = dcid; + chan->dcid = dcid; chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND; if (chan->conf_state & L2CAP_CONF_REQ_SENT) @@ -2270,7 +2272,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr len = cmd_len - sizeof(*req); if (chan->conf_len + len > sizeof(chan->conf_req)) { l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, - l2cap_build_conf_rsp(sk, rsp, + l2cap_build_conf_rsp(chan, rsp, L2CAP_CONF_REJECT, flags), rsp); goto unlock; } @@ -2282,7 +2284,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr if (flags & 0x0001) { /* Incomplete config. Send empty response. */ l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, - l2cap_build_conf_rsp(sk, rsp, + l2cap_build_conf_rsp(chan, rsp, L2CAP_CONF_SUCCESS, 0x0001), rsp); goto unlock; } @@ -2432,8 +2434,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd sk = chan->sk; - rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); - rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); + rsp.dcid = cpu_to_le16(chan->scid); + rsp.scid = cpu_to_le16(chan->dcid); l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); sk->sk_shutdown = SHUTDOWN_MASK; @@ -3920,8 +3922,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) if (sk->sk_state == BT_CONNECT) { if (!status) { struct l2cap_conn_req req; - req.scid = cpu_to_le16(l2cap_pi(sk)->scid); - req.psm = l2cap_pi(sk)->psm; + req.scid = cpu_to_le16(chan->scid); + req.psm = chan->psm; chan->ident = l2cap_get_ident(conn); chan->conf_state |= L2CAP_CONF_CONNECT_PEND; @@ -3945,8 +3947,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) result = L2CAP_CR_SEC_BLOCK; } - rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); - rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); + rsp.scid = cpu_to_le16(chan->dcid); + rsp.dcid = cpu_to_le16(chan->scid); rsp.result = cpu_to_le16(result); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, @@ -4086,8 +4088,8 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), - sk->sk_state, __le16_to_cpu(pi->psm), - pi->scid, pi->dcid, + sk->sk_state, __le16_to_cpu(chan->psm), + chan->scid, chan->dcid, chan->imtu, chan->omtu, chan->sec_level, chan->mode); } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index eef33b179f0..f5a27737c15 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -141,7 +141,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) } else { /* Save source address */ bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); - l2cap_pi(sk)->psm = la.l2_psm; + chan->psm = la.l2_psm; chan->sport = la.l2_psm; sk->sk_state = BT_BOUND; @@ -151,7 +151,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) } if (la.l2_cid) - l2cap_pi(sk)->scid = la.l2_cid; + chan->scid = la.l2_cid; write_unlock_bh(&l2cap_sk_list.lock); @@ -232,8 +232,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al /* Set destination address and psm */ bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr); - l2cap_pi(sk)->psm = la.l2_psm; - l2cap_pi(sk)->dcid = la.l2_cid; + chan->psm = la.l2_psm; + chan->dcid = la.l2_cid; err = l2cap_chan_connect(l2cap_pi(sk)->chan); if (err) @@ -276,7 +276,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) goto done; } - if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->scid) { + if (!chan->psm && !chan->scid) { bdaddr_t *src = &bt_sk(sk)->src; u16 psm; @@ -286,7 +286,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) for (psm = 0x1001; psm < 0x1100; psm += 2) if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) { - l2cap_pi(sk)->psm = cpu_to_le16(psm); + chan->psm = cpu_to_le16(psm); chan->sport = cpu_to_le16(psm); err = 0; break; @@ -375,13 +375,13 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l *len = sizeof(struct sockaddr_l2); if (peer) { - la->l2_psm = l2cap_pi(sk)->psm; + la->l2_psm = chan->psm; bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst); - la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid); + la->l2_cid = cpu_to_le16(chan->dcid); } else { la->l2_psm = chan->sport; bacpy(&la->l2_bdaddr, &bt_sk(sk)->src); - la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid); + la->l2_cid = cpu_to_le16(chan->scid); } return 0; @@ -737,7 +737,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms /* Connectionless channel */ if (sk->sk_type == SOCK_DGRAM) { - skb = l2cap_create_connless_pdu(sk, msg, len); + skb = l2cap_create_connless_pdu(chan, msg, len); if (IS_ERR(skb)) { err = PTR_ERR(skb); } else { @@ -756,7 +756,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms } /* Create a basic PDU */ - skb = l2cap_create_basic_pdu(sk, msg, len); + skb = l2cap_create_basic_pdu(chan, msg, len); if (IS_ERR(skb)) { err = PTR_ERR(skb); goto done; @@ -911,8 +911,8 @@ void __l2cap_sock_close(struct sock *sk, int reason) else result = L2CAP_CR_BAD_PSM; - rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); - rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); + rsp.scid = cpu_to_le16(chan->dcid); + rsp.dcid = cpu_to_le16(chan->scid); rsp.result = cpu_to_le16(result); rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, -- cgit v1.2.3-70-g09d2 From 8c1d787be4b62d2d1b6f04953eca4bcf7c839d44 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 13 Apr 2011 20:23:55 -0300 Subject: Bluetooth: Move conn to struct l2cap_chan There is no need to the socket deal directly with the channel, most of the time it cares about the channel only. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 7 ++-- net/bluetooth/l2cap_core.c | 92 +++++++++++++++++++------------------------ net/bluetooth/l2cap_sock.c | 12 +++--- net/bluetooth/rfcomm/core.c | 8 ++-- net/bluetooth/rfcomm/sock.c | 5 ++- 5 files changed, 59 insertions(+), 65 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index fd199cda752..3de90a91a4e 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -284,6 +284,9 @@ struct srej_list { struct l2cap_chan { struct sock *sk; + + struct l2cap_conn *conn; + __le16 psm; __u16 dcid; __u16 scid; @@ -385,8 +388,6 @@ struct l2cap_conn { struct l2cap_pinfo { struct bt_sock bt; - - struct l2cap_conn *conn; struct l2cap_chan *chan; }; @@ -447,7 +448,7 @@ int l2cap_init_sockets(void); void l2cap_cleanup_sockets(void); void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data); -void __l2cap_connect_rsp_defer(struct sock *sk); +void __l2cap_connect_rsp_defer(struct l2cap_chan *chan); int __l2cap_wait_ack(struct sock *sk); struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index dd726bdd6e0..8562ac1ba94 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -169,7 +169,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) conn->disc_reason = 0x13; - l2cap_pi(sk)->conn = conn; + chan->conn = conn; if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) { if (conn->hcon->type == LE_LINK) { @@ -204,7 +204,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) void l2cap_chan_del(struct l2cap_chan *chan, int err) { struct sock *sk = chan->sk; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = chan->conn; struct sock *parent = bt_sk(sk)->parent; l2cap_sock_clear_timer(sk); @@ -218,7 +218,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) write_unlock_bh(&conn->chan_lock); __sock_put(sk); - l2cap_pi(sk)->conn = NULL; + chan->conn = NULL; hci_conn_put(conn->hcon); } @@ -296,7 +296,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) /* Service level security */ static inline int l2cap_check_security(struct l2cap_chan *chan) { - struct l2cap_conn *conn = l2cap_pi(chan->sk)->conn; + struct l2cap_conn *conn = chan->conn; __u8 auth_type; auth_type = l2cap_get_auth_type(chan); @@ -349,7 +349,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) struct sk_buff *skb; struct l2cap_hdr *lh; struct l2cap_pinfo *pi = l2cap_pi(chan->sk); - struct l2cap_conn *conn = pi->conn; + struct l2cap_conn *conn = chan->conn; struct sock *sk = (struct sock *)pi; int count, hlen = L2CAP_HDR_SIZE + 2; u8 flags; @@ -394,7 +394,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) else flags = ACL_START; - hci_send_acl(pi->conn->hcon, skb, flags); + hci_send_acl(chan->conn->hcon, skb, flags); } static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control) @@ -417,8 +417,7 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) static void l2cap_do_start(struct l2cap_chan *chan) { - struct sock *sk = chan->sk; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = chan->conn; if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) @@ -920,12 +919,13 @@ done: int __l2cap_wait_ack(struct sock *sk) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; DECLARE_WAITQUEUE(wait, current); int err = 0; int timeo = HZ/5; add_wait_queue(sk_sleep(sk), &wait); - while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) { + while ((chan->unacked_frames > 0 && chan->conn)) { set_current_state(TASK_INTERRUPTIBLE); if (!timeo) @@ -958,7 +958,7 @@ static void l2cap_monitor_timeout(unsigned long arg) bh_lock_sock(sk); if (chan->retry_count >= chan->remote_max_tx) { - l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED); + l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); bh_unlock_sock(sk); return; } @@ -1008,8 +1008,7 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan) void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) { - struct sock *sk = chan->sk; - struct hci_conn *hcon = l2cap_pi(sk)->conn->hcon; + struct hci_conn *hcon = chan->conn->hcon; u16 flags; BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len); @@ -1045,8 +1044,6 @@ void l2cap_streaming_send(struct l2cap_chan *chan) static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) { - struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *skb, *tx_skb; u16 control, fcs; @@ -1065,7 +1062,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq) if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { - l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED); + l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); return; } @@ -1096,7 +1093,6 @@ int l2cap_ertm_send(struct l2cap_chan *chan) { struct sk_buff *skb, *tx_skb; struct sock *sk = chan->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; int nsent = 0; @@ -1107,7 +1103,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan) if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { - l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED); + l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); break; } @@ -1203,7 +1199,7 @@ static void l2cap_send_srejtail(struct l2cap_chan *chan) static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb) { - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; struct sk_buff **frag; int err, sent = 0; @@ -1236,7 +1232,7 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) { struct sock *sk = chan->sk; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = chan->conn; struct sk_buff *skb; int err, count, hlen = L2CAP_HDR_SIZE + 2; struct l2cap_hdr *lh; @@ -1266,7 +1262,7 @@ struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) { struct sock *sk = chan->sk; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = chan->conn; struct sk_buff *skb; int err, count, hlen = L2CAP_HDR_SIZE; struct l2cap_hdr *lh; @@ -1295,7 +1291,7 @@ struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *m struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen) { struct sock *sk = chan->sk; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = chan->conn; struct sk_buff *skb; int err, count, hlen = L2CAP_HDR_SIZE + 2; struct l2cap_hdr *lh; @@ -1611,7 +1607,6 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask) static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct l2cap_conf_req *req = data; struct l2cap_conf_rfc rfc = { .mode = chan->mode }; void *ptr = req->data; @@ -1629,7 +1624,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) /* fall through */ default: - chan->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); + chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); break; } @@ -1639,8 +1634,8 @@ done: switch (chan->mode) { case L2CAP_MODE_BASIC: - if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) && - !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING)) + if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && + !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) break; rfc.mode = L2CAP_MODE_BASIC; @@ -1661,13 +1656,13 @@ done: rfc.retrans_timeout = 0; rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); - if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) - rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); + if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10) + rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10); l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); - if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS)) + if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) break; if (chan->fcs == L2CAP_FCS_NONE || @@ -1684,13 +1679,13 @@ done: rfc.retrans_timeout = 0; rfc.monitor_timeout = 0; rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); - if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) - rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); + if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10) + rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10); l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), (unsigned long) &rfc); - if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS)) + if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) break; if (chan->fcs == L2CAP_FCS_NONE || @@ -1709,7 +1704,6 @@ done: static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct l2cap_conf_rsp *rsp = data; void *ptr = rsp->data; void *req = chan->conf_req; @@ -1769,7 +1763,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) case L2CAP_MODE_ERTM: if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) { chan->mode = l2cap_select_mode(rfc.mode, - pi->conn->feat_mask); + chan->conn->feat_mask); break; } @@ -1814,8 +1808,8 @@ done: chan->remote_tx_win = rfc.txwin_size; chan->remote_max_tx = rfc.max_transmit; - if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10) - rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); + if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10) + rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10); chan->remote_mps = le16_to_cpu(rfc.max_pdu_size); @@ -1832,8 +1826,8 @@ done: break; case L2CAP_MODE_STREAMING: - if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10) - rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); + if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10) + rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10); chan->remote_mps = le16_to_cpu(rfc.max_pdu_size); @@ -1943,15 +1937,12 @@ static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, return ptr - data; } -void __l2cap_connect_rsp_defer(struct sock *sk) +void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) { struct l2cap_conn_rsp rsp; - struct l2cap_conn *conn = l2cap_pi(sk)->conn; - struct l2cap_chan *chan = l2cap_pi(sk)->chan; + struct l2cap_conn *conn = chan->conn; u8 buf[128]; - sk->sk_state = BT_CONFIG; - rsp.scid = cpu_to_le16(chan->dcid); rsp.dcid = cpu_to_le16(chan->scid); rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); @@ -2856,7 +2847,6 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); struct sk_buff *_skb; int err; @@ -2957,7 +2947,7 @@ drop: chan->sdu = NULL; disconnect: - l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); kfree_skb(skb); return 0; } @@ -3018,7 +3008,7 @@ static void l2cap_busy_work(struct work_struct *work) if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) { err = -EBUSY; - l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY); + l2cap_send_disconn_req(chan->conn, chan, EBUSY); break; } @@ -3236,7 +3226,6 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) { - struct l2cap_pinfo *pi = l2cap_pi(chan->sk); u8 tx_seq = __get_txseq(rx_control); u8 req_seq = __get_reqseq(rx_control); u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; @@ -3267,7 +3256,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont /* invalid tx_seq */ if (tx_seq_offset >= chan->tx_win) { - l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); goto drop; } @@ -3534,7 +3523,6 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) { struct l2cap_chan *chan = l2cap_pi(sk)->chan; - struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control; u8 req_seq; int len, next_tx_seq_offset, req_seq_offset; @@ -3558,7 +3546,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) len -= 2; if (len > chan->mps) { - l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); goto drop; } @@ -3574,13 +3562,13 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) /* check for invalid req-seq */ if (req_seq_offset > next_tx_seq_offset) { - l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); goto drop; } if (__is_iframe(control)) { if (len < 0) { - l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); goto drop; } @@ -3588,7 +3576,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) } else { if (len != 0) { BT_ERR("%d", len); - l2cap_send_disconn_req(pi->conn, chan, ECONNRESET); + l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); goto drop; } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index f5a27737c15..61d93f6c36c 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -455,8 +455,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us break; } - cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle; - memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3); + cinfo.hci_handle = chan->conn->hcon->handle; + memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3); len = min_t(unsigned int, len, sizeof(cinfo)); if (copy_to_user(optval, (char *) &cinfo, len)) @@ -690,7 +690,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch } if (opt == BT_FLUSHABLE_OFF) { - struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_conn *conn = chan->conn; /* proceed futher only when we have l2cap_conn and No Flush support in the LM */ if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { @@ -823,7 +823,9 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms lock_sock(sk); if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { - __l2cap_connect_rsp_defer(sk); + sk->sk_state = BT_CONFIG; + + __l2cap_connect_rsp_defer(l2cap_pi(sk)->chan); release_sock(sk); return 0; } @@ -878,8 +880,8 @@ static void l2cap_sock_cleanup_listen(struct sock *parent) void __l2cap_sock_close(struct sock *sk, int reason) { - struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct l2cap_chan *chan = l2cap_pi(sk)->chan; + struct l2cap_conn *conn = chan->conn; BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index fdd8f5ab18c..121a5c13b98 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -232,6 +232,8 @@ static int rfcomm_l2sock_create(struct socket **sock) static inline int rfcomm_check_security(struct rfcomm_dlc *d) { struct sock *sk = d->session->sock->sk; + struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; + __u8 auth_type; switch (d->sec_level) { @@ -246,8 +248,7 @@ static inline int rfcomm_check_security(struct rfcomm_dlc *d) break; } - return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level, - auth_type); + return hci_conn_security(conn->hcon, d->sec_level, auth_type); } static void rfcomm_session_timeout(unsigned long arg) @@ -1241,6 +1242,7 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci) void rfcomm_dlc_accept(struct rfcomm_dlc *d) { struct sock *sk = d->session->sock->sk; + struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; BT_DBG("dlc %p", d); @@ -1254,7 +1256,7 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d) rfcomm_dlc_unlock(d); if (d->role_switch) - hci_conn_switch_role(l2cap_pi(sk)->conn->hcon, 0x00); + hci_conn_switch_role(conn->hcon, 0x00); rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig); } diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 66cc1f0c3df..386cfaffd4b 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -743,6 +743,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u struct sock *sk = sock->sk; struct sock *l2cap_sk; struct rfcomm_conninfo cinfo; + struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; int len, err = 0; u32 opt; @@ -787,8 +788,8 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk; - cinfo.hci_handle = l2cap_pi(l2cap_sk)->conn->hcon->handle; - memcpy(cinfo.dev_class, l2cap_pi(l2cap_sk)->conn->hcon->dev_class, 3); + cinfo.hci_handle = conn->hcon->handle; + memcpy(cinfo.dev_class, conn->hcon->dev_class, 3); len = min_t(unsigned int, len, sizeof(cinfo)); if (copy_to_user(optval, (char *) &cinfo, len)) -- cgit v1.2.3-70-g09d2 From 6ff5abbf4e4aa88feb9c2367d4fbd9ea081bf98c Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 25 Apr 2011 15:10:41 -0300 Subject: Bluetooth: Fix memory leak with L2CAP channels A new l2cap_chan_free() is added to free the channels. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 1 + net/bluetooth/l2cap_core.c | 10 ++++++---- net/bluetooth/l2cap_sock.c | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 3de90a91a4e..0a0134161b1 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -469,6 +469,7 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); void l2cap_chan_del(struct l2cap_chan *chan, int err); +void l2cap_chan_free(struct l2cap_chan *chan); int l2cap_chan_connect(struct l2cap_chan *chan); #endif /* __L2CAP_H */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8562ac1ba94..338d8c3eeda 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -160,6 +160,11 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) return chan; } +void l2cap_chan_free(struct l2cap_chan *chan) +{ + kfree(chan); +} + static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) { struct sock *sk = chan->sk; @@ -236,7 +241,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE && chan->conf_state & L2CAP_CONF_INPUT_DONE)) - goto free; + return; skb_queue_purge(&chan->tx_q); @@ -255,9 +260,6 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) kfree(l); } } - -free: - kfree(chan); } static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 61d93f6c36c..0e23ebdf7c8 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -849,6 +849,8 @@ void l2cap_sock_kill(struct sock *sk) BT_DBG("sk %p state %d", sk, sk->sk_state); /* Kill poor orphan */ + + l2cap_chan_free(l2cap_pi(sk)->chan); bt_sock_unlink(&l2cap_sk_list, sk); sock_set_flag(sk, SOCK_DEAD); sock_put(sk); -- cgit v1.2.3-70-g09d2 From cf2f90f59bbf2c2a539d171cde6e1dfe72048555 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 27 Apr 2011 18:40:39 -0300 Subject: Bluetooth: Don't export l2cap_sock_ops l2cap_sk_ops can be static, it's not used outside l2cap_sock.c Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 1 - net/bluetooth/l2cap_sock.c | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 0a0134161b1..c34b1c12636 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -441,7 +441,6 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch) #define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START) extern int disable_ertm; -extern const struct proto_ops l2cap_sock_ops; extern struct bt_sock_list l2cap_sk_list; int l2cap_init_sockets(void); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 0e23ebdf7c8..09cc7a00534 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -30,6 +30,8 @@ #include #include +static const struct proto_ops l2cap_sock_ops; + /* ---- L2CAP timers ---- */ static void l2cap_sock_timeout(unsigned long arg) { @@ -1106,7 +1108,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, return 0; } -const struct proto_ops l2cap_sock_ops = { +static const struct proto_ops l2cap_sock_ops = { .family = PF_BLUETOOTH, .owner = THIS_MODULE, .release = l2cap_sock_release, -- cgit v1.2.3-70-g09d2 From 9e4425fff9e0a0fb6a8c705777ed861f991f8747 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 18 Apr 2011 18:38:43 -0300 Subject: Bluetooth: Add l2cap_add_psm() and l2cap_add_scid() The intention is to get rid of the l2cap_sk_list usage inside l2cap_core.c. l2cap_sk_list will soon be replaced by a list that does not depend on socket usage. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 4 ++++ net/bluetooth/l2cap_core.c | 44 +++++++++++++++++++++++++++++++++++++++++++ net/bluetooth/l2cap_sock.c | 44 +++++++++++-------------------------------- 3 files changed, 59 insertions(+), 33 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index c34b1c12636..f5f3c2cf8a3 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -458,6 +458,10 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); void l2cap_streaming_send(struct l2cap_chan *chan); int l2cap_ertm_send(struct l2cap_chan *chan); +struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src); +int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); +int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); + void l2cap_sock_set_timer(struct sock *sk, long timeout); void l2cap_sock_clear_timer(struct sock *sk); void __l2cap_sock_close(struct sock *sk, int reason); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 338d8c3eeda..98ddd867cfd 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -135,6 +135,50 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn return c; } +struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) +{ + struct sock *sk; + struct hlist_node *node; + sk_for_each(sk, node, &l2cap_sk_list.head) { + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + + if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src)) + goto found; + } + + sk = NULL; +found: + return sk; +} + +int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) +{ + write_lock_bh(&l2cap_sk_list.lock); + + if (__l2cap_get_sock_by_addr(psm, src)) { + write_unlock_bh(&l2cap_sk_list.lock); + return -EADDRINUSE; + } + + chan->psm = psm; + chan->sport = psm; + + write_unlock_bh(&l2cap_sk_list.lock); + + return 0; +} + +int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) +{ + write_lock_bh(&l2cap_sk_list.lock); + + chan->scid = scid; + + write_unlock_bh(&l2cap_sk_list.lock); + + return 0; +} + static u16 l2cap_alloc_cid(struct l2cap_conn *conn) { u16 cid = L2CAP_CID_DYN_START; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 09cc7a00534..2156dcecec0 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -78,22 +78,6 @@ void l2cap_sock_clear_timer(struct sock *sk) sk_stop_timer(sk, &sk->sk_timer); } -static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) -{ - struct sock *sk; - struct hlist_node *node; - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_chan *chan = l2cap_pi(sk)->chan; - - if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src)) - goto found; - } - - sk = NULL; -found: - return sk; -} - static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) { struct sock *sk = sock->sk; @@ -136,26 +120,20 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) } } - write_lock_bh(&l2cap_sk_list.lock); + if (la.l2_cid) + err = l2cap_add_scid(chan, la.l2_cid); + else + err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm); - if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) { - err = -EADDRINUSE; - } else { - /* Save source address */ - bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); - chan->psm = la.l2_psm; - chan->sport = la.l2_psm; - sk->sk_state = BT_BOUND; - - if (__le16_to_cpu(la.l2_psm) == 0x0001 || - __le16_to_cpu(la.l2_psm) == 0x0003) - chan->sec_level = BT_SECURITY_SDP; - } + if (err < 0) + goto done; - if (la.l2_cid) - chan->scid = la.l2_cid; + if (__le16_to_cpu(la.l2_psm) == 0x0001 || + __le16_to_cpu(la.l2_psm) == 0x0003) + chan->sec_level = BT_SECURITY_SDP; - write_unlock_bh(&l2cap_sk_list.lock); + bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); + sk->sk_state = BT_BOUND; done: release_sock(sk); -- cgit v1.2.3-70-g09d2 From 73b2ec18532f45e9028ce4c7bc8d7f8818eabd2a Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 18 Apr 2011 19:36:44 -0300 Subject: Bluetooth: Handle psm == 0 case inside l2cap_add_psm() When the user doesn't specify a psm we have the choose one for the channel. Now we do this inside l2cap_add_psm(). Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 1 - net/bluetooth/l2cap_core.c | 32 ++++++++++++++++++++++++-------- net/bluetooth/l2cap_sock.c | 22 ---------------------- 3 files changed, 24 insertions(+), 31 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index f5f3c2cf8a3..fb3f90eaaaa 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -458,7 +458,6 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); void l2cap_streaming_send(struct l2cap_chan *chan); int l2cap_ertm_send(struct l2cap_chan *chan); -struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src); int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 98ddd867cfd..9e3f64f05d4 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -135,7 +135,7 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn return c; } -struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) +static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) { struct sock *sk; struct hlist_node *node; @@ -153,19 +153,35 @@ found: int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) { + int err; + write_lock_bh(&l2cap_sk_list.lock); - if (__l2cap_get_sock_by_addr(psm, src)) { - write_unlock_bh(&l2cap_sk_list.lock); - return -EADDRINUSE; + if (psm && __l2cap_get_sock_by_addr(psm, src)) { + err = -EADDRINUSE; + goto done; } - chan->psm = psm; - chan->sport = psm; + if (psm) { + chan->psm = psm; + chan->sport = psm; + err = 0; + } else { + u16 p; - write_unlock_bh(&l2cap_sk_list.lock); + err = -EINVAL; + for (p = 0x1001; p < 0x1100; p += 2) + if (!__l2cap_get_sock_by_addr(cpu_to_le16(p), src)) { + chan->psm = cpu_to_le16(p); + chan->sport = cpu_to_le16(p); + err = 0; + break; + } + } - return 0; +done: + write_unlock_bh(&l2cap_sk_list.lock); + return err; } int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 2156dcecec0..aca99cd5377 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -256,28 +256,6 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) goto done; } - if (!chan->psm && !chan->scid) { - bdaddr_t *src = &bt_sk(sk)->src; - u16 psm; - - err = -EINVAL; - - write_lock_bh(&l2cap_sk_list.lock); - - for (psm = 0x1001; psm < 0x1100; psm += 2) - if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) { - chan->psm = cpu_to_le16(psm); - chan->sport = cpu_to_le16(psm); - err = 0; - break; - } - - write_unlock_bh(&l2cap_sk_list.lock); - - if (err < 0) - goto done; - } - sk->sk_max_ack_backlog = backlog; sk->sk_ack_backlog = 0; sk->sk_state = BT_LISTEN; -- cgit v1.2.3-70-g09d2 From 23691d75cdc69c3b285211b4d77746aa20a17d18 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 27 Apr 2011 18:26:32 -0300 Subject: Bluetooth: Remove l2cap_sk_list A new list was added to replace the socket based one. This new list doesn't depent on sock and then fits better inside l2cap_core.c code. It also rename l2cap_chan_alloc() to l2cap_chan_create() and l2cap_chan_free() to l2cap_chan_destroy) Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 6 +- net/bluetooth/l2cap_core.c | 165 +++++++++++++++++++++++------------------- net/bluetooth/l2cap_sock.c | 6 +- 3 files changed, 95 insertions(+), 82 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index fb3f90eaaaa..d09c9b1118e 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -350,6 +350,7 @@ struct l2cap_chan { struct list_head srej_l; struct list_head list; + struct list_head global_l; }; struct l2cap_conn { @@ -441,7 +442,6 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch) #define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START) extern int disable_ertm; -extern struct bt_sock_list l2cap_sk_list; int l2cap_init_sockets(void); void l2cap_cleanup_sockets(void); @@ -469,9 +469,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent); struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); -struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); +struct l2cap_chan *l2cap_chan_create(struct sock *sk); void l2cap_chan_del(struct l2cap_chan *chan, int err); -void l2cap_chan_free(struct l2cap_chan *chan); +void l2cap_chan_destroy(struct l2cap_chan *chan); int l2cap_chan_connect(struct l2cap_chan *chan); #endif /* __L2CAP_H */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9e3f64f05d4..d0769a83cb5 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -62,9 +62,8 @@ static u8 l2cap_fixed_chan[8] = { 0x02, }; static struct workqueue_struct *_busy_wq; -struct bt_sock_list l2cap_sk_list = { - .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) -}; +LIST_HEAD(chan_list); +DEFINE_RWLOCK(chan_list_lock); static void l2cap_busy_work(struct work_struct *work); @@ -135,29 +134,27 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn return c; } -static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) +static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) { - struct sock *sk; - struct hlist_node *node; - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_chan *chan = l2cap_pi(sk)->chan; + struct l2cap_chan *c; - if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src)) + list_for_each_entry(c, &chan_list, global_l) { + if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) goto found; } - sk = NULL; + c = NULL; found: - return sk; + return c; } int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) { int err; - write_lock_bh(&l2cap_sk_list.lock); + write_lock_bh(&chan_list_lock); - if (psm && __l2cap_get_sock_by_addr(psm, src)) { + if (psm && __l2cap_global_chan_by_addr(psm, src)) { err = -EADDRINUSE; goto done; } @@ -171,7 +168,7 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) err = -EINVAL; for (p = 0x1001; p < 0x1100; p += 2) - if (!__l2cap_get_sock_by_addr(cpu_to_le16(p), src)) { + if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { chan->psm = cpu_to_le16(p); chan->sport = cpu_to_le16(p); err = 0; @@ -180,17 +177,17 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) } done: - write_unlock_bh(&l2cap_sk_list.lock); + write_unlock_bh(&chan_list_lock); return err; } int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) { - write_lock_bh(&l2cap_sk_list.lock); + write_lock_bh(&chan_list_lock); chan->scid = scid; - write_unlock_bh(&l2cap_sk_list.lock); + write_unlock_bh(&chan_list_lock); return 0; } @@ -207,7 +204,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) return 0; } -struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) +struct l2cap_chan *l2cap_chan_create(struct sock *sk) { struct l2cap_chan *chan; @@ -217,11 +214,19 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) chan->sk = sk; + write_lock_bh(&chan_list_lock); + list_add(&chan->global_l, &chan_list); + write_unlock_bh(&chan_list_lock); + return chan; } -void l2cap_chan_free(struct l2cap_chan *chan) +void l2cap_chan_destroy(struct l2cap_chan *chan) { + write_lock_bh(&chan_list_lock); + list_del(&chan->global_l); + write_unlock_bh(&chan_list_lock); + kfree(chan); } @@ -651,48 +656,51 @@ static void l2cap_conn_start(struct l2cap_conn *conn) /* Find socket with cid and source bdaddr. * Returns closest match, locked. */ -static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src) +static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src) { - struct sock *sk = NULL, *sk1 = NULL; - struct hlist_node *node; + struct l2cap_chan *c, *c1 = NULL; - read_lock(&l2cap_sk_list.lock); + read_lock(&chan_list_lock); - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_chan *chan = l2cap_pi(sk)->chan; + list_for_each_entry(c, &chan_list, global_l) { + struct sock *sk = c->sk; if (state && sk->sk_state != state) continue; - if (chan->scid == cid) { + if (c->scid == cid) { /* Exact match. */ - if (!bacmp(&bt_sk(sk)->src, src)) - break; + if (!bacmp(&bt_sk(sk)->src, src)) { + read_unlock(&chan_list_lock); + return c; + } /* Closest match */ if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) - sk1 = sk; + c1 = c; } } - read_unlock(&l2cap_sk_list.lock); + read_unlock(&chan_list_lock); - return node ? sk : sk1; + return c1; } static void l2cap_le_conn_ready(struct l2cap_conn *conn) { struct sock *parent, *sk; - struct l2cap_chan *chan; + struct l2cap_chan *chan, *pchan; BT_DBG(""); /* Check if we have socket listening on cid */ - parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, + pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, conn->src); - if (!parent) + if (!pchan) return; + parent = pchan->sk; + bh_lock_sock(parent); /* Check for backlog size */ @@ -705,7 +713,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) if (!sk) goto clean; - chan = l2cap_chan_alloc(sk); + chan = l2cap_chan_create(sk); if (!chan) { l2cap_sock_kill(sk); goto clean; @@ -883,33 +891,34 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *ch /* Find socket with psm and source bdaddr. * Returns closest match. */ -static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) +static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src) { - struct sock *sk = NULL, *sk1 = NULL; - struct hlist_node *node; + struct l2cap_chan *c, *c1 = NULL; - read_lock(&l2cap_sk_list.lock); + read_lock(&chan_list_lock); - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_chan *chan = l2cap_pi(sk)->chan; + list_for_each_entry(c, &chan_list, global_l) { + struct sock *sk = c->sk; if (state && sk->sk_state != state) continue; - if (chan->psm == psm) { + if (c->psm == psm) { /* Exact match. */ - if (!bacmp(&bt_sk(sk)->src, src)) - break; + if (!bacmp(&bt_sk(sk)->src, src)) { + read_unlock_bh(&chan_list_lock); + return c; + } /* Closest match */ if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) - sk1 = sk; + c1 = c; } } - read_unlock(&l2cap_sk_list.lock); + read_unlock(&chan_list_lock); - return node ? sk : sk1; + return c1; } int l2cap_chan_connect(struct l2cap_chan *chan) @@ -2079,22 +2088,26 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd { struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; struct l2cap_conn_rsp rsp; - struct l2cap_chan *chan = NULL; + struct l2cap_chan *chan = NULL, *pchan; struct sock *parent, *sk = NULL; int result, status = L2CAP_CS_NO_INFO; u16 dcid = 0, scid = __le16_to_cpu(req->scid); __le16 psm = req->psm; - BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); + BT_ERR("psm 0x%2.2x scid 0x%4.4x", psm, scid); /* Check if we have socket listening on psm */ - parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src); - if (!parent) { + pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src); + if (!pchan) { result = L2CAP_CR_BAD_PSM; goto sendresp; } + BT_ERR("%p 0x%2.2x", pchan, pchan->psm); + + parent = pchan->sk; + bh_lock_sock(parent); /* Check if the ACL is secure enough (if not SDP) */ @@ -2117,7 +2130,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd if (!sk) goto response; - chan = l2cap_chan_alloc(sk); + chan = l2cap_chan_create(sk); if (!chan) { l2cap_sock_kill(sk); goto response; @@ -3745,11 +3758,14 @@ done: static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) { struct sock *sk; + struct l2cap_chan *chan; - sk = l2cap_get_sock_by_psm(0, psm, conn->src); - if (!sk) + chan = l2cap_global_chan_by_psm(0, psm, conn->src); + if (!chan) goto drop; + sk = chan->sk; + bh_lock_sock(sk); BT_DBG("sk %p, len %d", sk, skb->len); @@ -3775,11 +3791,14 @@ done: static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) { struct sock *sk; + struct l2cap_chan *chan; - sk = l2cap_get_sock_by_scid(0, cid, conn->src); - if (!sk) + chan = l2cap_global_chan_by_scid(0, cid, conn->src); + if (!chan) goto drop; + sk = chan->sk; + bh_lock_sock(sk); BT_DBG("sk %p, len %d", sk, skb->len); @@ -3846,8 +3865,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) { int exact = 0, lm1 = 0, lm2 = 0; - register struct sock *sk; - struct hlist_node *node; + struct l2cap_chan *c; if (type != ACL_LINK) return -EINVAL; @@ -3855,25 +3873,25 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); /* Find listening sockets and check their link_mode */ - read_lock(&l2cap_sk_list.lock); - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_chan *chan = l2cap_pi(sk)->chan; + read_lock(&chan_list_lock); + list_for_each_entry(c, &chan_list, global_l) { + struct sock *sk = c->sk; if (sk->sk_state != BT_LISTEN) continue; if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { lm1 |= HCI_LM_ACCEPT; - if (chan->role_switch) + if (c->role_switch) lm1 |= HCI_LM_MASTER; exact++; } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { lm2 |= HCI_LM_ACCEPT; - if (chan->role_switch) + if (c->role_switch) lm2 |= HCI_LM_MASTER; } } - read_unlock(&l2cap_sk_list.lock); + read_unlock(&chan_list_lock); return exact ? lm1 : lm2; } @@ -4126,25 +4144,22 @@ drop: static int l2cap_debugfs_show(struct seq_file *f, void *p) { - struct sock *sk; - struct hlist_node *node; + struct l2cap_chan *c; - read_lock_bh(&l2cap_sk_list.lock); + read_lock_bh(&chan_list_lock); - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_pinfo *pi = l2cap_pi(sk); - struct l2cap_chan *chan = pi->chan; + list_for_each_entry(c, &chan_list, global_l) { + struct sock *sk = c->sk; seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), - sk->sk_state, __le16_to_cpu(chan->psm), - chan->scid, chan->dcid, - chan->imtu, chan->omtu, chan->sec_level, - chan->mode); + sk->sk_state, __le16_to_cpu(c->psm), + c->scid, c->dcid, c->imtu, c->omtu, + c->sec_level, c->mode); } - read_unlock_bh(&l2cap_sk_list.lock); + read_unlock_bh(&chan_list_lock); return 0; } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index aca99cd5377..c98360d40b8 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -808,8 +808,7 @@ void l2cap_sock_kill(struct sock *sk) /* Kill poor orphan */ - l2cap_chan_free(l2cap_pi(sk)->chan); - bt_sock_unlink(&l2cap_sk_list, sk); + l2cap_chan_destroy(l2cap_pi(sk)->chan); sock_set_flag(sk, SOCK_DEAD); sock_put(sk); } @@ -1025,7 +1024,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, g setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk); - bt_sock_link(&l2cap_sk_list, sk); return sk; } @@ -1052,7 +1050,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, if (!sk) return -ENOMEM; - chan = l2cap_chan_alloc(sk); + chan = l2cap_chan_create(sk); if (!chan) { l2cap_sock_kill(sk); return -ENOMEM; -- cgit v1.2.3-70-g09d2