[PATCH 018/149] USB: ehci refcounts work on ppc7448

Greg Kroah-Hartman <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
From: David Brownell <[email protected]>

Remove atomic operations on the reference counter for EHCI queue heads.
On various platforms (including ppc7448), atomic operations are unusable
with dma-coherent memory.

Signed-off-by: Steven J. Hill <[email protected]>
Signed-off-by: David Brownell <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
 drivers/usb/host/ehci-mem.c |   11 ++++++-----
 drivers/usb/host/ehci.h     |    9 ++++++++-
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index bdb29e6..8816d09 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -64,9 +64,8 @@ static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
 }
 
 
-static void qh_destroy (struct kref *kref)
+static void qh_destroy(struct ehci_qh *qh)
 {
-	struct ehci_qh *qh = container_of(kref, struct ehci_qh, kref);
 	struct ehci_hcd *ehci = qh->ehci;
 
 	/* clean qtds first, and know this is not linked */
@@ -90,7 +89,7 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
 		return qh;
 
 	memset (qh, 0, sizeof *qh);
-	kref_init(&qh->kref);
+	qh->refcount = 1;
 	qh->ehci = ehci;
 	qh->qh_dma = dma;
 	// INIT_LIST_HEAD (&qh->qh_list);
@@ -112,13 +111,15 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
 /* to share a qh (cpu threads, or hc) */
 static inline struct ehci_qh *qh_get (struct ehci_qh *qh)
 {
-	kref_get(&qh->kref);
+	WARN_ON(!qh->refcount);
+	qh->refcount++;
 	return qh;
 }
 
 static inline void qh_put (struct ehci_qh *qh)
 {
-	kref_put(&qh->kref, qh_destroy);
+	if (!--qh->refcount)
+		qh_destroy(qh);
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 79ad2af..6ef9d77 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -457,7 +457,14 @@ struct ehci_qh {
 	struct ehci_qh		*reclaim;	/* next to reclaim */
 
 	struct ehci_hcd		*ehci;
-	struct kref		kref;
+
+	/*
+	 * Do NOT use atomic operations for QH refcounting. On some CPUs
+	 * (PPC7448 for example), atomic operations cannot be performed on
+	 * memory that is cache-inhibited (i.e. being used for DMA).
+	 * Spinlocks are used to protect all QH fields.
+	 */
+	u32			refcount;
 	unsigned		stamp;
 
 	u8			qh_state;
-- 
1.5.2.2


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.