Am Donnerstag, 20. Dezember 2007 16:51:59 schrieb Alan Stern:
> On Thu, 20 Dec 2007, Oliver Neukum wrote:
>
> > @@ -1080,20 +1081,22 @@ void usb_serial_disconnect(struct usb_in
> > 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 use extra flag, as intfdata can be reset */
> > + serial->disconnected = 1;
>
> This comment is misleading. It implies there is a possibility you
> actually could check for disconnects by looking at the value of
> usb_get_intfdata(), but that's completely wrong. There are about 13
> places in various serial drivers where this mistake is made; they all
> need to be fixed.
>
> Don't you also have to check the disconnect flag in serial_close()
> before calling usb_autopm_put_interface()?
Where is that?
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]>
I'd call this 2.6.25 material.
Regards
Oliver
----
--- linux-2.6.24-rc7/include/linux/usb/serial.h 2008-01-16 15:04:38.000000000
+0100
+++ linux-2.6.24-serial_intfdata/include/linux/usb/serial.h 2008-01-16
14:55:12.000000000 +0100
@@ -128,6 +128,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;
@@ -137,6 +138,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)
--- linux-2.6.24-rc7/drivers/usb/serial/usb-serial.c 2008-01-16
15:04:26.000000000 +0100
+++ linux-2.6.24-serial_intfdata/drivers/usb/serial/usb-serial.c
2008-01-16 14:57:55.000000000 +0100
@@ -625,6 +625,7 @@ static struct usb_serial * create_serial
serial->type = driver;
serial->interface = interface;
kref_init(&serial->kref);
+ mutex_init(&serial->disc_mutex);
return serial;
}
@@ -1080,20 +1081,22 @@ void usb_serial_disconnect(struct usb_in
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");
}
@@ -1103,9 +1106,6 @@ int usb_serial_suspend(struct usb_interf
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)
--- linux-2.6.24-rc7/drivers/usb/serial/mos7720.c 2008-01-16
15:04:26.000000000 +0100
+++ linux-2.6.24-serial_intfdata/drivers/usb/serial/mos7720.c 2008-01-16
14:55:12.000000000 +0100
@@ -564,22 +564,25 @@ static void mos7720_close(struct usb_ser
}
/* 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__);
-
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html