aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2009-06-02 11:54:11 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:47 -0400
commitc706ebdfc8955b850e477255a8c0f93f9f14712d (patch)
tree1f880601cdd2663ee4206783092d5fa9d90c8922 /drivers/usb/serial
parentc6994e6f067cf0fc4c6cca3d164018b1150916f8 (diff)
USB: usb-serial: call port_probe and port_remove at the right times
This patch (as1253) prevents the usb-serial core from calling a driver's port_probe and port_remove methods more than once per port. It also removes some unnecessary try_module_get() calls and adds a missing port_remove method call in a failure path. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/bus.c27
-rw-r--r--drivers/usb/serial/usb-serial.c24
2 files changed, 33 insertions, 18 deletions
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 83bbb5bca2ef..ba555c528cc6 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -59,23 +59,22 @@ static int usb_serial_device_probe(struct device *dev)
59 retval = -ENODEV; 59 retval = -ENODEV;
60 goto exit; 60 goto exit;
61 } 61 }
62 if (port->dev_state != PORT_REGISTERING)
63 goto exit;
62 64
63 driver = port->serial->type; 65 driver = port->serial->type;
64 if (driver->port_probe) { 66 if (driver->port_probe) {
65 if (!try_module_get(driver->driver.owner)) {
66 dev_err(dev, "module get failed, exiting\n");
67 retval = -EIO;
68 goto exit;
69 }
70 retval = driver->port_probe(port); 67 retval = driver->port_probe(port);
71 module_put(driver->driver.owner);
72 if (retval) 68 if (retval)
73 goto exit; 69 goto exit;
74 } 70 }
75 71
76 retval = device_create_file(dev, &dev_attr_port_number); 72 retval = device_create_file(dev, &dev_attr_port_number);
77 if (retval) 73 if (retval) {
74 if (driver->port_remove)
75 retval = driver->port_remove(port);
78 goto exit; 76 goto exit;
77 }
79 78
80 minor = port->number; 79 minor = port->number;
81 tty_register_device(usb_serial_tty_driver, minor, dev); 80 tty_register_device(usb_serial_tty_driver, minor, dev);
@@ -98,19 +97,15 @@ static int usb_serial_device_remove(struct device *dev)
98 if (!port) 97 if (!port)
99 return -ENODEV; 98 return -ENODEV;
100 99
100 if (port->dev_state != PORT_UNREGISTERING)
101 return retval;
102
101 device_remove_file(&port->dev, &dev_attr_port_number); 103 device_remove_file(&port->dev, &dev_attr_port_number);
102 104
103 driver = port->serial->type; 105 driver = port->serial->type;
104 if (driver->port_remove) { 106 if (driver->port_remove)
105 if (!try_module_get(driver->driver.owner)) {
106 dev_err(dev, "module get failed, exiting\n");
107 retval = -EIO;
108 goto exit;
109 }
110 retval = driver->port_remove(port); 107 retval = driver->port_remove(port);
111 module_put(driver->driver.owner); 108
112 }
113exit:
114 minor = port->number; 109 minor = port->number;
115 tty_unregister_device(usb_serial_tty_driver, minor); 110 tty_unregister_device(usb_serial_tty_driver, minor);
116 dev_info(dev, "%s converter now disconnected from ttyUSB%d\n", 111 dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 1967a7edc10c..da890f030fac 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1046,10 +1046,15 @@ int usb_serial_probe(struct usb_interface *interface,
1046 1046
1047 dev_set_name(&port->dev, "ttyUSB%d", port->number); 1047 dev_set_name(&port->dev, "ttyUSB%d", port->number);
1048 dbg ("%s - registering %s", __func__, dev_name(&port->dev)); 1048 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
1049 port->dev_state = PORT_REGISTERING;
1049 retval = device_register(&port->dev); 1050 retval = device_register(&port->dev);
1050 if (retval) 1051 if (retval) {
1051 dev_err(&port->dev, "Error registering port device, " 1052 dev_err(&port->dev, "Error registering port device, "
1052 "continuing\n"); 1053 "continuing\n");
1054 port->dev_state = PORT_UNREGISTERED;
1055 } else {
1056 port->dev_state = PORT_REGISTERED;
1057 }
1053 } 1058 }
1054 1059
1055 usb_serial_console_init(debug, minor); 1060 usb_serial_console_init(debug, minor);
@@ -1130,7 +1135,22 @@ void usb_serial_disconnect(struct usb_interface *interface)
1130 } 1135 }
1131 kill_traffic(port); 1136 kill_traffic(port);
1132 cancel_work_sync(&port->work); 1137 cancel_work_sync(&port->work);
1133 device_del(&port->dev); 1138 if (port->dev_state == PORT_REGISTERED) {
1139
1140 /* Make sure the port is bound so that the
1141 * driver's port_remove method is called.
1142 */
1143 if (!port->dev.driver) {
1144 int rc;
1145
1146 port->dev.driver =
1147 &serial->type->driver;
1148 rc = device_bind_driver(&port->dev);
1149 }
1150 port->dev_state = PORT_UNREGISTERING;
1151 device_del(&port->dev);
1152 port->dev_state = PORT_UNREGISTERED;
1153 }
1134 } 1154 }
1135 } 1155 }
1136 serial->type->shutdown(serial); 1156 serial->type->shutdown(serial);