aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2009-09-01 11:38:34 -0400
committerLive-CD User <linux@linux.site>2009-09-19 16:13:39 -0400
commit41bd34ddd7aa46dbc03b5bb33896e0fa8100fe7b (patch)
treeadfd9b5af7a68cfa053f1c3f8192578d612ca18e /drivers/usb
parenta75b7b68ef73685784781d6d2bc416b6dac20969 (diff)
usb-serial: change referencing of port and serial structures
This patch (as1284) changes the referencing of the usb_serial and usb_serial_port structures in usb-serial.c. It's not feasible to make the port structures keep a reference to the serial structure, because the ports need to remain in existence when serial is released -- quite a few of the drivers expect this. Consequently taking a reference to the port when the device file is open is insufficient; such a reference would not pin serial. To fix this, we now take a reference to serial when the device file is opened. The final put_device() for the ports occurs in destroy_serial(), so that the ports will last as long as they are needed. The patch initializes all the port devices, including those in the unused "fake" ports. This makes the code more uniform because they can all be released in the same way. The error handling code in usb_serial_probe() is much simplified by this approach; instead of freeing everything by hand we can use a single usb_serial_put() call. Also simplified is the port-release mechanism. Instead of being two separate routines, port_release() and port_free() can be combined into one. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/usb-serial.c95
1 files changed, 20 insertions, 75 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 80c1f4d8e910..f1a1f0fb6d1b 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -43,8 +43,6 @@
43#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" 43#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
44#define DRIVER_DESC "USB Serial Driver core" 44#define DRIVER_DESC "USB Serial Driver core"
45 45
46static void port_free(struct usb_serial_port *port);
47
48/* Driver structure we register with the USB core */ 46/* Driver structure we register with the USB core */
49static struct usb_driver usb_serial_driver = { 47static struct usb_driver usb_serial_driver = {
50 .name = "usbserial", 48 .name = "usbserial",
@@ -145,27 +143,16 @@ static void destroy_serial(struct kref *kref)
145 143
146 serial->type->release(serial); 144 serial->type->release(serial);
147 145
148 for (i = 0; i < serial->num_ports; ++i) { 146 /* Now that nothing is using the ports, they can be freed */
147 for (i = 0; i < serial->num_port_pointers; ++i) {
149 port = serial->port[i]; 148 port = serial->port[i];
150 if (port) 149 if (port) {
150 port->serial = NULL;
151 put_device(&port->dev); 151 put_device(&port->dev);
152 }
153
154 /* If this is a "fake" port, we have to clean it up here, as it will
155 * not get cleaned up in port_release() as it was never registered with
156 * the driver core */
157 if (serial->num_ports < serial->num_port_pointers) {
158 for (i = serial->num_ports;
159 i < serial->num_port_pointers; ++i) {
160 port = serial->port[i];
161 if (port)
162 port_free(port);
163 } 152 }
164 } 153 }
165 154
166 usb_put_dev(serial->dev); 155 usb_put_dev(serial->dev);
167
168 /* free up any memory that we allocated */
169 kfree(serial); 156 kfree(serial);
170} 157}
171 158
@@ -201,8 +188,6 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
201 port = serial->port[portNumber]; 188 port = serial->port[portNumber];
202 if (!port || serial->disconnected) 189 if (!port || serial->disconnected)
203 retval = -ENODEV; 190 retval = -ENODEV;
204 else
205 get_device(&port->dev);
206 /* 191 /*
207 * Note: Our locking order requirement does not allow port->mutex 192 * Note: Our locking order requirement does not allow port->mutex
208 * to be acquired while serial->disc_mutex is held. 193 * to be acquired while serial->disc_mutex is held.
@@ -213,7 +198,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
213 198
214 if (mutex_lock_interruptible(&port->mutex)) { 199 if (mutex_lock_interruptible(&port->mutex)) {
215 retval = -ERESTARTSYS; 200 retval = -ERESTARTSYS;
216 goto bailout_port_put; 201 goto bailout_serial_put;
217 } 202 }
218 203
219 ++port->port.count; 204 ++port->port.count;
@@ -273,8 +258,6 @@ bailout_mutex_unlock:
273 tty->driver_data = NULL; 258 tty->driver_data = NULL;
274 tty_port_tty_set(&port->port, NULL); 259 tty_port_tty_set(&port->port, NULL);
275 mutex_unlock(&port->mutex); 260 mutex_unlock(&port->mutex);
276bailout_port_put:
277 put_device(&port->dev);
278bailout_serial_put: 261bailout_serial_put:
279 usb_serial_put(serial); 262 usb_serial_put(serial);
280 return retval; 263 return retval;
@@ -333,14 +316,13 @@ static void serial_do_free(struct tty_struct *tty)
333 316
334 serial = port->serial; 317 serial = port->serial;
335 owner = serial->type->driver.owner; 318 owner = serial->type->driver.owner;
336 put_device(&port->dev); 319
337 /* Mustn't dereference port any more */
338 mutex_lock(&serial->disc_mutex); 320 mutex_lock(&serial->disc_mutex);
339 if (!serial->disconnected) 321 if (!serial->disconnected)
340 usb_autopm_put_interface(serial->interface); 322 usb_autopm_put_interface(serial->interface);
341 mutex_unlock(&serial->disc_mutex); 323 mutex_unlock(&serial->disc_mutex);
324
342 usb_serial_put(serial); 325 usb_serial_put(serial);
343 /* Mustn't dereference serial any more */
344 module_put(owner); 326 module_put(owner);
345} 327}
346 328
@@ -581,14 +563,6 @@ static void usb_serial_port_work(struct work_struct *work)
581 tty_kref_put(tty); 563 tty_kref_put(tty);
582} 564}
583 565
584static void port_release(struct device *dev)
585{
586 struct usb_serial_port *port = to_usb_serial_port(dev);
587
588 dbg ("%s - %s", __func__, dev_name(dev));
589 port_free(port);
590}
591
592static void kill_traffic(struct usb_serial_port *port) 566static void kill_traffic(struct usb_serial_port *port)
593{ 567{
594 usb_kill_urb(port->read_urb); 568 usb_kill_urb(port->read_urb);
@@ -608,8 +582,12 @@ static void kill_traffic(struct usb_serial_port *port)
608 usb_kill_urb(port->interrupt_out_urb); 582 usb_kill_urb(port->interrupt_out_urb);
609} 583}
610 584
611static void port_free(struct usb_serial_port *port) 585static void port_release(struct device *dev)
612{ 586{
587 struct usb_serial_port *port = to_usb_serial_port(dev);
588
589 dbg ("%s - %s", __func__, dev_name(dev));
590
613 /* 591 /*
614 * Stop all the traffic before cancelling the work, so that 592 * Stop all the traffic before cancelling the work, so that
615 * nobody will restart it by calling usb_serial_port_softint. 593 * nobody will restart it by calling usb_serial_port_softint.
@@ -955,6 +933,11 @@ int usb_serial_probe(struct usb_interface *interface,
955 mutex_init(&port->mutex); 933 mutex_init(&port->mutex);
956 INIT_WORK(&port->work, usb_serial_port_work); 934 INIT_WORK(&port->work, usb_serial_port_work);
957 serial->port[i] = port; 935 serial->port[i] = port;
936 port->dev.parent = &interface->dev;
937 port->dev.driver = NULL;
938 port->dev.bus = &usb_serial_bus_type;
939 port->dev.release = &port_release;
940 device_initialize(&port->dev);
958 } 941 }
959 942
960 /* set up the endpoint information */ 943 /* set up the endpoint information */
@@ -1097,15 +1080,10 @@ int usb_serial_probe(struct usb_interface *interface,
1097 /* register all of the individual ports with the driver core */ 1080 /* register all of the individual ports with the driver core */
1098 for (i = 0; i < num_ports; ++i) { 1081 for (i = 0; i < num_ports; ++i) {
1099 port = serial->port[i]; 1082 port = serial->port[i];
1100 port->dev.parent = &interface->dev;
1101 port->dev.driver = NULL;
1102 port->dev.bus = &usb_serial_bus_type;
1103 port->dev.release = &port_release;
1104
1105 dev_set_name(&port->dev, "ttyUSB%d", port->number); 1083 dev_set_name(&port->dev, "ttyUSB%d", port->number);
1106 dbg ("%s - registering %s", __func__, dev_name(&port->dev)); 1084 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
1107 port->dev_state = PORT_REGISTERING; 1085 port->dev_state = PORT_REGISTERING;
1108 retval = device_register(&port->dev); 1086 retval = device_add(&port->dev);
1109 if (retval) { 1087 if (retval) {
1110 dev_err(&port->dev, "Error registering port device, " 1088 dev_err(&port->dev, "Error registering port device, "
1111 "continuing\n"); 1089 "continuing\n");
@@ -1123,39 +1101,7 @@ exit:
1123 return 0; 1101 return 0;
1124 1102
1125probe_error: 1103probe_error:
1126 for (i = 0; i < num_bulk_in; ++i) { 1104 usb_serial_put(serial);
1127 port = serial->port[i];
1128 if (!port)
1129 continue;
1130 usb_free_urb(port->read_urb);
1131 kfree(port->bulk_in_buffer);
1132 }
1133 for (i = 0; i < num_bulk_out; ++i) {
1134 port = serial->port[i];
1135 if (!port)
1136 continue;
1137 usb_free_urb(port->write_urb);
1138 kfree(port->bulk_out_buffer);
1139 }
1140 for (i = 0; i < num_interrupt_in; ++i) {
1141 port = serial->port[i];
1142 if (!port)
1143 continue;
1144 usb_free_urb(port->interrupt_in_urb);
1145 kfree(port->interrupt_in_buffer);
1146 }
1147 for (i = 0; i < num_interrupt_out; ++i) {
1148 port = serial->port[i];
1149 if (!port)
1150 continue;
1151 usb_free_urb(port->interrupt_out_urb);
1152 kfree(port->interrupt_out_buffer);
1153 }
1154
1155 /* free up any memory that we allocated */
1156 for (i = 0; i < serial->num_port_pointers; ++i)
1157 kfree(serial->port[i]);
1158 kfree(serial);
1159 return -EIO; 1105 return -EIO;
1160} 1106}
1161EXPORT_SYMBOL_GPL(usb_serial_probe); 1107EXPORT_SYMBOL_GPL(usb_serial_probe);
@@ -1206,8 +1152,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
1206 } 1152 }
1207 serial->type->disconnect(serial); 1153 serial->type->disconnect(serial);
1208 1154
1209 /* let the last holder of this object 1155 /* let the last holder of this object cause it to be cleaned up */
1210 * cause it to be cleaned up */
1211 usb_serial_put(serial); 1156 usb_serial_put(serial);
1212 dev_info(dev, "device disconnected\n"); 1157 dev_info(dev, "device disconnected\n");
1213} 1158}