aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-hub.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2010-12-15 15:47:14 -0500
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-03-13 21:23:36 -0400
commit20b67cf51fa606442bb343afad0ee1a393a6afb3 (patch)
tree1d85e8b93aff185211d065a5113beaeb68cfcb26 /drivers/usb/host/xhci-hub.c
parent5308a91b9fc1a8f94b860c2589b06908a97cba7e (diff)
xhci: Refactor bus suspend state into a struct.
There are several variables in the xhci_hcd structure that are related to bus suspend and resume state. There are a couple different port status arrays that are accessed by port index. Move those variables into a separate structure, xhci_bus_state. Stash that structure in xhci_hcd. When we have two roothhubs that can be suspended and resumed separately, we can have two xhci_bus_states, and index into the port arrays in each structure with the fake roothub port index (not the real hardware port index). Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb/host/xhci-hub.c')
-rw-r--r--drivers/usb/host/xhci-hub.c50
1 files changed, 29 insertions, 21 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 89ff025b41be..4944ba135f9a 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -291,6 +291,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
291 u32 __iomem *port_array[15 + USB_MAXCHILDREN]; 291 u32 __iomem *port_array[15 + USB_MAXCHILDREN];
292 int i; 292 int i;
293 int slot_id; 293 int slot_id;
294 struct xhci_bus_state *bus_state;
294 295
295 ports = HCS_MAX_PORTS(xhci->hcs_params1); 296 ports = HCS_MAX_PORTS(xhci->hcs_params1);
296 for (i = 0; i < ports; i++) { 297 for (i = 0; i < ports; i++) {
@@ -300,6 +301,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
300 port_array[i] = 301 port_array[i] =
301 xhci->usb2_ports[i - xhci->num_usb3_ports]; 302 xhci->usb2_ports[i - xhci->num_usb3_ports];
302 } 303 }
304 bus_state = &xhci->bus_state[hcd_index(hcd)];
303 305
304 spin_lock_irqsave(&xhci->lock, flags); 306 spin_lock_irqsave(&xhci->lock, flags);
305 switch (typeReq) { 307 switch (typeReq) {
@@ -336,10 +338,10 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
336 if ((temp & PORT_RESET) || !(temp & PORT_PE)) 338 if ((temp & PORT_RESET) || !(temp & PORT_PE))
337 goto error; 339 goto error;
338 if (!DEV_SUPERSPEED(temp) && time_after_eq(jiffies, 340 if (!DEV_SUPERSPEED(temp) && time_after_eq(jiffies,
339 xhci->resume_done[wIndex])) { 341 bus_state->resume_done[wIndex])) {
340 xhci_dbg(xhci, "Resume USB2 port %d\n", 342 xhci_dbg(xhci, "Resume USB2 port %d\n",
341 wIndex + 1); 343 wIndex + 1);
342 xhci->resume_done[wIndex] = 0; 344 bus_state->resume_done[wIndex] = 0;
343 temp1 = xhci_port_state_to_neutral(temp); 345 temp1 = xhci_port_state_to_neutral(temp);
344 temp1 &= ~PORT_PLS_MASK; 346 temp1 &= ~PORT_PLS_MASK;
345 temp1 |= PORT_LINK_STROBE | XDEV_U0; 347 temp1 |= PORT_LINK_STROBE | XDEV_U0;
@@ -354,15 +356,15 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
354 goto error; 356 goto error;
355 } 357 }
356 xhci_ring_device(xhci, slot_id); 358 xhci_ring_device(xhci, slot_id);
357 xhci->port_c_suspend |= 1 << wIndex; 359 bus_state->port_c_suspend |= 1 << wIndex;
358 xhci->suspended_ports &= ~(1 << wIndex); 360 bus_state->suspended_ports &= ~(1 << wIndex);
359 } 361 }
360 } 362 }
361 if ((temp & PORT_PLS_MASK) == XDEV_U0 363 if ((temp & PORT_PLS_MASK) == XDEV_U0
362 && (temp & PORT_POWER) 364 && (temp & PORT_POWER)
363 && (xhci->suspended_ports & (1 << wIndex))) { 365 && (bus_state->suspended_ports & (1 << wIndex))) {
364 xhci->suspended_ports &= ~(1 << wIndex); 366 bus_state->suspended_ports &= ~(1 << wIndex);
365 xhci->port_c_suspend |= 1 << wIndex; 367 bus_state->port_c_suspend |= 1 << wIndex;
366 } 368 }
367 if (temp & PORT_CONNECT) { 369 if (temp & PORT_CONNECT) {
368 status |= USB_PORT_STAT_CONNECTION; 370 status |= USB_PORT_STAT_CONNECTION;
@@ -376,7 +378,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
376 status |= USB_PORT_STAT_RESET; 378 status |= USB_PORT_STAT_RESET;
377 if (temp & PORT_POWER) 379 if (temp & PORT_POWER)
378 status |= USB_PORT_STAT_POWER; 380 status |= USB_PORT_STAT_POWER;
379 if (xhci->port_c_suspend & (1 << wIndex)) 381 if (bus_state->port_c_suspend & (1 << wIndex))
380 status |= 1 << USB_PORT_FEAT_C_SUSPEND; 382 status |= 1 << USB_PORT_FEAT_C_SUSPEND;
381 xhci_dbg(xhci, "Get port status returned 0x%x\n", status); 383 xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
382 put_unaligned(cpu_to_le32(status), (__le32 *) buf); 384 put_unaligned(cpu_to_le32(status), (__le32 *) buf);
@@ -422,7 +424,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
422 spin_lock_irqsave(&xhci->lock, flags); 424 spin_lock_irqsave(&xhci->lock, flags);
423 425
424 temp = xhci_readl(xhci, port_array[wIndex]); 426 temp = xhci_readl(xhci, port_array[wIndex]);
425 xhci->suspended_ports |= 1 << wIndex; 427 bus_state->suspended_ports |= 1 << wIndex;
426 break; 428 break;
427 case USB_PORT_FEAT_POWER: 429 case USB_PORT_FEAT_POWER:
428 /* 430 /*
@@ -493,7 +495,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
493 xhci_writel(xhci, temp, 495 xhci_writel(xhci, temp,
494 port_array[wIndex]); 496 port_array[wIndex]);
495 } 497 }
496 xhci->port_c_suspend |= 1 << wIndex; 498 bus_state->port_c_suspend |= 1 << wIndex;
497 } 499 }
498 500
499 slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1); 501 slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
@@ -504,7 +506,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
504 xhci_ring_device(xhci, slot_id); 506 xhci_ring_device(xhci, slot_id);
505 break; 507 break;
506 case USB_PORT_FEAT_C_SUSPEND: 508 case USB_PORT_FEAT_C_SUSPEND:
507 xhci->port_c_suspend &= ~(1 << wIndex); 509 bus_state->port_c_suspend &= ~(1 << wIndex);
508 case USB_PORT_FEAT_C_RESET: 510 case USB_PORT_FEAT_C_RESET:
509 case USB_PORT_FEAT_C_CONNECTION: 511 case USB_PORT_FEAT_C_CONNECTION:
510 case USB_PORT_FEAT_C_OVER_CURRENT: 512 case USB_PORT_FEAT_C_OVER_CURRENT:
@@ -546,6 +548,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
546 struct xhci_hcd *xhci = hcd_to_xhci(hcd); 548 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
547 int ports; 549 int ports;
548 u32 __iomem *port_array[15 + USB_MAXCHILDREN]; 550 u32 __iomem *port_array[15 + USB_MAXCHILDREN];
551 struct xhci_bus_state *bus_state;
549 552
550 ports = HCS_MAX_PORTS(xhci->hcs_params1); 553 ports = HCS_MAX_PORTS(xhci->hcs_params1);
551 for (i = 0; i < ports; i++) { 554 for (i = 0; i < ports; i++) {
@@ -555,6 +558,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
555 port_array[i] = 558 port_array[i] =
556 xhci->usb2_ports[i - xhci->num_usb3_ports]; 559 xhci->usb2_ports[i - xhci->num_usb3_ports];
557 } 560 }
561 bus_state = &xhci->bus_state[hcd_index(hcd)];
558 562
559 /* Initial status is no changes */ 563 /* Initial status is no changes */
560 retval = (ports + 8) / 8; 564 retval = (ports + 8) / 8;
@@ -568,9 +572,9 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
568 for (i = 0; i < ports; i++) { 572 for (i = 0; i < ports; i++) {
569 temp = xhci_readl(xhci, port_array[i]); 573 temp = xhci_readl(xhci, port_array[i]);
570 if ((temp & mask) != 0 || 574 if ((temp & mask) != 0 ||
571 (xhci->port_c_suspend & 1 << i) || 575 (bus_state->port_c_suspend & 1 << i) ||
572 (xhci->resume_done[i] && time_after_eq( 576 (bus_state->resume_done[i] && time_after_eq(
573 jiffies, xhci->resume_done[i]))) { 577 jiffies, bus_state->resume_done[i]))) {
574 buf[(i + 1) / 8] |= 1 << (i + 1) % 8; 578 buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
575 status = 1; 579 status = 1;
576 } 580 }
@@ -587,6 +591,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
587 int max_ports, port_index; 591 int max_ports, port_index;
588 u32 __iomem *port_array[15 + USB_MAXCHILDREN]; 592 u32 __iomem *port_array[15 + USB_MAXCHILDREN];
589 int i; 593 int i;
594 struct xhci_bus_state *bus_state;
590 unsigned long flags; 595 unsigned long flags;
591 596
592 xhci_dbg(xhci, "suspend root hub\n"); 597 xhci_dbg(xhci, "suspend root hub\n");
@@ -598,13 +603,14 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
598 port_array[i] = 603 port_array[i] =
599 xhci->usb2_ports[i - xhci->num_usb3_ports]; 604 xhci->usb2_ports[i - xhci->num_usb3_ports];
600 } 605 }
606 bus_state = &xhci->bus_state[hcd_index(hcd)];
601 607
602 spin_lock_irqsave(&xhci->lock, flags); 608 spin_lock_irqsave(&xhci->lock, flags);
603 609
604 if (hcd->self.root_hub->do_remote_wakeup) { 610 if (hcd->self.root_hub->do_remote_wakeup) {
605 port_index = max_ports; 611 port_index = max_ports;
606 while (port_index--) { 612 while (port_index--) {
607 if (xhci->resume_done[port_index] != 0) { 613 if (bus_state->resume_done[port_index] != 0) {
608 spin_unlock_irqrestore(&xhci->lock, flags); 614 spin_unlock_irqrestore(&xhci->lock, flags);
609 xhci_dbg(xhci, "suspend failed because " 615 xhci_dbg(xhci, "suspend failed because "
610 "port %d is resuming\n", 616 "port %d is resuming\n",
@@ -615,7 +621,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
615 } 621 }
616 622
617 port_index = max_ports; 623 port_index = max_ports;
618 xhci->bus_suspended = 0; 624 bus_state->bus_suspended = 0;
619 while (port_index--) { 625 while (port_index--) {
620 /* suspend the port if the port is not suspended */ 626 /* suspend the port if the port is not suspended */
621 u32 t1, t2; 627 u32 t1, t2;
@@ -635,7 +641,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
635 } 641 }
636 t2 &= ~PORT_PLS_MASK; 642 t2 &= ~PORT_PLS_MASK;
637 t2 |= PORT_LINK_STROBE | XDEV_U3; 643 t2 |= PORT_LINK_STROBE | XDEV_U3;
638 set_bit(port_index, &xhci->bus_suspended); 644 set_bit(port_index, &bus_state->bus_suspended);
639 } 645 }
640 if (hcd->self.root_hub->do_remote_wakeup) { 646 if (hcd->self.root_hub->do_remote_wakeup) {
641 if (t1 & PORT_CONNECT) { 647 if (t1 & PORT_CONNECT) {
@@ -667,7 +673,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
667 } 673 }
668 } 674 }
669 hcd->state = HC_STATE_SUSPENDED; 675 hcd->state = HC_STATE_SUSPENDED;
670 xhci->next_statechange = jiffies + msecs_to_jiffies(10); 676 bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
671 spin_unlock_irqrestore(&xhci->lock, flags); 677 spin_unlock_irqrestore(&xhci->lock, flags);
672 return 0; 678 return 0;
673} 679}
@@ -678,6 +684,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
678 int max_ports, port_index; 684 int max_ports, port_index;
679 u32 __iomem *port_array[15 + USB_MAXCHILDREN]; 685 u32 __iomem *port_array[15 + USB_MAXCHILDREN];
680 int i; 686 int i;
687 struct xhci_bus_state *bus_state;
681 u32 temp; 688 u32 temp;
682 unsigned long flags; 689 unsigned long flags;
683 690
@@ -690,8 +697,9 @@ int xhci_bus_resume(struct usb_hcd *hcd)
690 port_array[i] = 697 port_array[i] =
691 xhci->usb2_ports[i - xhci->num_usb3_ports]; 698 xhci->usb2_ports[i - xhci->num_usb3_ports];
692 } 699 }
700 bus_state = &xhci->bus_state[hcd_index(hcd)];
693 701
694 if (time_before(jiffies, xhci->next_statechange)) 702 if (time_before(jiffies, bus_state->next_statechange))
695 msleep(5); 703 msleep(5);
696 704
697 spin_lock_irqsave(&xhci->lock, flags); 705 spin_lock_irqsave(&xhci->lock, flags);
@@ -717,7 +725,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
717 temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS); 725 temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
718 else 726 else
719 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); 727 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
720 if (test_bit(port_index, &xhci->bus_suspended) && 728 if (test_bit(port_index, &bus_state->bus_suspended) &&
721 (temp & PORT_PLS_MASK)) { 729 (temp & PORT_PLS_MASK)) {
722 if (DEV_SUPERSPEED(temp)) { 730 if (DEV_SUPERSPEED(temp)) {
723 temp = xhci_port_state_to_neutral(temp); 731 temp = xhci_port_state_to_neutral(temp);
@@ -763,7 +771,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
763 771
764 (void) xhci_readl(xhci, &xhci->op_regs->command); 772 (void) xhci_readl(xhci, &xhci->op_regs->command);
765 773
766 xhci->next_statechange = jiffies + msecs_to_jiffies(5); 774 bus_state->next_statechange = jiffies + msecs_to_jiffies(5);
767 /* re-enable irqs */ 775 /* re-enable irqs */
768 temp = xhci_readl(xhci, &xhci->op_regs->command); 776 temp = xhci_readl(xhci, &xhci->op_regs->command);
769 temp |= CMD_EIE; 777 temp |= CMD_EIE;