usb: Fix linker errors with CONFIG_PM=n
[pandora-kernel.git] / drivers / usb / host / xhci.c
index d5c550e..5d7d4e9 100644 (file)
@@ -551,6 +551,218 @@ void xhci_shutdown(struct usb_hcd *hcd)
                    xhci_readl(xhci, &xhci->op_regs->status));
 }
 
+#ifdef CONFIG_PM
+static void xhci_save_registers(struct xhci_hcd *xhci)
+{
+       xhci->s3.command = xhci_readl(xhci, &xhci->op_regs->command);
+       xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification);
+       xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
+       xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg);
+       xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
+       xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
+       xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size);
+       xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base);
+       xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+}
+
+static void xhci_restore_registers(struct xhci_hcd *xhci)
+{
+       xhci_writel(xhci, xhci->s3.command, &xhci->op_regs->command);
+       xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
+       xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
+       xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg);
+       xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
+       xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
+       xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size);
+       xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
+}
+
+/*
+ * Stop HC (not bus-specific)
+ *
+ * This is called when the machine transition into S3/S4 mode.
+ *
+ */
+int xhci_suspend(struct xhci_hcd *xhci)
+{
+       int                     rc = 0;
+       struct usb_hcd          *hcd = xhci_to_hcd(xhci);
+       u32                     command;
+
+       spin_lock_irq(&xhci->lock);
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       /* step 1: stop endpoint */
+       /* skipped assuming that port suspend has done */
+
+       /* step 2: clear Run/Stop bit */
+       command = xhci_readl(xhci, &xhci->op_regs->command);
+       command &= ~CMD_RUN;
+       xhci_writel(xhci, command, &xhci->op_regs->command);
+       if (handshake(xhci, &xhci->op_regs->status,
+                     STS_HALT, STS_HALT, 100*100)) {
+               xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
+               spin_unlock_irq(&xhci->lock);
+               return -ETIMEDOUT;
+       }
+
+       /* step 3: save registers */
+       xhci_save_registers(xhci);
+
+       /* step 4: set CSS flag */
+       command = xhci_readl(xhci, &xhci->op_regs->command);
+       command |= CMD_CSS;
+       xhci_writel(xhci, command, &xhci->op_regs->command);
+       if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10*100)) {
+               xhci_warn(xhci, "WARN: xHC CMD_CSS timeout\n");
+               spin_unlock_irq(&xhci->lock);
+               return -ETIMEDOUT;
+       }
+       /* step 5: remove core well power */
+       xhci_cleanup_msix(xhci);
+       spin_unlock_irq(&xhci->lock);
+
+       return rc;
+}
+
+/*
+ * start xHC (not bus-specific)
+ *
+ * This is called when the machine transition from S3/S4 mode.
+ *
+ */
+int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+{
+       u32                     command, temp = 0;
+       struct usb_hcd          *hcd = xhci_to_hcd(xhci);
+       struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
+       u64     val_64;
+       int     old_state, retval;
+
+       old_state = hcd->state;
+       if (time_before(jiffies, xhci->next_statechange))
+               msleep(100);
+
+       spin_lock_irq(&xhci->lock);
+
+       if (!hibernated) {
+               /* step 1: restore register */
+               xhci_restore_registers(xhci);
+               /* step 2: initialize command ring buffer */
+               val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
+               val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
+                        (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+                                              xhci->cmd_ring->dequeue) &
+                        (u64) ~CMD_RING_RSVD_BITS) |
+                        xhci->cmd_ring->cycle_state;
+               xhci_dbg(xhci, "// Setting command ring address to 0x%llx\n",
+                               (long unsigned long) val_64);
+               xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
+               /* step 3: restore state and start state*/
+               /* step 3: set CRS flag */
+               command = xhci_readl(xhci, &xhci->op_regs->command);
+               command |= CMD_CRS;
+               xhci_writel(xhci, command, &xhci->op_regs->command);
+               if (handshake(xhci, &xhci->op_regs->status,
+                             STS_RESTORE, 0, 10*100)) {
+                       xhci_dbg(xhci, "WARN: xHC CMD_CSS timeout\n");
+                       spin_unlock_irq(&xhci->lock);
+                       return -ETIMEDOUT;
+               }
+               temp = xhci_readl(xhci, &xhci->op_regs->status);
+       }
+
+       /* If restore operation fails, re-initialize the HC during resume */
+       if ((temp & STS_SRE) || hibernated) {
+               usb_root_hub_lost_power(hcd->self.root_hub);
+
+               xhci_dbg(xhci, "Stop HCD\n");
+               xhci_halt(xhci);
+               xhci_reset(xhci);
+               if (hibernated)
+                       xhci_cleanup_msix(xhci);
+               spin_unlock_irq(&xhci->lock);
+
+#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
+               /* Tell the event ring poll function not to reschedule */
+               xhci->zombie = 1;
+               del_timer_sync(&xhci->event_ring_timer);
+#endif
+
+               xhci_dbg(xhci, "// Disabling event ring interrupts\n");
+               temp = xhci_readl(xhci, &xhci->op_regs->status);
+               xhci_writel(xhci, temp & ~STS_EINT, &xhci->op_regs->status);
+               temp = xhci_readl(xhci, &xhci->ir_set->irq_pending);
+               xhci_writel(xhci, ER_IRQ_DISABLE(temp),
+                               &xhci->ir_set->irq_pending);
+               xhci_print_ir_set(xhci, xhci->ir_set, 0);
+
+               xhci_dbg(xhci, "cleaning up memory\n");
+               xhci_mem_cleanup(xhci);
+               xhci_dbg(xhci, "xhci_stop completed - status = %x\n",
+                           xhci_readl(xhci, &xhci->op_regs->status));
+
+               xhci_dbg(xhci, "Initialize the HCD\n");
+               retval = xhci_init(hcd);
+               if (retval)
+                       return retval;
+
+               xhci_dbg(xhci, "Start the HCD\n");
+               retval = xhci_run(hcd);
+               if (!retval)
+                       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+               hcd->state = HC_STATE_SUSPENDED;
+               return retval;
+       }
+
+       /* Re-setup MSI-X */
+       if (hcd->irq)
+               free_irq(hcd->irq, hcd);
+       hcd->irq = -1;
+
+       retval = xhci_setup_msix(xhci);
+       if (retval)
+               /* fall back to msi*/
+               retval = xhci_setup_msi(xhci);
+
+       if (retval) {
+               /* fall back to legacy interrupt*/
+               retval = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
+                                       hcd->irq_descr, hcd);
+               if (retval) {
+                       xhci_err(xhci, "request interrupt %d failed\n",
+                                       pdev->irq);
+                       return retval;
+               }
+               hcd->irq = pdev->irq;
+       }
+
+       /* step 4: set Run/Stop bit */
+       command = xhci_readl(xhci, &xhci->op_regs->command);
+       command |= CMD_RUN;
+       xhci_writel(xhci, command, &xhci->op_regs->command);
+       handshake(xhci, &xhci->op_regs->status, STS_HALT,
+                 0, 250 * 1000);
+
+       /* step 5: walk topology and initialize portsc,
+        * portpmsc and portli
+        */
+       /* this is done in bus_resume */
+
+       /* step 6: restart each of the previously
+        * Running endpoints by ringing their doorbells
+        */
+
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       if (!hibernated)
+               hcd->state = old_state;
+       else
+               hcd->state = HC_STATE_SUSPENDED;
+
+       spin_unlock_irq(&xhci->lock);
+       return 0;
+}
+#endif /* CONFIG_PM */
+
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -607,7 +819,11 @@ unsigned int xhci_last_valid_endpoint(u32 added_ctxs)
  * returns 0 this is a root hub; returns -EINVAL for NULL pointers.
  */
 int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
