aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Pan <jacob.jun.pan@intel.com>2010-12-09 10:37:42 +0000
committerAlan Cox <alan@linux.intel.com>2010-12-09 10:37:42 +0000
commitf26ab70974967a94eaac9390dc65bb5836a98ee6 (patch)
tree8d80ad1a6cec03e58c36ee4b1f4709ff7715fe0a
parent6be72e9b54479e7a2c473bc6cc778319e5f925e3 (diff)
downloadmrst-s0i3-test-f26ab70974967a94eaac9390dc65bb5836a98ee6.tar.gz
mrst-s0i3-test-f26ab70974967a94eaac9390dc65bb5836a98ee6.tar.xz
mrst-s0i3-test-f26ab70974967a94eaac9390dc65bb5836a98ee6.zip
ehci: Support Intel Moorestown EHCI controller SRAM QH/QTD/ITD/SITD pool caching
The Intel Moorestown platform has MPH and OTG EHCI controllers that have internal SRAM that could be used as descriptors DMA pool caching. The SRAM is exposed via PCI BAR1. The limitation here is the SRAM access should be 32bit aligned. A separate patch "EHCI: Make ehci_qh structure items all 32bit aligned" has been submitted to linux-usb mailling list. Signed-off-by: Jacob Pan <jacob.jun.pan@intel.com> Signed-off-by: Alek Du <alek.du@intel.com> Signed-off-by: Alan Cox <alan@linux.intel.com>
-rw-r--r--drivers/usb/core/buffer.c21
-rw-r--r--drivers/usb/host/ehci-hcd.c3
-rw-r--r--drivers/usb/host/ehci-pci.c39
-rw-r--r--drivers/usb/host/ehci.h8
-rw-r--r--include/linux/usb/hcd.h2
5 files changed, 64 insertions, 9 deletions
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 2c6965484fe..08e33fbeccd 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -115,9 +115,14 @@ void *hcd_buffer_alloc(
return kmalloc(size, mem_flags);
}
- for (i = 0; i < HCD_BUFFER_POOLS; i++) {
- if (size <= pool_max [i])
- return dma_pool_alloc(hcd->pool [i], mem_flags, dma);
+ /* we won't use internal SRAM as data payload, when we can't get
+ any benefits from it */
+ if (!hcd->has_sram || !hcd->sram_no_payload) {
+ for (i = 0; i < HCD_BUFFER_POOLS; i++) {
+ if (size <= pool_max [i])
+ return dma_pool_alloc(hcd->pool [i],
+ mem_flags, dma);
+ }
}
return dma_alloc_coherent(hcd->self.controller, size, dma, mem_flags);
}
@@ -141,10 +146,12 @@ void hcd_buffer_free(
return;
}
- for (i = 0; i < HCD_BUFFER_POOLS; i++) {
- if (size <= pool_max [i]) {
- dma_pool_free(hcd->pool [i], addr, dma);
- return;
+ if (!hcd->has_sram || !hcd->sram_no_payload) {
+ for (i = 0; i < HCD_BUFFER_POOLS; i++) {
+ if (size <= pool_max [i]) {
+ dma_pool_free(hcd->pool [i], addr, dma);
+ return;
+ }
}
}
dma_free_coherent(hcd->self.controller, size, addr, dma);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c59361e6e91..535a1aa8990 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -530,7 +530,8 @@ static void ehci_stop (struct usb_hcd *hcd)
ehci_work (ehci);
spin_unlock_irq (&ehci->lock);
ehci_mem_cleanup (ehci);
-
+ if (hcd->has_sram)
+ sram_deinit(hcd);
#ifdef EHCI_STATS
ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index c3637bb299c..f823a3651bd 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -41,6 +41,39 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
return 0;
}
+/* enable SRAM if sram detected */
+static void sram_init(struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+
+ if (!hcd->has_sram)
+ return;
+ ehci->sram_addr = pci_resource_start(pdev, 1);
+ ehci->sram_size = pci_resource_len(pdev, 1);
+ ehci_info(ehci, "Found HCD SRAM at %x size:%x\n",
+ ehci->sram_addr, ehci->sram_size);
+ if (pci_request_region(pdev, 1, kobject_name(&pdev->dev.kobj))) {
+ ehci_warn(ehci, "SRAM request failed\n");
+ hcd->has_sram = 0;
+ } else if (!dma_declare_coherent_memory(&pdev->dev, ehci->sram_addr,
+ ehci->sram_addr, ehci->sram_size, DMA_MEMORY_MAP)) {
+ ehci_warn(ehci, "SRAM DMA declare failed\n");
+ pci_release_region(pdev, 1);
+ hcd->has_sram = 0;
+ }
+}
+
+static void sram_deinit(struct usb_hcd *hcd)
+{
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+
+ if (!hcd->has_sram)
+ return;
+ dma_release_declared_memory(&pdev->dev);
+ pci_release_region(pdev, 1);
+}
+
/* called during probe() after chip reset completes */
static int ehci_pci_setup(struct usb_hcd *hcd)
{
@@ -71,10 +104,16 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
ehci->has_hostpc = 1;
ehci->has_otg = 1;
force_otg_hc_mode = 1;
+ hcd->has_sram = 1;
+ hcd->sram_no_payload = 1;
+ sram_init(hcd);
} else if (pdev->device == 0x0806) {
ehci_info(ehci, "Detected Langwell MPH\n");
hcd->has_tt = 1;
ehci->has_hostpc = 1;
+ hcd->has_sram = 1;
+ hcd->sram_no_payload = 1;
+ sram_init(hcd);
}
}
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index d78a781a49b..7a6de9c6e51 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -148,6 +148,8 @@ struct ehci_hcd { /* one per controller */
unsigned has_otg:1; /* if it is otg host*/
u8 sbrn; /* packed release number */
+ unsigned int sram_addr;
+ unsigned int sram_size;
/* irq statistics */
#ifdef EHCI_STATS
@@ -733,5 +735,9 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
#endif /* DEBUG */
/*-------------------------------------------------------------------------*/
-
+#ifdef CONFIG_PCI
+static void sram_deinit(struct usb_hcd *hcd);
+#else
+static void sram_deinit(struct usb_hcd *hcd) { return; };
+#endif
#endif /* __LINUX_EHCI_HCD_H */
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 57098cd8476..08a8fedfc7e 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -119,6 +119,8 @@ struct usb_hcd {
unsigned wireless:1; /* Wireless USB HCD */
unsigned authorized_default:1;
unsigned has_tt:1; /* Integrated TT in root hub */
+ unsigned has_sram:1; /* Local SRAM for caching */
+ unsigned sram_no_payload:1; /* sram not for payload */
int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */