aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2014-02-09 20:59:24 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-02-14 16:39:32 -0500
commit8981be9b2fe5553af35a43865d9ab4271c3aa2e2 (patch)
tree717062972b1186decc17184b29b9e7ecce80cde3 /net/bluetooth
parentb16b4351313fb89ccb4c227d432d16aa32ffec72 (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.c14
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
365static void rfcomm_wfree(struct sk_buff *skb) 361static 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)
374static void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev) 370static 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}