-               struct usb_host_endpoint *ep, int check_ep, const char *func) {
+               struct usb_host_endpoint *ep, int check_ep, bool check_virt_dev,
+               const char *func) {
+       struct xhci_hcd *xhci;
+       struct xhci_virt_device *virt_dev;
+
        if (!hcd || (check_ep && !ep) || !udev) {
                printk(KERN_DEBUG "xHCI %s called with invalid args\n",
                                func);
@@ -618,11 +834,24 @@ int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
                                func);
                return 0;
        }
-       if (!udev->slot_id) {
-               printk(KERN_DEBUG "xHCI %s called with unaddressed device\n",
-                               func);
-               return -EINVAL;
+
+       if (check_virt_dev) {
+               xhci = hcd_to_xhci(hcd);
+               if (!udev->slot_id || !xhci->devs
+                       || !xhci->devs[udev->slot_id]) {
+                       printk(KERN_DEBUG "xHCI %s called with unaddressed "
+                                               "device\n", func);
+                       return -EINVAL;
+               }
+
+               virt_dev = xhci->devs[udev->slot_id];
+               if (virt_dev->udev != udev) {
+                       printk(KERN_DEBUG "xHCI %s called with udev and "
+                                         "virt_dev does not match\n", func);
+                       return -EINVAL;
+               }
        }
+
        return 1;
 }
 
