* [PATCH 0/6] usb console improvements series
@ 2010-03-09 6:29 Jason Wessel
2010-03-09 6:29 ` [PATCH 1/6] tty_port,usb-console: Fix usb serial console open/close regression Jason Wessel
2010-03-16 20:30 ` [PATCH 0/6] usb console improvements series Greg KH
0 siblings, 2 replies; 12+ messages in thread
From: Jason Wessel @ 2010-03-09 6:29 UTC (permalink / raw)
To: gregkh; +Cc: linux-usb, Alan Stern, linux-kernel
I aggregated and ported all usb patches I have previously posted which
are not mainlined into a single series aimed at providing a stable usb
console.
This is picking up where Alan Stern and I left after a discussion in
September 2009.
-- The recap about synchronous usb serial consoles --
The serial uart code implements the console writes synchronously such
that you get the data right away and "pay the toll" in terms of system
performance loss if you do lots of printk's to the console. The usb
serial console code just eats the data if there is no room left in the
queue, and you do not see the data until the interrupts are restored.
If we assume the main reason you would use a usb console device is to
get printk's then every effort should be made to be able to see the
printk's on the usb console device. In this patch series, two
conditions must be met before the hcd device would get polled.
1) The data write is a usb serial console write
2) The usb serial driver has set the variable max_in_flight_urbs
Based on Alan's comments about the 1ms minimum response time for the
hcd device I ended up using a maximum 3ms delay loop. The 3ms was
selected based on testing the usb_debug device and the ftdi usb rs232
port. I found the usb_debug device needed the 1ms and the ftdi device
required slightly more than 2ms in the worst case else there was some
sporadic data loss.
I also tested incurring the penalty 3ms for each write with the device
in a "failed" capacity. In that case it introduced a 3ms delay for
each printk() which only showed any noticeable delay with the "SysRq t"
packet.
Part of having the console stable requires that usb sysrq handler get
executed in a tasklet. The hcd device lock is always held while the
driver call backs are executed. The means you cannot get the sysrq
printk's out to the usb console device after the in_flight urb queue
is filled.
Thanks,
Jason.
---
The following changes since commit 57d54889cd00db2752994b389ba714138652e60c:
Linus Torvalds (1):
Linux 2.6.34-rc1
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb.git for_gregkh
Jason Wessel (6):
tty_port,usb-console: Fix usb serial console open/close regression
usb-serial: Use tty_port version of console instead of the usb_serial_port version
usb-console: pass baud from console to the initial tty open
usb-serial: optimize sysrq function calls
usb-hcd,usb-console: poll hcd device to force usb console writes
usb-serialy,sysrq: Run the sysrq handler in a tasklet
drivers/char/sysrq.c | 29 ++++++++++++++++
drivers/char/tty_port.c | 2 +-
drivers/usb/core/hcd.c | 11 ++++++
drivers/usb/core/hcd.h | 1 +
drivers/usb/serial/console.c | 71 ++++++++++++++++++++++----------------
drivers/usb/serial/ftdi_sio.c | 9 +++--
drivers/usb/serial/generic.c | 28 +---------------
drivers/usb/serial/pl2303.c | 8 +++--
drivers/usb/serial/usb-serial.c | 4 +-
drivers/usb/serial/usb_debug.c | 2 +-
include/linux/sysrq.h | 4 ++
include/linux/tty.h | 1 +
include/linux/usb/serial.h | 36 ++++++++++++++++----
13 files changed, 131 insertions(+), 75 deletions(-)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/6] tty_port,usb-console: Fix usb serial console open/close regression
2010-03-09 6:29 [PATCH 0/6] usb console improvements series Jason Wessel
@ 2010-03-09 6:29 ` Jason Wessel
2010-03-09 6:29 ` [PATCH 2/6] usb-serial: Use tty_port version of console instead of the usb_serial_port version Jason Wessel
2010-03-16 20:30 ` [PATCH 0/6] usb console improvements series Greg KH
1 sibling, 1 reply; 12+ messages in thread
From: Jason Wessel @ 2010-03-09 6:29 UTC (permalink / raw)
To: gregkh
Cc: linux-usb, Alan Stern, linux-kernel, Jason Wessel, Alan Cox,
Oliver Neukum, Andrew Morton
Commit e1108a63e10d344284011cccc06328b2cd3e5da3 ("usb_serial: Use the
shutdown() operation") breaks the ability to use a usb console
starting in 2.6.33. This was observed when using
console=ttyUSB0,115200 as a boot argument with an FTDI device. The
error is:
ftdi_sio ttyUSB0: ftdi_submit_read_urb - failed submitting read urb, error -22
The handling of the ASYNCB_INITIALIZED changed in 2.6.32 such that in
tty_port_shutdown() it always clears the flag if it is set. The fix
is to add a variable to the tty_port struct to indicate when the tty
port is a console.
CC: Greg Kroah-Hartman <gregkh@suse.de>
CC: Alan Cox <alan@linux.intel.com>
CC: Alan Stern <stern@rowland.harvard.edu>
CC: Oliver Neukum <oliver@neukum.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: linux-usb@vger.kernel.org
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
---
drivers/char/tty_port.c | 2 +-
drivers/usb/serial/console.c | 1 +
include/linux/tty.h | 1 +
3 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index be492dd..a3bd1d0 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -119,7 +119,7 @@ EXPORT_SYMBOL(tty_port_tty_set);
static void tty_port_shutdown(struct tty_port *port)
{
mutex_lock(&port->mutex);
- if (port->ops->shutdown &&
+ if (port->ops->shutdown && !port->console &&
test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
port->ops->shutdown(port);
mutex_unlock(&port->mutex);
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index b22ac32..f347da2 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -181,6 +181,7 @@ static int usb_console_setup(struct console *co, char *options)
/* The console is special in terms of closing the device so
* indicate this port is now acting as a system console. */
port->console = 1;
+ port->port.console = 1;
mutex_unlock(&serial->disc_mutex);
return retval;
diff --git a/include/linux/tty.h b/include/linux/tty.h
index d96e588..a42d7a6 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -223,6 +223,7 @@ struct tty_port {
wait_queue_head_t close_wait; /* Close waiters */
wait_queue_head_t delta_msr_wait; /* Modem status change */
unsigned long flags; /* TTY flags ASY_*/
+ unsigned char console:1; /* port is a console */
struct mutex mutex; /* Locking */
struct mutex buf_mutex; /* Buffer alloc lock */
unsigned char *xmit_buf; /* Optional buffer */
--
1.6.3.1.9.g95405b
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/6] usb-serial: Use tty_port version of console instead of the usb_serial_port version
2010-03-09 6:29 ` [PATCH 1/6] tty_port,usb-console: Fix usb serial console open/close regression Jason Wessel
@ 2010-03-09 6:29 ` Jason Wessel
2010-03-09 6:29 ` [PATCH 3/6] usb-console: pass baud from console to the initial tty open Jason Wessel
0 siblings, 1 reply; 12+ messages in thread
From: Jason Wessel @ 2010-03-09 6:29 UTC (permalink / raw)
To: gregkh
Cc: linux-usb, Alan Stern, linux-kernel, Jason Wessel, Alan Cox,
Oliver Neukum, Andrew Morton
Replace all instances of using the console variable in struct
usb_serial_port with the struct tty_port version.
CC: Greg Kroah-Hartman <gregkh@suse.de>
CC: Alan Cox <alan@linux.intel.com>
CC: Alan Stern <stern@rowland.harvard.edu>
CC: Oliver Neukum <oliver@neukum.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: linux-usb@vger.kernel.org
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
---
drivers/usb/serial/console.c | 5 ++---
drivers/usb/serial/ftdi_sio.c | 2 +-
drivers/usb/serial/generic.c | 4 ++--
drivers/usb/serial/pl2303.c | 2 +-
drivers/usb/serial/usb-serial.c | 4 ++--
include/linux/usb/serial.h | 2 --
6 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index f347da2..4ea64fe 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -180,7 +180,6 @@ static int usb_console_setup(struct console *co, char *options)
--port->port.count;
/* The console is special in terms of closing the device so
* indicate this port is now acting as a system console. */
- port->console = 1;
port->port.console = 1;
mutex_unlock(&serial->disc_mutex);
@@ -217,7 +216,7 @@ static void usb_console_write(struct console *co,
dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
- if (!port->console) {
+ if (!port->port.console) {
dbg("%s - port not opened", __func__);
return;
}
@@ -313,7 +312,7 @@ void usb_serial_console_exit(void)
{
if (usbcons_info.port) {
unregister_console(&usbcons);
- usbcons_info.port->console = 0;
+ usbcons_info.port->port.console = 0;
usbcons_info.port = NULL;
}
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 6af0dfa..95ec748 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -2073,7 +2073,7 @@ static int ftdi_process_packet(struct tty_struct *tty,
return 0; /* status only */
ch = packet + 2;
- if (!(port->console && port->sysrq) && flag == TTY_NORMAL)
+ if (!(port->port.console && port->sysrq) && flag == TTY_NORMAL)
tty_insert_flip_string(tty, ch, len);
else {
for (i = 0; i < len; i++, ch++) {
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 89fac36..4dea9d7 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -437,7 +437,7 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
/* The per character mucking around with sysrq path it too slow for
stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases
where the USB serial is not a console anyway */
- if (!port->console || !port->sysrq)
+ if (!port->port.console || !port->sysrq)
tty_insert_flip_string(tty, ch, urb->actual_length);
else {
/* Push data to tty */
@@ -556,7 +556,7 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
int usb_serial_handle_sysrq_char(struct tty_struct *tty,
struct usb_serial_port *port, unsigned int ch)
{
- if (port->sysrq && port->console) {
+ if (port->sysrq && port->port.console) {
if (ch && time_before(jiffies, port->sysrq)) {
handle_sysrq(ch, tty);
port->sysrq = 0;
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 73d5f34..1891cfb 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -1056,7 +1056,7 @@ static void pl2303_push_data(struct tty_struct *tty,
if (line_status & UART_OVERRUN_ERROR)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- if (tty_flag == TTY_NORMAL && !(port->console && port->sysrq))
+ if (tty_flag == TTY_NORMAL && !(port->port.console && port->sysrq))
tty_insert_flip_string(tty, data, urb->actual_length);
else {
int i;
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 3873660..f3f6517 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -289,7 +289,7 @@ static void serial_down(struct tty_port *tport)
* The console is magical. Do not hang up the console hardware
* or there will be tears.
*/
- if (port->console)
+ if (port->port.console)
return;
if (drv->close)
drv->close(port);
@@ -328,7 +328,7 @@ static void serial_cleanup(struct tty_struct *tty)
/* The console is magical. Do not hang up the console hardware
* or there will be tears.
*/
- if (port->console)
+ if (port->port.console)
return;
dbg("%s - port %d", __func__, port->number);
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 0a458b8..b7682fe 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -66,7 +66,6 @@ enum port_dev_state {
* @work: work queue entry for the line discipline waking up.
* @throttled: nonzero if the read urb is inactive to throttle the device
* @throttle_req: nonzero if the tty wants to throttle us
- * @console: attached usb serial console
* @dev: pointer to the serial device
*
* This structure is used by the usb-serial core and drivers for the specific
@@ -106,7 +105,6 @@ struct usb_serial_port {
struct work_struct work;
char throttled;
char throttle_req;
- char console;
unsigned long sysrq; /* sysrq timeout */
struct device dev;
enum port_dev_state dev_state;
--
1.6.3.1.9.g95405b
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/6] usb-console: pass baud from console to the initial tty open
2010-03-09 6:29 ` [PATCH 2/6] usb-serial: Use tty_port version of console instead of the usb_serial_port version Jason Wessel
@ 2010-03-09 6:29 ` Jason Wessel
2010-03-09 6:29 ` [PATCH 4/6] usb-serial: optimize sysrq function calls Jason Wessel
0 siblings, 1 reply; 12+ messages in thread
From: Jason Wessel @ 2010-03-09 6:29 UTC (permalink / raw)
To: gregkh; +Cc: linux-usb, Alan Stern, linux-kernel, Jason Wessel, Alan Cox
The usb console code has had a long standing problem of not being able
to pass the baud rate from the kernel argument console=ttyUSB0,BAUD
down to the initial tty open, unless you were willing to settle for
9600 baud.
The solution is to directly use tty_init_termios() in
usb_console_setup() as this will preserve any changes to the initial
termios setting on future opens.
CC: Greg Kroah-Hartman <gregkh@suse.de>
CC: Alan Cox <alan@linux.intel.com>
CC: Alan Stern <stern@rowland.harvard.edu>
CC: linux-usb@vger.kernel.org
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
---
drivers/usb/serial/console.c | 22 ++++++++++------------
1 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 4ea64fe..1ee6b2a 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -66,7 +66,7 @@ static int usb_console_setup(struct console *co, char *options)
struct usb_serial_port *port;
int retval;
struct tty_struct *tty = NULL;
- struct ktermios *termios = NULL, dummy;
+ struct ktermios dummy;
dbg("%s", __func__);
@@ -141,15 +141,14 @@ static int usb_console_setup(struct console *co, char *options)
goto reset_open_count;
}
kref_init(&tty->kref);
- termios = kzalloc(sizeof(*termios), GFP_KERNEL);
- if (!termios) {
+ tty_port_tty_set(&port->port, tty);
+ tty->driver = usb_serial_tty_driver;
+ tty->index = co->index;
+ if (tty_init_termios(tty)) {
retval = -ENOMEM;
err("no more memory");
goto free_tty;
}
- memset(&dummy, 0, sizeof(struct ktermios));
- tty->termios = termios;
- tty_port_tty_set(&port->port, tty);
}
/* only call the device specific open if this
@@ -161,16 +160,16 @@ static int usb_console_setup(struct console *co, char *options)
if (retval) {
err("could not open USB console port");
- goto free_termios;
+ goto fail;
}
if (serial->type->set_termios) {
- termios->c_cflag = cflag;
- tty_termios_encode_baud_rate(termios, baud, baud);
+ tty->termios->c_cflag = cflag;
+ tty_termios_encode_baud_rate(tty->termios, baud, baud);
+ memset(&dummy, 0, sizeof(struct ktermios));
serial->type->set_termios(tty, port, &dummy);
tty_port_tty_set(&port->port, NULL);
- kfree(termios);
kfree(tty);
}
set_bit(ASYNCB_INITIALIZED, &port->port.flags);
@@ -185,8 +184,7 @@ static int usb_console_setup(struct console *co, char *options)
mutex_unlock(&serial->disc_mutex);
return retval;
- free_termios:
- kfree(termios);
+ fail:
tty_port_tty_set(&port->port, NULL);
free_tty:
kfree(tty);
--
1.6.3.1.9.g95405b
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/6] usb-serial: optimize sysrq function calls
2010-03-09 6:29 ` [PATCH 3/6] usb-console: pass baud from console to the initial tty open Jason Wessel
@ 2010-03-09 6:29 ` Jason Wessel
2010-03-09 6:29 ` [PATCH 5/6] usb-hcd,usb-console: poll hcd device to force usb console writes Jason Wessel
2010-03-09 15:14 ` [PATCH 4/6] usb-serial: optimize sysrq function calls Alan Stern
0 siblings, 2 replies; 12+ messages in thread
From: Jason Wessel @ 2010-03-09 6:29 UTC (permalink / raw)
To: gregkh
Cc: linux-usb, Alan Stern, linux-kernel, Jason Wessel, Alan Cox,
Oliver Neukum
There is no need to have external function calls for the sysrq
functions. The compiler can inline the sysrq calls such that they are
entirely a NOP if CONFIG_MAGIC_SYSRQ is not set.
CC: Greg Kroah-Hartman <gregkh@suse.de>
CC: Alan Cox <alan@linux.intel.com>
CC: Alan Stern <stern@rowland.harvard.edu>
CC: Oliver Neukum <oliver@neukum.org>
CC: linux-usb@vger.kernel.org
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
---
drivers/usb/serial/generic.c | 26 --------------------------
include/linux/usb/serial.h | 34 +++++++++++++++++++++++++++++-----
2 files changed, 29 insertions(+), 31 deletions(-)
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 4dea9d7..0cdfccb 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -553,32 +553,6 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
}
}
-int usb_serial_handle_sysrq_char(struct tty_struct *tty,
- struct usb_serial_port *port, unsigned int ch)
-{
- if (port->sysrq && port->port.console) {
- if (ch && time_before(jiffies, port->sysrq)) {
- handle_sysrq(ch, tty);
- port->sysrq = 0;
- return 1;
- }
- port->sysrq = 0;
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_serial_handle_sysrq_char);
-
-int usb_serial_handle_break(struct usb_serial_port *port)
-{
- if (!port->sysrq) {
- port->sysrq = jiffies + HZ*5;
- return 1;
- }
- port->sysrq = 0;
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_serial_handle_break);
-
int usb_serial_generic_resume(struct usb_serial *serial)
{
struct usb_serial_port *port;
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index b7682fe..60f8422 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -318,11 +318,6 @@ extern int usb_serial_generic_register(int debug);
extern void usb_serial_generic_deregister(void);
extern void usb_serial_generic_resubmit_read_urb(struct usb_serial_port *port,
gfp_t mem_flags);
-extern int usb_serial_handle_sysrq_char(struct tty_struct *tty,
- struct usb_serial_port *port,
- unsigned int ch);
-extern int usb_serial_handle_break(struct usb_serial_port *port);
-
extern int usb_serial_bus_register(struct usb_serial_driver *device);
extern void usb_serial_bus_deregister(struct usb_serial_driver *device);
@@ -331,6 +326,35 @@ extern struct usb_serial_driver usb_serial_generic_device;
extern struct bus_type usb_serial_bus_type;
extern struct tty_driver *usb_serial_tty_driver;
+static inline int usb_serial_handle_sysrq_char(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ unsigned int ch)
+{
+#ifdef CONFIG_MAGIC_SYSRQ
+ if (port->sysrq && port->port.console) {
+ if (ch && time_before(jiffies, port->sysrq)) {
+ handle_sysrq(ch, tty);
+ port->sysrq = 0;
+ return 1;
+ }
+ port->sysrq = 0;
+ }
+#endif /* CONFIG_MAGIC_SYSRQ */
+ return 0;
+}
+
+static inline int usb_serial_handle_break(struct usb_serial_port *port)
+{
+#ifdef CONFIG_MAGIC_SYSRQ
+ if (!port->sysrq) {
+ port->sysrq = jiffies + HZ*5;
+ return 1;
+ }
+ port->sysrq = 0;
+#endif /* CONFIG_MAGIC_SYSRQ */
+ return 0;
+}
+
static inline void usb_serial_debug_data(int debug,
struct device *dev,
const char *function, int size,
--
1.6.3.1.9.g95405b
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 5/6] usb-hcd,usb-console: poll hcd device to force usb console writes
2010-03-09 6:29 ` [PATCH 4/6] usb-serial: optimize sysrq function calls Jason Wessel
@ 2010-03-09 6:29 ` Jason Wessel
2010-03-09 6:29 ` [PATCH 6/6] usb-serialy,sysrq: Run the sysrq handler in a tasklet Jason Wessel
2010-03-09 15:08 ` [PATCH 5/6] usb-hcd,usb-console: poll hcd device to force usb console writes Alan Stern
2010-03-09 15:14 ` [PATCH 4/6] usb-serial: optimize sysrq function calls Alan Stern
1 sibling, 2 replies; 12+ messages in thread
From: Jason Wessel @ 2010-03-09 6:29 UTC (permalink / raw)
To: gregkh
Cc: linux-usb, Alan Stern, linux-kernel, Jason Wessel, Alan Cox,
Oliver Neukum
This patch tries to solve the problem that data is lost because there
are too many outstanding transmit urb's while trying to execute
printk's to a console. The same is true if you try something like
"echo t > /proc/sysrq-trigger".
This patch takes the route of forcibly polling the hcd device to drain
the urb queue in order to initiate the bulk write call backs. This
only happens if the device is a usb serial console device that sets
the max_in_flight_urbs to a non zero value in the serial device
structure.
A few millisecond penalty will get incurred to allow the hcd controller
to complete a write urb, else the console data is thrown away.
The max_in_flight_urbs was reduced in the usb_debug driver because it
is highly desired to push things out to the console in a timely
fashion and there is no need to have a queue that large for the
interrupt driven mode of operation when used through the tty
interface.
CC: Greg Kroah-Hartman <gregkh@suse.de>
CC: Alan Cox <alan@linux.intel.com>
CC: Alan Stern <stern@rowland.harvard.edu>
CC: Oliver Neukum <oliver@neukum.org>
CC: linux-usb@vger.kernel.org
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
---
drivers/usb/core/hcd.c | 11 ++++++++++
drivers/usb/core/hcd.h | 1 +
drivers/usb/serial/console.c | 43 ++++++++++++++++++++++++++--------------
drivers/usb/serial/ftdi_sio.c | 7 +++--
drivers/usb/serial/pl2303.c | 6 +++-
drivers/usb/serial/usb_debug.c | 2 +-
6 files changed, 49 insertions(+), 21 deletions(-)
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 2f8cedd..3484446 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1973,6 +1973,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
local_irq_restore(flags);
return rc;
}
+EXPORT_SYMBOL_GPL(usb_hcd_irq);
/*-------------------------------------------------------------------------*/
@@ -2271,6 +2272,16 @@ usb_hcd_platform_shutdown(struct platform_device* dev)
}
EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown);
+void
+usb_hcd_poll_irq(struct usb_device *udev)
+{
+ struct usb_hcd *hcd;
+
+ hcd = bus_to_hcd(udev->bus);
+ usb_hcd_irq(0, hcd);
+}
+EXPORT_SYMBOL_GPL(usb_hcd_poll_irq);
+
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index a3cdb09..703f407 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -318,6 +318,7 @@ extern void usb_put_hcd(struct usb_hcd *hcd);
extern int usb_add_hcd(struct usb_hcd *hcd,
unsigned int irqnum, unsigned long irqflags);
extern void usb_remove_hcd(struct usb_hcd *hcd);
+extern void usb_hcd_poll_irq(struct usb_device *udev);
struct platform_device;
extern void usb_hcd_platform_shutdown(struct platform_device *dev);
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 1ee6b2a..3786d75 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -19,6 +19,7 @@
#include <linux/serial.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#include "../core/hcd.h"
static int debug;
@@ -197,13 +198,37 @@ static int usb_console_setup(struct console *co, char *options)
return retval;
}
+static void usb_do_console_write(struct usb_serial *serial,
+ struct usb_serial_port *port,
+ const char *buf, unsigned count)
+{
+ int retval;
+ int loops = 100;
+try_again:
+ /* pass on to the driver specific version of this function if
+ it is available */
+ if (serial->type->write)
+ retval = serial->type->write(NULL, port, buf, count);
+ else
+ retval = usb_serial_generic_write(NULL, port, buf, count);
+ if (retval < count && retval >= 0 &&
+ serial->type->max_in_flight_urbs != 0 && loops--) {
+ /* poll the hcd device because the queue is full */
+ count -= retval;
+ buf += retval;
+ udelay(100);
+ usb_hcd_poll_irq(serial->dev);
+ goto try_again;
+ }
+ dbg("%s - return value : %d", __func__, retval);
+}
+
static void usb_console_write(struct console *co,
const char *buf, unsigned count)
{
static struct usbcons_info *info = &usbcons_info;
struct usb_serial_port *port = info->port;
struct usb_serial *serial;
- int retval = -ENODEV;
if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
return;
@@ -230,23 +255,11 @@ static void usb_console_write(struct console *co,
break;
}
}
- /* pass on to the driver specific version of this function if
- it is available */
- if (serial->type->write)
- retval = serial->type->write(NULL, port, buf, i);
- else
- retval = usb_serial_generic_write(NULL, port, buf, i);
- dbg("%s - return value : %d", __func__, retval);
+ usb_do_console_write(serial, port, buf, i);
if (lf) {
/* append CR after LF */
unsigned char cr = 13;
- if (serial->type->write)
- retval = serial->type->write(NULL,
- port, &cr, 1);
- else
- retval = usb_serial_generic_write(NULL,
- port, &cr, 1);
- dbg("%s - return value : %d", __func__, retval);
+ usb_do_console_write(serial, port, &cr, 1);
}
buf += i;
count -= i;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 95ec748..c7f559c 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -53,6 +53,9 @@
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>, Andreas Mohr"
#define DRIVER_DESC "USB FTDI Serial Converters Driver"
+/* number of outstanding urbs to prevent userspace DoS from happening */
+#define URB_UPPER_LIMIT 42
+
static int debug;
static __u16 vendor = FTDI_VID;
static __u16 product;
@@ -838,6 +841,7 @@ static struct usb_serial_driver ftdi_sio_device = {
.ioctl = ftdi_ioctl,
.set_termios = ftdi_set_termios,
.break_ctl = ftdi_break_ctl,
+ .max_in_flight_urbs = URB_UPPER_LIMIT,
};
@@ -848,9 +852,6 @@ static struct usb_serial_driver ftdi_sio_device = {
#define HIGH 1
#define LOW 0
-/* number of outstanding urbs to prevent userspace DoS from happening */
-#define URB_UPPER_LIMIT 42
-
/*
* ***************************************************************************
* Utility functions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 1891cfb..2615fe1 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -453,8 +453,9 @@ static void pl2303_send(struct usb_serial_port *port)
port->write_urb->transfer_buffer_length = count;
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - failed submitting write urb,"
- " error %d\n", __func__, result);
+ if (!(port->port.console))
+ dev_err(&port->dev, "%s - failed submitting write urb,"
+ " error %d\n", __func__, result);
priv->write_urb_in_use = 0;
/* TODO: reschedule pl2303_send */
}
@@ -1185,6 +1186,7 @@ static struct usb_serial_driver pl2303_device = {
.chars_in_buffer = pl2303_chars_in_buffer,
.attach = pl2303_startup,
.release = pl2303_release,
+ .max_in_flight_urbs = -1,
};
static int __init pl2303_init(void)
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
index 252cc2d..4a04552 100644
--- a/drivers/usb/serial/usb_debug.c
+++ b/drivers/usb/serial/usb_debug.c
@@ -15,7 +15,7 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#define URB_DEBUG_MAX_IN_FLIGHT_URBS 4000
+#define URB_DEBUG_MAX_IN_FLIGHT_URBS 42
#define USB_DEBUG_MAX_PACKET_SIZE 8
#define USB_DEBUG_BRK_SIZE 8
static char USB_DEBUG_BRK[USB_DEBUG_BRK_SIZE] = {
--
1.6.3.1.9.g95405b
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 6/6] usb-serialy,sysrq: Run the sysrq handler in a tasklet
2010-03-09 6:29 ` [PATCH 5/6] usb-hcd,usb-console: poll hcd device to force usb console writes Jason Wessel
@ 2010-03-09 6:29 ` Jason Wessel
2010-03-09 15:08 ` [PATCH 5/6] usb-hcd,usb-console: poll hcd device to force usb console writes Alan Stern
1 sibling, 0 replies; 12+ messages in thread
From: Jason Wessel @ 2010-03-09 6:29 UTC (permalink / raw)
To: gregkh; +Cc: linux-usb, Alan Stern, linux-kernel, Jason Wessel, Alan Cox
If a sysrq is processed on the while holding the usb hcd lock, it is
impossible to drain the queue of urbs via the polling interface and
all the printk output is lost.
Using a tasklet to schedule the sysrq allows the hcd device lock to
free up, and you can issue a sysrq-t to get the task list.
CC: Greg Kroah-Hartman <gregkh@suse.de>
CC: Alan Cox <alan@linux.intel.com>
CC: Alan Stern <stern@rowland.harvard.edu>
CC: linux-usb@vger.kernel.org
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
---
drivers/char/sysrq.c | 29 +++++++++++++++++++++++++++++
include/linux/sysrq.h | 4 ++++
include/linux/usb/serial.h | 2 +-
3 files changed, 34 insertions(+), 1 deletions(-)
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 1ae2de7..ad62e53 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -584,6 +584,35 @@ int unregister_sysrq_key(int key, struct sysrq_key_op *op_p)
}
EXPORT_SYMBOL(unregister_sysrq_key);
+/* The sysrq tasklet is used only in the rare case that an
+ * input/output character device processes a sysrq in its input
+ * routine while holding a lock required for the output routine for
+ * the console device.
+ */
+static struct sysrq_tasklet_data {
+ struct tty_struct *tty;
+ unsigned int key;
+ int pending;
+} priv_sysrq_data;
+
+static void sysrq_task(unsigned long args)
+{
+ handle_sysrq(priv_sysrq_data.key, priv_sysrq_data.tty);
+ priv_sysrq_data.pending = 0;
+}
+static DECLARE_TASKLET(sysrq_tasklet, sysrq_task, 0);
+
+void handle_sysrq_tasklet(int key, struct tty_struct *tty)
+{
+ if (priv_sysrq_data.pending)
+ return;
+ priv_sysrq_data.pending = 1;
+ priv_sysrq_data.key = key;
+ priv_sysrq_data.tty = tty;
+ tasklet_schedule(&sysrq_tasklet);
+}
+EXPORT_SYMBOL(handle_sysrq_tasklet);
+
#ifdef CONFIG_PROC_FS
/*
* writing 'C' to /proc/sysrq-trigger is like sysrq-C
diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
index 99adcdc..0ff5fb4 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
@@ -52,6 +52,7 @@ extern int __sysrq_enabled;
*/
void handle_sysrq(int key, struct tty_struct *tty);
+void handle_sysrq_tasklet(int key, struct tty_struct *tty);
void __handle_sysrq(int key, struct tty_struct *tty, int check_mask);
int register_sysrq_key(int key, struct sysrq_key_op *op);
int unregister_sysrq_key(int key, struct sysrq_key_op *op);
@@ -70,6 +71,9 @@ static inline int __reterr(void)
static inline void handle_sysrq(int key, struct tty_struct *tty)
{
}
+static inline void handle_sysrq_tasklet(int key, struct tty_struct *tty)
+{
+}
#define register_sysrq_key(ig,nore) __reterr()
#define unregister_sysrq_key(ig,nore) __reterr()
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 60f8422..ae8887e 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -333,7 +333,7 @@ static inline int usb_serial_handle_sysrq_char(struct tty_struct *tty,
#ifdef CONFIG_MAGIC_SYSRQ
if (port->sysrq && port->port.console) {
if (ch && time_before(jiffies, port->sysrq)) {
- handle_sysrq(ch, tty);
+ handle_sysrq_tasklet(ch, tty);
port->sysrq = 0;
return 1;
}
--
1.6.3.1.9.g95405b
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 5/6] usb-hcd,usb-console: poll hcd device to force usb console writes
2010-03-09 6:29 ` [PATCH 5/6] usb-hcd,usb-console: poll hcd device to force usb console writes Jason Wessel
2010-03-09 6:29 ` [PATCH 6/6] usb-serialy,sysrq: Run the sysrq handler in a tasklet Jason Wessel
@ 2010-03-09 15:08 ` Alan Stern
2010-03-10 22:27 ` Jason Wessel
1 sibling, 1 reply; 12+ messages in thread
From: Alan Stern @ 2010-03-09 15:08 UTC (permalink / raw)
To: Jason Wessel; +Cc: gregkh, linux-usb, linux-kernel, Alan Cox, Oliver Neukum
On Tue, 9 Mar 2010, Jason Wessel wrote:
> This patch tries to solve the problem that data is lost because there
> are too many outstanding transmit urb's while trying to execute
> printk's to a console. The same is true if you try something like
> "echo t > /proc/sysrq-trigger".
>
> This patch takes the route of forcibly polling the hcd device to drain
> the urb queue in order to initiate the bulk write call backs. This
> only happens if the device is a usb serial console device that sets
> the max_in_flight_urbs to a non zero value in the serial device
> structure.
>
> A few millisecond penalty will get incurred to allow the hcd controller
> to complete a write urb, else the console data is thrown away.
>
> The max_in_flight_urbs was reduced in the usb_debug driver because it
> is highly desired to push things out to the console in a timely
> fashion and there is no need to have a queue that large for the
> interrupt driven mode of operation when used through the tty
> interface.
> --- a/drivers/usb/core/hcd.c
> +++ b/drivers/usb/core/hcd.c
> @@ -1973,6 +1973,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
> local_irq_restore(flags);
> return rc;
> }
> +EXPORT_SYMBOL_GPL(usb_hcd_irq);
Is there any reason for EXPORTing this? It doesn't get used anywhere
else.
> index a3cdb09..703f407 100644
> --- a/drivers/usb/core/hcd.h
> +++ b/drivers/usb/core/hcd.h
> @@ -318,6 +318,7 @@ extern void usb_put_hcd(struct usb_hcd *hcd);
> extern int usb_add_hcd(struct usb_hcd *hcd,
> unsigned int irqnum, unsigned long irqflags);
> extern void usb_remove_hcd(struct usb_hcd *hcd);
> +extern void usb_hcd_poll_irq(struct usb_device *udev);
>
> struct platform_device;
> extern void usb_hcd_platform_shutdown(struct platform_device *dev);
It might be better to put this in a "public" header file; that is,
something under include/linux/usb or include/linux/usb.h. You could
even take the "_hcd" part out of the name, because the interface uses
only a struct usb_device, not a struct usb_hcd.
Alan Stern
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 4/6] usb-serial: optimize sysrq function calls
2010-03-09 6:29 ` [PATCH 4/6] usb-serial: optimize sysrq function calls Jason Wessel
2010-03-09 6:29 ` [PATCH 5/6] usb-hcd,usb-console: poll hcd device to force usb console writes Jason Wessel
@ 2010-03-09 15:14 ` Alan Stern
2010-03-10 22:18 ` Jason Wessel
1 sibling, 1 reply; 12+ messages in thread
From: Alan Stern @ 2010-03-09 15:14 UTC (permalink / raw)
To: Jason Wessel; +Cc: gregkh, linux-usb, linux-kernel, Alan Cox, Oliver Neukum
On Tue, 9 Mar 2010, Jason Wessel wrote:
> There is no need to have external function calls for the sysrq
> functions. The compiler can inline the sysrq calls such that they are
> entirely a NOP if CONFIG_MAGIC_SYSRQ is not set.
This is not the best way to do what you want. Keep
usb_serial_handle_sysrq_char() and usb_serial_handle_break() as
out-of-line routines in generic.c, but make them conditional on
CONFIG_MAGIC_SYSRQ. Then in the header file, depending on whether or
not CONFIG_MAGIC_SYSRQ is defined, either put the usual extern function
declarations or else put do-nothing inline definitions.
The advantage of keeping the functions out-of-line is the reduced
amount of code space (since the bodies aren't replicated every place
they get used). This way you keep that advantage while still getting
the NOP implementation if CONFIG_MAGIC_SYSRQ isn't set.
Alan Stern
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 4/6] usb-serial: optimize sysrq function calls
2010-03-09 15:14 ` [PATCH 4/6] usb-serial: optimize sysrq function calls Alan Stern
@ 2010-03-10 22:18 ` Jason Wessel
0 siblings, 0 replies; 12+ messages in thread
From: Jason Wessel @ 2010-03-10 22:18 UTC (permalink / raw)
To: Alan Stern; +Cc: gregkh, linux-usb, linux-kernel, Alan Cox, Oliver Neukum
Alan Stern wrote:
> On Tue, 9 Mar 2010, Jason Wessel wrote:
>
>
>> There is no need to have external function calls for the sysrq
>> functions. The compiler can inline the sysrq calls such that they are
>> entirely a NOP if CONFIG_MAGIC_SYSRQ is not set.
>>
>
> This is not the best way to do what you want. Keep
> usb_serial_handle_sysrq_char() and usb_serial_handle_break() as
> out-of-line routines in generic.c, but make them conditional on
> CONFIG_MAGIC_SYSRQ. Then in the header file, depending on whether or
> not CONFIG_MAGIC_SYSRQ is defined, either put the usual extern function
> declarations or else put do-nothing inline definitions.
>
> The advantage of keeping the functions out-of-line is the reduced
> amount of code space (since the bodies aren't replicated every place
> they get used). This way you keep that advantage while still getting
> the NOP implementation if CONFIG_MAGIC_SYSRQ isn't set.
>
It is probably fine to just drop this patch entirely then.
I had originally made the change to keep it similar to the uart based
serial drivers where the definitions are inlined.
Jason.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 5/6] usb-hcd,usb-console: poll hcd device to force usb console writes
2010-03-09 15:08 ` [PATCH 5/6] usb-hcd,usb-console: poll hcd device to force usb console writes Alan Stern
@ 2010-03-10 22:27 ` Jason Wessel
0 siblings, 0 replies; 12+ messages in thread
From: Jason Wessel @ 2010-03-10 22:27 UTC (permalink / raw)
To: Alan Stern; +Cc: gregkh, linux-usb, linux-kernel, Alan Cox, Oliver Neukum
Alan Stern wrote:
> On Tue, 9 Mar 2010, Jason Wessel wrote:
>
>> This patch tries to solve the problem that data is lost because there
>> are too many outstanding transmit urb's while trying to execute
>> printk's to a console. The same is true if you try something like
>> "echo t > /proc/sysrq-trigger".
>>
>> This patch takes the route of forcibly polling the hcd device to drain
>> the urb queue in order to initiate the bulk write call backs. This
>> only happens if the device is a usb serial console device that sets
>> the max_in_flight_urbs to a non zero value in the serial device
>> structure.
>>
>> A few millisecond penalty will get incurred to allow the hcd controller
>> to complete a write urb, else the console data is thrown away.
>>
>> The max_in_flight_urbs was reduced in the usb_debug driver because it
>> is highly desired to push things out to the console in a timely
>> fashion and there is no need to have a queue that large for the
>> interrupt driven mode of operation when used through the tty
>> interface.
>
>> --- a/drivers/usb/core/hcd.c
>> +++ b/drivers/usb/core/hcd.c
>> @@ -1973,6 +1973,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
>> local_irq_restore(flags);
>> return rc;
>> }
>> +EXPORT_SYMBOL_GPL(usb_hcd_irq);
>
> Is there any reason for EXPORTing this? It doesn't get used anywhere
> else.
>
Certainly not anymore. The previous iteration of this code used this
function. Thanks for catching that.
>> index a3cdb09..703f407 100644
>> --- a/drivers/usb/core/hcd.h
>> +++ b/drivers/usb/core/hcd.h
>> @@ -318,6 +318,7 @@ extern void usb_put_hcd(struct usb_hcd *hcd);
>> extern int usb_add_hcd(struct usb_hcd *hcd,
>> unsigned int irqnum, unsigned long irqflags);
>> extern void usb_remove_hcd(struct usb_hcd *hcd);
>> +extern void usb_hcd_poll_irq(struct usb_device *udev);
>>
>> struct platform_device;
>> extern void usb_hcd_platform_shutdown(struct platform_device *dev);
>
> It might be better to put this in a "public" header file; that is,
> something under include/linux/usb or include/linux/usb.h. You could
> even take the "_hcd" part out of the name, because the interface uses
> only a struct usb_device, not a struct usb_hcd.
If this is what you prefer, I have no problem with it. I'll post a v2
of the series after some testing.
Jason.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 0/6] usb console improvements series
2010-03-09 6:29 [PATCH 0/6] usb console improvements series Jason Wessel
2010-03-09 6:29 ` [PATCH 1/6] tty_port,usb-console: Fix usb serial console open/close regression Jason Wessel
@ 2010-03-16 20:30 ` Greg KH
1 sibling, 0 replies; 12+ messages in thread
From: Greg KH @ 2010-03-16 20:30 UTC (permalink / raw)
To: Jason Wessel; +Cc: gregkh, linux-usb, Alan Stern, linux-kernel
On Tue, Mar 09, 2010 at 12:29:05AM -0600, Jason Wessel wrote:
> I aggregated and ported all usb patches I have previously posted which
> are not mainlined into a single series aimed at providing a stable usb
> console.
Hm, there was more discussion about this, care to resend what you want
to have applied?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2010-03-16 20:46 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-03-09 6:29 [PATCH 0/6] usb console improvements series Jason Wessel
2010-03-09 6:29 ` [PATCH 1/6] tty_port,usb-console: Fix usb serial console open/close regression Jason Wessel
2010-03-09 6:29 ` [PATCH 2/6] usb-serial: Use tty_port version of console instead of the usb_serial_port version Jason Wessel
2010-03-09 6:29 ` [PATCH 3/6] usb-console: pass baud from console to the initial tty open Jason Wessel
2010-03-09 6:29 ` [PATCH 4/6] usb-serial: optimize sysrq function calls Jason Wessel
2010-03-09 6:29 ` [PATCH 5/6] usb-hcd,usb-console: poll hcd device to force usb console writes Jason Wessel
2010-03-09 6:29 ` [PATCH 6/6] usb-serialy,sysrq: Run the sysrq handler in a tasklet Jason Wessel
2010-03-09 15:08 ` [PATCH 5/6] usb-hcd,usb-console: poll hcd device to force usb console writes Alan Stern
2010-03-10 22:27 ` Jason Wessel
2010-03-09 15:14 ` [PATCH 4/6] usb-serial: optimize sysrq function calls Alan Stern
2010-03-10 22:18 ` Jason Wessel
2010-03-16 20:30 ` [PATCH 0/6] usb console improvements series Greg KH
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).