[PATCH v4 10/14] xhci: cancel in-flight resume requests when the port is powered off

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Work around a remote wakeup vs port poweroff request race.  A wakeup request
sets the timer, but by the time it expires the port has been turned off, so we
hit:
                if ((raw_port_status & PORT_RESET) ||
                                !(raw_port_status & PORT_PE))
                        return 0xffffffff;

...in xhci_get_port_status

When userspace has set the port policy to allow poweroff the assumption is that
it no longer cares about remote wakeup requests for that port.  If a request
happens to collide with autosuspend of the port we need to make sure to cancel
an in-flight request otherwise we can end up in an infinite loop.

Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>
---
 drivers/usb/host/xhci-hub.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 9992fbfec85f..2333ec573594 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1004,9 +1004,16 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			xhci_disable_port(hcd, xhci, wIndex,
 					port_array[wIndex], temp);
 			break;
-		case USB_PORT_FEAT_POWER:
-			writel(temp & ~PORT_POWER, port_array[wIndex]);
+		case USB_PORT_FEAT_POWER: {
+			struct xhci_bus_state *bus_state;
 
+			bus_state = &xhci->bus_state[hcd_index(hcd)];
+			writel(temp & ~PORT_POWER, port_array[wIndex]);
+			if (test_and_clear_bit(wIndex, &bus_state->resuming_ports)) {
+				bus_state->resume_done[wIndex] = 0;
+				xhci_dbg(xhci, "port%d: resume cancelled\n",
+					 wIndex);
+			}
 			spin_unlock_irqrestore(&xhci->lock, flags);
 			temp = usb_acpi_power_manageable(hcd->self.root_hub,
 					wIndex);
@@ -1015,6 +1022,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 						wIndex, false);
 			spin_lock_irqsave(&xhci->lock, flags);
 			break;
+		}
 		default:
 			goto error;
 		}

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux