diff options
author | Oliver Neukum <oliver@neukum.org> | 2008-01-16 11:18:52 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-02-01 17:35:03 -0500 |
commit | a1cd7e99b343543af2be4c8c5755e26f6bfd725a (patch) | |
tree | 41f8de097dd0889a9c6d02fa0a22b16d5146de46 /drivers/usb | |
parent | 828d55c58cba6b652fd30e00c3d940cb7c523e3c (diff) |
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 <oneukum@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/mos7720.c | 33 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 28 |
2 files changed, 32 insertions, 29 deletions
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 725991fadc26..40f3a0188807 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) | |||
564 | } | 564 | } |
565 | 565 | ||
566 | /* While closing port, shutdown all bulk read, write * | 566 | /* While closing port, shutdown all bulk read, write * |
567 | * and interrupt read if they exists */ | 567 | * and interrupt read if they exists, otherwise nop */ |
568 | if (serial->dev) { | 568 | dbg("Shutdown bulk write"); |
569 | dbg("Shutdown bulk write"); | 569 | usb_kill_urb(port->write_urb); |
570 | usb_kill_urb(port->write_urb); | 570 | dbg("Shutdown bulk read"); |
571 | dbg("Shutdown bulk read"); | 571 | usb_kill_urb(port->read_urb); |
572 | usb_kill_urb(port->read_urb); | 572 | |
573 | mutex_lock(&serial->disc_mutex); | ||
574 | /* these commands must not be issued if the device has | ||
575 | * been disconnected */ | ||
576 | if (!serial->disconnected) { | ||
577 | data = 0x00; | ||
578 | send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, | ||
579 | 0x04, &data); | ||
580 | |||
581 | data = 0x00; | ||
582 | send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, | ||
583 | 0x01, &data); | ||
573 | } | 584 | } |
574 | 585 | mutex_unlock(&serial->disc_mutex); | |
575 | data = 0x00; | ||
576 | send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, | ||
577 | 0x04, &data); | ||
578 | |||
579 | data = 0x00; | ||
580 | send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, | ||
581 | 0x01, &data); | ||
582 | |||
583 | mos7720_port->open = 0; | 586 | mos7720_port->open = 0; |
584 | 587 | ||
585 | dbg("Leaving %s", __FUNCTION__); | 588 | dbg("Leaving %s", __FUNCTION__); |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 28315b05c9cc..3ce98e8d7bce 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, | |||
634 | serial->type = driver; | 634 | serial->type = driver; |
635 | serial->interface = interface; | 635 | serial->interface = interface; |
636 | kref_init(&serial->kref); | 636 | kref_init(&serial->kref); |
637 | mutex_init(&serial->disc_mutex); | ||
637 | 638 | ||
638 | return serial; | 639 | return serial; |
639 | } | 640 | } |
@@ -1089,20 +1090,22 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
1089 | usb_serial_console_disconnect(serial); | 1090 | usb_serial_console_disconnect(serial); |
1090 | dbg ("%s", __FUNCTION__); | 1091 | dbg ("%s", __FUNCTION__); |
1091 | 1092 | ||
1093 | mutex_lock(&serial->disc_mutex); | ||
1092 | usb_set_intfdata (interface, NULL); | 1094 | usb_set_intfdata (interface, NULL); |
1093 | if (serial) { | 1095 | /* must set a flag, to signal subdrivers */ |
1094 | for (i = 0; i < serial->num_ports; ++i) { | 1096 | serial->disconnected = 1; |
1095 | port = serial->port[i]; | 1097 | for (i = 0; i < serial->num_ports; ++i) { |
1096 | if (port) { | 1098 | port = serial->port[i]; |
1097 | if (port->tty) | 1099 | if (port) { |
1098 | tty_hangup(port->tty); | 1100 | if (port->tty) |
1099 | kill_traffic(port); | 1101 | tty_hangup(port->tty); |
1100 | } | 1102 | kill_traffic(port); |
1101 | } | 1103 | } |
1102 | /* let the last holder of this object | ||
1103 | * cause it to be cleaned up */ | ||
1104 | usb_serial_put(serial); | ||
1105 | } | 1104 | } |
1105 | /* let the last holder of this object | ||
1106 | * cause it to be cleaned up */ | ||
1107 | mutex_unlock(&serial->disc_mutex); | ||
1108 | usb_serial_put(serial); | ||
1106 | dev_info(dev, "device disconnected\n"); | 1109 | dev_info(dev, "device disconnected\n"); |
1107 | } | 1110 | } |
1108 | 1111 | ||
@@ -1112,9 +1115,6 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) | |||
1112 | struct usb_serial_port *port; | 1115 | struct usb_serial_port *port; |
1113 | int i, r = 0; | 1116 | int i, r = 0; |
1114 | 1117 | ||
1115 | if (!serial) /* device has been disconnected */ | ||
1116 | return 0; | ||
1117 | |||
1118 | for (i = 0; i < serial->num_ports; ++i) { | 1118 | for (i = 0; i < serial->num_ports; ++i) { |
1119 | port = serial->port[i]; | 1119 | port = serial->port[i]; |
1120 | if (port) | 1120 | if (port) |