aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2010-12-09 17:52:41 -0500
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-03-13 21:07:08 -0400
commit1d5810b6923c76fc95e52d9d3491c91824c2f075 (patch)
tree714c95e2f75cf703442abb4dd8f2cb522200616d /drivers/usb
parentabc4f9b099e9e7db3f6f945210aee125571c236d (diff)
xhci: Rework port suspend structures for limited ports.
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci-hub.c28
-rw-r--r--drivers/usb/host/xhci-mem.c2
-rw-r--r--drivers/usb/host/xhci.h9
3 files changed, 16 insertions, 23 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index d83c27b9725b..50e250ceee96 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -347,20 +347,15 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
347 goto error; 347 goto error;
348 } 348 }
349 xhci_ring_device(xhci, slot_id); 349 xhci_ring_device(xhci, slot_id);
350 xhci->port_c_suspend[wIndex >> 5] |= 350 xhci->port_c_suspend |= 1 << wIndex;
351 1 << (wIndex & 31); 351 xhci->suspended_ports &= ~(1 << wIndex);
352 xhci->suspended_ports[wIndex >> 5] &=
353 ~(1 << (wIndex & 31));
354 } 352 }
355 } 353 }
356 if ((temp & PORT_PLS_MASK) == XDEV_U0 354 if ((temp & PORT_PLS_MASK) == XDEV_U0
357 && (temp & PORT_POWER) 355 && (temp & PORT_POWER)
358 && (xhci->suspended_ports[wIndex >> 5] & 356 && (xhci->suspended_ports & (1 << wIndex))) {
359 (1 << (wIndex & 31)))) { 357 xhci->suspended_ports &= ~(1 << wIndex);
360 xhci->suspended_ports[wIndex >> 5] &= 358 xhci->port_c_suspend |= 1 << wIndex;
361 ~(1 << (wIndex & 31));
362 xhci->port_c_suspend[wIndex >> 5] |=
363 1 << (wIndex & 31);
364 } 359 }
365 if (temp & PORT_CONNECT) { 360 if (temp & PORT_CONNECT) {
366 status |= USB_PORT_STAT_CONNECTION; 361 status |= USB_PORT_STAT_CONNECTION;
@@ -374,7 +369,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
374 status |= USB_PORT_STAT_RESET; 369 status |= USB_PORT_STAT_RESET;
375 if (temp & PORT_POWER) 370 if (temp & PORT_POWER)
376 status |= USB_PORT_STAT_POWER; 371 status |= USB_PORT_STAT_POWER;
377 if (xhci->port_c_suspend[wIndex >> 5] & (1 << (wIndex & 31))) 372 if (xhci->port_c_suspend & (1 << wIndex))
378 status |= 1 << USB_PORT_FEAT_C_SUSPEND; 373 status |= 1 << USB_PORT_FEAT_C_SUSPEND;
379 xhci_dbg(xhci, "Get port status returned 0x%x\n", status); 374 xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
380 put_unaligned(cpu_to_le32(status), (__le32 *) buf); 375 put_unaligned(cpu_to_le32(status), (__le32 *) buf);
@@ -421,8 +416,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
421 spin_lock_irqsave(&xhci->lock, flags); 416 spin_lock_irqsave(&xhci->lock, flags);
422 417
423 temp = xhci_readl(xhci, addr); 418 temp = xhci_readl(xhci, addr);
424 xhci->suspended_ports[wIndex >> 5] |= 419 xhci->suspended_ports |= 1 << wIndex;
425 1 << (wIndex & (31));
426 break; 420 break;
427 case USB_PORT_FEAT_POWER: 421 case USB_PORT_FEAT_POWER:
428 /* 422 /*
@@ -489,8 +483,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
489 temp |= PORT_LINK_STROBE | XDEV_U0; 483 temp |= PORT_LINK_STROBE | XDEV_U0;
490 xhci_writel(xhci, temp, addr); 484 xhci_writel(xhci, temp, addr);
491 } 485 }
492 xhci->port_c_suspend[wIndex >> 5] |= 486 xhci->port_c_suspend |= 1 << wIndex;
493 1 << (wIndex & 31);
494 } 487 }
495 488
496 slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1); 489 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,
501 xhci_ring_device(xhci, slot_id); 494 xhci_ring_device(xhci, slot_id);
502 break; 495 break;
503 case USB_PORT_FEAT_C_SUSPEND: 496 case USB_PORT_FEAT_C_SUSPEND:
504 xhci->port_c_suspend[wIndex >> 5] &= 497 xhci->port_c_suspend &= ~(1 << wIndex);
505 ~(1 << (wIndex & 31));
506 case USB_PORT_FEAT_C_RESET: 498 case USB_PORT_FEAT_C_RESET:
507 case USB_PORT_FEAT_C_CONNECTION: 499 case USB_PORT_FEAT_C_CONNECTION:
508 case USB_PORT_FEAT_C_OVER_CURRENT: 500 case USB_PORT_FEAT_C_OVER_CURRENT:
@@ -560,7 +552,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
560 NUM_PORT_REGS*i; 552 NUM_PORT_REGS*i;
561 temp = xhci_readl(xhci, addr); 553 temp = xhci_readl(xhci, addr);
562 if ((temp & mask) != 0 || 554 if ((temp & mask) != 0 ||
563 (xhci->port_c_suspend[i >> 5] & 1 << (i & 31)) || 555 (xhci->port_c_suspend & 1 << i) ||
564 (xhci->resume_done[i] && time_after_eq( 556 (xhci->resume_done[i] && time_after_eq(
565 jiffies, xhci->resume_done[i]))) { 557 jiffies, xhci->resume_done[i]))) {
566 buf[(i + 1) / 8] |= 1 << (i + 1) % 8; 558 buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 1d0f45f0e7a6..e3e6410d7b5e 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1971,7 +1971,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
1971 init_completion(&xhci->addr_dev); 1971 init_completion(&xhci->addr_dev);
1972 for (i = 0; i < MAX_HC_SLOTS; ++i) 1972 for (i = 0; i < MAX_HC_SLOTS; ++i)
1973 xhci->devs[i] = NULL; 1973 xhci->devs[i] = NULL;
1974 for (i = 0; i < MAX_HC_PORTS; ++i) 1974 for (i = 0; i < USB_MAXCHILDREN; ++i)
1975 xhci->resume_done[i] = 0; 1975 xhci->resume_done[i] = 0;
1976 1976
1977 if (scratchpad_alloc(xhci, flags)) 1977 if (scratchpad_alloc(xhci, flags))
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 2cb5932935d4..c4e70c6d809c 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1248,10 +1248,11 @@ struct xhci_hcd {
1248#define XHCI_LINK_TRB_QUIRK (1 << 0) 1248#define XHCI_LINK_TRB_QUIRK (1 << 0)
1249#define XHCI_RESET_EP_QUIRK (1 << 1) 1249#define XHCI_RESET_EP_QUIRK (1 << 1)
1250#define XHCI_NEC_HOST (1 << 2) 1250#define XHCI_NEC_HOST (1 << 2)
1251 u32 port_c_suspend[8]; /* port suspend change*/ 1251 /* port suspend change*/
1252 u32 suspended_ports[8]; /* which ports are 1252 u32 port_c_suspend;
1253 suspended */ 1253 /* which ports are suspended */
1254 unsigned long resume_done[MAX_HC_PORTS]; 1254 u32 suspended_ports;
1255 unsigned long resume_done[USB_MAXCHILDREN];
1255 /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */ 1256 /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
1256 u8 *port_array; 1257 u8 *port_array;
1257 /* Array of pointers to USB 3.0 PORTSC registers */ 1258 /* Array of pointers to USB 3.0 PORTSC registers */