Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=9c033e810eef0aff6d4d3bf028aa1e583c074f93
Commit:     9c033e810eef0aff6d4d3bf028aa1e583c074f93
Parent:     04d06ad0f1fdb499af84ae3d7969e2136a462f38
Author:     David Brownell <[EMAIL PROTECTED]>
AuthorDate: Thu May 17 12:21:19 2007 -0700
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Thu Jul 12 16:29:47 2007 -0700

    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 <[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;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to