Merge tag 'backport/v3.14.24-ltsi-rc1/phy-rcar-gen2-usb-to-v3.15' into backport/v3...
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / usb / host / xhci.c
index 924a6cc..5e8e87d 100644 (file)
@@ -404,16 +404,16 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
 
 #else
 
-static int xhci_try_enable_msi(struct usb_hcd *hcd)
+static inline int xhci_try_enable_msi(struct usb_hcd *hcd)
 {
        return 0;
 }
 
-static void xhci_cleanup_msix(struct xhci_hcd *xhci)
+static inline void xhci_cleanup_msix(struct xhci_hcd *xhci)
 {
 }
 
-static void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
+static inline void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
 {
 }
 
@@ -928,7 +928,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
  */
 int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 {
-       u32                     command, temp = 0;
+       u32                     command, temp = 0, status;
        struct usb_hcd          *hcd = xhci_to_hcd(xhci);
        struct usb_hcd          *secondary_hcd;
        int                     retval = 0;
@@ -1046,8 +1046,12 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 
  done:
        if (retval == 0) {
-               usb_hcd_resume_root_hub(hcd);
-               usb_hcd_resume_root_hub(xhci->shared_hcd);
+               /* Resume root hubs only when have pending events. */
+               status = readl(&xhci->op_regs->status);
+               if (status & STS_EINT) {
+                       usb_hcd_resume_root_hub(hcd);
+                       usb_hcd_resume_root_hub(xhci->shared_hcd);
+               }
        }
 
        /*
@@ -2933,7 +2937,6 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
                xhci_ring_cmd_db(xhci);
        }
        virt_ep->stopped_td = NULL;
-       virt_ep->stopped_trb = NULL;
        virt_ep->stopped_stream = 0;
        spin_unlock_irqrestore(&xhci->lock, flags);
 
@@ -3925,13 +3928,21 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
        int ret;
 
        spin_lock_irqsave(&xhci->lock, flags);
-       if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) {
+
+       virt_dev = xhci->devs[udev->slot_id];
+
+       /*
+        * virt_dev might not exists yet if xHC resumed from hibernate (S4) and
+        * xHC was re-initialized. Exit latency will be set later after
+        * hub_port_finish_reset() is done and xhci->devs[] are re-allocated
+        */
+
+       if (!virt_dev || max_exit_latency == virt_dev->current_mel) {
                spin_unlock_irqrestore(&xhci->lock, flags);
                return 0;
        }
 
        /* Attempt to issue an Evaluate Context command to change the MEL. */
-       virt_dev = xhci->devs[udev->slot_id];
        command = xhci->lpm_command;
        ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx);
        if (!ctrl_ctx) {
@@ -4820,6 +4831,75 @@ error:
        return retval;
 }
 
+static const struct hc_driver xhci_hc_driver = {
+       .description =          "xhci-hcd",
+       .product_desc =         "xHCI Host Controller",
+       .hcd_priv_size =        sizeof(struct xhci_hcd *),
+
+       /*
+        * generic hardware linkage
+        */
+       .irq =                  xhci_irq,
+       .flags =                HCD_MEMORY | HCD_USB3 | HCD_SHARED,
+
+       /*
+        * basic lifecycle operations
+        */
+       .reset =                NULL, /* set in xhci_init_driver() */
+       .start =                xhci_run,
+       .stop =                 xhci_stop,
+       .shutdown =             xhci_shutdown,
+
+       /*
+        * managing i/o requests and associated device resources
+        */
+       .urb_enqueue =          xhci_urb_enqueue,
+       .urb_dequeue =          xhci_urb_dequeue,
+       .alloc_dev =            xhci_alloc_dev,
+       .free_dev =             xhci_free_dev,
+       .alloc_streams =        xhci_alloc_streams,
+       .free_streams =         xhci_free_streams,
+       .add_endpoint =         xhci_add_endpoint,
+       .drop_endpoint =        xhci_drop_endpoint,
+       .endpoint_reset =       xhci_endpoint_reset,
+       .check_bandwidth =      xhci_check_bandwidth,
+       .reset_bandwidth =      xhci_reset_bandwidth,
+       .address_device =       xhci_address_device,
+       .enable_device =        xhci_enable_device,
+       .update_hub_device =    xhci_update_hub_device,
+       .reset_device =         xhci_discover_or_reset_device,
+
+       /*
+        * scheduling support
+        */
+       .get_frame_number =     xhci_get_frame,
+
+       /*
+        * root hub support
+        */
+       .hub_control =          xhci_hub_control,
+       .hub_status_data =      xhci_hub_status_data,
+       .bus_suspend =          xhci_bus_suspend,
+       .bus_resume =           xhci_bus_resume,
+
+       /*
+        * call back when device connected and addressed
+        */
+       .update_device =        xhci_update_device,
+       .set_usb2_hw_lpm =      xhci_set_usb2_hardware_lpm,
+       .enable_usb3_lpm_timeout =      xhci_enable_usb3_lpm_timeout,
+       .disable_usb3_lpm_timeout =     xhci_disable_usb3_lpm_timeout,
+       .find_raw_port_number = xhci_find_raw_port_number,
+};
+
+void xhci_init_driver(struct hc_driver *drv, int (*setup_fn)(struct usb_hcd *))
+{
+       BUG_ON(!setup_fn);
+       *drv = xhci_hc_driver;
+       drv->reset = setup_fn;
+}
+EXPORT_SYMBOL_GPL(xhci_init_driver);
+
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_LICENSE("GPL");