ChangeSet 1.1041.1.2, 2003/04/07 10:59:54-07:00, alborchers@steinerpoint.com [PATCH] USB: patch for oops in io_edgeport.c I tracked down a problem that caused an oops in io_edgeport.c. The oops is reliably reproduced by using an EdgePort USB serial port in dosemu and then exiting dosemu. When dosemu closed the port the oops would occur. (Tested in RH 7.3 2.4.18-10.) The problem was that a USB cmd callback would come in after the close with the tty struct freed, and the edge_bulk_out_cmd_callback function would do a wakeup on the tty->write_wait queue. The tty struct was gone (I checked that tty->magic was bad) and the wakeup would oops. As you did in other places in io_edgeport.c, I added a check that edge_port->open was true before using the edge_port->port->tty struct. I added a similar check in edge_bulk_out_data_callback, though I never actually saw the problem here. I notice that in 2.4.20 a check has been added to be sure that edge_port->port->tty is not null--however, this is not enough because the tty pointer is not set to null when the port is closed. An alternate solution in 2.4.20 would be to set the usb_serial_port->tty pointer to null in usbserial.c serial_close(). This seems like a good thing to do in general, since the tty struct should not be used after a close which frees it. If you would like I investigate this a bit more--it could affect other usb serial drivers and reveal some hidden bugs. drivers/usb/serial/io_edgeport.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c --- a/drivers/usb/serial/io_edgeport.c Mon Apr 7 15:11:50 2003 +++ b/drivers/usb/serial/io_edgeport.c Mon Apr 7 15:11:50 2003 @@ -25,6 +25,10 @@ * * Version history: * + * 2003_04_03 al borchers + * - fixed a bug (that shows up with dosemu) where the tty struct is + * used in a callback after it has been freed + * * 2.3 2002_03_08 greg kroah-hartman * - fixed bug when multiple devices were attached at the same time. * @@ -918,7 +922,7 @@ tty = edge_port->port->tty; - if (tty) { + if (tty && edge_port->open) { /* let the tty driver wakeup if it has a special write_wakeup function */ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { (tty->ldisc.write_wakeup)(tty); @@ -975,7 +979,7 @@ tty = edge_port->port->tty; /* tell the tty driver that something has changed */ - if (tty) + if (tty && edge_port->open) wake_up_interruptible(&tty->write_wait); /* we have completed the command */