diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2012-05-07 11:20:06 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-06-01 15:18:20 +0800 |
commit | 2aa5c3521c154db6e3bbbda1a2f0b07da4938626 (patch) | |
tree | 4dec143b6b632fbc38aef5bcfec3bc5a2d71f70f | |
parent | 27234cee48f54e3f3125e44bc8b05c42b977a113 (diff) | |
download | linux-3.10-2aa5c3521c154db6e3bbbda1a2f0b07da4938626.tar.gz linux-3.10-2aa5c3521c154db6e3bbbda1a2f0b07da4938626.tar.bz2 linux-3.10-2aa5c3521c154db6e3bbbda1a2f0b07da4938626.zip |
usb-serial: ftdi_sio: fix oops during autosuspend
commit 5cbe61c5aff0a8ada691eb8b07dbfb55c303f640 upstream.
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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 97355a15bbe..6933355c964 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1338,7 +1338,6 @@ static int usb_serial_register(struct usb_serial_driver *driver) driver->description); return -EINVAL; } - driver->usb_driver->supports_autosuspend = 1; /* Add this device to our list of devices */ mutex_lock(&table_lock); @@ -1373,7 +1372,7 @@ static void usb_serial_deregister(struct usb_serial_driver *device) * @serial_drivers: NULL-terminated array of pointers to drivers to be registered * * Registers @udriver and all the drivers in the @serial_drivers array. - * Automatically fills in the .no_dynamic_id field in @udriver and + * Automatically fills in the .no_dynamic_id and PM fields in @udriver and * the .usb_driver field in each serial driver. */ int usb_serial_register_drivers(struct usb_driver *udriver, @@ -1392,11 +1391,17 @@ int usb_serial_register_drivers(struct usb_driver *udriver, * the serial drivers are registered, because the probe would * simply fail for lack of a matching serial driver. * Therefore save off udriver's id_table until we are all set. + * + * Suspend/resume support is implemented in the usb-serial core, + * so fill in the PM-related fields in udriver. */ saved_id_table = udriver->id_table; udriver->id_table = NULL; udriver->no_dynamic_id = 1; + udriver->supports_autosuspend = 1; + udriver->suspend = usb_serial_suspend; + udriver->resume = usb_serial_resume; rc = usb_register(udriver); if (rc) return rc; |