@@ -704,18 +933,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
        struct urb_priv *urb_priv;
        int size, i;
 
-       if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0)
+       if (!urb || xhci_check_args(hcd, urb->dev, urb->ep,
+                                       true, true, __func__) <= 0)
                return -EINVAL;
 
        slot_id = urb->dev->slot_id;
        ep_index = xhci_get_endpoint_index(&urb->ep->desc);
 
-       if (!xhci->devs || !xhci->devs[slot_id]) {
-               if (!in_interrupt())
-                       dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n");
-               ret = -EINVAL;
-               goto exit;
-       }
        if (!HCD_HW_ACCESSIBLE(hcd)) {
                if (!in_interrupt())
                        xhci_dbg(xhci, "urb submitted during PCI suspend\n");
@@ -956,7 +1180,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                ep->stop_cmd_timer.expires = jiffies +
                        XHCI_STOP_EP_CMD_TIMEOUT * HZ;
                add_timer(&ep->stop_cmd_timer);
-               xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index);
+               xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index, 0);
                xhci_ring_cmd_db(xhci);
        }
 done:
@@ -991,7 +1215,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        u32 new_add_flags, new_drop_flags, new_slot_info;
        int ret;
 
-       ret = xhci_check_args(hcd, udev, ep, 1, __func__);
+       ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
        if (ret <= 0)
                return ret;
        xhci = hcd_to_xhci(hcd);
@@ -1004,12 +1228,6 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
                return 0;
        }
 
-       if (!xhci->devs || !xhci->devs[udev->slot_id]) {
-               xhci_warn(xhci, "xHCI %s called with unaddressed device\n",
-                               __func__);
-               return -EINVAL;
-       }
-
        in_ctx = xhci->devs[udev->slot_id]->in_ctx;
        out_ctx = xhci->devs[udev->slot_id]->out_ctx;
        ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
@@ -1078,7 +1296,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        u32 new_add_flags, new_drop_flags, new_slot_info;
        int ret = 0;
 
-       ret = xhci_check_args(hcd, udev, ep, 1, __func__);
+       ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
        if (ret <= 0) {
                /* So we won't queue a reset ep command for a root hub */
                ep->hcpriv = NULL;
@@ -1098,12 +1316,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
                return 0;
        }
 
-       if (!xhci->devs || !xhci->devs[udev->slot_id]) {
-               xhci_warn(xhci, "xHCI %s called with unaddressed device\n",
-                               __func__);
-               return -EINVAL;
-       }
-
        in_ctx = xhci->devs[udev->slot_id]->in_ctx;
        out_ctx = xhci->devs[udev->slot_id]->out_ctx;
        ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
@@ -1346,16 +1558,11 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
        struct xhci_input_control_ctx *ctrl_ctx;
        struct xhci_slot_ctx *slot_ctx;
 
-       ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
+       ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
        if (ret <= 0)
                return ret;
        xhci = hcd_to_xhci(hcd);
 
-       if (!udev->slot_id || !xhci->devs || !xhci->devs[udev->slot_id]) {
-               xhci_warn(xhci, "xHCI %s called with unaddressed device\n",
-                               __func__);
-               return -EINVAL;
-       }
        xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev);
        virt_dev = xhci->devs[udev->slot_id];
 
@@ -1405,16 +1612,11 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
        struct xhci_virt_device *virt_dev;
        int i, ret;
 
-       ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
+       ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
        if (ret <= 0)
                return;
        xhci = hcd_to_xhci(hcd);
 
-       if (!xhci->devs || !xhci->devs[udev->slot_id]) {
-               xhci_warn(xhci, "xHCI %s called with unaddressed device\n",
-                               __func__);
-               return;
-       }
        xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev);
        virt_dev = xhci->devs[udev->slot_id];
        /* Free any rings allocated for added endpoints */
