Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: roles: intel_xhci: Enable runtime PM

This fixes an issue where the mux does not get configured
when the parent device is suspended. The registers for this
mux are mapped to the parent device MMIO (usually xHCI PCI
device), so in order for the driver to be able to program
the registers, the parent device must be resumed.

Reported-by: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
Fixes: f6fb9ec02be1 ("usb: roles: Add Intel xHCI USB role switch driver")
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Heikki Krogerus and committed by
Greg Kroah-Hartman
cb296846 c9359f41

+13 -1
+13 -1
drivers/usb/roles/intel-xhci-usb-role-switch.c
··· 18 18 #include <linux/kernel.h> 19 19 #include <linux/module.h> 20 20 #include <linux/platform_device.h> 21 + #include <linux/pm_runtime.h> 21 22 #include <linux/usb/role.h> 22 23 23 24 /* register definition */ ··· 57 56 return -EIO; 58 57 } 59 58 59 + pm_runtime_get_sync(dev); 60 + 60 61 /* Set idpin value as requested */ 61 62 val = readl(data->base + DUAL_ROLE_CFG0); 62 63 switch (role) { ··· 87 84 /* Polling on CFG1 register to confirm mode switch.*/ 88 85 do { 89 86 val = readl(data->base + DUAL_ROLE_CFG1); 90 - if (!!(val & HOST_MODE) == (role == USB_ROLE_HOST)) 87 + if (!!(val & HOST_MODE) == (role == USB_ROLE_HOST)) { 88 + pm_runtime_put(dev); 91 89 return 0; 90 + } 92 91 93 92 /* Interval for polling is set to about 5 - 10 ms */ 94 93 usleep_range(5000, 10000); 95 94 } while (time_before(jiffies, timeout)); 95 + 96 + pm_runtime_put(dev); 96 97 97 98 dev_warn(dev, "Timeout waiting for role-switch\n"); 98 99 return -ETIMEDOUT; ··· 108 101 enum usb_role role; 109 102 u32 val; 110 103 104 + pm_runtime_get_sync(dev); 111 105 val = readl(data->base + DUAL_ROLE_CFG0); 106 + pm_runtime_put(dev); 112 107 113 108 if (!(val & SW_IDPIN)) 114 109 role = USB_ROLE_HOST; ··· 150 141 data->role_sw = usb_role_switch_register(dev, &sw_desc); 151 142 if (IS_ERR(data->role_sw)) 152 143 return PTR_ERR(data->role_sw); 144 + 145 + pm_runtime_set_active(dev); 146 + pm_runtime_enable(dev); 153 147 154 148 return 0; 155 149 }