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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
04d06ad0f1
commit
9c033e810e
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user