@@ -1575,7 +1777,7 @@ static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
 
        if (!ep)
                return -EINVAL;
-       ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, __func__);
+       ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, true, __func__);
        if (ret <= 0)
                return -EINVAL;
        if (ep->ss_ep_comp.bmAttributes == 0) {
@@ -1953,8 +2155,13 @@ int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
  * Wait for the Reset Device command to finish.  Remove all structures
  * associated with the endpoints that were disabled.  Clear the input device
  * structure?  Cache the rings?  Reset the control endpoint 0 max packet size?
+ *
+ * If the virt_dev to be reset does not exist or does not match the udev,
+ * it means the device is lost, possibly due to the xHC restore error and
+ * re-initialization during S3/S4. In this case, call xhci_alloc_dev() to
+ * re-allocate the device.
  */
-int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
+int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
 {
        int ret, i;
        unsigned long flags;
@@ -1965,16 +2172,35 @@ int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
        int timeleft;
        int last_freed_endpoint;
 
-       ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
+       ret = xhci_check_args(hcd, udev, NULL, 0, false, __func__);
        if (ret <= 0)
                return ret;
        xhci = hcd_to_xhci(hcd);
        slot_id = udev->slot_id;
        virt_dev = xhci->devs[slot_id];
        if (!virt_dev) {
-               xhci_dbg(xhci, "%s called with invalid slot ID %u\n",
-                               __func__, slot_id);
-               return -EINVAL;
+               xhci_dbg(xhci, "The device to be reset with slot ID %u does "
+                               "not exist. Re-allocate the device\n", slot_id);
+               ret = xhci_alloc_dev(hcd, udev);
+               if (ret == 1)
+                       return 0;
+               else
+                       return -EINVAL;
+       }
+
+       if (virt_dev->udev != udev) {
+               /* If the virt_dev and the udev does not match, this virt_dev
+                * may belong to another udev.
+                * Re-allocate the device.
+                */
+               xhci_dbg(xhci, "The device to be reset with slot ID %u does "
+                               "not match the udev. Re-allocate the device\n",
+                               slot_id);
+               ret = xhci_alloc_dev(hcd, udev);
+               if (ret == 1)
+                       return 0;
+               else
+                       return -EINVAL;
        }
 
        xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id);
@@ -2077,13 +2303,13 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
        struct xhci_virt_device *virt_dev;
        unsigned long flags;
        u32 state;
-       int i;
+       int i, ret;
 
-       if (udev->slot_id == 0)
+       ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
+       if (ret <= 0)
                return;
+
        virt_dev = xhci->devs[udev->slot_id];
-       if (!virt_dev)
-               return;
 
        /* Stop any wayward timer functions (which may grab the lock) */
        for (i = 0; i < 31; ++i) {
@@ -2191,12 +2417,17 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
 
        virt_dev = xhci->devs[udev->slot_id];
 
-       /* If this is a Set Address to an unconfigured device, setup ep 0 */
-       if (!udev->config)
+       slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
+       /*
+        * If this is the first Set Address since device plug-in or
+        * virt_device realloaction after a resume with an xHCI power loss,
+        * then set up the slot context.
+        */
+       if (!slot_ctx->dev_info)
                xhci_setup_addressable_virt_dev(xhci, udev);
+       /* Otherwise, update the control endpoint ring enqueue pointer. */
        else
                xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev);
-       /* Otherwise, assume the core has the device configured how it wants */
        xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
        xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
 
@@ -2268,15 +2499,15 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
         * address given back to us by the HC.
         */
        slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
-       udev->devnum = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
+       /* Use kernel assigned address for devices; store xHC assigned
+        * address locally. */
+       virt_dev->address = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
        /* Zero the input context control for later use */
        ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
        ctrl_ctx->add_flags = 0;
        ctrl_ctx->drop_flags = 0;
 
-       xhci_dbg(xhci, "Device address = %d\n", udev->devnum);
-       /* XXX Meh, not sure if anyone else but choose_address uses this. */
-       set_bit(udev->devnum, udev->bus->devmap.devicemap);
+       xhci_dbg(xhci, "Internal device address = %d\n", virt_dev->address);
 
        return 0;
 }