xhci: Refactor port status into a new function.
authorSarah Sharp <sarah.a.sharp@linux.intel.com>
Tue, 2 Apr 2013 15:42:20 +0000 (08:42 -0700)
committerSarah Sharp <sarah.a.sharp@linux.intel.com>
Tue, 23 Jul 2013 21:19:19 +0000 (14:19 -0700)
The hub control function is *way* too long.  Refactor it into a new
function, and document the side effects of calling that function.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
drivers/usb/host/xhci-hub.c

index 1d3545943c50a792de25a35a4cfc150b4c5ac347..83fc636fa254e9a6bbd48d1f3173eaad59902b92 100644 (file)
@@ -534,6 +534,118 @@ void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex)
        }
 }
 
+/*
+ * Converts a raw xHCI port status into the format that external USB 2.0 or USB
+ * 3.0 hubs use.
+ *
+ * Possible side effects:
+ *  - Mark a port as being done with device resume,
+ *    and ring the endpoint doorbells.
+ *  - Stop the Synopsys redriver Compliance Mode polling.
+ */
+static u32 xhci_get_port_status(struct usb_hcd *hcd,
+               struct xhci_bus_state *bus_state,
+               __le32 __iomem **port_array,
+               u16 wIndex, u32 raw_port_status)
+{
+       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+       u32 status = 0;
+       int slot_id;
+
+       /* wPortChange bits */
+       if (raw_port_status & PORT_CSC)
+               status |= USB_PORT_STAT_C_CONNECTION << 16;
+       if (raw_port_status & PORT_PEC)
+               status |= USB_PORT_STAT_C_ENABLE << 16;
+       if ((raw_port_status & PORT_OCC))
+               status |= USB_PORT_STAT_C_OVERCURRENT << 16;
+       if ((raw_port_status & PORT_RC))
+               status |= USB_PORT_STAT_C_RESET << 16;
+       /* USB3.0 only */
+       if (hcd->speed == HCD_USB3) {
+               if ((raw_port_status & PORT_PLC))
+                       status |= USB_PORT_STAT_C_LINK_STATE << 16;
+               if ((raw_port_status & PORT_WRC))
+                       status |= USB_PORT_STAT_C_BH_RESET << 16;
+       }
+
+       if (hcd->speed != HCD_USB3) {
+               if ((raw_port_status & PORT_PLS_MASK) == XDEV_U3
+                               && (raw_port_status & PORT_POWER))
+                       status |= USB_PORT_STAT_SUSPEND;
+       }
+       if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME &&
+                       !DEV_SUPERSPEED(raw_port_status)) {
+               if ((raw_port_status & PORT_RESET) ||
+                               !(raw_port_status & PORT_PE))
+                       return 0xffffffff;
+               if (time_after_eq(jiffies,
+                                       bus_state->resume_done[wIndex])) {
+                       xhci_dbg(xhci, "Resume USB2 port %d\n",
+                                       wIndex + 1);
+                       bus_state->resume_done[wIndex] = 0;
+                       clear_bit(wIndex, &bus_state->resuming_ports);
+                       xhci_set_link_state(xhci, port_array, wIndex,
+                                       XDEV_U0);
+                       xhci_dbg(xhci, "set port %d resume\n",
+                                       wIndex + 1);
+                       slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+                                       wIndex + 1);
+                       if (!slot_id) {
+                               xhci_dbg(xhci, "slot_id is zero\n");
+                               return 0xffffffff;
+                       }
+                       xhci_ring_device(xhci, slot_id);
+                       bus_state->port_c_suspend |= 1 << wIndex;
+                       bus_state->suspended_ports &= ~(1 << wIndex);
+               } else {
+                       /*
+                        * The resume has been signaling for less than
+                        * 20ms. Report the port status as SUSPEND,
+                        * let the usbcore check port status again
+                        * and clear resume signaling later.
+                        */
+                       status |= USB_PORT_STAT_SUSPEND;
+               }
+       }
+       if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0
+                       && (raw_port_status & PORT_POWER)
+                       && (bus_state->suspended_ports & (1 << wIndex))) {
+               bus_state->suspended_ports &= ~(1 << wIndex);
+               if (hcd->speed != HCD_USB3)
+                       bus_state->port_c_suspend |= 1 << wIndex;
+       }
+       if (raw_port_status & PORT_CONNECT) {
+               status |= USB_PORT_STAT_CONNECTION;
+               status |= xhci_port_speed(raw_port_status);
+       }
+       if (raw_port_status & PORT_PE)
+               status |= USB_PORT_STAT_ENABLE;
+       if (raw_port_status & PORT_OC)
+               status |= USB_PORT_STAT_OVERCURRENT;
+       if (raw_port_status & PORT_RESET)
+               status |= USB_PORT_STAT_RESET;
+       if (raw_port_status & PORT_POWER) {
+               if (hcd->speed == HCD_USB3)
+                       status |= USB_SS_PORT_STAT_POWER;
+               else
+                       status |= USB_PORT_STAT_POWER;
+       }
+       /* Update Port Link State for super speed ports*/
+       if (hcd->speed == HCD_USB3) {
+               xhci_hub_report_link_state(&status, raw_port_status);
+               /*
+                * Verify if all USB3 Ports Have entered U0 already.
+                * Delete Compliance Mode Timer if so.
+                */
+               xhci_del_comp_mod_timer(xhci, raw_port_status, wIndex);
+       }
+       if (bus_state->port_c_suspend & (1 << wIndex))
+               status |= 1 << USB_PORT_FEAT_C_SUSPEND;
+
+       return status;
+}
+
 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                u16 wIndex, char *buf, u16 wLength)
 {
@@ -598,104 +710,20 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                if (!wIndex || wIndex > max_ports)
                        goto error;
                wIndex--;
-               status = 0;
                temp = xhci_readl(xhci, port_array[wIndex]);
                if (temp == 0xffffffff) {
                        retval = -ENODEV;
                        break;
                }
-               xhci_dbg(xhci, "get port status, actual port %d status  = 0x%x\n", wIndex, temp);
-
-               /* wPortChange bits */
-               if (temp & PORT_CSC)
-                       status |= USB_PORT_STAT_C_CONNECTION << 16;
-               if (temp & PORT_PEC)
-                       status |= USB_PORT_STAT_C_ENABLE << 16;
-               if ((temp & PORT_OCC))
-                       status |= USB_PORT_STAT_C_OVERCURRENT << 16;
-               if ((temp & PORT_RC))
-                       status |= USB_PORT_STAT_C_RESET << 16;
-               /* USB3.0 only */
-               if (hcd->speed == HCD_USB3) {
-                       if ((temp & PORT_PLC))
-                               status |= USB_PORT_STAT_C_LINK_STATE << 16;
-                       if ((temp & PORT_WRC))
-                               status |= USB_PORT_STAT_C_BH_RESET << 16;
-               }
+               status = xhci_get_port_status(hcd, bus_state, port_array,
+                               wIndex, temp);
+               if (status == 0xffffffff)
+                       goto error;
 
-               if (hcd->speed != HCD_USB3) {
-                       if ((temp & PORT_PLS_MASK) == XDEV_U3
-                                       && (temp & PORT_POWER))
-                               status |= USB_PORT_STAT_SUSPEND;
-               }
-               if ((temp & PORT_PLS_MASK) == XDEV_RESUME &&
-                               !DEV_SUPERSPEED(temp)) {
-                       if ((temp & PORT_RESET) || !(temp & PORT_PE))
-                               goto error;
-                       if (time_after_eq(jiffies,
-                                       bus_state->resume_done[wIndex])) {
-                               xhci_dbg(xhci, "Resume USB2 port %d\n",
-                                       wIndex + 1);
-                               bus_state->resume_done[wIndex] = 0;
-                               clear_bit(wIndex, &bus_state->resuming_ports);
-                               xhci_set_link_state(xhci, port_array, wIndex,
-                                                       XDEV_U0);
-                               xhci_dbg(xhci, "set port %d resume\n",
-                                       wIndex + 1);
-                               slot_id = xhci_find_slot_id_by_port(hcd, xhci,
-                                                                wIndex + 1);
-                               if (!slot_id) {
-                                       xhci_dbg(xhci, "slot_id is zero\n");
-                                       goto error;
-                               }
-                               xhci_ring_device(xhci, slot_id);
-                               bus_state->port_c_suspend |= 1 << wIndex;
-                               bus_state->suspended_ports &= ~(1 << wIndex);
-                       } else {
-                               /*
-                                * The resume has been signaling for less than
-                                * 20ms. Report the port status as SUSPEND,
-                                * let the usbcore check port status again
-                                * and clear resume signaling later.
-                                */
-                               status |= USB_PORT_STAT_SUSPEND;
-                       }
-               }
-               if ((temp & PORT_PLS_MASK) == XDEV_U0
-                       && (temp & PORT_POWER)
-                       && (bus_state->suspended_ports & (1 << wIndex))) {
-                       bus_state->suspended_ports &= ~(1 << wIndex);
-                       if (hcd->speed != HCD_USB3)
-                               bus_state->port_c_suspend |= 1 << wIndex;
-               }
-               if (temp & PORT_CONNECT) {
-                       status |= USB_PORT_STAT_CONNECTION;
-                       status |= xhci_port_speed(temp);
-               }
-               if (temp & PORT_PE)
-                       status |= USB_PORT_STAT_ENABLE;
-               if (temp & PORT_OC)
-                       status |= USB_PORT_STAT_OVERCURRENT;
-               if (temp & PORT_RESET)
-                       status |= USB_PORT_STAT_RESET;
-               if (temp & PORT_POWER) {
-                       if (hcd->speed == HCD_USB3)
-                               status |= USB_SS_PORT_STAT_POWER;
-                       else
-                               status |= USB_PORT_STAT_POWER;
-               }
-               /* Update Port Link State for super speed ports*/
-               if (hcd->speed == HCD_USB3) {
-                       xhci_hub_report_link_state(&status, temp);
-                       /*
-                        * Verify if all USB3 Ports Have entered U0 already.
-                        * Delete Compliance Mode Timer if so.
-                        */
-                       xhci_del_comp_mod_timer(xhci, temp, wIndex);
-               }
-               if (bus_state->port_c_suspend & (1 << wIndex))
-                       status |= 1 << USB_PORT_FEAT_C_SUSPEND;
+               xhci_dbg(xhci, "get port status, actual port %d status  = 0x%x\n",
+                               wIndex, temp);
                xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
+
                put_unaligned(cpu_to_le32(status), (__le32 *) buf);
                break;
        case SetPortFeature: