[PATCH 4/4] EHCI: Support Intel Moorestown EHCI controller SRAM as DMA pool caching

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>From f3c088f9e609a54140498cce27f6f12f737c870b Mon Sep 17 00:00:00 2001
From: Jacob Pan <jacob.jun.pan@xxxxxxxxx>
Date: Wed, 20 May 2009 14:41:55 +0800
Subject: [PATCH] EHCI: Support Intel Moorestown EHCI controller SRAM as DMA pool caching

The Intel Moorestown platform has MPH and OTG EHCI controllers that have Internal
SRAM could be used as QH/QTD/ITD/SITD DMA pool caching. The SRAM are 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@xxxxxxxxx>
Signed-off-by: Alek Du <alek.du@xxxxxxxxx>
---
 drivers/usb/core/buffer.c   |    5 +++++
 drivers/usb/core/hcd.h      |    1 +
 drivers/usb/host/ehci-hcd.c |    9 ++++++++-
 drivers/usb/host/ehci-pci.c |   39 +++++++++++++++++++++++++++++++++++++++
 drivers/usb/host/ehci.h     |    8 +++++++-
 5 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 3ba2fff..ab0f462 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -115,6 +115,11 @@ void *hcd_buffer_alloc(
 		return kmalloc(size, mem_flags);
 	}
 
+	/* we won't use internal SRAM as data payload, we can't get
+	   any benefits from it */
+	if (hcd->has_sram)
+		return dma_alloc_coherent(NULL, size, dma, 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);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index e7d4479..696fcf2 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -104,6 +104,7 @@ 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 */
 
 	int			irq;		/* irq allocated */
 	void __iomem		*regs;		/* device memory/io */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 31122e0..d37de6b 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -106,6 +106,12 @@ static int ignore_oc = 0;
 module_param (ignore_oc, bool, S_IRUGO);
 MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
 
+static unsigned int sram_force_off;
+module_param(sram_force_off, int, S_IRUGO);
+MODULE_PARM_DESC(sram_force_off,
+		"force private SRAM off, otherwise SRAM will be used"
+		"if detected\n");
+
 #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
 /*-------------------------------------------------------------------------*/
@@ -496,7 +502,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 e5e05b0..79eb0db 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -61,6 +61,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)
 {
@@ -91,11 +124,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 			hcd->has_tt = 1;
 			ehci->has_hostpc = 1;
 			force_otg_hc_mode = 1;
+			/* enable SRAM caching if selected */
+			hcd->has_sram = (sram_force_off) ? 0 : 1;
+			sram_init(hcd);
 		} else if (pdev->device == 0x0806) {
 			ehci_info(ehci, "Detected Langwell MPH\n");
 			ehci->no_io_watchdog = 1;
 			hcd->has_tt = 1;
 			ehci->has_hostpc = 1;
+			/* enable SRAM caching if selected */
+			hcd->has_sram = (sram_force_off) ? 0 : 1;
+			sram_init(hcd);
 		}
 	}
 
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 3cfc3cc..cfa16ad 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -138,6 +138,8 @@ struct ehci_hcd {			/* one per controller */
 	unsigned		has_hostpc:1;
 
 	u8			sbrn;		/* packed release number */
+	unsigned int		sram_addr;
+	unsigned int		sram_size;
 
 	/* irq statistics */
 #ifdef EHCI_STATS
@@ -718,5 +720,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 */
-- 
1.6.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux