wIndex, link_state);
                                goto error;
                        }
+
+                       if (link_state == USB_SS_PORT_LS_U0) {
+                               if ((temp & PORT_PLS_MASK) == XDEV_U0)
+                                       break;
+
+                               if (!((temp & PORT_PLS_MASK) == XDEV_U1 ||
+                                   (temp & PORT_PLS_MASK) == XDEV_U2 ||
+                                   (temp & PORT_PLS_MASK) == XDEV_U3)) {
+                                       xhci_warn(xhci, "Can only set port %d to U0 from U state\n",
+                                                       wIndex);
+                                       goto error;
+                               }
+                               reinit_completion(&bus_state->u3exit_done[wIndex]);
+                               xhci_set_link_state(xhci, ports[wIndex],
+                                                   USB_SS_PORT_LS_U0);
+                               spin_unlock_irqrestore(&xhci->lock, flags);
+                               if (!wait_for_completion_timeout(&bus_state->u3exit_done[wIndex],
+                                                                msecs_to_jiffies(100)))
+                                       xhci_dbg(xhci, "missing U0 port change event for port %d\n",
+                                                wIndex);
+                               spin_lock_irqsave(&xhci->lock, flags);
+                               temp = readl(ports[wIndex]->addr);
+                               break;
+                       }
+
                        if (link_state == USB_SS_PORT_LS_U3) {
+                               int retries = 16;
                                slot_id = xhci_find_slot_id_by_port(hcd, xhci,
                                                wIndex + 1);
                                if (slot_id) {
                                        xhci_stop_device(xhci, slot_id, 1);
                                        spin_lock_irqsave(&xhci->lock, flags);
                                }
-                       }
-
-                       xhci_set_link_state(xhci, ports[wIndex], link_state);
-
-                       spin_unlock_irqrestore(&xhci->lock, flags);
-                       if (link_state == USB_SS_PORT_LS_U3) {
-                               int retries = 16;
-
+                               xhci_set_link_state(xhci, ports[wIndex], USB_SS_PORT_LS_U3);
+                               spin_unlock_irqrestore(&xhci->lock, flags);
                                while (retries--) {
                                        usleep_range(4000, 8000);
                                        temp = readl(ports[wIndex]->addr);
                                        if ((temp & PORT_PLS_MASK) == XDEV_U3)
                                                break;
                                }
-                       }
-                       spin_lock_irqsave(&xhci->lock, flags);
-
-                       temp = readl(ports[wIndex]->addr);
-                       if (link_state == USB_SS_PORT_LS_U3)
+                               spin_lock_irqsave(&xhci->lock, flags);
+                               temp = readl(ports[wIndex]->addr);
                                bus_state->suspended_ports |= 1 << wIndex;
+                       }
                        break;
                case USB_PORT_FEAT_POWER:
                        /*
 
             (portsc & PORT_PLS_MASK) == XDEV_U1 ||
             (portsc & PORT_PLS_MASK) == XDEV_U2)) {
                xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
+               complete(&bus_state->u3exit_done[hcd_portnum]);
                /* We've just brought the device into U0/1/2 through either the
                 * Resume state after a device remote wakeup, or through the
                 * U3Exit state after a host-initiated resume.  If it's a device