[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1391997564-1805-25-git-send-email-peter@hurleysoftware.com>
Date: Sun, 9 Feb 2014 20:59:24 -0500
From: Peter Hurley <peter@...leysoftware.com>
To: Marcel Holtmann <marcel@...tmann.org>
Cc: Gustavo Padovan <gustavo@...ovan.org>,
Johan Hedberg <johan.hedberg@...il.com>,
Gianluca Anzolin <gianluca@...tospazio.it>,
Alexander Holler <holler@...oftware.de>,
Andrey Vihrov <andrey.vihrov@...il.com>,
Sander Eikelenboom <linux@...elenboom.it>,
linux-bluetooth@...r.kernel.org, linux-kernel@...r.kernel.org,
Peter Hurley <peter@...leysoftware.com>
Subject: [PATCH 24/24] 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@...leysoftware.com>
---
net/bluetooth/rfcomm/tty.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 3f44195..403ec09 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)
{
struct rfcomm_dlc *dlc = dev->dlc;
- /* The limit is bogus; the number of packets which can
- * currently be sent by the krfcommd thread has no relevance
- * to the number of packets which can be queued on the dlc's
- * tx queue.
- */
- int limit = dlc->mtu * (dlc->tx_credits?:1);
+ /* Limit the outstanding number of packets not yet sent to 40 */
+ int pending = 40 - atomic_read(&dev->wmem_alloc);
- return max(0, limit - atomic_read(&dev->wmem_alloc));
+ return max(0, pending) * dlc->mtu;
}
static void rfcomm_wfree(struct sk_buff *skb)
{
struct rfcomm_dev *dev = (void *) skb->sk;
- atomic_sub(skb->truesize, &dev->wmem_alloc);
+ atomic_dec(&dev->wmem_alloc);
if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags))
tty_port_tty_wakeup(&dev->port);
tty_port_put(&dev->port);
@@ -374,7 +370,7 @@ static void rfcomm_wfree(struct sk_buff *skb)
static void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev)
{
tty_port_get(&dev->port);
- atomic_add(skb->truesize, &dev->wmem_alloc);
+ atomic_inc(&dev->wmem_alloc);
skb->sk = (void *) dev;
skb->destructor = rfcomm_wfree;
}
--
1.8.1.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists