aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2011-03-31 15:17:41 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-04-07 17:06:25 -0400
commitbaa7e1fa6d2870462bd744df1c6ddbd497fe86d6 (patch)
tree44b459ce553a586e2fc8e43ba19d1e9a99a339da
parent48454079c2d4b9ee65c570a22c5fdfe1827996a4 (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.h12
-rw-r--r--net/bluetooth/l2cap_core.c188
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
281struct l2cap_chan { 280struct 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
287struct l2cap_chan_list {
288 struct l2cap_chan *head;
289 rwlock_t lock;
290}; 283};
291 284
292struct l2cap_conn { 285struct 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
318struct sock_del_list { 312struct 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,
74static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); 74static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
75 75
76/* ---- L2CAP channels ---- */ 76/* ---- L2CAP channels ---- */
77static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) 77static 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
87static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) 90static 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 */
99static inline struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) 104static 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
110static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) 116static 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
120static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) 128static 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
131static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) 140static 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
156static 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
168static 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
185static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 165static 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