diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-03-31 15:17:41 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-04-07 17:06:25 -0400 |
commit | baa7e1fa6d2870462bd744df1c6ddbd497fe86d6 (patch) | |
tree | 44b459ce553a586e2fc8e43ba19d1e9a99a339da | |
parent | 48454079c2d4b9ee65c570a22c5fdfe1827996a4 (diff) |
Bluetooth: Use struct list_head for L2CAP channels list
Use a well known Kernel API is always a good idea than implement your own
list.
In the future we might use RCU on this list.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r-- | include/net/bluetooth/l2cap.h | 12 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 188 |
2 files changed, 88 insertions, 112 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 6378bcc94e2b..ddf4bc56a5b5 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -277,16 +277,9 @@ struct l2cap_conn_param_update_rsp { | |||
277 | #define L2CAP_CONN_PARAM_REJECTED 0x0001 | 277 | #define L2CAP_CONN_PARAM_REJECTED 0x0001 |
278 | 278 | ||
279 | /* ----- L2CAP channels and connections ----- */ | 279 | /* ----- L2CAP channels and connections ----- */ |
280 | |||
281 | struct l2cap_chan { | 280 | struct l2cap_chan { |
282 | struct sock *sk; | 281 | struct sock *sk; |
283 | struct l2cap_chan *next_c; | 282 | struct list_head list; |
284 | struct l2cap_chan *prev_c; | ||
285 | }; | ||
286 | |||
287 | struct l2cap_chan_list { | ||
288 | struct l2cap_chan *head; | ||
289 | rwlock_t lock; | ||
290 | }; | 283 | }; |
291 | 284 | ||
292 | struct l2cap_conn { | 285 | struct l2cap_conn { |
@@ -312,7 +305,8 @@ struct l2cap_conn { | |||
312 | 305 | ||
313 | __u8 disc_reason; | 306 | __u8 disc_reason; |
314 | 307 | ||
315 | struct l2cap_chan_list chan_list; | 308 | struct list_head chan_l; |
309 | rwlock_t chan_lock; | ||
316 | }; | 310 | }; |
317 | 311 | ||
318 | struct sock_del_list { | 312 | struct sock_del_list { |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index e49d8f7b80a5..0dbbaf394c13 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -74,66 +74,75 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, | |||
74 | static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); | 74 | static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); |
75 | 75 | ||
76 | /* ---- L2CAP channels ---- */ | 76 | /* ---- L2CAP channels ---- */ |
77 | static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) | 77 | static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) |
78 | { | 78 | { |
79 | struct l2cap_chan *c; | 79 | struct l2cap_chan *c; |
80 | for (c = l->head; c; c = c->next_c) { | 80 | |
81 | if (l2cap_pi(c->sk)->dcid == cid) | 81 | list_for_each_entry(c, &conn->chan_l, list) { |
82 | break; | 82 | struct sock *s = c->sk; |
83 | if (l2cap_pi(s)->dcid == cid) | ||
84 | return c; | ||
83 | } | 85 | } |
84 | return c; | 86 | return NULL; |
87 | |||
85 | } | 88 | } |
86 | 89 | ||
87 | static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) | 90 | static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) |
88 | { | 91 | { |
89 | struct l2cap_chan *c; | 92 | struct l2cap_chan *c; |
90 | for (c = l->head; c; c = c->next_c) { | 93 | |
91 | if (l2cap_pi(c->sk)->scid == cid) | 94 | list_for_each_entry(c, &conn->chan_l, list) { |
92 | break; | 95 | struct sock *s = c->sk; |
96 | if (l2cap_pi(s)->scid == cid) | ||
97 | return c; | ||
93 | } | 98 | } |
94 | return c; | 99 | return NULL; |
95 | } | 100 | } |
96 | 101 | ||
97 | /* Find channel with given SCID. | 102 | /* Find channel with given SCID. |
98 | * Returns locked socket */ | 103 | * Returns locked socket */ |
99 | static inline struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) | 104 | static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) |
100 | { | 105 | { |
101 | struct l2cap_chan *c; | 106 | struct l2cap_chan *c; |
102 | read_lock(&l->lock); | 107 | |
103 | c = __l2cap_get_chan_by_scid(l, cid); | 108 | read_lock(&conn->chan_lock); |
109 | c = __l2cap_get_chan_by_scid(conn, cid); | ||
104 | if (c) | 110 | if (c) |
105 | bh_lock_sock(c->sk); | 111 | bh_lock_sock(c->sk); |
106 | read_unlock(&l->lock); | 112 | read_unlock(&conn->chan_lock); |
107 | return c; | 113 | return c; |
108 | } | 114 | } |
109 | 115 | ||
110 | static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) | 116 | static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) |
111 | { | 117 | { |
112 | struct l2cap_chan *c; | 118 | struct l2cap_chan *c; |
113 | for (c = l->head; c; c = c->next_c) { | 119 | |
114 | if (l2cap_pi(c->sk)->ident == ident) | 120 | list_for_each_entry(c, &conn->chan_l, list) { |
115 | break; | 121 | struct sock *s = c->sk; |
122 | if (l2cap_pi(s)->ident == ident) | ||
123 | return c; | ||
116 | } | 124 | } |
117 | return c; | 125 | return NULL; |
118 | } | 126 | } |
119 | 127 | ||
120 | static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) | 128 | static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) |
121 | { | 129 | { |
122 | struct l2cap_chan *c; | 130 | struct l2cap_chan *c; |
123 | read_lock(&l->lock); | 131 | |
124 | c = __l2cap_get_chan_by_ident(l, ident); | 132 | read_lock(&conn->chan_lock); |
133 | c = __l2cap_get_chan_by_ident(conn, ident); | ||
125 | if (c) | 134 | if (c) |
126 | bh_lock_sock(c->sk); | 135 | bh_lock_sock(c->sk); |
127 | read_unlock(&l->lock); | 136 | read_unlock(&conn->chan_lock); |
128 | return c; | 137 | return c; |
129 | } | 138 | } |
130 | 139 | ||
131 | static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) | 140 | static u16 l2cap_alloc_cid(struct l2cap_conn *conn) |
132 | { | 141 | { |
133 | u16 cid = L2CAP_CID_DYN_START; | 142 | u16 cid = L2CAP_CID_DYN_START; |
134 | 143 | ||
135 | for (; cid < L2CAP_CID_DYN_END; cid++) { | 144 | for (; cid < L2CAP_CID_DYN_END; cid++) { |
136 | if (!__l2cap_get_chan_by_scid(l, cid)) | 145 | if (!__l2cap_get_chan_by_scid(conn, cid)) |
137 | return cid; | 146 | return cid; |
138 | } | 147 | } |
139 | 148 | ||
@@ -153,38 +162,8 @@ static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) | |||
153 | return chan; | 162 | return chan; |
154 | } | 163 | } |
155 | 164 | ||
156 | static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct l2cap_chan *chan) | ||
157 | { | ||
158 | sock_hold(chan->sk); | ||
159 | |||
160 | if (l->head) | ||
161 | l->head->prev_c = chan; | ||
162 | |||
163 | chan->next_c = l->head; | ||
164 | chan->prev_c = NULL; | ||
165 | l->head = chan; | ||
166 | } | ||
167 | |||
168 | static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct l2cap_chan *chan) | ||
169 | { | ||
170 | struct l2cap_chan *next = chan->next_c, *prev = chan->prev_c; | ||
171 | |||
172 | write_lock_bh(&l->lock); | ||
173 | if (chan == l->head) | ||
174 | l->head = next; | ||
175 | |||
176 | if (next) | ||
177 | next->prev_c = prev; | ||
178 | if (prev) | ||
179 | prev->next_c = next; | ||
180 | write_unlock_bh(&l->lock); | ||
181 | |||
182 | __sock_put(chan->sk); | ||
183 | } | ||
184 | |||
185 | static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | 165 | static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) |
186 | { | 166 | { |
187 | struct l2cap_chan_list *l = &conn->chan_list; | ||
188 | struct sock *sk = chan->sk; | 167 | struct sock *sk = chan->sk; |
189 | 168 | ||
190 | BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, | 169 | BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, |
@@ -202,7 +181,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |||
202 | l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA; | 181 | l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA; |
203 | } else { | 182 | } else { |
204 | /* Alloc CID for connection-oriented socket */ | 183 | /* Alloc CID for connection-oriented socket */ |
205 | l2cap_pi(sk)->scid = l2cap_alloc_cid(l); | 184 | l2cap_pi(sk)->scid = l2cap_alloc_cid(conn); |
206 | l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; | 185 | l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; |
207 | } | 186 | } |
208 | } else if (sk->sk_type == SOCK_DGRAM) { | 187 | } else if (sk->sk_type == SOCK_DGRAM) { |
@@ -217,7 +196,9 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |||
217 | l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; | 196 | l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; |
218 | } | 197 | } |
219 | 198 | ||
220 | __l2cap_chan_link(l, chan); | 199 | sock_hold(sk); |
200 | |||
201 | list_add(&chan->list, &conn->chan_l); | ||
221 | } | 202 | } |
222 | 203 | ||
223 | /* Delete channel. | 204 | /* Delete channel. |
@@ -233,8 +214,12 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
233 | BT_DBG("sk %p, conn %p, err %d", sk, conn, err); | 214 | BT_DBG("sk %p, conn %p, err %d", sk, conn, err); |
234 | 215 | ||
235 | if (conn) { | 216 | if (conn) { |
236 | /* Unlink from channel list */ | 217 | /* Delete from channel list */ |
237 | l2cap_chan_unlink(&conn->chan_list, chan); | 218 | write_lock_bh(&conn->chan_lock); |
219 | list_del(&chan->list); | ||
220 | write_unlock_bh(&conn->chan_lock); | ||
221 | __sock_put(sk); | ||
222 | |||
238 | l2cap_pi(sk)->conn = NULL; | 223 | l2cap_pi(sk)->conn = NULL; |
239 | hci_conn_put(conn->hcon); | 224 | hci_conn_put(conn->hcon); |
240 | } | 225 | } |
@@ -502,7 +487,6 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err) | |||
502 | /* ---- L2CAP connections ---- */ | 487 | /* ---- L2CAP connections ---- */ |
503 | static void l2cap_conn_start(struct l2cap_conn *conn) | 488 | static void l2cap_conn_start(struct l2cap_conn *conn) |
504 | { | 489 | { |
505 | struct l2cap_chan_list *l = &conn->chan_list; | ||
506 | struct sock_del_list del, *tmp1, *tmp2; | 490 | struct sock_del_list del, *tmp1, *tmp2; |
507 | struct l2cap_chan *chan; | 491 | struct l2cap_chan *chan; |
508 | 492 | ||
@@ -510,10 +494,11 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
510 | 494 | ||
511 | INIT_LIST_HEAD(&del.list); | 495 | INIT_LIST_HEAD(&del.list); |
512 | 496 | ||
513 | read_lock(&l->lock); | 497 | read_lock(&conn->chan_lock); |
514 | 498 | ||
515 | for (chan = l->head; chan; chan = chan->next_c) { | 499 | list_for_each_entry(chan, &conn->chan_l, list) { |
516 | struct sock *sk = chan->sk; | 500 | struct sock *sk = chan->sk; |
501 | |||
517 | bh_lock_sock(sk); | 502 | bh_lock_sock(sk); |
518 | 503 | ||
519 | if (sk->sk_type != SOCK_SEQPACKET && | 504 | if (sk->sk_type != SOCK_SEQPACKET && |
@@ -593,7 +578,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
593 | bh_unlock_sock(sk); | 578 | bh_unlock_sock(sk); |
594 | } | 579 | } |
595 | 580 | ||
596 | read_unlock(&l->lock); | 581 | read_unlock(&conn->chan_lock); |
597 | 582 | ||
598 | list_for_each_entry_safe(tmp1, tmp2, &del.list, list) { | 583 | list_for_each_entry_safe(tmp1, tmp2, &del.list, list) { |
599 | bh_lock_sock(tmp1->sk); | 584 | bh_lock_sock(tmp1->sk); |
@@ -638,7 +623,6 @@ static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src) | |||
638 | 623 | ||
639 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) | 624 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) |
640 | { | 625 | { |
641 | struct l2cap_chan_list *list = &conn->chan_list; | ||
642 | struct sock *parent, *uninitialized_var(sk); | 626 | struct sock *parent, *uninitialized_var(sk); |
643 | struct l2cap_chan *chan; | 627 | struct l2cap_chan *chan; |
644 | 628 | ||
@@ -666,11 +650,12 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
666 | goto clean; | 650 | goto clean; |
667 | } | 651 | } |
668 | 652 | ||
669 | write_lock_bh(&list->lock); | 653 | write_lock_bh(&conn->chan_lock); |
670 | 654 | ||
671 | hci_conn_hold(conn->hcon); | 655 | hci_conn_hold(conn->hcon); |
672 | 656 | ||
673 | l2cap_sock_init(sk, parent); | 657 | l2cap_sock_init(sk, parent); |
658 | |||
674 | bacpy(&bt_sk(sk)->src, conn->src); | 659 | bacpy(&bt_sk(sk)->src, conn->src); |
675 | bacpy(&bt_sk(sk)->dst, conn->dst); | 660 | bacpy(&bt_sk(sk)->dst, conn->dst); |
676 | 661 | ||
@@ -685,7 +670,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
685 | sk->sk_state = BT_CONNECTED; | 670 | sk->sk_state = BT_CONNECTED; |
686 | parent->sk_data_ready(parent, 0); | 671 | parent->sk_data_ready(parent, 0); |
687 | 672 | ||
688 | write_unlock_bh(&list->lock); | 673 | write_unlock_bh(&conn->chan_lock); |
689 | 674 | ||
690 | clean: | 675 | clean: |
691 | bh_unlock_sock(parent); | 676 | bh_unlock_sock(parent); |
@@ -693,7 +678,6 @@ clean: | |||
693 | 678 | ||
694 | static void l2cap_conn_ready(struct l2cap_conn *conn) | 679 | static void l2cap_conn_ready(struct l2cap_conn *conn) |
695 | { | 680 | { |
696 | struct l2cap_chan_list *l = &conn->chan_list; | ||
697 | struct l2cap_chan *chan; | 681 | struct l2cap_chan *chan; |
698 | 682 | ||
699 | BT_DBG("conn %p", conn); | 683 | BT_DBG("conn %p", conn); |
@@ -701,10 +685,11 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
701 | if (!conn->hcon->out && conn->hcon->type == LE_LINK) | 685 | if (!conn->hcon->out && conn->hcon->type == LE_LINK) |
702 | l2cap_le_conn_ready(conn); | 686 | l2cap_le_conn_ready(conn); |
703 | 687 | ||
704 | read_lock(&l->lock); | 688 | read_lock(&conn->chan_lock); |
705 | 689 | ||
706 | for (chan = l->head; chan; chan = chan->next_c) { | 690 | list_for_each_entry(chan, &conn->chan_l, list) { |
707 | struct sock *sk = chan->sk; | 691 | struct sock *sk = chan->sk; |
692 | |||
708 | bh_lock_sock(sk); | 693 | bh_lock_sock(sk); |
709 | 694 | ||
710 | if (conn->hcon->type == LE_LINK) { | 695 | if (conn->hcon->type == LE_LINK) { |
@@ -724,26 +709,26 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
724 | bh_unlock_sock(sk); | 709 | bh_unlock_sock(sk); |
725 | } | 710 | } |
726 | 711 | ||
727 | read_unlock(&l->lock); | 712 | read_unlock(&conn->chan_lock); |
728 | } | 713 | } |
729 | 714 | ||
730 | /* Notify sockets that we cannot guaranty reliability anymore */ | 715 | /* Notify sockets that we cannot guaranty reliability anymore */ |
731 | static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) | 716 | static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) |
732 | { | 717 | { |
733 | struct l2cap_chan_list *l = &conn->chan_list; | ||
734 | struct l2cap_chan *chan; | 718 | struct l2cap_chan *chan; |
735 | 719 | ||
736 | BT_DBG("conn %p", conn); | 720 | BT_DBG("conn %p", conn); |
737 | 721 | ||
738 | read_lock(&l->lock); | 722 | read_lock(&conn->chan_lock); |
739 | 723 | ||
740 | for (chan = l->head; chan; chan = chan->next_c) { | 724 | list_for_each_entry(chan, &conn->chan_l, list) { |
741 | struct sock *sk = chan->sk; | 725 | struct sock *sk = chan->sk; |
726 | |||
742 | if (l2cap_pi(sk)->force_reliable) | 727 | if (l2cap_pi(sk)->force_reliable) |
743 | sk->sk_err = err; | 728 | sk->sk_err = err; |
744 | } | 729 | } |
745 | 730 | ||
746 | read_unlock(&l->lock); | 731 | read_unlock(&conn->chan_lock); |
747 | } | 732 | } |
748 | 733 | ||
749 | static void l2cap_info_timeout(unsigned long arg) | 734 | static void l2cap_info_timeout(unsigned long arg) |
@@ -783,7 +768,9 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) | |||
783 | conn->feat_mask = 0; | 768 | conn->feat_mask = 0; |
784 | 769 | ||
785 | spin_lock_init(&conn->lock); | 770 | spin_lock_init(&conn->lock); |
786 | rwlock_init(&conn->chan_list.lock); | 771 | rwlock_init(&conn->chan_lock); |
772 | |||
773 | INIT_LIST_HEAD(&conn->chan_l); | ||
787 | 774 | ||
788 | if (hcon->type != LE_LINK) | 775 | if (hcon->type != LE_LINK) |
789 | setup_timer(&conn->info_timer, l2cap_info_timeout, | 776 | setup_timer(&conn->info_timer, l2cap_info_timeout, |
@@ -797,7 +784,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) | |||
797 | static void l2cap_conn_del(struct hci_conn *hcon, int err) | 784 | static void l2cap_conn_del(struct hci_conn *hcon, int err) |
798 | { | 785 | { |
799 | struct l2cap_conn *conn = hcon->l2cap_data; | 786 | struct l2cap_conn *conn = hcon->l2cap_data; |
800 | struct l2cap_chan *chan; | 787 | struct l2cap_chan *chan, *l; |
801 | struct sock *sk; | 788 | struct sock *sk; |
802 | 789 | ||
803 | if (!conn) | 790 | if (!conn) |
@@ -808,7 +795,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) | |||
808 | kfree_skb(conn->rx_skb); | 795 | kfree_skb(conn->rx_skb); |
809 | 796 | ||
810 | /* Kill channels */ | 797 | /* Kill channels */ |
811 | while ((chan = conn->chan_list.head)) { | 798 | list_for_each_entry_safe(chan, l, &conn->chan_l, list) { |
812 | sk = chan->sk; | 799 | sk = chan->sk; |
813 | bh_lock_sock(sk); | 800 | bh_lock_sock(sk); |
814 | l2cap_chan_del(chan, err); | 801 | l2cap_chan_del(chan, err); |
@@ -825,10 +812,9 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) | |||
825 | 812 | ||
826 | static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | 813 | static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) |
827 | { | 814 | { |
828 | struct l2cap_chan_list *l = &conn->chan_list; | 815 | write_lock_bh(&conn->chan_lock); |
829 | write_lock_bh(&l->lock); | ||
830 | __l2cap_chan_add(conn, chan); | 816 | __l2cap_chan_add(conn, chan); |
831 | write_unlock_bh(&l->lock); | 817 | write_unlock_bh(&conn->chan_lock); |
832 | } | 818 | } |
833 | 819 | ||
834 | /* ---- Socket interface ---- */ | 820 | /* ---- Socket interface ---- */ |
@@ -1426,14 +1412,13 @@ static void l2cap_chan_ready(struct sock *sk) | |||
1426 | /* Copy frame to all raw sockets on that connection */ | 1412 | /* Copy frame to all raw sockets on that connection */ |
1427 | static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) | 1413 | static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) |
1428 | { | 1414 | { |
1429 | struct l2cap_chan_list *l = &conn->chan_list; | ||
1430 | struct sk_buff *nskb; | 1415 | struct sk_buff *nskb; |
1431 | struct l2cap_chan *chan; | 1416 | struct l2cap_chan *chan; |
1432 | 1417 | ||
1433 | BT_DBG("conn %p", conn); | 1418 | BT_DBG("conn %p", conn); |
1434 | 1419 | ||
1435 | read_lock(&l->lock); | 1420 | read_lock(&conn->chan_lock); |
1436 | for (chan = l->head; chan; chan = chan->next_c) { | 1421 | list_for_each_entry(chan, &conn->chan_l, list) { |
1437 | struct sock *sk = chan->sk; | 1422 | struct sock *sk = chan->sk; |
1438 | if (sk->sk_type != SOCK_RAW) | 1423 | if (sk->sk_type != SOCK_RAW) |
1439 | continue; | 1424 | continue; |
@@ -1448,7 +1433,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1448 | if (sock_queue_rcv_skb(sk, nskb)) | 1433 | if (sock_queue_rcv_skb(sk, nskb)) |
1449 | kfree_skb(nskb); | 1434 | kfree_skb(nskb); |
1450 | } | 1435 | } |
1451 | read_unlock(&l->lock); | 1436 | read_unlock(&conn->chan_lock); |
1452 | } | 1437 | } |
1453 | 1438 | ||
1454 | /* ---- L2CAP signalling commands ---- */ | 1439 | /* ---- L2CAP signalling commands ---- */ |
@@ -2015,7 +2000,6 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2015 | 2000 | ||
2016 | static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 2001 | static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) |
2017 | { | 2002 | { |
2018 | struct l2cap_chan_list *list = &conn->chan_list; | ||
2019 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; | 2003 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
2020 | struct l2cap_conn_rsp rsp; | 2004 | struct l2cap_conn_rsp rsp; |
2021 | struct l2cap_chan *chan; | 2005 | struct l2cap_chan *chan; |
@@ -2062,11 +2046,11 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2062 | goto response; | 2046 | goto response; |
2063 | } | 2047 | } |
2064 | 2048 | ||
2065 | write_lock_bh(&list->lock); | 2049 | write_lock_bh(&conn->chan_lock); |
2066 | 2050 | ||
2067 | /* Check if we already have channel with that dcid */ | 2051 | /* Check if we already have channel with that dcid */ |
2068 | if (__l2cap_get_chan_by_dcid(list, scid)) { | 2052 | if (__l2cap_get_chan_by_dcid(conn, scid)) { |
2069 | write_unlock_bh(&list->lock); | 2053 | write_unlock_bh(&conn->chan_lock); |
2070 | sock_set_flag(sk, SOCK_ZAPPED); | 2054 | sock_set_flag(sk, SOCK_ZAPPED); |
2071 | l2cap_sock_kill(sk); | 2055 | l2cap_sock_kill(sk); |
2072 | goto response; | 2056 | goto response; |
@@ -2115,7 +2099,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2115 | status = L2CAP_CS_NO_INFO; | 2099 | status = L2CAP_CS_NO_INFO; |
2116 | } | 2100 | } |
2117 | 2101 | ||
2118 | write_unlock_bh(&list->lock); | 2102 | write_unlock_bh(&conn->chan_lock); |
2119 | 2103 | ||
2120 | response: | 2104 | response: |
2121 | bh_unlock_sock(parent); | 2105 | bh_unlock_sock(parent); |
@@ -2169,11 +2153,11 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2169 | BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status); | 2153 | BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status); |
2170 | 2154 | ||
2171 | if (scid) { | 2155 | if (scid) { |
2172 | chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); | 2156 | chan = l2cap_get_chan_by_scid(conn, scid); |
2173 | if (!chan) | 2157 | if (!chan) |
2174 | return -EFAULT; | 2158 | return -EFAULT; |
2175 | } else { | 2159 | } else { |
2176 | chan = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident); | 2160 | chan = l2cap_get_chan_by_ident(conn, cmd->ident); |
2177 | if (!chan) | 2161 | if (!chan) |
2178 | return -EFAULT; | 2162 | return -EFAULT; |
2179 | } | 2163 | } |
@@ -2243,7 +2227,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2243 | 2227 | ||
2244 | BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); | 2228 | BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); |
2245 | 2229 | ||
2246 | chan = l2cap_get_chan_by_scid(&conn->chan_list, dcid); | 2230 | chan = l2cap_get_chan_by_scid(conn, dcid); |
2247 | if (!chan) | 2231 | if (!chan) |
2248 | return -ENOENT; | 2232 | return -ENOENT; |
2249 | 2233 | ||
@@ -2338,7 +2322,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2338 | BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", | 2322 | BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", |
2339 | scid, flags, result); | 2323 | scid, flags, result); |
2340 | 2324 | ||
2341 | chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); | 2325 | chan = l2cap_get_chan_by_scid(conn, scid); |
2342 | if (!chan) | 2326 | if (!chan) |
2343 | return 0; | 2327 | return 0; |
2344 | 2328 | ||
@@ -2418,7 +2402,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
2418 | 2402 | ||
2419 | BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); | 2403 | BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); |
2420 | 2404 | ||
2421 | chan = l2cap_get_chan_by_scid(&conn->chan_list, dcid); | 2405 | chan = l2cap_get_chan_by_scid(conn, dcid); |
2422 | if (!chan) | 2406 | if (!chan) |
2423 | return 0; | 2407 | return 0; |
2424 | 2408 | ||
@@ -2458,7 +2442,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
2458 | 2442 | ||
2459 | BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); | 2443 | BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); |
2460 | 2444 | ||
2461 | chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); | 2445 | chan = l2cap_get_chan_by_scid(conn, scid); |
2462 | if (!chan) | 2446 | if (!chan) |
2463 | return 0; | 2447 | return 0; |
2464 | 2448 | ||
@@ -3612,7 +3596,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3612 | u8 tx_seq; | 3596 | u8 tx_seq; |
3613 | int len; | 3597 | int len; |
3614 | 3598 | ||
3615 | chan = l2cap_get_chan_by_scid(&conn->chan_list, cid); | 3599 | chan = l2cap_get_chan_by_scid(conn, cid); |
3616 | if (!chan) { | 3600 | if (!chan) { |
3617 | BT_DBG("unknown cid 0x%4.4x", cid); | 3601 | BT_DBG("unknown cid 0x%4.4x", cid); |
3618 | goto drop; | 3602 | goto drop; |
@@ -3855,21 +3839,19 @@ static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt) | |||
3855 | 3839 | ||
3856 | static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | 3840 | static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) |
3857 | { | 3841 | { |
3858 | struct l2cap_chan_list *l; | ||
3859 | struct l2cap_conn *conn = hcon->l2cap_data; | 3842 | struct l2cap_conn *conn = hcon->l2cap_data; |
3860 | struct l2cap_chan *chan; | 3843 | struct l2cap_chan *chan; |
3861 | 3844 | ||
3862 | if (!conn) | 3845 | if (!conn) |
3863 | return 0; | 3846 | return 0; |
3864 | 3847 | ||
3865 | l = &conn->chan_list; | ||
3866 | |||
3867 | BT_DBG("conn %p", conn); | 3848 | BT_DBG("conn %p", conn); |
3868 | 3849 | ||
3869 | read_lock(&l->lock); | 3850 | read_lock(&conn->chan_lock); |
3870 | 3851 | ||
3871 | for (chan = l->head; chan; chan = chan->next_c) { | 3852 | list_for_each_entry(chan, &conn->chan_l, list) { |
3872 | struct sock *sk = chan->sk; | 3853 | struct sock *sk = chan->sk; |
3854 | |||
3873 | bh_lock_sock(sk); | 3855 | bh_lock_sock(sk); |
3874 | 3856 | ||
3875 | if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) { | 3857 | if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) { |
@@ -3923,7 +3905,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
3923 | bh_unlock_sock(sk); | 3905 | bh_unlock_sock(sk); |
3924 | } | 3906 | } |
3925 | 3907 | ||
3926 | read_unlock(&l->lock); | 3908 | read_unlock(&conn->chan_lock); |
3927 | 3909 | ||
3928 | return 0; | 3910 | return 0; |
3929 | } | 3911 | } |
@@ -3980,7 +3962,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl | |||
3980 | goto drop; | 3962 | goto drop; |
3981 | } | 3963 | } |
3982 | 3964 | ||
3983 | chan = l2cap_get_chan_by_scid(&conn->chan_list, cid); | 3965 | chan = l2cap_get_chan_by_scid(conn, cid); |
3984 | 3966 | ||
3985 | if (chan && chan->sk) { | 3967 | if (chan && chan->sk) { |
3986 | struct sock *sk = chan->sk; | 3968 | struct sock *sk = chan->sk; |