diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index bd5d9926bf4f..f7ada4a2cc5d 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -3227,22 +3227,26 @@ disconnect: | |||
3227 | return 0; | 3227 | return 0; |
3228 | } | 3228 | } |
3229 | 3229 | ||
3230 | static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) | 3230 | static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan) |
3231 | { | 3231 | { |
3232 | struct sk_buff *skb; | ||
3233 | u16 control; | 3232 | u16 control; |
3234 | int err; | ||
3235 | 3233 | ||
3236 | while ((skb = skb_dequeue(&chan->busy_q))) { | 3234 | BT_DBG("chan %p, Enter local busy", chan); |
3237 | control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; | ||
3238 | err = l2cap_ertm_reassembly_sdu(chan, skb, control); | ||
3239 | if (err < 0) { | ||
3240 | skb_queue_head(&chan->busy_q, skb); | ||
3241 | return -EBUSY; | ||
3242 | } | ||
3243 | 3235 | ||
3244 | chan->buffer_seq = (chan->buffer_seq + 1) % 64; | 3236 | set_bit(CONN_LOCAL_BUSY, &chan->conn_state); |
3245 | } | 3237 | |
3238 | control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | ||
3239 | control |= L2CAP_SUPER_RCV_NOT_READY; | ||
3240 | l2cap_send_sframe(chan, control); | ||
3241 | |||
3242 | set_bit(CONN_RNR_SENT, &chan->conn_state); | ||
3243 | |||
3244 | __clear_ack_timer(chan); | ||
3245 | } | ||
3246 | |||
3247 | static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan) | ||
3248 | { | ||
3249 | u16 control; | ||
3246 | 3250 | ||
3247 | if (!test_bit(CONN_RNR_SENT, &chan->conn_state)) | 3251 | if (!test_bit(CONN_RNR_SENT, &chan->conn_state)) |
3248 | goto done; | 3252 | goto done; |
@@ -3262,6 +3266,26 @@ done: | |||
3262 | clear_bit(CONN_RNR_SENT, &chan->conn_state); | 3266 | clear_bit(CONN_RNR_SENT, &chan->conn_state); |
3263 | 3267 | ||
3264 | BT_DBG("chan %p, Exit local busy", chan); | 3268 | BT_DBG("chan %p, Exit local busy", chan); |
3269 | } | ||
3270 | |||
3271 | static int l2cap_try_push_rx_skb(struct l2cap_chan *chan) | ||
3272 | { | ||
3273 | struct sk_buff *skb; | ||
3274 | u16 control; | ||
3275 | int err; | ||
3276 | |||
3277 | while ((skb = skb_dequeue(&chan->busy_q))) { | ||
3278 | control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; | ||
3279 | err = l2cap_ertm_reassembly_sdu(chan, skb, control); | ||
3280 | if (err < 0) { | ||
3281 | skb_queue_head(&chan->busy_q, skb); | ||
3282 | return -EBUSY; | ||
3283 | } | ||
3284 | |||
3285 | chan->buffer_seq = (chan->buffer_seq + 1) % 64; | ||
3286 | } | ||
3287 | |||
3288 | l2cap_ertm_exit_local_busy(chan); | ||
3265 | 3289 | ||
3266 | return 0; | 3290 | return 0; |
3267 | } | 3291 | } |
@@ -3315,7 +3339,7 @@ static void l2cap_busy_work(struct work_struct *work) | |||
3315 | 3339 | ||
3316 | static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) | 3340 | static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control) |
3317 | { | 3341 | { |
3318 | int sctrl, err; | 3342 | int err; |
3319 | 3343 | ||
3320 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | 3344 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { |
3321 | bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; | 3345 | bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; |
@@ -3331,21 +3355,11 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c | |||
3331 | return err; | 3355 | return err; |
3332 | } | 3356 | } |
3333 | 3357 | ||
3334 | /* Busy Condition */ | 3358 | l2cap_ertm_enter_local_busy(chan); |
3335 | BT_DBG("chan %p, Enter local busy", chan); | ||
3336 | 3359 | ||
3337 | set_bit(CONN_LOCAL_BUSY, &chan->conn_state); | ||
3338 | bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; | 3360 | bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; |
3339 | __skb_queue_tail(&chan->busy_q, skb); | 3361 | __skb_queue_tail(&chan->busy_q, skb); |
3340 | 3362 | ||
3341 | sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | ||
3342 | sctrl |= L2CAP_SUPER_RCV_NOT_READY; | ||
3343 | l2cap_send_sframe(chan, sctrl); | ||
3344 | |||
3345 | set_bit(CONN_RNR_SENT, &chan->conn_state); | ||
3346 | |||
3347 | __clear_ack_timer(chan); | ||
3348 | |||
3349 | queue_work(_busy_wq, &chan->busy_work); | 3363 | queue_work(_busy_wq, &chan->busy_work); |
3350 | 3364 | ||
3351 | return err; | 3365 | return err; |