aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-hub.c
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/host/xhci-hub.c
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/host/xhci-hub.c')
-rw-r--r--drivers/usb/host/xhci-hub.c28
1 files changed, 10 insertions, 18 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;