xhci: Rework port suspend structures for limited ports.
authorSarah Sharp <sarah.a.sharp@linux.intel.com>
Thu, 9 Dec 2010 22:52:41 +0000 (14:52 -0800)
committerSarah Sharp <sarah.a.sharp@linux.intel.com>
Mon, 14 Mar 2011 01:07:08 +0000 (18:07 -0700)
The USB core only allows up to 31 (USB_MAXCHILDREN) ports under a roothub.
The xHCI driver keeps track of which ports are suspended, which ports have
a suspend change bit set, and what time the port will be done resuming.
It keeps track of the first two by setting a bit in a u32 variable,
suspended_ports or port_c_suspend.  The xHCI driver currently assumes we
can have up to 256 ports under a roothub, so it allocates an array of 8
u32 variables for both suspended_ports and port_c_suspend.  It also
allocates a 256-element array to keep track of when the ports will be done
resuming.

Since we can only have 31 roothub ports, we only need to use one u32 for
each of the suspend state and change variables.  We simplify the bit math
that's trying to index into those arrays and set the correct bit, if we
assume wIndex never exceeds 30.  (wIndex is zero-based after it's
decremented from the value passed in from the USB core.)  Finally, we
change the resume_done array to only hold 31 elements.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Cc: Andiry Xu <andiry.xu@amd.com>
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci.h

index d83c27b9725bc99f5f9ed8aa1ea1392b478e2e62..50e250ceee960f9bed6b7b1442fe6a924034aa80 100644 (file)
@@ -347,20 +347,15 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                                        goto error;
                                }
                                xhci_ring_device(xhci, slot_id);
-                               xhci->port_c_suspend[wIndex >> 5] |=
-                                               1 << (wIndex & 31);
-                               xhci->suspended_ports[wIndex >> 5] &=
-                                               ~(1 << (wIndex & 31));
+                               xhci->port_c_suspend |= 1 << wIndex;
+                               xhci->suspended_ports &= ~(1 << wIndex);
                        }
                }
                if ((temp & PORT_PLS_MASK) == XDEV_U0
                        && (temp & PORT_POWER)
-                       && (xhci->suspended_ports[wIndex >> 5] &
-                           (1 << (wIndex & 31)))) {
-                       xhci->suspended_ports[wIndex >> 5] &=
-                                       ~(1 << (wIndex & 31));
-                       xhci->port_c_suspend[wIndex >> 5] |=
-                                       1 << (wIndex & 31);
+                       && (xhci->suspended_ports & (1 << wIndex))) {
+                       xhci->suspended_ports &= ~(1 << wIndex);
+                       xhci->port_c_suspend |= 1 << wIndex;
                }
                if (temp & PORT_CONNECT) {
                        status |= USB_PORT_STAT_CONNECTION;
@@ -374,7 +369,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        status |= USB_PORT_STAT_RESET;
                if (temp & PORT_POWER)
                        status |= USB_PORT_STAT_POWER;
-               if (xhci->port_c_suspend[wIndex >> 5] & (1 << (wIndex & 31)))
+               if (xhci->port_c_suspend & (1 << wIndex))
                        status |= 1 << USB_PORT_FEAT_C_SUSPEND;
                xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
                put_unaligned(cpu_to_le32(status), (__le32 *) buf);
@@ -421,8 +416,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        spin_lock_irqsave(&xhci->lock, flags);
 
                        temp = xhci_readl(xhci, addr);
-                       xhci->suspended_ports[wIndex >> 5] |=
-                                       1 << (wIndex & (31));
+                       xhci->suspended_ports |= 1 << wIndex;
                        break;
                case USB_PORT_FEAT_POWER:
                        /*
@@ -489,8 +483,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                                        temp |= PORT_LINK_STROBE | XDEV_U0;
                                        xhci_writel(xhci, temp, addr);
                                }
-                               xhci->port_c_suspend[wIndex >> 5] |=
-                                               1 << (wIndex & 31);
+                               xhci->port_c_suspend |= 1 << wIndex;
                        }
 
                        slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
@@ -501,8 +494,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        xhci_ring_device(xhci, slot_id);
                        break;
                case USB_PORT_FEAT_C_SUSPEND:
-                       xhci->port_c_suspend[wIndex >> 5] &=
-                                       ~(1 << (wIndex & 31));
+                       xhci->port_c_suspend &= ~(1 << wIndex);
                case USB_PORT_FEAT_C_RESET:
                case USB_PORT_FEAT_C_CONNECTION:
                case USB_PORT_FEAT_C_OVER_CURRENT:
@@ -560,7 +552,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
                        NUM_PORT_REGS*i;
                temp = xhci_readl(xhci, addr);
                if ((temp & mask) != 0 ||
-                       (xhci->port_c_suspend[i >> 5] & 1 << (i & 31)) ||
+                       (xhci->port_c_suspend & 1 << i) ||
                        (xhci->resume_done[i] && time_after_eq(
                            jiffies, xhci->resume_done[i]))) {
                        buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
index 1d0f45f0e7a62fd191d4c856d0de87715456bfbf..e3e6410d7b5e7fc5fc74a0470cbe3c889d204b48 100644 (file)
@@ -1971,7 +1971,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        init_completion(&xhci->addr_dev);
        for (i = 0; i < MAX_HC_SLOTS; ++i)
                xhci->devs[i] = NULL;
-       for (i = 0; i < MAX_HC_PORTS; ++i)
+       for (i = 0; i < USB_MAXCHILDREN; ++i)
                xhci->resume_done[i] = 0;
 
        if (scratchpad_alloc(xhci, flags))
index 2cb5932935d4444bf4580987803ae58900f20d44..c4e70c6d809ca8eec3e9dc8e288e2af37a966801 100644 (file)
@@ -1248,10 +1248,11 @@ struct xhci_hcd {
 #define        XHCI_LINK_TRB_QUIRK     (1 << 0)
 #define XHCI_RESET_EP_QUIRK    (1 << 1)
 #define XHCI_NEC_HOST          (1 << 2)
-       u32                     port_c_suspend[8];      /* port suspend change*/
-       u32                     suspended_ports[8];     /* which ports are
-                                                          suspended */
-       unsigned long           resume_done[MAX_HC_PORTS];
+       /* port suspend change*/
+       u32                     port_c_suspend;
+       /* which ports are suspended */
+       u32                     suspended_ports;
+       unsigned long           resume_done[USB_MAXCHILDREN];
        /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
        u8                      *port_array;
        /* Array of pointers to USB 3.0 PORTSC registers */