diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2014-02-09 20:59:24 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-02-14 16:39:32 -0500 |
commit | 8981be9b2fe5553af35a43865d9ab4271c3aa2e2 (patch) | |
tree | 717062972b1186decc17184b29b9e7ecce80cde3 /net/bluetooth | |
parent | b16b4351313fb89ccb4c227d432d16aa32ffec72 (diff) |
Bluetooth: Fix write_room() calculation
The skb truesize of a 12-byte payload with a 10-byte head/tail
reserve is 768 bytes. Consequently, even with 40 tx_credits, at
most 6 packets could be queued at any one time:
40 tx_credits * 127-byte mtu < 768-byte truesize * 7
This error could also cause the tx queue to apparently stall if
credit flow control is disabled (where tx_credits is fixed at 5),
or if the receiver only granted a limited number of tx credits
(eg., less than 7).
Instead, track the outstanding number of queued packets not yet sent
in wmem_alloc and allow for a maximum of 40 queued packets. Report
the space avail for a single write() as the mtu * number of packets
left before reaching the maximum.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Tested-By: Alexander Holler <holler@ahsoftware.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 14 |
1 files changed, 5 insertions, 9 deletions
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 3f44195c04ad..403ec09f480a 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -352,20 +352,16 @@ static inline unsigned int rfcomm_room(struct rfcomm_dev *dev) | |||
352 | { | 352 | { |
353 | struct rfcomm_dlc *dlc = dev->dlc; | 353 | struct rfcomm_dlc *dlc = dev->dlc; |
354 | 354 | ||
355 | /* The limit is bogus; the number of packets which can | 355 | /* Limit the outstanding number of packets not yet sent to 40 */ |
356 | * currently be sent by the krfcommd thread has no relevance | 356 | int pending = 40 - atomic_read(&dev->wmem_alloc); |
357 | * to the number of packets which can be queued on the dlc's | ||
358 | * tx queue. | ||
359 | */ | ||
360 | int limit = dlc->mtu * (dlc->tx_credits?:1); | ||
361 | 357 | ||
362 | return max(0, limit - atomic_read(&dev->wmem_alloc)); | 358 | return max(0, pending) * dlc->mtu; |
363 | } | 359 | } |
364 | 360 | ||
365 | static void rfcomm_wfree(struct sk_buff *skb) | 361 | static void rfcomm_wfree(struct sk_buff *skb) |
366 | { | 362 | { |
367 | struct rfcomm_dev *dev = (void *) skb->sk; | 363 | struct rfcomm_dev *dev = (void *) skb->sk; |
368 | atomic_sub(skb->truesize, &dev->wmem_alloc); | 364 | atomic_dec(&dev->wmem_alloc); |
369 | if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags)) | 365 | if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags)) |
370 | tty_port_tty_wakeup(&dev->port); | 366 | tty_port_tty_wakeup(&dev->port); |
371 | tty_port_put(&dev->port); | 367 | tty_port_put(&dev->port); |
@@ -374,7 +370,7 @@ static void rfcomm_wfree(struct sk_buff *skb) | |||
374 | static void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev) | 370 | static void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev) |
375 | { | 371 | { |
376 | tty_port_get(&dev->port); | 372 | tty_port_get(&dev->port); |
377 | atomic_add(skb->truesize, &dev->wmem_alloc); | 373 | atomic_inc(&dev->wmem_alloc); |
378 | skb->sk = (void *) dev; | 374 | skb->sk = (void *) dev; |
379 | skb->destructor = rfcomm_wfree; | 375 | skb->destructor = rfcomm_wfree; |
380 | } | 376 | } |