diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2012-05-07 11:20:06 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-07 15:59:02 -0400 |
commit | 5cbe61c5aff0a8ada691eb8b07dbfb55c303f640 (patch) | |
tree | 7cacf1d68cbc681faa658d0fb15e035186c79908 /drivers/usb/serial | |
parent | 23063b378de734383c9f42de770b01cd661cd9b4 (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>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 9 |
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 | */ |
1377 | int usb_serial_register_drivers(struct usb_driver *udriver, | 1376 | int 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; |