Merge tag 'usb-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB merge for 3.4-rc1 from Greg KH: "Here's the big USB merge for the 3.4-rc1 merge window. Lots of gadget driver reworks here, driver updates, xhci changes, some new drivers added, usb-serial core reworking to fix some bugs, and other various minor things. There are some patches touching arch code, but they have all been acked by the various arch maintainers." * tag 'usb-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (302 commits) net: qmi_wwan: add support for ZTE MF820D USB: option: add ZTE MF820D usb: gadget: f_fs: Remove lock is held before freeing checks USB: option: make interface blacklist work again usb/ub: deprecate & schedule for removal the "Low Performance USB Block" driver USB: ohci-pxa27x: add clk_prepare/clk_unprepare calls USB: use generic platform driver on ath79 USB: EHCI: Add a generic platform device driver USB: OHCI: Add a generic platform device driver USB: ftdi_sio: new PID: LUMEL PD12 USB: ftdi_sio: add support for FT-X series devices USB: serial: mos7840: Fixed MCS7820 device attach problem usb: Don't make USB_ARCH_HAS_{XHCI,OHCI,EHCI} depend on USB_SUPPORT. usb gadget: fix a section mismatch when compiling g_ffs with CONFIG_USB_FUNCTIONFS_ETH USB: ohci-nxp: Remove i2c_write(), use smbus USB: ohci-nxp: Support for LPC32xx USB: ohci-nxp: Rename symbols from pnx4008 to nxp USB: OHCI-HCD: Rename ohci-pnx4008 to ohci-nxp usb: gadget: Kconfig: fix typo for 'different' usb: dwc3: pci: fix another failure path in dwc3_pci_probe() ...
This commit is contained in:
@ -934,13 +934,8 @@ void usb_rebind_intf(struct usb_interface *intf)
|
||||
int rc;
|
||||
|
||||
/* Delayed unbind of an existing driver */
|
||||
if (intf->dev.driver) {
|
||||
struct usb_driver *driver =
|
||||
to_usb_driver(intf->dev.driver);
|
||||
|
||||
dev_dbg(&intf->dev, "forced unbind\n");
|
||||
usb_driver_release_interface(driver, intf);
|
||||
}
|
||||
if (intf->dev.driver)
|
||||
usb_forced_unbind_intf(intf);
|
||||
|
||||
/* Try to rebind the interface */
|
||||
if (!intf->dev.power.is_prepared) {
|
||||
@ -953,15 +948,13 @@ void usb_rebind_intf(struct usb_interface *intf)
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
#define DO_UNBIND 0
|
||||
#define DO_REBIND 1
|
||||
|
||||
/* Unbind drivers for @udev's interfaces that don't support suspend/resume,
|
||||
* or rebind interfaces that have been unbound, according to @action.
|
||||
/* Unbind drivers for @udev's interfaces that don't support suspend/resume
|
||||
* There is no check for reset_resume here because it can be determined
|
||||
* only during resume whether reset_resume is needed.
|
||||
*
|
||||
* The caller must hold @udev's device lock.
|
||||
*/
|
||||
static void do_unbind_rebind(struct usb_device *udev, int action)
|
||||
static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
|
||||
{
|
||||
struct usb_host_config *config;
|
||||
int i;
|
||||
@ -972,23 +965,53 @@ static void do_unbind_rebind(struct usb_device *udev, int action)
|
||||
if (config) {
|
||||
for (i = 0; i < config->desc.bNumInterfaces; ++i) {
|
||||
intf = config->interface[i];
|
||||
switch (action) {
|
||||
case DO_UNBIND:
|
||||
if (intf->dev.driver) {
|
||||
drv = to_usb_driver(intf->dev.driver);
|
||||
if (!drv->suspend || !drv->resume)
|
||||
usb_forced_unbind_intf(intf);
|
||||
}
|
||||
break;
|
||||
case DO_REBIND:
|
||||
if (intf->needs_binding)
|
||||
usb_rebind_intf(intf);
|
||||
break;
|
||||
|
||||
if (intf->dev.driver) {
|
||||
drv = to_usb_driver(intf->dev.driver);
|
||||
if (!drv->suspend || !drv->resume)
|
||||
usb_forced_unbind_intf(intf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Unbind drivers for @udev's interfaces that failed to support reset-resume.
|
||||
* These interfaces have the needs_binding flag set by usb_resume_interface().
|
||||
*
|
||||
* The caller must hold @udev's device lock.
|
||||
*/
|
||||
static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev)
|
||||
{
|
||||
struct usb_host_config *config;
|
||||
int i;
|
||||
struct usb_interface *intf;
|
||||
|
||||
config = udev->actconfig;
|
||||
if (config) {
|
||||
for (i = 0; i < config->desc.bNumInterfaces; ++i) {
|
||||
intf = config->interface[i];
|
||||
if (intf->dev.driver && intf->needs_binding)
|
||||
usb_forced_unbind_intf(intf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void do_rebind_interfaces(struct usb_device *udev)
|
||||
{
|
||||
struct usb_host_config *config;
|
||||
int i;
|
||||
struct usb_interface *intf;
|
||||
|
||||
config = udev->actconfig;
|
||||
if (config) {
|
||||
for (i = 0; i < config->desc.bNumInterfaces; ++i) {
|
||||
intf = config->interface[i];
|
||||
if (intf->needs_binding)
|
||||
usb_rebind_intf(intf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
|
||||
{
|
||||
struct usb_device_driver *udriver;
|
||||
@ -1278,35 +1301,48 @@ int usb_suspend(struct device *dev, pm_message_t msg)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
|
||||
do_unbind_rebind(udev, DO_UNBIND);
|
||||
unbind_no_pm_drivers_interfaces(udev);
|
||||
|
||||
/* From now on we are sure all drivers support suspend/resume
|
||||
* but not necessarily reset_resume()
|
||||
* so we may still need to unbind and rebind upon resume
|
||||
*/
|
||||
choose_wakeup(udev, msg);
|
||||
return usb_suspend_both(udev, msg);
|
||||
}
|
||||
|
||||
/* The device lock is held by the PM core */
|
||||
int usb_resume_complete(struct device *dev)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
|
||||
/* For PM complete calls, all we do is rebind interfaces
|
||||
* whose needs_binding flag is set
|
||||
*/
|
||||
if (udev->state != USB_STATE_NOTATTACHED)
|
||||
do_rebind_interfaces(udev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The device lock is held by the PM core */
|
||||
int usb_resume(struct device *dev, pm_message_t msg)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
int status;
|
||||
|
||||
/* For PM complete calls, all we do is rebind interfaces */
|
||||
if (msg.event == PM_EVENT_ON) {
|
||||
if (udev->state != USB_STATE_NOTATTACHED)
|
||||
do_unbind_rebind(udev, DO_REBIND);
|
||||
status = 0;
|
||||
|
||||
/* For all other calls, take the device back to full power and
|
||||
/* For all calls, take the device back to full power and
|
||||
* tell the PM core in case it was autosuspended previously.
|
||||
* Unbind the interfaces that will need rebinding later.
|
||||
* Unbind the interfaces that will need rebinding later,
|
||||
* because they fail to support reset_resume.
|
||||
* (This can't be done in usb_resume_interface()
|
||||
* above because it doesn't own the right set of locks.)
|
||||
*/
|
||||
} else {
|
||||
status = usb_resume_both(udev, msg);
|
||||
if (status == 0) {
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
do_unbind_rebind(udev, DO_REBIND);
|
||||
}
|
||||
status = usb_resume_both(udev, msg);
|
||||
if (status == 0) {
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
unbind_no_reset_resume_drivers_interfaces(udev);
|
||||
}
|
||||
|
||||
/* Avoid PM error messages for devices disconnected while suspended
|
||||
|
Reference in New Issue
Block a user