[PATCH] USB: fix bug in serial driver unregistration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch (as1536) fixes a bug in the USB serial core.  Unloading and
reloading a serial driver while a serial device is plugged in causes
errors because of the code in usb_serial_disconnect() that tries to
make sure the port_remove method is called.  With the new order of
driver registration introduced in the 3.4 kernel, this is definitely
not the right thing to do (if indeed it ever was).

The patch removes that whole section code, along with the mechanism
for keeping track of each port's registration state, which is no
longer needed.  The driver core can handle all that stuff for us.

Note: This has been tested only with one or two USB serial drivers.
In theory, other drivers might still run into trouble.  But if they
do, it will be the fault of the drivers, not of this patch -- that is,
the drivers will need to be fixed.

Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Reported-and-tested-by: Johan Hovold <jhovold@xxxxxxxxx>

---

 drivers/usb/serial/bus.c        |    5 -----
 drivers/usb/serial/usb-serial.c |   23 ++---------------------
 include/linux/usb/serial.h      |    8 --------
 3 files changed, 2 insertions(+), 34 deletions(-)

Index: usb-3.3/include/linux/usb/serial.h
===================================================================
--- usb-3.3.orig/include/linux/usb/serial.h
+++ usb-3.3/include/linux/usb/serial.h
@@ -28,13 +28,6 @@
 /* parity check flag */
 #define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
 
-enum port_dev_state {
-	PORT_UNREGISTERED,
-	PORT_REGISTERING,
-	PORT_REGISTERED,
-	PORT_UNREGISTERING,
-};
-
 /* USB serial flags */
 #define USB_SERIAL_WRITE_BUSY	0
 
@@ -124,7 +117,6 @@ struct usb_serial_port {
 	char			throttle_req;
 	unsigned long		sysrq; /* sysrq timeout */
 	struct device		dev;
-	enum port_dev_state	dev_state;
 };
 #define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
 
Index: usb-3.3/drivers/usb/serial/usb-serial.c
===================================================================
--- usb-3.3.orig/drivers/usb/serial/usb-serial.c
+++ usb-3.3/drivers/usb/serial/usb-serial.c
@@ -1074,17 +1074,12 @@ int usb_serial_probe(struct usb_interfac
 		port = serial->port[i];
 		dev_set_name(&port->dev, "ttyUSB%d", port->number);
 		dbg ("%s - registering %s", __func__, dev_name(&port->dev));
-		port->dev_state = PORT_REGISTERING;
 		device_enable_async_suspend(&port->dev);
 
 		retval = device_add(&port->dev);
-		if (retval) {
+		if (retval)
 			dev_err(&port->dev, "Error registering port device, "
 				"continuing\n");
-			port->dev_state = PORT_UNREGISTERED;
-		} else {
-			port->dev_state = PORT_REGISTERED;
-		}
 	}
 
 	usb_serial_console_init(debug, minor);
@@ -1128,22 +1123,8 @@ void usb_serial_disconnect(struct usb_in
 			}
 			kill_traffic(port);
 			cancel_work_sync(&port->work);
-			if (port->dev_state == PORT_REGISTERED) {
-
-				/* Make sure the port is bound so that the
-				 * driver's port_remove method is called.
-				 */
-				if (!port->dev.driver) {
-					int rc;
-
-					port->dev.driver =
-							&serial->type->driver;
-					rc = device_bind_driver(&port->dev);
-				}
-				port->dev_state = PORT_UNREGISTERING;
+			if (device_is_registered(&port->dev))
 				device_del(&port->dev);
-				port->dev_state = PORT_UNREGISTERED;
-			}
 		}
 	}
 	serial->type->disconnect(serial);
Index: usb-3.3/drivers/usb/serial/bus.c
===================================================================
--- usb-3.3.orig/drivers/usb/serial/bus.c
+++ usb-3.3/drivers/usb/serial/bus.c
@@ -60,8 +60,6 @@ static int usb_serial_device_probe(struc
 		retval = -ENODEV;
 		goto exit;
 	}
-	if (port->dev_state != PORT_REGISTERING)
-		goto exit;
 
 	driver = port->serial->type;
 	if (driver->port_probe) {
@@ -98,9 +96,6 @@ static int usb_serial_device_remove(stru
 	if (!port)
 		return -ENODEV;
 
-	if (port->dev_state != PORT_UNREGISTERING)
-		return retval;
-
 	device_remove_file(&port->dev, &dev_attr_port_number);
 
 	driver = port->serial->type;

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux