aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/kl5kusb105.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/kl5kusb105.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/kl5kusb105.c')
-rw-r--r--drivers/usb/serial/kl5kusb105.c39
1 files changed, 22 insertions, 17 deletions
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index fa817c66b3e8..0f44bb8e8d4f 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -73,7 +73,8 @@ static int debug;
73 * Function prototypes 73 * Function prototypes
74 */ 74 */
75static int klsi_105_startup(struct usb_serial *serial); 75static int klsi_105_startup(struct usb_serial *serial);
76static void klsi_105_shutdown(struct usb_serial *serial); 76static void klsi_105_disconnect(struct usb_serial *serial);
77static void klsi_105_release(struct usb_serial *serial);
77static int klsi_105_open(struct tty_struct *tty, 78static int klsi_105_open(struct tty_struct *tty,
78 struct usb_serial_port *port, struct file *filp); 79 struct usb_serial_port *port, struct file *filp);
79static void klsi_105_close(struct usb_serial_port *port); 80static void klsi_105_close(struct usb_serial_port *port);
@@ -131,7 +132,8 @@ static struct usb_serial_driver kl5kusb105d_device = {
131 .tiocmget = klsi_105_tiocmget, 132 .tiocmget = klsi_105_tiocmget,
132 .tiocmset = klsi_105_tiocmset, 133 .tiocmset = klsi_105_tiocmset,
133 .attach = klsi_105_startup, 134 .attach = klsi_105_startup,
134 .shutdown = klsi_105_shutdown, 135 .disconnect = klsi_105_disconnect,
136 .release = klsi_105_release,
135 .throttle = klsi_105_throttle, 137 .throttle = klsi_105_throttle,
136 .unthrottle = klsi_105_unthrottle, 138 .unthrottle = klsi_105_unthrottle,
137}; 139};
@@ -315,7 +317,7 @@ err_cleanup:
315} /* klsi_105_startup */ 317} /* klsi_105_startup */
316 318
317 319
318static void klsi_105_shutdown(struct usb_serial *serial) 320static void klsi_105_disconnect(struct usb_serial *serial)
319{ 321{
320 int i; 322 int i;
321 323
@@ -325,33 +327,36 @@ static void klsi_105_shutdown(struct usb_serial *serial)
325 for (i = 0; i < serial->num_ports; ++i) { 327 for (i = 0; i < serial->num_ports; ++i) {
326 struct klsi_105_private *priv = 328 struct klsi_105_private *priv =
327 usb_get_serial_port_data(serial->port[i]); 329 usb_get_serial_port_data(serial->port[i]);
328 unsigned long flags;
329 330
330 if (priv) { 331 if (priv) {
331 /* kill our write urb pool */ 332 /* kill our write urb pool */
332 int j; 333 int j;
333 struct urb **write_urbs = priv->write_urb_pool; 334 struct urb **write_urbs = priv->write_urb_pool;
334 spin_lock_irqsave(&priv->lock, flags);
335 335
336 for (j = 0; j < NUM_URBS; j++) { 336 for (j = 0; j < NUM_URBS; j++) {
337 if (write_urbs[j]) { 337 if (write_urbs[j]) {
338 /* FIXME - uncomment the following 338 usb_kill_urb(write_urbs[j]);
339 * usb_kill_urb call when the host
340 * controllers get fixed to set
341 * urb->dev = NULL after the urb is
342 * finished. Otherwise this call
343 * oopses. */
344 /* usb_kill_urb(write_urbs[j]); */
345 kfree(write_urbs[j]->transfer_buffer);
346 usb_free_urb(write_urbs[j]); 339 usb_free_urb(write_urbs[j]);
347 } 340 }
348 } 341 }
349 spin_unlock_irqrestore(&priv->lock, flags);
350 kfree(priv);
351 usb_set_serial_port_data(serial->port[i], NULL);
352 } 342 }
353 } 343 }
354} /* klsi_105_shutdown */ 344} /* klsi_105_disconnect */
345
346
347static void klsi_105_release(struct usb_serial *serial)
348{
349 int i;
350
351 dbg("%s", __func__);
352
353 for (i = 0; i < serial->num_ports; ++i) {
354 struct klsi_105_private *priv =
355 usb_get_serial_port_data(serial->port[i]);
356
357 kfree(priv);
358 }
359} /* klsi_105_release */
355 360
356static int klsi_105_open(struct tty_struct *tty, 361static int klsi_105_open(struct tty_struct *tty,
357 struct usb_serial_port *port, struct file *filp) 362 struct usb_serial_port *port, struct file *filp)