[PATCH 3/3 v5 resent] EHCI: Support Intel Moorestown EHCI controller SRAM for periodic descriptor caching

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

 



From: Alek Du <alek.du@xxxxxxxxx>
>From 18e325bdfcc27f68c705563cfd37ec2427a4fec3 Mon Sep 17 00:00:00 2001
From: Alek Du <alek.du@xxxxxxxxx>
Date: Thu, 25 Jun 2009 16:02:31 +0800
Subject: [PATCH] EHCI: Support Intel Moorestown EHCI controller SRAM for periodic descriptor caching

The Intel Moorestown platform has MPH and OTG EHCI controllers that have internal
SRAM could be used as descriptor DMA pool caching. The SRAM are exposed via PCI
BAR1.

Signed-off-by: Alek Du <alek.du@xxxxxxxxx>
---
 drivers/usb/core/buffer.c   |   10 ++++++++++
 drivers/usb/core/hcd.h      |    2 ++
 drivers/usb/host/ehci-hcd.c |    3 ++-
 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..8db547d 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 && hcd->sram_no_payload)
+		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);
@@ -141,6 +146,11 @@ void hcd_buffer_free(
 		return;
 	}
 
+	if (hcd->has_sram && hcd->sram_no_payload) {
+		dma_free_coherent(NULL, size, addr, dma);
+		return;
+	}
+
 	for (i = 0; i < HCD_BUFFER_POOLS; i++) {
 		if (size <= pool_max [i]) {
 			dma_pool_free(hcd->pool [i], addr, dma);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index ab5449b..f0332de 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -104,6 +104,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 */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index a9dc1bc..c6f109f 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -495,7 +495,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 7aeed8c..861a08a 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)
 {
@@ -93,10 +126,16 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 			ehci->has_otg = 1;
 #endif
 			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 dfc9b71..57bac7e 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -144,6 +144,8 @@ struct ehci_hcd {			/* one per controller */
 	int (*otg_resume)(struct usb_hcd *hcd);
 #endif
 	u8			sbrn;		/* packed release number */
+	unsigned int		sram_addr;
+	unsigned int		sram_size;
 
 	/* irq statistics */
 #ifdef EHCI_STATS
@@ -722,5 +724,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