Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=a1cd7e99b343543af2be4c8c5755e26f6bfd725a
Commit:     a1cd7e99b343543af2be4c8c5755e26f6bfd725a
Parent:     828d55c58cba6b652fd30e00c3d940cb7c523e3c
Author:     Oliver Neukum <[EMAIL PROTECTED]>
AuthorDate: Wed Jan 16 17:18:52 2008 +0100
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Fri Feb 1 14:35:03 2008 -0800

    USB: stop io performed by mos7720 upon close()
    
    This fixes a problem where the mos7720 driver will make io to a device from
    which it has been logically disconnected. It does so by introducing a flag 
by
    which the generic usb serial code can signal the subdrivers their
    disconnection and appropriate locking.
    
    Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/serial/mos7720.c    |   33 ++++++++++++++++++---------------
 drivers/usb/serial/usb-serial.c |   28 ++++++++++++++--------------
 include/linux/usb/serial.h      |    2 ++
 3 files changed, 34 insertions(+), 29 deletions(-)

diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 725991f..40f3a01 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -564,22 +564,25 @@ static void mos7720_close(struct usb_serial_port *port, 
struct file *filp)
        }
 
        /* While closing port, shutdown all bulk read, write  *
-        * and interrupt read if they exists                  */
-       if (serial->dev) {
-               dbg("Shutdown bulk write");
-               usb_kill_urb(port->write_urb);
-               dbg("Shutdown bulk read");
-               usb_kill_urb(port->read_urb);
+        * and interrupt read if they exists, otherwise nop   */
+       dbg("Shutdown bulk write");
+       usb_kill_urb(port->write_urb);
+       dbg("Shutdown bulk read");
+       usb_kill_urb(port->read_urb);
+
+       mutex_lock(&serial->disc_mutex);
+       /* these commands must not be issued if the device has
+        * been disconnected */
+       if (!serial->disconnected) {
+               data = 0x00;
+               send_mos_cmd(serial, MOS_WRITE, port->number - 
port->serial->minor,
+                            0x04, &data);
+
+               data = 0x00;
+               send_mos_cmd(serial, MOS_WRITE, port->number - 
port->serial->minor,
+                            0x01, &data);
        }
-
-       data = 0x00;
-       send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
-                    0x04, &data);
-
-       data = 0x00;
-       send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
-                    0x01, &data);
-
+       mutex_unlock(&serial->disc_mutex);
        mos7720_port->open = 0;
 
        dbg("Leaving %s", __FUNCTION__);
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 28315b0..3ce98e8 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -634,6 +634,7 @@ static struct usb_serial * create_serial (struct usb_device 
*dev,
        serial->type = driver;
        serial->interface = interface;
        kref_init(&serial->kref);
+       mutex_init(&serial->disc_mutex);
 
        return serial;
 }
@@ -1089,20 +1090,22 @@ void usb_serial_disconnect(struct usb_interface 
*interface)
        usb_serial_console_disconnect(serial);
        dbg ("%s", __FUNCTION__);
 
+       mutex_lock(&serial->disc_mutex);
        usb_set_intfdata (interface, NULL);
-       if (serial) {
-               for (i = 0; i < serial->num_ports; ++i) {
-                       port = serial->port[i];
-                       if (port) {
-                               if (port->tty)
-                                       tty_hangup(port->tty);
-                               kill_traffic(port);
-                       }
+       /* must set a flag, to signal subdrivers */
+       serial->disconnected = 1;
+       for (i = 0; i < serial->num_ports; ++i) {
+               port = serial->port[i];
+               if (port) {
+                       if (port->tty)
+                               tty_hangup(port->tty);
+                       kill_traffic(port);
                }
-               /* let the last holder of this object 
-                * cause it to be cleaned up */
-               usb_serial_put(serial);
        }
+       /* let the last holder of this object
+        * cause it to be cleaned up */
+       mutex_unlock(&serial->disc_mutex);
+       usb_serial_put(serial);
        dev_info(dev, "device disconnected\n");
 }
 
@@ -1112,9 +1115,6 @@ int usb_serial_suspend(struct usb_interface *intf, 
pm_message_t message)
        struct usb_serial_port *port;
        int i, r = 0;
 
-       if (!serial) /* device has been disconnected */
-               return 0;
-
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
                if (port)
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index ef1e430..63b29b5 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -129,6 +129,7 @@ struct usb_serial {
        struct usb_device *             dev;
        struct usb_serial_driver *      type;
        struct usb_interface *          interface;
+       unsigned char                   disconnected;
        unsigned char                   minor;
        unsigned char                   num_ports;
        unsigned char                   num_port_pointers;
@@ -138,6 +139,7 @@ struct usb_serial {
        char                            num_bulk_out;
        struct usb_serial_port *        port[MAX_NUM_PORTS];
        struct kref                     kref;
+       struct mutex                    disc_mutex;
        void *                          private;
 };
 #define to_usb_serial(d) container_of(d, struct usb_serial, kref)
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to