diff -r -U5 a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c --- a/net/bluetooth/rfcomm/tty.c 2007-08-23 09:23:54.000000000 +1000 +++ b/net/bluetooth/rfcomm/tty.c 2007-12-14 11:13:23.000000000 +1000 @@ -292,18 +311,17 @@ } /* ---- Send buffer ---- */ static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc) { - /* We can't let it be zero, because we don't get a callback - when tx_credits becomes nonzero, hence we'd never wake up */ - return dlc->mtu * (dlc->tx_credits?:1); + return RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10; } static void rfcomm_wfree(struct sk_buff *skb) { struct rfcomm_dev *dev = (void *) skb->sk; + atomic_sub(skb->truesize, &dev->wmem_alloc); if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags)) tasklet_schedule(&dev->wakeup_task); rfcomm_dev_put(dev); } @@ -690,14 +745,30 @@ struct sk_buff *skb; int err = 0, sent = 0, size; BT_DBG("tty %p count %d", tty, count); + /* We get lots of 1 byte requests in canonical mode */ + /* So we just put them on the tail of our tx queue */ + /* if possible */ + + rfcomm_dlc_lock(dlc); + skb = skb_peek_tail(&dlc->tx_queue); + if (skb) { + size = min_t(uint, count, dlc->mtu - skb->len); + memcpy(skb_put(skb, size), buf + sent, size); + + sent += size; + count -= size; + } + rfcomm_dlc_unlock(dlc); + skb = 0; + while (count) { size = min_t(uint, count, dlc->mtu); - skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_ATOMIC); + skb = rfcomm_wmalloc(dev, dlc->mtu + RFCOMM_SKB_RESERVE, GFP_ATOMIC); if (!skb) break; skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE); @@ -964,12 +1035,10 @@ BT_DBG("tty %p dev %p", tty, dev); if (!dev || !dev->dlc) return; - skb_queue_purge(&dev->dlc->tx_queue); - if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && tty->ldisc.write_wakeup) tty->ldisc.write_wakeup(tty); } static void rfcomm_tty_send_xchar(struct tty_struct *tty, char ch)