aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorDave Young <hidave.darkstar@gmail.com>2009-09-27 12:00:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-27 16:35:16 -0400
commitf278a2f7bbc2239f479eaf63d0b3ae573b1d746c (patch)
treec768ba0ccfefa0be7d9e330b3d86100e0c48472b /drivers/usb
parent569ec4cc779c8aae03a4659939d08822c9e4a242 (diff)
tty: Fix regressions caused by commit b50989dc
The following commit made console open fails while booting: commit b50989dc444599c8b21edc23536fc305f4e9b7d5 Author: Alan Cox <alan@linux.intel.com> Date: Sat Sep 19 13:13:22 2009 -0700 tty: make the kref destructor occur asynchronously Due to tty release routines run in a workqueue now, error like the following will be reported while booting: INIT open /dev/console Input/output error It also causes hibernation regression to appear as reported at http://bugzilla.kernel.org/show_bug.cgi?id=14229 The reason is that now there's latency issue with closing, but when we open a "closing not finished" tty, -EIO will be returned. Fix it as per the following Alan's suggestion: Fun but it's actually not a bug and the fix is wrong in itself as the port may be closing but not yet being destructed, in which case it seems to do the wrong thing. Opening a tty that is closing (and could be closing for long periods) is supposed to return -EIO. I suspect a better way to deal with this and keep the old console timing is to split tty->shutdown into two functions. tty->shutdown() - called synchronously just before we dump the tty onto the waitqueue for destruction tty->cleanup() - called when the destructor runs. We would then do the shutdown part which can occur in IRQ context fine, before queueing the rest of the release (from tty->magic = 0 ... the end) to occur asynchronously The USB update in -next would then need a call like if (tty->cleanup) tty->cleanup(tty); at the top of the async function and the USB shutdown to be split between shutdown and cleanup as the USB resource cleanup and final tidy cannot occur synchronously as it needs to sleep. In other words the logic becomes final kref put make object unfindable async clean it up Signed-off-by: Dave Young <hidave.darkstar@gmail.com> [ rjw: Rebased on top of 2.6.31-git, reworked the changelog. ] Signed-off-by: "Rafael J. Wysocki" <rjw@sisk.pl> [ Changed serial naming to match new rules, dropped tty_shutdown as per comments from Alan Stern - Linus ] Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/usb-serial.c14
1 files changed, 6 insertions, 8 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index ff75a3589e7e..aa6b2ae951ae 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -192,7 +192,7 @@ void usb_serial_put(struct usb_serial *serial)
192 * This is the first place a new tty gets used. Hence this is where we 192 * This is the first place a new tty gets used. Hence this is where we
193 * acquire references to the usb_serial structure and the driver module, 193 * acquire references to the usb_serial structure and the driver module,
194 * where we store a pointer to the port, and where we do an autoresume. 194 * where we store a pointer to the port, and where we do an autoresume.
195 * All these actions are reversed in serial_release(). 195 * All these actions are reversed in serial_cleanup().
196 */ 196 */
197static int serial_install(struct tty_driver *driver, struct tty_struct *tty) 197static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
198{ 198{
@@ -339,15 +339,16 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
339} 339}
340 340
341/** 341/**
342 * serial_release - free resources post close/hangup 342 * serial_cleanup - free resources post close/hangup
343 * @port: port to free up 343 * @port: port to free up
344 * 344 *
345 * Do the resource freeing and refcount dropping for the port. 345 * Do the resource freeing and refcount dropping for the port.
346 * Avoid freeing the console. 346 * Avoid freeing the console.
347 * 347 *
348 * Called when the last tty kref is dropped. 348 * Called asynchronously after the last tty kref is dropped,
349 * and the tty layer has already done the tty_shutdown(tty);
349 */ 350 */
350static void serial_release(struct tty_struct *tty) 351static void serial_cleanup(struct tty_struct *tty)
351{ 352{
352 struct usb_serial_port *port = tty->driver_data; 353 struct usb_serial_port *port = tty->driver_data;
353 struct usb_serial *serial; 354 struct usb_serial *serial;
@@ -361,9 +362,6 @@ static void serial_release(struct tty_struct *tty)
361 362
362 dbg("%s - port %d", __func__, port->number); 363 dbg("%s - port %d", __func__, port->number);
363 364
364 /* Standard shutdown processing */
365 tty_shutdown(tty);
366
367 tty->driver_data = NULL; 365 tty->driver_data = NULL;
368 366
369 serial = port->serial; 367 serial = port->serial;
@@ -1210,7 +1208,7 @@ static const struct tty_operations serial_ops = {
1210 .chars_in_buffer = serial_chars_in_buffer, 1208 .chars_in_buffer = serial_chars_in_buffer,
1211 .tiocmget = serial_tiocmget, 1209 .tiocmget = serial_tiocmget,
1212 .tiocmset = serial_tiocmset, 1210 .tiocmset = serial_tiocmset,
1213 .shutdown = serial_release, 1211 .cleanup = serial_cleanup,
1214 .install = serial_install, 1212 .install = serial_install,
1215 .proc_fops = &serial_proc_fops, 1213 .proc_fops = &serial_proc_fops,
1216}; 1214};