diff options
Diffstat (limited to 'drivers/usb/host/xhci-hub.c')
-rw-r--r-- | drivers/usb/host/xhci-hub.c | 231 |
1 files changed, 143 insertions, 88 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 73f75d26436c..0be788cc2fdb 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c | |||
@@ -50,7 +50,7 @@ static void xhci_common_hub_descriptor(struct xhci_hcd *xhci, | |||
50 | temp |= 0x0008; | 50 | temp |= 0x0008; |
51 | /* Bits 6:5 - no TTs in root ports */ | 51 | /* Bits 6:5 - no TTs in root ports */ |
52 | /* Bit 7 - no port indicators */ | 52 | /* Bit 7 - no port indicators */ |
53 | desc->wHubCharacteristics = (__force __u16) cpu_to_le16(temp); | 53 | desc->wHubCharacteristics = cpu_to_le16(temp); |
54 | } | 54 | } |
55 | 55 | ||
56 | /* Fill in the USB 2.0 roothub descriptor */ | 56 | /* Fill in the USB 2.0 roothub descriptor */ |
@@ -314,7 +314,7 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id) | |||
314 | } | 314 | } |
315 | 315 | ||
316 | static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, | 316 | static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, |
317 | u16 wIndex, u32 __iomem *addr, u32 port_status) | 317 | u16 wIndex, __le32 __iomem *addr, u32 port_status) |
318 | { | 318 | { |
319 | /* Don't allow the USB core to disable SuperSpeed ports. */ | 319 | /* Don't allow the USB core to disable SuperSpeed ports. */ |
320 | if (hcd->speed == HCD_USB3) { | 320 | if (hcd->speed == HCD_USB3) { |
@@ -331,7 +331,7 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, | |||
331 | } | 331 | } |
332 | 332 | ||
333 | static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, | 333 | static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, |
334 | u16 wIndex, u32 __iomem *addr, u32 port_status) | 334 | u16 wIndex, __le32 __iomem *addr, u32 port_status) |
335 | { | 335 | { |
336 | char *port_change_bit; | 336 | char *port_change_bit; |
337 | u32 status; | 337 | u32 status; |
@@ -341,6 +341,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, | |||
341 | status = PORT_RC; | 341 | status = PORT_RC; |
342 | port_change_bit = "reset"; | 342 | port_change_bit = "reset"; |
343 | break; | 343 | break; |
344 | case USB_PORT_FEAT_C_BH_PORT_RESET: | ||
345 | status = PORT_WRC; | ||
346 | port_change_bit = "warm(BH) reset"; | ||
347 | break; | ||
344 | case USB_PORT_FEAT_C_CONNECTION: | 348 | case USB_PORT_FEAT_C_CONNECTION: |
345 | status = PORT_CSC; | 349 | status = PORT_CSC; |
346 | port_change_bit = "connect"; | 350 | port_change_bit = "connect"; |
@@ -357,6 +361,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, | |||
357 | status = PORT_PLC; | 361 | status = PORT_PLC; |
358 | port_change_bit = "suspend/resume"; | 362 | port_change_bit = "suspend/resume"; |
359 | break; | 363 | break; |
364 | case USB_PORT_FEAT_C_PORT_LINK_STATE: | ||
365 | status = PORT_PLC; | ||
366 | port_change_bit = "link state"; | ||
367 | break; | ||
360 | default: | 368 | default: |
361 | /* Should never happen */ | 369 | /* Should never happen */ |
362 | return; | 370 | return; |
@@ -368,25 +376,36 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, | |||
368 | port_change_bit, wIndex, port_status); | 376 | port_change_bit, wIndex, port_status); |
369 | } | 377 | } |
370 | 378 | ||
379 | static int xhci_get_ports(struct usb_hcd *hcd, __le32 __iomem ***port_array) | ||
380 | { | ||
381 | int max_ports; | ||
382 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
383 | |||
384 | if (hcd->speed == HCD_USB3) { | ||
385 | max_ports = xhci->num_usb3_ports; | ||
386 | *port_array = xhci->usb3_ports; | ||
387 | } else { | ||
388 | max_ports = xhci->num_usb2_ports; | ||
389 | *port_array = xhci->usb2_ports; | ||
390 | } | ||
391 | |||
392 | return max_ports; | ||
393 | } | ||
394 | |||
371 | int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | 395 | int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, |
372 | u16 wIndex, char *buf, u16 wLength) | 396 | u16 wIndex, char *buf, u16 wLength) |
373 | { | 397 | { |
374 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 398 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
375 | int ports; | 399 | int max_ports; |
376 | unsigned long flags; | 400 | unsigned long flags; |
377 | u32 temp, temp1, status; | 401 | u32 temp, temp1, status; |
378 | int retval = 0; | 402 | int retval = 0; |
379 | u32 __iomem **port_array; | 403 | __le32 __iomem **port_array; |
380 | int slot_id; | 404 | int slot_id; |
381 | struct xhci_bus_state *bus_state; | 405 | struct xhci_bus_state *bus_state; |
406 | u16 link_state = 0; | ||
382 | 407 | ||
383 | if (hcd->speed == HCD_USB3) { | 408 | max_ports = xhci_get_ports(hcd, &port_array); |
384 | ports = xhci->num_usb3_ports; | ||
385 | port_array = xhci->usb3_ports; | ||
386 | } else { | ||
387 | ports = xhci->num_usb2_ports; | ||
388 | port_array = xhci->usb2_ports; | ||
389 | } | ||
390 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 409 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
391 | 410 | ||
392 | spin_lock_irqsave(&xhci->lock, flags); | 411 | spin_lock_irqsave(&xhci->lock, flags); |
@@ -411,7 +430,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
411 | (struct usb_hub_descriptor *) buf); | 430 | (struct usb_hub_descriptor *) buf); |
412 | break; | 431 | break; |
413 | case GetPortStatus: | 432 | case GetPortStatus: |
414 | if (!wIndex || wIndex > ports) | 433 | if (!wIndex || wIndex > max_ports) |
415 | goto error; | 434 | goto error; |
416 | wIndex--; | 435 | wIndex--; |
417 | status = 0; | 436 | status = 0; |
@@ -422,9 +441,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
422 | } | 441 | } |
423 | xhci_dbg(xhci, "get port status, actual port %d status = 0x%x\n", wIndex, temp); | 442 | xhci_dbg(xhci, "get port status, actual port %d status = 0x%x\n", wIndex, temp); |
424 | 443 | ||
425 | /* FIXME - should we return a port status value like the USB | ||
426 | * 3.0 external hubs do? | ||
427 | */ | ||
428 | /* wPortChange bits */ | 444 | /* wPortChange bits */ |
429 | if (temp & PORT_CSC) | 445 | if (temp & PORT_CSC) |
430 | status |= USB_PORT_STAT_C_CONNECTION << 16; | 446 | status |= USB_PORT_STAT_C_CONNECTION << 16; |
@@ -432,13 +448,21 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
432 | status |= USB_PORT_STAT_C_ENABLE << 16; | 448 | status |= USB_PORT_STAT_C_ENABLE << 16; |
433 | if ((temp & PORT_OCC)) | 449 | if ((temp & PORT_OCC)) |
434 | status |= USB_PORT_STAT_C_OVERCURRENT << 16; | 450 | status |= USB_PORT_STAT_C_OVERCURRENT << 16; |
435 | /* | 451 | if ((temp & PORT_RC)) |
436 | * FIXME ignoring reset and USB 2.1/3.0 specific | 452 | status |= USB_PORT_STAT_C_RESET << 16; |
437 | * changes | 453 | /* USB3.0 only */ |
438 | */ | 454 | if (hcd->speed == HCD_USB3) { |
439 | if ((temp & PORT_PLS_MASK) == XDEV_U3 | 455 | if ((temp & PORT_PLC)) |
440 | && (temp & PORT_POWER)) | 456 | status |= USB_PORT_STAT_C_LINK_STATE << 16; |
441 | status |= 1 << USB_PORT_FEAT_SUSPEND; | 457 | if ((temp & PORT_WRC)) |
458 | status |= USB_PORT_STAT_C_BH_RESET << 16; | ||
459 | } | ||
460 | |||
461 | if (hcd->speed != HCD_USB3) { | ||
462 | if ((temp & PORT_PLS_MASK) == XDEV_U3 | ||
463 | && (temp & PORT_POWER)) | ||
464 | status |= USB_PORT_STAT_SUSPEND; | ||
465 | } | ||
442 | if ((temp & PORT_PLS_MASK) == XDEV_RESUME) { | 466 | if ((temp & PORT_PLS_MASK) == XDEV_RESUME) { |
443 | if ((temp & PORT_RESET) || !(temp & PORT_PE)) | 467 | if ((temp & PORT_RESET) || !(temp & PORT_PE)) |
444 | goto error; | 468 | goto error; |
@@ -469,7 +493,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
469 | && (temp & PORT_POWER) | 493 | && (temp & PORT_POWER) |
470 | && (bus_state->suspended_ports & (1 << wIndex))) { | 494 | && (bus_state->suspended_ports & (1 << wIndex))) { |
471 | bus_state->suspended_ports &= ~(1 << wIndex); | 495 | bus_state->suspended_ports &= ~(1 << wIndex); |
472 | bus_state->port_c_suspend |= 1 << wIndex; | 496 | if (hcd->speed != HCD_USB3) |
497 | bus_state->port_c_suspend |= 1 << wIndex; | ||
473 | } | 498 | } |
474 | if (temp & PORT_CONNECT) { | 499 | if (temp & PORT_CONNECT) { |
475 | status |= USB_PORT_STAT_CONNECTION; | 500 | status |= USB_PORT_STAT_CONNECTION; |
@@ -481,16 +506,30 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
481 | status |= USB_PORT_STAT_OVERCURRENT; | 506 | status |= USB_PORT_STAT_OVERCURRENT; |
482 | if (temp & PORT_RESET) | 507 | if (temp & PORT_RESET) |
483 | status |= USB_PORT_STAT_RESET; | 508 | status |= USB_PORT_STAT_RESET; |
484 | if (temp & PORT_POWER) | 509 | if (temp & PORT_POWER) { |
485 | status |= USB_PORT_STAT_POWER; | 510 | if (hcd->speed == HCD_USB3) |
511 | status |= USB_SS_PORT_STAT_POWER; | ||
512 | else | ||
513 | status |= USB_PORT_STAT_POWER; | ||
514 | } | ||
515 | /* Port Link State */ | ||
516 | if (hcd->speed == HCD_USB3) { | ||
517 | /* resume state is a xHCI internal state. | ||
518 | * Do not report it to usb core. | ||
519 | */ | ||
520 | if ((temp & PORT_PLS_MASK) != XDEV_RESUME) | ||
521 | status |= (temp & PORT_PLS_MASK); | ||
522 | } | ||
486 | if (bus_state->port_c_suspend & (1 << wIndex)) | 523 | if (bus_state->port_c_suspend & (1 << wIndex)) |
487 | status |= 1 << USB_PORT_FEAT_C_SUSPEND; | 524 | status |= 1 << USB_PORT_FEAT_C_SUSPEND; |
488 | xhci_dbg(xhci, "Get port status returned 0x%x\n", status); | 525 | xhci_dbg(xhci, "Get port status returned 0x%x\n", status); |
489 | put_unaligned(cpu_to_le32(status), (__le32 *) buf); | 526 | put_unaligned(cpu_to_le32(status), (__le32 *) buf); |
490 | break; | 527 | break; |
491 | case SetPortFeature: | 528 | case SetPortFeature: |
529 | if (wValue == USB_PORT_FEAT_LINK_STATE) | ||
530 | link_state = (wIndex & 0xff00) >> 3; | ||
492 | wIndex &= 0xff; | 531 | wIndex &= 0xff; |
493 | if (!wIndex || wIndex > ports) | 532 | if (!wIndex || wIndex > max_ports) |
494 | goto error; | 533 | goto error; |
495 | wIndex--; | 534 | wIndex--; |
496 | temp = xhci_readl(xhci, port_array[wIndex]); | 535 | temp = xhci_readl(xhci, port_array[wIndex]); |
@@ -537,6 +576,44 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
537 | temp = xhci_readl(xhci, port_array[wIndex]); | 576 | temp = xhci_readl(xhci, port_array[wIndex]); |
538 | bus_state->suspended_ports |= 1 << wIndex; | 577 | bus_state->suspended_ports |= 1 << wIndex; |
539 | break; | 578 | break; |
579 | case USB_PORT_FEAT_LINK_STATE: | ||
580 | temp = xhci_readl(xhci, port_array[wIndex]); | ||
581 | /* Software should not attempt to set | ||
582 | * port link state above '5' (Rx.Detect) and the port | ||
583 | * must be enabled. | ||
584 | */ | ||
585 | if ((temp & PORT_PE) == 0 || | ||
586 | (link_state > USB_SS_PORT_LS_RX_DETECT)) { | ||
587 | xhci_warn(xhci, "Cannot set link state.\n"); | ||
588 | goto error; | ||
589 | } | ||
590 | |||
591 | if (link_state == USB_SS_PORT_LS_U3) { | ||
592 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, | ||
593 | wIndex + 1); | ||
594 | if (slot_id) { | ||
595 | /* unlock to execute stop endpoint | ||
596 | * commands */ | ||
597 | spin_unlock_irqrestore(&xhci->lock, | ||
598 | flags); | ||
599 | xhci_stop_device(xhci, slot_id, 1); | ||
600 | spin_lock_irqsave(&xhci->lock, flags); | ||
601 | } | ||
602 | } | ||
603 | |||
604 | temp = xhci_port_state_to_neutral(temp); | ||
605 | temp &= ~PORT_PLS_MASK; | ||
606 | temp |= PORT_LINK_STROBE | link_state; | ||
607 | xhci_writel(xhci, temp, port_array[wIndex]); | ||
608 | |||
609 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
610 | msleep(20); /* wait device to enter */ | ||
611 | spin_lock_irqsave(&xhci->lock, flags); | ||
612 | |||
613 | temp = xhci_readl(xhci, port_array[wIndex]); | ||
614 | if (link_state == USB_SS_PORT_LS_U3) | ||
615 | bus_state->suspended_ports |= 1 << wIndex; | ||
616 | break; | ||
540 | case USB_PORT_FEAT_POWER: | 617 | case USB_PORT_FEAT_POWER: |
541 | /* | 618 | /* |
542 | * Turn on ports, even if there isn't per-port switching. | 619 | * Turn on ports, even if there isn't per-port switching. |
@@ -557,6 +634,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
557 | temp = xhci_readl(xhci, port_array[wIndex]); | 634 | temp = xhci_readl(xhci, port_array[wIndex]); |
558 | xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp); | 635 | xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp); |
559 | break; | 636 | break; |
637 | case USB_PORT_FEAT_BH_PORT_RESET: | ||
638 | temp |= PORT_WR; | ||
639 | xhci_writel(xhci, temp, port_array[wIndex]); | ||
640 | |||
641 | temp = xhci_readl(xhci, port_array[wIndex]); | ||
642 | break; | ||
560 | default: | 643 | default: |
561 | goto error; | 644 | goto error; |
562 | } | 645 | } |
@@ -564,7 +647,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
564 | temp = xhci_readl(xhci, port_array[wIndex]); | 647 | temp = xhci_readl(xhci, port_array[wIndex]); |
565 | break; | 648 | break; |
566 | case ClearPortFeature: | 649 | case ClearPortFeature: |
567 | if (!wIndex || wIndex > ports) | 650 | if (!wIndex || wIndex > max_ports) |
568 | goto error; | 651 | goto error; |
569 | wIndex--; | 652 | wIndex--; |
570 | temp = xhci_readl(xhci, port_array[wIndex]); | 653 | temp = xhci_readl(xhci, port_array[wIndex]); |
@@ -584,35 +667,27 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
584 | if (temp & XDEV_U3) { | 667 | if (temp & XDEV_U3) { |
585 | if ((temp & PORT_PE) == 0) | 668 | if ((temp & PORT_PE) == 0) |
586 | goto error; | 669 | goto error; |
587 | if (DEV_SUPERSPEED(temp)) { | ||
588 | temp = xhci_port_state_to_neutral(temp); | ||
589 | temp &= ~PORT_PLS_MASK; | ||
590 | temp |= PORT_LINK_STROBE | XDEV_U0; | ||
591 | xhci_writel(xhci, temp, | ||
592 | port_array[wIndex]); | ||
593 | xhci_readl(xhci, port_array[wIndex]); | ||
594 | } else { | ||
595 | temp = xhci_port_state_to_neutral(temp); | ||
596 | temp &= ~PORT_PLS_MASK; | ||
597 | temp |= PORT_LINK_STROBE | XDEV_RESUME; | ||
598 | xhci_writel(xhci, temp, | ||
599 | port_array[wIndex]); | ||
600 | 670 | ||
601 | spin_unlock_irqrestore(&xhci->lock, | 671 | temp = xhci_port_state_to_neutral(temp); |
602 | flags); | 672 | temp &= ~PORT_PLS_MASK; |
603 | msleep(20); | 673 | temp |= PORT_LINK_STROBE | XDEV_RESUME; |
604 | spin_lock_irqsave(&xhci->lock, flags); | 674 | xhci_writel(xhci, temp, |
675 | port_array[wIndex]); | ||
605 | 676 | ||
606 | temp = xhci_readl(xhci, | 677 | spin_unlock_irqrestore(&xhci->lock, |
607 | port_array[wIndex]); | 678 | flags); |
608 | temp = xhci_port_state_to_neutral(temp); | 679 | msleep(20); |
609 | temp &= ~PORT_PLS_MASK; | 680 | spin_lock_irqsave(&xhci->lock, flags); |
610 | temp |= PORT_LINK_STROBE | XDEV_U0; | 681 | |
611 | xhci_writel(xhci, temp, | 682 | temp = xhci_readl(xhci, |
612 | port_array[wIndex]); | 683 | port_array[wIndex]); |
613 | } | 684 | temp = xhci_port_state_to_neutral(temp); |
614 | bus_state->port_c_suspend |= 1 << wIndex; | 685 | temp &= ~PORT_PLS_MASK; |
686 | temp |= PORT_LINK_STROBE | XDEV_U0; | ||
687 | xhci_writel(xhci, temp, | ||
688 | port_array[wIndex]); | ||
615 | } | 689 | } |
690 | bus_state->port_c_suspend |= 1 << wIndex; | ||
616 | 691 | ||
617 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, | 692 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, |
618 | wIndex + 1); | 693 | wIndex + 1); |
@@ -625,9 +700,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
625 | case USB_PORT_FEAT_C_SUSPEND: | 700 | case USB_PORT_FEAT_C_SUSPEND: |
626 | bus_state->port_c_suspend &= ~(1 << wIndex); | 701 | bus_state->port_c_suspend &= ~(1 << wIndex); |
627 | case USB_PORT_FEAT_C_RESET: | 702 | case USB_PORT_FEAT_C_RESET: |
703 | case USB_PORT_FEAT_C_BH_PORT_RESET: | ||
628 | case USB_PORT_FEAT_C_CONNECTION: | 704 | case USB_PORT_FEAT_C_CONNECTION: |
629 | case USB_PORT_FEAT_C_OVER_CURRENT: | 705 | case USB_PORT_FEAT_C_OVER_CURRENT: |
630 | case USB_PORT_FEAT_C_ENABLE: | 706 | case USB_PORT_FEAT_C_ENABLE: |
707 | case USB_PORT_FEAT_C_PORT_LINK_STATE: | ||
631 | xhci_clear_port_change_bit(xhci, wValue, wIndex, | 708 | xhci_clear_port_change_bit(xhci, wValue, wIndex, |
632 | port_array[wIndex], temp); | 709 | port_array[wIndex], temp); |
633 | break; | 710 | break; |
@@ -663,29 +740,23 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
663 | u32 mask; | 740 | u32 mask; |
664 | int i, retval; | 741 | int i, retval; |
665 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 742 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
666 | int ports; | 743 | int max_ports; |
667 | u32 __iomem **port_array; | 744 | __le32 __iomem **port_array; |
668 | struct xhci_bus_state *bus_state; | 745 | struct xhci_bus_state *bus_state; |
669 | 746 | ||
670 | if (hcd->speed == HCD_USB3) { | 747 | max_ports = xhci_get_ports(hcd, &port_array); |
671 | ports = xhci->num_usb3_ports; | ||
672 | port_array = xhci->usb3_ports; | ||
673 | } else { | ||
674 | ports = xhci->num_usb2_ports; | ||
675 | port_array = xhci->usb2_ports; | ||
676 | } | ||
677 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 748 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
678 | 749 | ||
679 | /* Initial status is no changes */ | 750 | /* Initial status is no changes */ |
680 | retval = (ports + 8) / 8; | 751 | retval = (max_ports + 8) / 8; |
681 | memset(buf, 0, retval); | 752 | memset(buf, 0, retval); |
682 | status = 0; | 753 | status = 0; |
683 | 754 | ||
684 | mask = PORT_CSC | PORT_PEC | PORT_OCC; | 755 | mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC; |
685 | 756 | ||
686 | spin_lock_irqsave(&xhci->lock, flags); | 757 | spin_lock_irqsave(&xhci->lock, flags); |
687 | /* For each port, did anything change? If so, set that bit in buf. */ | 758 | /* For each port, did anything change? If so, set that bit in buf. */ |
688 | for (i = 0; i < ports; i++) { | 759 | for (i = 0; i < max_ports; i++) { |
689 | temp = xhci_readl(xhci, port_array[i]); | 760 | temp = xhci_readl(xhci, port_array[i]); |
690 | if (temp == 0xffffffff) { | 761 | if (temp == 0xffffffff) { |
691 | retval = -ENODEV; | 762 | retval = -ENODEV; |
@@ -709,19 +780,11 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
709 | { | 780 | { |
710 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 781 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
711 | int max_ports, port_index; | 782 | int max_ports, port_index; |
712 | u32 __iomem **port_array; | 783 | __le32 __iomem **port_array; |
713 | struct xhci_bus_state *bus_state; | 784 | struct xhci_bus_state *bus_state; |
714 | unsigned long flags; | 785 | unsigned long flags; |
715 | 786 | ||
716 | if (hcd->speed == HCD_USB3) { | 787 | max_ports = xhci_get_ports(hcd, &port_array); |
717 | max_ports = xhci->num_usb3_ports; | ||
718 | port_array = xhci->usb3_ports; | ||
719 | xhci_dbg(xhci, "suspend USB 3.0 root hub\n"); | ||
720 | } else { | ||
721 | max_ports = xhci->num_usb2_ports; | ||
722 | port_array = xhci->usb2_ports; | ||
723 | xhci_dbg(xhci, "suspend USB 2.0 root hub\n"); | ||
724 | } | ||
725 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 788 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
726 | 789 | ||
727 | spin_lock_irqsave(&xhci->lock, flags); | 790 | spin_lock_irqsave(&xhci->lock, flags); |
@@ -779,7 +842,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
779 | 842 | ||
780 | if (hcd->speed != HCD_USB3) { | 843 | if (hcd->speed != HCD_USB3) { |
781 | /* enable remote wake up for USB 2.0 */ | 844 | /* enable remote wake up for USB 2.0 */ |
782 | u32 __iomem *addr; | 845 | __le32 __iomem *addr; |
783 | u32 tmp; | 846 | u32 tmp; |
784 | 847 | ||
785 | /* Add one to the port status register address to get | 848 | /* Add one to the port status register address to get |
@@ -801,20 +864,12 @@ int xhci_bus_resume(struct usb_hcd *hcd) | |||
801 | { | 864 | { |
802 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 865 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
803 | int max_ports, port_index; | 866 | int max_ports, port_index; |
804 | u32 __iomem **port_array; | 867 | __le32 __iomem **port_array; |
805 | struct xhci_bus_state *bus_state; | 868 | struct xhci_bus_state *bus_state; |
806 | u32 temp; | 869 | u32 temp; |
807 | unsigned long flags; | 870 | unsigned long flags; |
808 | 871 | ||
809 | if (hcd->speed == HCD_USB3) { | 872 | max_ports = xhci_get_ports(hcd, &port_array); |
810 | max_ports = xhci->num_usb3_ports; | ||
811 | port_array = xhci->usb3_ports; | ||
812 | xhci_dbg(xhci, "resume USB 3.0 root hub\n"); | ||
813 | } else { | ||
814 | max_ports = xhci->num_usb2_ports; | ||
815 | port_array = xhci->usb2_ports; | ||
816 | xhci_dbg(xhci, "resume USB 2.0 root hub\n"); | ||
817 | } | ||
818 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 873 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
819 | 874 | ||
820 | if (time_before(jiffies, bus_state->next_statechange)) | 875 | if (time_before(jiffies, bus_state->next_statechange)) |
@@ -890,7 +945,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) | |||
890 | 945 | ||
891 | if (hcd->speed != HCD_USB3) { | 946 | if (hcd->speed != HCD_USB3) { |
892 | /* disable remote wake up for USB 2.0 */ | 947 | /* disable remote wake up for USB 2.0 */ |
893 | u32 __iomem *addr; | 948 | __le32 __iomem *addr; |
894 | u32 tmp; | 949 | u32 tmp; |
895 | 950 | ||
896 | /* Add one to the port status register address to get | 951 | /* Add one to the port status register address to get |