On Tue, Feb 26, 2002 at 07:51:37PM +0100, Oliver Neukum wrote:
> On Tuesday 26 February 2002 18:32, Greg KH wrote:
> > On Tue, Feb 26, 2002 at 06:06:32PM +0100, Oliver Neukum wrote:
> > > Hi,
> > >
> > > it seems that serial_disconnect() can race with visor_close()
> >
> > Yup it sure can :)
> >
> > Any ideas on how to solve this race?  I can't reproduce it to test
> > different things here, but lots of different people keep reporting it.
> 
> Can't usb_serial_disconnect() take the semaphore visor_close() takes ?

Yes it could, but there would still be a small race window.  I would
have to push "down (&port->sem);" back to the serial_close() function.

Hm, that might be a good idea anyway...  I'll go make up a patch to try
that out...  Ah, here we go.

Hugo, could you try this patch out and let me know if it solves your
problem?  It's against 2.4.18 and "works for me" (tm) 

Warning, if you have any other usb-serial devices in the system, do not
use this patch, it will break them :)

thanks,

greg k-h


diff -Nru a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
--- a/drivers/usb/serial/usbserial.c    Tue Feb 26 15:02:46 2002
+++ b/drivers/usb/serial/usbserial.c    Tue Feb 26 15:02:46 2002
@@ -553,12 +553,21 @@
                return;
        }
 
+       down (&port->sem);
+
+       if (tty->driver_data == NULL) {
+               /* disconnect beat us to the punch here, so handle it gracefully */
+               goto exit;
+       }
+       
        /* pass on to the driver specific version of this function if it is available 
*/
        if (serial->type->close) {
                serial->type->close(port, filp);
        } else {
                generic_close(port, filp);
        }
+exit:
+       up (&port->sem);
 }      
 
 
@@ -1350,8 +1359,10 @@
        if (serial) {
                /* fail all future close/read/write/ioctl/etc calls */
                for (i = 0; i < serial->num_ports; ++i) {
+                       down (&serial->port[i].sem);
                        if (serial->port[i].tty != NULL)
                                serial->port[i].tty->driver_data = NULL;
+                       up (&serial->port[i].sem);
                }
 
                serial->dev = NULL;
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c        Tue Feb 26 15:02:46 2002
+++ b/drivers/usb/serial/visor.c        Tue Feb 26 15:02:46 2002
@@ -363,8 +363,6 @@
        if (!serial)
                return;
        
-       down (&port->sem);
-
        --port->open_count;
 
        if (port->open_count <= 0) {
@@ -389,7 +387,6 @@
                port->active = 0;
                port->open_count = 0;
        }
-       up (&port->sem);
 
        /* Uncomment the following line if you want to see some statistics in your 
syslog */
        /* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */




_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to