Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: xhci: Scratchpad buffer allocation

Allocates and initializes the scratchpad buffer array (XHCI 4.20). This is an
array of 64-bit DMA addresses to scratch pages that the controller may use
during operation. The number of pages is specified in the "Max Scratchpad
Buffers" field of HCSPARAMS2. The DMA address of this array is written into
slot 0 of the DCBAA.

Signed-off-by: John Youn <johnyoun@synopsys.com>
Acked-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

John Youn and committed by
Greg Kroah-Hartman
254c80a3 9f8e4438

+113
+102
drivers/usb/host/xhci-mem.c
··· 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 645 void xhci_mem_cleanup(struct xhci_hcd *xhci) 549 646 { 550 647 struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); ··· 690 593 691 594 xhci->page_size = 0; 692 595 xhci->page_shift = 0; 596 + scratchpad_free(xhci); 693 597 } 694 598 695 599 int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) ··· 853 755 for (i = 0; i < MAX_HC_SLOTS; ++i) 854 756 xhci->devs[i] = 0; 855 757 758 + if (scratchpad_alloc(xhci, flags)) 759 + goto fail; 760 + 856 761 return 0; 762 + 857 763 fail: 858 764 xhci_warn(xhci, "Couldn't initialize memory\n"); 859 765 xhci_mem_cleanup(xhci);
+11
drivers/usb/host/xhci.h
··· 89 89 #define HCS_ERST_MAX(p) (((p) >> 4) & 0xf) 90 90 /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */ 91 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 94 /* HCSPARAMS3 - hcs_params3 - bitmasks */ 94 95 /* bits 0:7, Max U1 to U0 latency for the roothub ports */ ··· 952 951 unsigned int erst_size; 953 952 }; 954 953 954 + struct xhci_scratchpad { 955 + u64 *sp_array; 956 + dma_addr_t sp_dma; 957 + void **sp_buffers; 958 + dma_addr_t *sp_dma_buffers; 959 + }; 960 + 955 961 /* 956 962 * Each segment table entry is 4*32bits long. 1K seems like an ok size: 957 963 * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, ··· 1013 1005 struct xhci_ring *cmd_ring; 1014 1006 struct xhci_ring *event_ring; 1015 1007 struct xhci_erst erst; 1008 + /* Scratchpad */ 1009 + struct xhci_scratchpad *scratchpad; 1010 + 1016 1011 /* slot enabling and address device helpers */ 1017 1012 struct completion addr_dev; 1018 1013 int slot_id;