Commit 72e5108c authored by Peter Hurley's avatar Peter Hurley Committed by Marcel Holtmann

Bluetooth: Don't fail RFCOMM tty writes

The tty driver api design prefers no-fail writes if the driver
write_room() method has previously indicated space is available
to accept writes. Since this is trivially possible for the
RFCOMM tty driver, do so.

Introduce rfcomm_dlc_send_noerror(), which queues but does not
schedule the krfcomm thread if the dlc is not yet connected
(and thus does not error based on the connection state).
The mtu size test is also unnecessary since the caller already
chunks the written data into mtu size.
Signed-off-by: default avatarPeter Hurley <peter@hurleysoftware.com>
Tested-By: default avatarAlexander Holler <holler@ahsoftware.de>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 5326a4ee
...@@ -238,6 +238,7 @@ int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, ...@@ -238,6 +238,7 @@ int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
u8 channel); u8 channel);
int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason); int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb); int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
void rfcomm_dlc_send_noerror(struct rfcomm_dlc *d, struct sk_buff *skb);
int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig); int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig); int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig);
void rfcomm_dlc_accept(struct rfcomm_dlc *d); void rfcomm_dlc_accept(struct rfcomm_dlc *d);
......
...@@ -569,6 +569,20 @@ int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb) ...@@ -569,6 +569,20 @@ int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb)
return len; return len;
} }
void rfcomm_dlc_send_noerror(struct rfcomm_dlc *d, struct sk_buff *skb)
{
int len = skb->len;
BT_DBG("dlc %p mtu %d len %d", d, d->mtu, len);
rfcomm_make_uih(skb, d->addr);
skb_queue_tail(&d->tx_queue, skb);
if (d->state == BT_CONNECTED &&
!test_bit(RFCOMM_TX_THROTTLED, &d->flags))
rfcomm_schedule();
}
void __rfcomm_dlc_throttle(struct rfcomm_dlc *d) void __rfcomm_dlc_throttle(struct rfcomm_dlc *d)
{ {
BT_DBG("dlc %p state %ld", d, d->state); BT_DBG("dlc %p state %ld", d, d->state);
......
...@@ -374,14 +374,10 @@ static void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev) ...@@ -374,14 +374,10 @@ static void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev)
static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, gfp_t priority) static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, gfp_t priority)
{ {
if (atomic_read(&dev->wmem_alloc) < rfcomm_room(dev->dlc)) {
struct sk_buff *skb = alloc_skb(size, priority); struct sk_buff *skb = alloc_skb(size, priority);
if (skb) { if (skb)
rfcomm_set_owner_w(skb, dev); rfcomm_set_owner_w(skb, dev);
return skb; return skb;
}
}
return NULL;
} }
/* ---- Device IOCTLs ---- */ /* ---- Device IOCTLs ---- */
...@@ -786,7 +782,7 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in ...@@ -786,7 +782,7 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
struct rfcomm_dlc *dlc = dev->dlc; struct rfcomm_dlc *dlc = dev->dlc;
struct sk_buff *skb; struct sk_buff *skb;
int err = 0, sent = 0, size; int sent = 0, size;
BT_DBG("tty %p count %d", tty, count); BT_DBG("tty %p count %d", tty, count);
...@@ -794,7 +790,6 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in ...@@ -794,7 +790,6 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in
size = min_t(uint, count, dlc->mtu); size = min_t(uint, count, dlc->mtu);
skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_ATOMIC); skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_ATOMIC);
if (!skb) if (!skb)
break; break;
...@@ -802,17 +797,13 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in ...@@ -802,17 +797,13 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in
memcpy(skb_put(skb, size), buf + sent, size); memcpy(skb_put(skb, size), buf + sent, size);
err = rfcomm_dlc_send(dlc, skb); rfcomm_dlc_send_noerror(dlc, skb);
if (err < 0) {
kfree_skb(skb);
break;
}
sent += size; sent += size;
count -= size; count -= size;
} }
return sent ? sent : err; return sent;
} }
static int rfcomm_tty_write_room(struct tty_struct *tty) static int rfcomm_tty_write_room(struct tty_struct *tty)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment