* [PATCH v2 1/2] hso: remove unused workqueue
@ 2014-07-14 10:08 Olivier Sobrie
2014-07-14 10:08 ` [PATCH v2 2/2] hso: fix deadlock when receiving bursts of data Olivier Sobrie
2014-07-15 2:27 ` [PATCH v2 1/2] hso: remove unused workqueue David Miller
0 siblings, 2 replies; 7+ messages in thread
From: Olivier Sobrie @ 2014-07-14 10:08 UTC (permalink / raw)
To: linux-usb, netdev; +Cc: linux-kernel, Olivier Sobrie
The workqueue "retry_unthrottle_workqueue" is not scheduled anywhere
in the code. So, remove it.
Signed-off-by: Olivier Sobrie <olivier@sobrie.be>
---
drivers/net/usb/hso.c | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index a3a0586..9ca2b41 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -261,7 +261,6 @@ struct hso_serial {
u16 curr_rx_urb_offset;
u8 rx_urb_filled[MAX_RX_URBS];
struct tasklet_struct unthrottle_tasklet;
- struct work_struct retry_unthrottle_workqueue;
};
struct hso_device {
@@ -1252,14 +1251,6 @@ static void hso_unthrottle(struct tty_struct *tty)
tasklet_hi_schedule(&serial->unthrottle_tasklet);
}
-static void hso_unthrottle_workfunc(struct work_struct *work)
-{
- struct hso_serial *serial =
- container_of(work, struct hso_serial,
- retry_unthrottle_workqueue);
- hso_unthrottle_tasklet(serial);
-}
-
/* open the requested serial port */
static int hso_serial_open(struct tty_struct *tty, struct file *filp)
{
@@ -1295,8 +1286,6 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
tasklet_init(&serial->unthrottle_tasklet,
(void (*)(unsigned long))hso_unthrottle_tasklet,
(unsigned long)serial);
- INIT_WORK(&serial->retry_unthrottle_workqueue,
- hso_unthrottle_workfunc);
result = hso_start_serial_device(serial->parent, GFP_KERNEL);
if (result) {
hso_stop_serial_device(serial->parent);
@@ -1345,7 +1334,6 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)
if (!usb_gone)
hso_stop_serial_device(serial->parent);
tasklet_kill(&serial->unthrottle_tasklet);
- cancel_work_sync(&serial->retry_unthrottle_workqueue);
}
if (!usb_gone)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] hso: fix deadlock when receiving bursts of data
2014-07-14 10:08 [PATCH v2 1/2] hso: remove unused workqueue Olivier Sobrie
@ 2014-07-14 10:08 ` Olivier Sobrie
[not found] ` <1405332530-2507-2-git-send-email-olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org>
2014-07-15 2:27 ` [PATCH v2 1/2] hso: remove unused workqueue David Miller
1 sibling, 1 reply; 7+ messages in thread
From: Olivier Sobrie @ 2014-07-14 10:08 UTC (permalink / raw)
To: linux-usb, netdev
Cc: linux-kernel, Olivier Sobrie, David Miller, David Laight,
One Thousand Gnomes, Dan Williams, Jan Dumon
When the module sends bursts of data, sometimes a deadlock happens in
the hso driver when the tty buffer doesn't get the chance to be flushed
quickly enough.
Remove the endless while loop in function put_rxbuf_data() which is
called by the urb completion handler.
If there isn't enough room in the tty buffer, discards all the data
received in the URB.
Cc: David Miller <davem@davemloft.net>
Cc: David Laight <David.Laight@ACULAB.COM>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Dan Williams <dcbw@redhat.com>
Cc: Jan Dumon <j.dumon@option.com>
Signed-off-by: Olivier Sobrie <olivier@sobrie.be>
---
Changes in v2:
- remove the unthrottle timer added in the previous patch version
- drop entire rx urb data if there is not enough space in tty buffer
- remove variable curr_rx_urb_offset from hso_serial structure
drivers/net/usb/hso.c | 38 +++++++++++++++++---------------------
1 file changed, 17 insertions(+), 21 deletions(-)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 9ca2b41..a4272ed 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -258,7 +258,6 @@ struct hso_serial {
* so as not to drop characters on the floor.
*/
int curr_rx_urb_idx;
- u16 curr_rx_urb_offset;
u8 rx_urb_filled[MAX_RX_URBS];
struct tasklet_struct unthrottle_tasklet;
};
@@ -2001,8 +2000,7 @@ static void ctrl_callback(struct urb *urb)
static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
{
struct tty_struct *tty;
- int write_length_remaining = 0;
- int curr_write_len;
+ int count;
/* Sanity check */
if (urb == NULL || serial == NULL) {
@@ -2012,29 +2010,28 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
tty = tty_port_tty_get(&serial->port);
+ if (tty && test_bit(TTY_THROTTLED, &tty->flags)) {
+ tty_kref_put(tty);
+ return -1;
+ }
+
/* Push data to tty */
- write_length_remaining = urb->actual_length -
- serial->curr_rx_urb_offset;
D1("data to push to tty");
- while (write_length_remaining) {
- if (tty && test_bit(TTY_THROTTLED, &tty->flags)) {
- tty_kref_put(tty);
- return -1;
- }
- curr_write_len = tty_insert_flip_string(&serial->port,
- urb->transfer_buffer + serial->curr_rx_urb_offset,
- write_length_remaining);
- serial->curr_rx_urb_offset += curr_write_len;
- write_length_remaining -= curr_write_len;
+ count = tty_buffer_request_room(&serial->port, urb->actual_length);
+ if (count >= urb->actual_length) {
+ tty_insert_flip_string(&serial->port, urb->transfer_buffer,
+ urb->actual_length);
tty_flip_buffer_push(&serial->port);
+ } else {
+ dev_warn(&serial->parent->usb->dev,
+ "dropping data, %d bytes lost\n", urb->actual_length);
}
+
tty_kref_put(tty);
- if (write_length_remaining == 0) {
- serial->curr_rx_urb_offset = 0;
- serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
- }
- return write_length_remaining;
+ serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
+
+ return 0;
}
@@ -2205,7 +2202,6 @@ static int hso_stop_serial_device(struct hso_device *hso_dev)
}
}
serial->curr_rx_urb_idx = 0;
- serial->curr_rx_urb_offset = 0;
if (serial->tx_urb)
usb_kill_urb(serial->tx_urb);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] hso: remove unused workqueue
2014-07-14 10:08 [PATCH v2 1/2] hso: remove unused workqueue Olivier Sobrie
2014-07-14 10:08 ` [PATCH v2 2/2] hso: fix deadlock when receiving bursts of data Olivier Sobrie
@ 2014-07-15 2:27 ` David Miller
1 sibling, 0 replies; 7+ messages in thread
From: David Miller @ 2014-07-15 2:27 UTC (permalink / raw)
To: olivier; +Cc: linux-usb, netdev, linux-kernel
From: Olivier Sobrie <olivier@sobrie.be>
Date: Mon, 14 Jul 2014 12:08:49 +0200
> The workqueue "retry_unthrottle_workqueue" is not scheduled anywhere
> in the code. So, remove it.
>
> Signed-off-by: Olivier Sobrie <olivier@sobrie.be>
Applied.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/2] hso: fix deadlock when receiving bursts of data
@ 2014-07-07 9:06 Olivier Sobrie
2014-07-11 13:05 ` [PATCH v2 " Olivier Sobrie
0 siblings, 1 reply; 7+ messages in thread
From: Olivier Sobrie @ 2014-07-07 9:06 UTC (permalink / raw)
To: Jan Dumon, linux-usb, netdev; +Cc: linux-kernel, Olivier Sobrie
When the module sends bursts of data, sometimes a deadlock happens in
the hso driver when the tty buffer doesn't get the chance to be flushed
quickly enough.
To avoid this, first, we remove the endless while loop in
put_rx_bufdata() which is the root cause of the deadlock.
Secondly, when there is no room anymore in the tty buffer, we set up a
timer of 100 msecs to give a chance to the upper layer to flush the tty
buffer and make room for new data.
Signed-off-by: Olivier Sobrie <olivier@sobrie.be>
---
drivers/net/usb/hso.c | 51 +++++++++++++++++++++++++++++++++----------------
1 file changed, 35 insertions(+), 16 deletions(-)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 9ca2b41..1dff74f 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -106,6 +106,8 @@
#define MAX_RX_URBS 2
+#define UNTHROTTLE_TIMEOUT 100 /* msecs */
+
/*****************************************************************************/
/* Debugging functions */
/*****************************************************************************/
@@ -261,6 +263,7 @@ struct hso_serial {
u16 curr_rx_urb_offset;
u8 rx_urb_filled[MAX_RX_URBS];
struct tasklet_struct unthrottle_tasklet;
+ struct timer_list unthrottle_timer;
};
struct hso_device {
@@ -1161,13 +1164,18 @@ static void put_rxbuf_data_and_resubmit_bulk_urb(struct hso_serial *serial)
while (serial->rx_urb_filled[serial->curr_rx_urb_idx]) {
curr_urb = serial->rx_urb[serial->curr_rx_urb_idx];
count = put_rxbuf_data(curr_urb, serial);
- if (count == -1)
- return;
if (count == 0) {
serial->curr_rx_urb_idx++;
if (serial->curr_rx_urb_idx >= serial->num_rx_urbs)
serial->curr_rx_urb_idx = 0;
hso_resubmit_rx_bulk_urb(serial, curr_urb);
+ } else if (count > 0) {
+ mod_timer(&serial->unthrottle_timer,
+ jiffies
+ + msecs_to_jiffies(UNTHROTTLE_TIMEOUT));
+ break;
+ } else {
+ break;
}
}
}
@@ -1251,6 +1259,11 @@ static void hso_unthrottle(struct tty_struct *tty)
tasklet_hi_schedule(&serial->unthrottle_tasklet);
}
+static void hso_unthrottle_schedule(unsigned long data)
+{
+ tasklet_schedule((struct tasklet_struct *)data);
+}
+
/* open the requested serial port */
static int hso_serial_open(struct tty_struct *tty, struct file *filp)
{
@@ -1286,6 +1299,10 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
tasklet_init(&serial->unthrottle_tasklet,
(void (*)(unsigned long))hso_unthrottle_tasklet,
(unsigned long)serial);
+ serial->unthrottle_timer.function = hso_unthrottle_schedule;
+ serial->unthrottle_timer.data =
+ (unsigned long)&serial->unthrottle_tasklet;
+ init_timer(&serial->unthrottle_timer);
result = hso_start_serial_device(serial->parent, GFP_KERNEL);
if (result) {
hso_stop_serial_device(serial->parent);
@@ -1333,6 +1350,7 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)
tty_port_tty_set(&serial->port, NULL);
if (!usb_gone)
hso_stop_serial_device(serial->parent);
+ del_timer_sync(&serial->unthrottle_timer);
tasklet_kill(&serial->unthrottle_tasklet);
}
@@ -2012,22 +2030,23 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
tty = tty_port_tty_get(&serial->port);
+ if (tty && test_bit(TTY_THROTTLED, &tty->flags)) {
+ tty_kref_put(tty);
+ return -1;
+ }
+
/* Push data to tty */
- write_length_remaining = urb->actual_length -
- serial->curr_rx_urb_offset;
D1("data to push to tty");
- while (write_length_remaining) {
- if (tty && test_bit(TTY_THROTTLED, &tty->flags)) {
- tty_kref_put(tty);
- return -1;
- }
- curr_write_len = tty_insert_flip_string(&serial->port,
- urb->transfer_buffer + serial->curr_rx_urb_offset,
- write_length_remaining);
- serial->curr_rx_urb_offset += curr_write_len;
- write_length_remaining -= curr_write_len;
- tty_flip_buffer_push(&serial->port);
- }
+ write_length_remaining = urb->actual_length -
+ serial->curr_rx_urb_offset;
+ curr_write_len =
+ tty_insert_flip_string(&serial->port,
+ urb->transfer_buffer
+ + serial->curr_rx_urb_offset,
+ write_length_remaining);
+ serial->curr_rx_urb_offset += curr_write_len;
+ write_length_remaining -= curr_write_len;
+ tty_flip_buffer_push(&serial->port);
tty_kref_put(tty);
if (write_length_remaining == 0) {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] hso: fix deadlock when receiving bursts of data
2014-07-07 9:06 [PATCH 2/2] hso: fix deadlock when receiving bursts of data Olivier Sobrie
@ 2014-07-11 13:05 ` Olivier Sobrie
2014-07-11 18:36 ` David Miller
0 siblings, 1 reply; 7+ messages in thread
From: Olivier Sobrie @ 2014-07-11 13:05 UTC (permalink / raw)
To: linux-usb, netdev
Cc: linux-kernel, Olivier Sobrie, David Miller, David Laight,
One Thousand Gnomes, Dan Williams, Jan Dumon
When the module sends bursts of data, sometimes a deadlock happens in
the hso driver when the tty buffer doesn't get the chance to be flushed
quickly enough.
Remove the endless while loop in function put_rxbuf_data() which is
called by the urb completion handler.
If there isn't enough room in the tty buffer, discards all the data
received in the URB.
Cc: David Miller <davem@davemloft.net>
Cc: David Laight <David.Laight@ACULAB.COM>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Dan Williams <dcbw@redhat.com>
Cc: Jan Dumon <j.dumon@option.com>
Signed-off-by: Olivier Sobrie <olivier@sobrie.be>
---
Changes in v2:
- remove the unthrottle timer added in the previous patch version
- drop entire rx urb data if there is not enough space in tty buffer
- remove variable curr_rx_urb_offset from hso_serial structure
drivers/net/usb/hso.c | 38 +++++++++++++++++---------------------
1 file changed, 17 insertions(+), 21 deletions(-)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 9ca2b41..a4272ed 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -258,7 +258,6 @@ struct hso_serial {
* so as not to drop characters on the floor.
*/
int curr_rx_urb_idx;
- u16 curr_rx_urb_offset;
u8 rx_urb_filled[MAX_RX_URBS];
struct tasklet_struct unthrottle_tasklet;
};
@@ -2001,8 +2000,7 @@ static void ctrl_callback(struct urb *urb)
static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
{
struct tty_struct *tty;
- int write_length_remaining = 0;
- int curr_write_len;
+ int count;
/* Sanity check */
if (urb == NULL || serial == NULL) {
@@ -2012,29 +2010,28 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
tty = tty_port_tty_get(&serial->port);
+ if (tty && test_bit(TTY_THROTTLED, &tty->flags)) {
+ tty_kref_put(tty);
+ return -1;
+ }
+
/* Push data to tty */
- write_length_remaining = urb->actual_length -
- serial->curr_rx_urb_offset;
D1("data to push to tty");
- while (write_length_remaining) {
- if (tty && test_bit(TTY_THROTTLED, &tty->flags)) {
- tty_kref_put(tty);
- return -1;
- }
- curr_write_len = tty_insert_flip_string(&serial->port,
- urb->transfer_buffer + serial->curr_rx_urb_offset,
- write_length_remaining);
- serial->curr_rx_urb_offset += curr_write_len;
- write_length_remaining -= curr_write_len;
+ count = tty_buffer_request_room(&serial->port, urb->actual_length);
+ if (count >= urb->actual_length) {
+ tty_insert_flip_string(&serial->port, urb->transfer_buffer,
+ urb->actual_length);
tty_flip_buffer_push(&serial->port);
+ } else {
+ dev_warn(&serial->parent->usb->dev,
+ "dropping data, %d bytes lost\n", urb->actual_length);
}
+
tty_kref_put(tty);
- if (write_length_remaining == 0) {
- serial->curr_rx_urb_offset = 0;
- serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
- }
- return write_length_remaining;
+ serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
+
+ return 0;
}
@@ -2205,7 +2202,6 @@ static int hso_stop_serial_device(struct hso_device *hso_dev)
}
}
serial->curr_rx_urb_idx = 0;
- serial->curr_rx_urb_offset = 0;
if (serial->tx_urb)
usb_kill_urb(serial->tx_urb);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-07-15 2:27 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-14 10:08 [PATCH v2 1/2] hso: remove unused workqueue Olivier Sobrie
2014-07-14 10:08 ` [PATCH v2 2/2] hso: fix deadlock when receiving bursts of data Olivier Sobrie
[not found] ` <1405332530-2507-2-git-send-email-olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org>
2014-07-14 13:27 ` One Thousand Gnomes
2014-07-15 2:27 ` David Miller
2014-07-15 2:27 ` [PATCH v2 1/2] hso: remove unused workqueue David Miller
-- strict thread matches above, loose matches on Subject: below --
2014-07-07 9:06 [PATCH 2/2] hso: fix deadlock when receiving bursts of data Olivier Sobrie
2014-07-11 13:05 ` [PATCH v2 " Olivier Sobrie
2014-07-11 18:36 ` David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).