aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-05-07 11:20:06 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-07 15:59:02 -0400
commit5cbe61c5aff0a8ada691eb8b07dbfb55c303f640 (patch)
tree7cacf1d68cbc681faa658d0fb15e035186c79908
parent23063b378de734383c9f42de770b01cd661cd9b4 (diff)
usb-serial: ftdi_sio: fix oops during autosuspend
This patch (as1550) fixes a bug in the usb-serial core that affects the ftdi_sio driver and most likely others as well. The core implements suspend and resume routines, but it doesn't store pointers to those routines in the usb_driver structures that it registers, even though it does set those drivers' supports_autosuspend flag. The end result is that when one of these devices is autosuspended, we try to call through a NULL pointer. The patch fixes the problem by setting the suspend and resume method pointers to the appropriate routines in the USB serial core, along with the supports_autosuspend field, in each driver as it is registered. This should be back-ported to all the stable kernels that have the new usb_serial_register_drivers() interface. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Reported-and-tested-by: Frank Schäfer <schaefer.frank@gmx.net> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/serial/usb-serial.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 906f06e97fde..f7b263e237ef 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1336,7 +1336,6 @@ static int usb_serial_register(struct usb_serial_driver *driver)
1336 driver->description); 1336 driver->description);
1337 return -EINVAL; 1337 return -EINVAL;
1338 } 1338 }
1339 driver->usb_driver->supports_autosuspend = 1;
1340 1339
1341 /* Add this device to our list of devices */ 1340 /* Add this device to our list of devices */
1342 mutex_lock(&table_lock); 1341 mutex_lock(&table_lock);
@@ -1371,7 +1370,7 @@ static void usb_serial_deregister(struct usb_serial_driver *device)
1371 * @serial_drivers: NULL-terminated array of pointers to drivers to be registered 1370 * @serial_drivers: NULL-terminated array of pointers to drivers to be registered
1372 * 1371 *
1373 * Registers @udriver and all the drivers in the @serial_drivers array. 1372 * Registers @udriver and all the drivers in the @serial_drivers array.
1374 * Automatically fills in the .no_dynamic_id field in @udriver and 1373 * Automatically fills in the .no_dynamic_id and PM fields in @udriver and
1375 * the .usb_driver field in each serial driver. 1374 * the .usb_driver field in each serial driver.
1376 */ 1375 */
1377int usb_serial_register_drivers(struct usb_driver *udriver, 1376int usb_serial_register_drivers(struct usb_driver *udriver,
@@ -1390,11 +1389,17 @@ int usb_serial_register_drivers(struct usb_driver *udriver,
1390 * the serial drivers are registered, because the probe would 1389 * the serial drivers are registered, because the probe would
1391 * simply fail for lack of a matching serial driver. 1390 * simply fail for lack of a matching serial driver.
1392 * Therefore save off udriver's id_table until we are all set. 1391 * Therefore save off udriver's id_table until we are all set.
1392 *
1393 * Suspend/resume support is implemented in the usb-serial core,
1394 * so fill in the PM-related fields in udriver.
1393 */ 1395 */
1394 saved_id_table = udriver->id_table; 1396 saved_id_table = udriver->id_table;
1395 udriver->id_table = NULL; 1397 udriver->id_table = NULL;
1396 1398
1397 udriver->no_dynamic_id = 1; 1399 udriver->no_dynamic_id = 1;
1400 udriver->supports_autosuspend = 1;
1401 udriver->suspend = usb_serial_suspend;
1402 udriver->resume = usb_serial_resume;
1398 rc = usb_register(udriver); 1403 rc = usb_register(udriver);
1399 if (rc) 1404 if (rc)
1400 return rc; 1405 return rc;