aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/usb-serial.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2009-06-02 11:53:55 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:47 -0400
commitf9c99bb8b3a1ec81af68d484a551307326c2e933 (patch)
tree9031ebe390ecd558d54ad484dde5ba66dcf823b7 /drivers/usb/serial/usb-serial.c
parentc706ebdfc8955b850e477255a8c0f93f9f14712d (diff)
USB: usb-serial: replace shutdown with disconnect, release
This patch (as1254) splits up the shutdown method of usb_serial_driver into a disconnect and a release method. The problem is that the usb-serial core was calling shutdown during disconnect handling, but drivers didn't expect it to be called until after all the open file references had been closed. The result was an oops when the close method tried to use memory that had been deallocated by shutdown. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r--drivers/usb/serial/usb-serial.c29
1 files changed, 13 insertions, 16 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index da890f030fac..d595aa5586a7 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -141,6 +141,14 @@ static void destroy_serial(struct kref *kref)
141 if (serial->minor != SERIAL_TTY_NO_MINOR) 141 if (serial->minor != SERIAL_TTY_NO_MINOR)
142 return_serial(serial); 142 return_serial(serial);
143 143
144 serial->type->release(serial);
145
146 for (i = 0; i < serial->num_ports; ++i) {
147 port = serial->port[i];
148 if (port)
149 put_device(&port->dev);
150 }
151
144 /* If this is a "fake" port, we have to clean it up here, as it will 152 /* If this is a "fake" port, we have to clean it up here, as it will
145 * not get cleaned up in port_release() as it was never registered with 153 * not get cleaned up in port_release() as it was never registered with
146 * the driver core */ 154 * the driver core */
@@ -148,9 +156,8 @@ static void destroy_serial(struct kref *kref)
148 for (i = serial->num_ports; 156 for (i = serial->num_ports;
149 i < serial->num_port_pointers; ++i) { 157 i < serial->num_port_pointers; ++i) {
150 port = serial->port[i]; 158 port = serial->port[i];
151 if (!port) 159 if (port)
152 continue; 160 port_free(port);
153 port_free(port);
154 } 161 }
155 } 162 }
156 163
@@ -1118,10 +1125,6 @@ void usb_serial_disconnect(struct usb_interface *interface)
1118 serial->disconnected = 1; 1125 serial->disconnected = 1;
1119 mutex_unlock(&serial->disc_mutex); 1126 mutex_unlock(&serial->disc_mutex);
1120 1127
1121 /* Unfortunately, many of the sub-drivers expect the port structures
1122 * to exist when their shutdown method is called, so we have to go
1123 * through this awkward two-step unregistration procedure.
1124 */
1125 for (i = 0; i < serial->num_ports; ++i) { 1128 for (i = 0; i < serial->num_ports; ++i) {
1126 port = serial->port[i]; 1129 port = serial->port[i];
1127 if (port) { 1130 if (port) {
@@ -1153,14 +1156,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
1153 } 1156 }
1154 } 1157 }
1155 } 1158 }
1156 serial->type->shutdown(serial); 1159 serial->type->disconnect(serial);
1157 for (i = 0; i < serial->num_ports; ++i) {
1158 port = serial->port[i];
1159 if (port) {
1160 put_device(&port->dev);
1161 serial->port[i] = NULL;
1162 }
1163 }
1164 1160
1165 /* let the last holder of this object 1161 /* let the last holder of this object
1166 * cause it to be cleaned up */ 1162 * cause it to be cleaned up */
@@ -1338,7 +1334,8 @@ static void fixup_generic(struct usb_serial_driver *device)
1338 set_to_generic_if_null(device, chars_in_buffer); 1334 set_to_generic_if_null(device, chars_in_buffer);
1339 set_to_generic_if_null(device, read_bulk_callback); 1335 set_to_generic_if_null(device, read_bulk_callback);
1340 set_to_generic_if_null(device, write_bulk_callback); 1336 set_to_generic_if_null(device, write_bulk_callback);
1341 set_to_generic_if_null(device, shutdown); 1337 set_to_generic_if_null(device, disconnect);
1338 set_to_generic_if_null(device, release);
1342} 1339}
1343 1340
1344int usb_serial_register(struct usb_serial_driver *driver) 1341int usb_serial_register(struct usb_serial_driver *driver)