Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>


authored by

David Brownell and committed by
Greg Kroah-Hartman
9c033e81 04d06ad0

+14 -6
+6 -5
drivers/usb/host/ehci-mem.c
··· 64 64 } 65 65 66 66 67 - static void qh_destroy (struct kref *kref) 67 + static void qh_destroy(struct ehci_qh *qh) 68 68 { 69 - struct ehci_qh *qh = container_of(kref, struct ehci_qh, kref); 70 69 struct ehci_hcd *ehci = qh->ehci; 71 70 72 71 /* clean qtds first, and know this is not linked */ ··· 89 90 return qh; 90 91 91 92 memset (qh, 0, sizeof *qh); 92 - kref_init(&qh->kref); 93 + qh->refcount = 1; 93 94 qh->ehci = ehci; 94 95 qh->qh_dma = dma; 95 96 // INIT_LIST_HEAD (&qh->qh_list); ··· 111 112 /* to share a qh (cpu threads, or hc) */ 112 113 static inline struct ehci_qh *qh_get (struct ehci_qh *qh) 113 114 { 114 - kref_get(&qh->kref); 115 + WARN_ON(!qh->refcount); 116 + qh->refcount++; 115 117 return qh; 116 118 } 117 119 118 120 static inline void qh_put (struct ehci_qh *qh) 119 121 { 120 - kref_put(&qh->kref, qh_destroy); 122 + if (!--qh->refcount) 123 + qh_destroy(qh); 121 124 } 122 125 123 126 /*-------------------------------------------------------------------------*/
+8 -1
drivers/usb/host/ehci.h
··· 457 457 struct ehci_qh *reclaim; /* next to reclaim */ 458 458 459 459 struct ehci_hcd *ehci; 460 - struct kref kref; 460 + 461 + /* 462 + * Do NOT use atomic operations for QH refcounting. On some CPUs 463 + * (PPC7448 for example), atomic operations cannot be performed on 464 + * memory that is cache-inhibited (i.e. being used for DMA). 465 + * Spinlocks are used to protect all QH fields. 466 + */ 467 + u32 refcount; 461 468 unsigned stamp; 462 469 463 470 u8 qh_state;