diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2010-12-15 15:47:14 -0500 |
---|---|---|
committer | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2011-03-13 21:23:36 -0400 |
commit | 20b67cf51fa606442bb343afad0ee1a393a6afb3 (patch) | |
tree | 1d85e8b93aff185211d065a5113beaeb68cfcb26 /drivers/usb/host/xhci-hub.c | |
parent | 5308a91b9fc1a8f94b860c2589b06908a97cba7e (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.c | 50 |
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; |