diff options
| -rw-r--r-- | drivers/usb/host/xhci-mem.c | 102 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.h | 11 |
2 files changed, 113 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 41aca003ee82..71121d99235d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
| @@ -545,6 +545,103 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci, | |||
| 545 | */ | 545 | */ |
| 546 | } | 546 | } |
| 547 | 547 | ||
| 548 | /* Set up the scratchpad buffer array and scratchpad buffers, if needed. */ | ||
| 549 | static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) | ||
| 550 | { | ||
| 551 | int i; | ||
| 552 | struct device *dev = xhci_to_hcd(xhci)->self.controller; | ||
| 553 | int num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2); | ||
| 554 | |||
| 555 | xhci_dbg(xhci, "Allocating %d scratchpad buffers\n", num_sp); | ||
| 556 | |||
| 557 | if (!num_sp) | ||
| 558 | return 0; | ||
| 559 | |||
| 560 | xhci->scratchpad = kzalloc(sizeof(*xhci->scratchpad), flags); | ||
| 561 | if (!xhci->scratchpad) | ||
| 562 | goto fail_sp; | ||
| 563 | |||
| 564 | xhci->scratchpad->sp_array = | ||
| 565 | pci_alloc_consistent(to_pci_dev(dev), | ||
| 566 | num_sp * sizeof(u64), | ||
| 567 | &xhci->scratchpad->sp_dma); | ||
| 568 | if (!xhci->scratchpad->sp_array) | ||
| 569 | goto fail_sp2; | ||
| 570 | |||
| 571 | xhci->scratchpad->sp_buffers = kzalloc(sizeof(void *) * num_sp, flags); | ||
| 572 | if (!xhci->scratchpad->sp_buffers) | ||
| 573 | goto fail_sp3; | ||
| 574 | |||
| 575 | xhci->scratchpad->sp_dma_buffers = | ||
| 576 | kzalloc(sizeof(dma_addr_t) * num_sp, flags); | ||
| 577 | |||
| 578 | if (!xhci->scratchpad->sp_dma_buffers) | ||
| 579 | goto fail_sp4; | ||
| 580 | |||
| 581 | xhci->dcbaa->dev_context_ptrs[0] = xhci->scratchpad->sp_dma; | ||
| 582 | for (i = 0; i < num_sp; i++) { | ||
| 583 | dma_addr_t dma; | ||
| 584 | void *buf = pci_alloc_consistent(to_pci_dev(dev), | ||
| 585 | xhci->page_size, &dma); | ||
| 586 | if (!buf) | ||
| 587 | goto fail_sp5; | ||
| 588 | |||
| 589 | xhci->scratchpad->sp_array[i] = dma; | ||
| 590 | xhci->scratchpad->sp_buffers[i] = buf; | ||
| 591 | xhci->scratchpad->sp_dma_buffers[i] = dma; | ||
| 592 | } | ||
| 593 | |||
| 594 | return 0; | ||
| 595 | |||
| 596 | fail_sp5: | ||
| 597 | for (i = i - 1; i >= 0; i--) { | ||
| 598 | pci_free_consistent(to_pci_dev(dev), xhci->page_size, | ||
| 599 | xhci->scratchpad->sp_buffers[i], | ||
| 600 | xhci->scratchpad->sp_dma_buffers[i]); | ||
| 601 | } | ||
| 602 | kfree(xhci->scratchpad->sp_dma_buffers); | ||
| 603 | |||
| 604 | fail_sp4: | ||
| 605 | kfree(xhci->scratchpad->sp_buffers); | ||
| 606 | |||
| 607 | fail_sp3: | ||
| 608 | pci_free_consistent(to_pci_dev(dev), num_sp * sizeof(u64), | ||
| 609 | xhci->scratchpad->sp_array, | ||
| 610 | xhci->scratchpad->sp_dma); | ||
| 611 | |||
| 612 | fail_sp2: | ||
| 613 | kfree(xhci->scratchpad); | ||
| 614 | xhci->scratchpad = NULL; | ||
| 615 | |||
| 616 | fail_sp: | ||
| 617 | return -ENOMEM; | ||
| 618 | } | ||
| 619 | |||
| 620 | static void scratchpad_free(struct xhci_hcd *xhci) | ||
| 621 | { | ||
| 622 | int num_sp; | ||
| 623 | int i; | ||
| 624 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | ||
| 625 | |||
| 626 | if (!xhci->scratchpad) | ||
| 627 | return; | ||
| 628 | |||
| 629 | num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2); | ||
| 630 | |||
| 631 | for (i = 0; i < num_sp; i++) { | ||
| 632 | pci_free_consistent(pdev, xhci->page_size, | ||
| 633 | xhci->scratchpad->sp_buffers[i], | ||
| 634 | xhci->scratchpad->sp_dma_buffers[i]); | ||
| 635 | } | ||
| 636 | kfree(xhci->scratchpad->sp_dma_buffers); | ||
| 637 | kfree(xhci->scratchpad->sp_buffers); | ||
| 638 | pci_free_consistent(pdev, num_sp * sizeof(u64), | ||
| 639 | xhci->scratchpad->sp_array, | ||
| 640 | xhci->scratchpad->sp_dma); | ||
| 641 | kfree(xhci->scratchpad); | ||
| 642 | xhci->scratchpad = NULL; | ||
| 643 | } | ||
| 644 | |||
| 548 | void xhci_mem_cleanup(struct xhci_hcd *xhci) | 645 | void xhci_mem_cleanup(struct xhci_hcd *xhci) |
| 549 | { | 646 | { |
| 550 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | 647 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); |
| @@ -593,6 +690,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) | |||
| 593 | 690 | ||
| 594 | xhci->page_size = 0; | 691 | xhci->page_size = 0; |
| 595 | xhci->page_shift = 0; | 692 | xhci->page_shift = 0; |
| 693 | scratchpad_free(xhci); | ||
| 596 | } | 694 | } |
| 597 | 695 | ||
| 598 | int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | 696 | int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) |
| @@ -755,7 +853,11 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | |||
| 755 | for (i = 0; i < MAX_HC_SLOTS; ++i) | 853 | for (i = 0; i < MAX_HC_SLOTS; ++i) |
| 756 | xhci->devs[i] = 0; | 854 | xhci->devs[i] = 0; |
| 757 | 855 | ||
| 856 | if (scratchpad_alloc(xhci, flags)) | ||
| 857 | goto fail; | ||
| 858 | |||
| 758 | return 0; | 859 | return 0; |
| 860 | |||
| 759 | fail: | 861 | fail: |
| 760 | xhci_warn(xhci, "Couldn't initialize memory\n"); | 862 | xhci_warn(xhci, "Couldn't initialize memory\n"); |
| 761 | xhci_mem_cleanup(xhci); | 863 | xhci_mem_cleanup(xhci); |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 074728e10225..5a09b9a26e0d 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
| @@ -89,6 +89,7 @@ struct xhci_cap_regs { | |||
| 89 | #define HCS_ERST_MAX(p) (((p) >> 4) & 0xf) | 89 | #define HCS_ERST_MAX(p) (((p) >> 4) & 0xf) |
| 90 | /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */ | 90 | /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */ |
| 91 | /* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */ | 91 | /* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */ |
| 92 | #define HCS_MAX_SCRATCHPAD(p) (((p) >> 27) & 0x1f) | ||
| 92 | 93 | ||
| 93 | /* HCSPARAMS3 - hcs_params3 - bitmasks */ | 94 | /* HCSPARAMS3 - hcs_params3 - bitmasks */ |
| 94 | /* bits 0:7, Max U1 to U0 latency for the roothub ports */ | 95 | /* bits 0:7, Max U1 to U0 latency for the roothub ports */ |
| @@ -951,6 +952,13 @@ struct xhci_erst { | |||
| 951 | unsigned int erst_size; | 952 | unsigned int erst_size; |
| 952 | }; | 953 | }; |
| 953 | 954 | ||
| 955 | struct xhci_scratchpad { | ||
| 956 | u64 *sp_array; | ||
| 957 | dma_addr_t sp_dma; | ||
| 958 | void **sp_buffers; | ||
| 959 | dma_addr_t *sp_dma_buffers; | ||
| 960 | }; | ||
| 961 | |||
| 954 | /* | 962 | /* |
| 955 | * Each segment table entry is 4*32bits long. 1K seems like an ok size: | 963 | * Each segment table entry is 4*32bits long. 1K seems like an ok size: |
| 956 | * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, | 964 | * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, |
| @@ -1005,6 +1013,9 @@ struct xhci_hcd { | |||
| 1005 | struct xhci_ring *cmd_ring; | 1013 | struct xhci_ring *cmd_ring; |
| 1006 | struct xhci_ring *event_ring; | 1014 | struct xhci_ring *event_ring; |
| 1007 | struct xhci_erst erst; | 1015 | struct xhci_erst erst; |
| 1016 | /* Scratchpad */ | ||
| 1017 | struct xhci_scratchpad *scratchpad; | ||
| 1018 | |||
| 1008 | /* slot enabling and address device helpers */ | 1019 | /* slot enabling and address device helpers */ |
| 1009 | struct completion addr_dev; | 1020 | struct completion addr_dev; |
| 1010 | int slot_id; | 1021 | int slot_id; |
