aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/xhci-mem.c102
-rw-r--r--drivers/usb/host/xhci.h11
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. */
549static 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
620static 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
548void xhci_mem_cleanup(struct xhci_hcd *xhci) 645void 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
598int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) 696int 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
759fail: 861fail:
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
955struct 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;