mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-13 01:08:50 +00:00
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>
This commit is contained in:
parent
b16b435131
commit
8981be9b2f
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user