aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */