diff options
-rw-r--r-- | include/net/bluetooth/l2cap.h | 13 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 22 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 1 |
3 files changed, 17 insertions, 19 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index d05d91f2fd32..ec56d8861a4e 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -277,6 +277,11 @@ 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 | struct srej_list { | ||
281 | __u8 tx_seq; | ||
282 | struct list_head list; | ||
283 | }; | ||
284 | |||
280 | struct l2cap_chan { | 285 | struct l2cap_chan { |
281 | struct sock *sk; | 286 | struct sock *sk; |
282 | __u8 ident; | 287 | __u8 ident; |
@@ -312,6 +317,7 @@ struct l2cap_chan { | |||
312 | struct sk_buff_head srej_q; | 317 | struct sk_buff_head srej_q; |
313 | struct sk_buff_head busy_q; | 318 | struct sk_buff_head busy_q; |
314 | struct work_struct busy_work; | 319 | struct work_struct busy_work; |
320 | struct list_head srej_l; | ||
315 | 321 | ||
316 | struct list_head list; | 322 | struct list_head list; |
317 | }; | 323 | }; |
@@ -350,12 +356,6 @@ struct l2cap_conn { | |||
350 | /* ----- L2CAP socket info ----- */ | 356 | /* ----- L2CAP socket info ----- */ |
351 | #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) | 357 | #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) |
352 | #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) | 358 | #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) |
353 | #define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list) | ||
354 | |||
355 | struct srej_list { | ||
356 | __u8 tx_seq; | ||
357 | struct list_head list; | ||
358 | }; | ||
359 | 359 | ||
360 | struct l2cap_pinfo { | 360 | struct l2cap_pinfo { |
361 | struct bt_sock bt; | 361 | struct bt_sock bt; |
@@ -385,7 +385,6 @@ struct l2cap_pinfo { | |||
385 | __le16 sport; | 385 | __le16 sport; |
386 | 386 | ||
387 | struct sk_buff_head tx_queue; | 387 | struct sk_buff_head tx_queue; |
388 | struct srej_list srej_l; | ||
389 | struct l2cap_conn *conn; | 388 | struct l2cap_conn *conn; |
390 | struct l2cap_chan *chan; | 389 | struct l2cap_chan *chan; |
391 | }; | 390 | }; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 7264119b64a6..9580d6cd55da 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) | |||
252 | skb_queue_purge(&chan->srej_q); | 252 | skb_queue_purge(&chan->srej_q); |
253 | skb_queue_purge(&chan->busy_q); | 253 | skb_queue_purge(&chan->busy_q); |
254 | 254 | ||
255 | list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { | 255 | list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { |
256 | list_del(&l->list); | 256 | list_del(&l->list); |
257 | kfree(l); | 257 | kfree(l); |
258 | } | 258 | } |
@@ -1205,7 +1205,7 @@ static void l2cap_send_srejtail(struct l2cap_chan *chan) | |||
1205 | control = L2CAP_SUPER_SELECT_REJECT; | 1205 | control = L2CAP_SUPER_SELECT_REJECT; |
1206 | control |= L2CAP_CTRL_FINAL; | 1206 | control |= L2CAP_CTRL_FINAL; |
1207 | 1207 | ||
1208 | tail = list_entry(SREJ_LIST(chan->sk)->prev, struct srej_list, list); | 1208 | tail = list_entry((&chan->srej_l)->prev, struct srej_list, list); |
1209 | control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; | 1209 | control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; |
1210 | 1210 | ||
1211 | l2cap_send_sframe(chan, control); | 1211 | l2cap_send_sframe(chan, control); |
@@ -1596,6 +1596,8 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan) | |||
1596 | skb_queue_head_init(&chan->srej_q); | 1596 | skb_queue_head_init(&chan->srej_q); |
1597 | skb_queue_head_init(&chan->busy_q); | 1597 | skb_queue_head_init(&chan->busy_q); |
1598 | 1598 | ||
1599 | INIT_LIST_HEAD(&chan->srej_l); | ||
1600 | |||
1599 | INIT_WORK(&chan->busy_work, l2cap_busy_work); | 1601 | INIT_WORK(&chan->busy_work, l2cap_busy_work); |
1600 | 1602 | ||
1601 | sk->sk_backlog_rcv = l2cap_ertm_data_rcv; | 1603 | 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) | |||
3207 | 3209 | ||
3208 | static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq) | 3210 | static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq) |
3209 | { | 3211 | { |
3210 | struct sock *sk = chan->sk; | ||
3211 | struct srej_list *l, *tmp; | 3212 | struct srej_list *l, *tmp; |
3212 | u16 control; | 3213 | u16 control; |
3213 | 3214 | ||
3214 | list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { | 3215 | list_for_each_entry_safe(l, tmp, &chan->srej_l, list) { |
3215 | if (l->tx_seq == tx_seq) { | 3216 | if (l->tx_seq == tx_seq) { |
3216 | list_del(&l->list); | 3217 | list_del(&l->list); |
3217 | kfree(l); | 3218 | kfree(l); |
@@ -3221,13 +3222,12 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq) | |||
3221 | control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; | 3222 | control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; |
3222 | l2cap_send_sframe(chan, control); | 3223 | l2cap_send_sframe(chan, control); |
3223 | list_del(&l->list); | 3224 | list_del(&l->list); |
3224 | list_add_tail(&l->list, SREJ_LIST(sk)); | 3225 | list_add_tail(&l->list, &chan->srej_l); |
3225 | } | 3226 | } |
3226 | } | 3227 | } |
3227 | 3228 | ||
3228 | static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) | 3229 | static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) |
3229 | { | 3230 | { |
3230 | struct sock *sk = chan->sk; | ||
3231 | struct srej_list *new; | 3231 | struct srej_list *new; |
3232 | u16 control; | 3232 | u16 control; |
3233 | 3233 | ||
@@ -3239,7 +3239,7 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) | |||
3239 | new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); | 3239 | new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); |
3240 | new->tx_seq = chan->expected_tx_seq; | 3240 | new->tx_seq = chan->expected_tx_seq; |
3241 | chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; | 3241 | chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; |
3242 | list_add_tail(&new->list, SREJ_LIST(sk)); | 3242 | list_add_tail(&new->list, &chan->srej_l); |
3243 | } | 3243 | } |
3244 | chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; | 3244 | chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; |
3245 | } | 3245 | } |
@@ -3288,7 +3288,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont | |||
3288 | if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { | 3288 | if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { |
3289 | struct srej_list *first; | 3289 | struct srej_list *first; |
3290 | 3290 | ||
3291 | first = list_first_entry(SREJ_LIST(sk), | 3291 | first = list_first_entry(&chan->srej_l, |
3292 | struct srej_list, list); | 3292 | struct srej_list, list); |
3293 | if (tx_seq == first->tx_seq) { | 3293 | if (tx_seq == first->tx_seq) { |
3294 | l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); | 3294 | 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 | |||
3297 | list_del(&first->list); | 3297 | list_del(&first->list); |
3298 | kfree(first); | 3298 | kfree(first); |
3299 | 3299 | ||
3300 | if (list_empty(SREJ_LIST(sk))) { | 3300 | if (list_empty(&chan->srej_l)) { |
3301 | chan->buffer_seq = chan->buffer_seq_srej; | 3301 | chan->buffer_seq = chan->buffer_seq_srej; |
3302 | chan->conn_state &= ~L2CAP_CONN_SREJ_SENT; | 3302 | chan->conn_state &= ~L2CAP_CONN_SREJ_SENT; |
3303 | l2cap_send_ack(chan); | 3303 | l2cap_send_ack(chan); |
@@ -3310,7 +3310,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont | |||
3310 | if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0) | 3310 | if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0) |
3311 | goto drop; | 3311 | goto drop; |
3312 | 3312 | ||
3313 | list_for_each_entry(l, SREJ_LIST(sk), list) { | 3313 | list_for_each_entry(l, &chan->srej_l, list) { |
3314 | if (l->tx_seq == tx_seq) { | 3314 | if (l->tx_seq == tx_seq) { |
3315 | l2cap_resend_srejframe(chan, tx_seq); | 3315 | l2cap_resend_srejframe(chan, tx_seq); |
3316 | return 0; | 3316 | return 0; |
@@ -3332,7 +3332,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont | |||
3332 | 3332 | ||
3333 | BT_DBG("sk %p, Enter SREJ", sk); | 3333 | BT_DBG("sk %p, Enter SREJ", sk); |
3334 | 3334 | ||
3335 | INIT_LIST_HEAD(SREJ_LIST(sk)); | 3335 | INIT_LIST_HEAD(&chan->srej_l); |
3336 | chan->buffer_seq_srej = chan->buffer_seq; | 3336 | chan->buffer_seq_srej = chan->buffer_seq; |
3337 | 3337 | ||
3338 | __skb_queue_head_init(&chan->srej_q); | 3338 | __skb_queue_head_init(&chan->srej_q); |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 55dee999af94..16a223bfa8f5 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) | |||
1018 | /* Default config options */ | 1018 | /* Default config options */ |
1019 | pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; | 1019 | pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; |
1020 | skb_queue_head_init(TX_QUEUE(sk)); | 1020 | skb_queue_head_init(TX_QUEUE(sk)); |
1021 | INIT_LIST_HEAD(SREJ_LIST(sk)); | ||
1022 | } | 1021 | } |
1023 | 1022 | ||
1024 | static struct proto l2cap_proto = { | 1023 | static struct proto l2cap_proto = { |