On Thu, Apr 26, 2007 at 11:30:03AM -0700, David Brownell wrote:
> 
> Looks OK except it's missing a comment about why standard
> atomic refcount utilities (kref, atomic_t, etc) must not
> be used.  (That's in addition to the patch comment.)
> 
Dave,

The patch to remove atomic operations on the reference counter for EHCI
is attached. Thank you.

-Steve

Signed-off-by: Steven J. Hill <[EMAIL PROTECTED]>
diff -ur linux-2.6.21.1/drivers/usb/host/ehci.h linux-2.6.21.1-patched/drivers/usb/host/ehci.h
--- linux-2.6.21.1/drivers/usb/host/ehci.h	2007-05-08 09:22:05.000000000 -0500
+++ linux-2.6.21.1-patched/drivers/usb/host/ehci.h	2007-05-08 09:31:51.000000000 -0500
@@ -418,7 +418,14 @@
 	struct ehci_qh		*reclaim;	/* next to reclaim */
 
 	struct ehci_hcd		*ehci;
-	struct kref		kref;
+
+	/*
+	 * Do NOT use atomic operations for reference counting. On some CPUs
+	 * (PPC7448 for example), atomic operations cannot be performed on
+	 * memory that is cache-inhibited (i.e. being used for DMA). Currently
+	 * spinlocks are sufficient to protect the counter.
+	 */
+	u32			refcount;
 	unsigned		stamp;
 
 	u8			qh_state;
diff -ur linux-2.6.21.1/drivers/usb/host/ehci-mem.c linux-2.6.21.1-patched/drivers/usb/host/ehci-mem.c
--- linux-2.6.21.1/drivers/usb/host/ehci-mem.c	2007-02-04 12:44:54.000000000 -0600
+++ linux-2.6.21.1-patched/drivers/usb/host/ehci-mem.c	2007-05-08 09:31:51.000000000 -0500
@@ -63,9 +63,8 @@
 }
 
 
-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 */
@@ -89,7 +88,7 @@
 		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);
@@ -108,13 +107,16 @@
 /* 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);
+	}
 }
 
 /*-------------------------------------------------------------------------*/
-------------------------------------------------------------------------
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/
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to