--- /dev/null
+From 6fd4562178508a0949c9fdecd8558d8b10d671bd Mon Sep 17 00:00:00 2001
+From: Andiry Xu <andiry.xu@amd.com>
+Date: Fri, 23 Sep 2011 14:19:50 -0700
+Subject: xHCI: Clear PLC for USB2 root hub ports
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+commit 6fd4562178508a0949c9fdecd8558d8b10d671bd upstream.
+
+When the link state changes, xHC will report a port status change event
+and set the PORT_PLC bit, for both USB3 and USB2 root hub ports.
+
+The PLC will be cleared by usbcore for USB3 root hub ports, but not for
+USB2 ports, because they do not report USB_PORT_STAT_C_LINK_STATE in
+wPortChange.
+
+Clear it for USB2 root hub ports in handle_port_status().
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1356,6 +1356,10 @@ static void handle_port_status(struct xh
+ }
+ }
+
++ if (hcd->speed != HCD_USB3)
++ xhci_test_and_clear_bit(xhci, port_array, faked_port_index,
++ PORT_PLC);
++
+ cleanup:
+ /* Update event ring dequeue pointer before dropping the lock */
+ inc_deq(xhci, xhci->event_ring, true);
--- /dev/null
+From d2f52c9e585bbb1a3c164e02b8dcd0d996c67353 Mon Sep 17 00:00:00 2001
+From: Andiry Xu <andiry.xu@amd.com>
+Date: Fri, 23 Sep 2011 14:19:49 -0700
+Subject: xHCI: test and clear RWC bit
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+commit d2f52c9e585bbb1a3c164e02b8dcd0d996c67353 upstream.
+
+Introduce xhci_test_and_clear_bit() to clear RWC bit in PORTSC register.
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-hub.c | 22 ++++++++++++++++------
+ drivers/usb/host/xhci-ring.c | 6 ++----
+ drivers/usb/host/xhci.h | 2 ++
+ 3 files changed, 20 insertions(+), 10 deletions(-)
+
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -392,6 +392,20 @@ static int xhci_get_ports(struct usb_hcd
+ return max_ports;
+ }
+
++/* Test and clear port RWC bit */
++void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
++ int port_id, u32 port_bit)
++{
++ u32 temp;
++
++ temp = xhci_readl(xhci, port_array[port_id]);
++ if (temp & port_bit) {
++ temp = xhci_port_state_to_neutral(temp);
++ temp |= port_bit;
++ xhci_writel(xhci, temp, port_array[port_id]);
++ }
++}
++
+ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ u16 wIndex, char *buf, u16 wLength)
+ {
+@@ -938,12 +952,8 @@ int xhci_bus_resume(struct usb_hcd *hcd)
+ spin_lock_irqsave(&xhci->lock, flags);
+
+ /* Clear PLC */
+- temp = xhci_readl(xhci, port_array[port_index]);
+- if (temp & PORT_PLC) {
+- temp = xhci_port_state_to_neutral(temp);
+- temp |= PORT_PLC;
+- xhci_writel(xhci, temp, port_array[port_index]);
+- }
++ xhci_test_and_clear_bit(xhci, port_array, port_index,
++ PORT_PLC);
+
+ slot_id = xhci_find_slot_id_by_port(hcd,
+ xhci, port_index + 1);
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1344,10 +1344,8 @@ static void handle_port_status(struct xh
+ xhci_ring_device(xhci, slot_id);
+ xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
+ /* Clear PORT_PLC */
+- temp = xhci_readl(xhci, port_array[faked_port_index]);
+- temp = xhci_port_state_to_neutral(temp);
+- temp |= PORT_PLC;
+- xhci_writel(xhci, temp, port_array[faked_port_index]);
++ xhci_test_and_clear_bit(xhci, port_array,
++ faked_port_index, PORT_PLC);
+ } else {
+ xhci_dbg(xhci, "resume HS port %d\n", port_id);
+ bus_state->resume_done[faked_port_index] = jiffies +
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1573,6 +1573,8 @@ void xhci_ring_ep_doorbell(struct xhci_h
+ unsigned int ep_index, unsigned int stream_id);
+
+ /* xHCI roothub code */
++void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
++ int port_id, u32 port_bit);
+ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
+ char *buf, u16 wLength);
+ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);