浏览代码

USB: ehci refcounts work on ppc7448

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 <sjhill1@rockwellcollins.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
David Brownell 18 年之前
父节点
当前提交
9c033e810e
共有 2 个文件被更改,包括 14 次插入6 次删除
  1. 6 5
      drivers/usb/host/ehci-mem.c
  2. 8 1
      drivers/usb/host/ehci.h

+ 6 - 5
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;
 	struct ehci_hcd *ehci = qh->ehci;
 
 
 	/* clean qtds first, and know this is not linked */
 	/* 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;
 		return qh;
 
 
 	memset (qh, 0, sizeof *qh);
 	memset (qh, 0, sizeof *qh);
-	kref_init(&qh->kref);
+	qh->refcount = 1;
 	qh->ehci = ehci;
 	qh->ehci = ehci;
 	qh->qh_dma = dma;
 	qh->qh_dma = dma;
 	// INIT_LIST_HEAD (&qh->qh_list);
 	// 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) */
 /* to share a qh (cpu threads, or hc) */
 static inline struct ehci_qh *qh_get (struct ehci_qh *qh)
 static inline struct ehci_qh *qh_get (struct ehci_qh *qh)
 {
 {
-	kref_get(&qh->kref);
+	WARN_ON(!qh->refcount);
+	qh->refcount++;
 	return qh;
 	return qh;
 }
 }
 
 
 static inline void qh_put (struct ehci_qh *qh)
 static inline void qh_put (struct ehci_qh *qh)
 {
 {
-	kref_put(&qh->kref, qh_destroy);
+	if (!--qh->refcount)
+		qh_destroy(qh);
 }
 }
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/

+ 8 - 1
drivers/usb/host/ehci.h

@@ -457,7 +457,14 @@ struct ehci_qh {
 	struct ehci_qh		*reclaim;	/* next to reclaim */
 	struct ehci_qh		*reclaim;	/* next to reclaim */
 
 
 	struct ehci_hcd		*ehci;
 	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;
 	unsigned		stamp;
 
 
 	u8			qh_state;
 	u8			qh_state;