[PATCH 3/25] USB: EHCI: don't refcount QHs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch (as1567) removes ehci-hcd's reference counting of QH
structures.  It's not necessary to refcount these things because they
always get deallocated at exactly one spot in ehci_endpoint_disable()
(except for two special QHs, ehci->async and ehci->dummy) and are
never used again.

Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>

---

 drivers/usb/host/ehci-hcd.c   |    2 +-
 drivers/usb/host/ehci-mem.c   |   24 +++---------------------
 drivers/usb/host/ehci-q.c     |   12 +++---------
 drivers/usb/host/ehci-sched.c |    5 +----
 drivers/usb/host/ehci.h       |    9 ---------
 5 files changed, 8 insertions(+), 44 deletions(-)

Index: usb-3.4/drivers/usb/host/ehci.h
===================================================================
--- usb-3.4.orig/drivers/usb/host/ehci.h
+++ usb-3.4/drivers/usb/host/ehci.h
@@ -350,16 +350,7 @@ struct ehci_qh {
 	struct ehci_qtd		*dummy;
 	struct ehci_qh		*reclaim;	/* next to reclaim */
 
-	struct ehci_hcd		*ehci;
 	unsigned long		unlink_time;
-
-	/*
-	 * 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			needs_rescan;	/* Dequeue during giveback */
Index: usb-3.4/drivers/usb/host/ehci-hcd.c
===================================================================
--- usb-3.4.orig/drivers/usb/host/ehci-hcd.c
+++ usb-3.4/drivers/usb/host/ehci-hcd.c
@@ -1179,7 +1179,7 @@ idle_timeout:
 		if (qh->clearing_tt)
 			goto idle_timeout;
 		if (list_empty (&qh->qtd_list)) {
-			qh_put (qh);
+			qh_destroy(ehci, qh);
 			break;
 		}
 		/* else FALL THROUGH */
Index: usb-3.4/drivers/usb/host/ehci-mem.c
===================================================================
--- usb-3.4.orig/drivers/usb/host/ehci-mem.c
+++ usb-3.4/drivers/usb/host/ehci-mem.c
@@ -64,10 +64,8 @@ static inline void ehci_qtd_free (struct
 }
 
 
-static void qh_destroy(struct ehci_qh *qh)
+static void qh_destroy(struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	struct ehci_hcd *ehci = qh->ehci;
-
 	/* clean qtds first, and know this is not linked */
 	if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) {
 		ehci_dbg (ehci, "unused qh not empty!\n");
@@ -92,8 +90,6 @@ static struct ehci_qh *ehci_qh_alloc (st
 	if (!qh->hw)
 		goto fail;
 	memset(qh->hw, 0, sizeof *qh->hw);
-	qh->refcount = 1;
-	qh->ehci = ehci;
 	qh->qh_dma = dma;
 	// INIT_LIST_HEAD (&qh->qh_list);
 	INIT_LIST_HEAD (&qh->qtd_list);
@@ -113,20 +109,6 @@ fail:
 	return NULL;
 }
 
-/* to share a qh (cpu threads, or hc) */
-static inline struct ehci_qh *qh_get (struct ehci_qh *qh)
-{
-	WARN_ON(!qh->refcount);
-	qh->refcount++;
-	return qh;
-}
-
-static inline void qh_put (struct ehci_qh *qh)
-{
-	if (!--qh->refcount)
-		qh_destroy(qh);
-}
-
 /*-------------------------------------------------------------------------*/
 
 /* The queue heads and transfer descriptors are managed from pools tied
@@ -138,11 +120,11 @@ static void ehci_mem_cleanup (struct ehc
 {
 	free_cached_lists(ehci);
 	if (ehci->async)
-		qh_put (ehci->async);
+		qh_destroy(ehci, ehci->async);
 	ehci->async = NULL;
 
 	if (ehci->dummy)
-		qh_put(ehci->dummy);
+		qh_destroy(ehci, ehci->dummy);
 	ehci->dummy = NULL;
 
 	/* DMA consistent memory and pools */
Index: usb-3.4/drivers/usb/host/ehci-q.c
===================================================================
--- usb-3.4.orig/drivers/usb/host/ehci-q.c
+++ usb-3.4/drivers/usb/host/ehci-q.c
@@ -265,7 +265,6 @@ __acquires(ehci->lock)
 			/* ... update hc-wide periodic stats (for usbfs) */
 			ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
 		}
-		qh_put (qh);
 	}
 
 	if (unlikely(urb->unlinked)) {
@@ -946,7 +945,7 @@ qh_make (
 		ehci_dbg(ehci, "bogus dev %p speed %d\n", urb->dev,
 			urb->dev->speed);
 done:
-		qh_put (qh);
+		qh_destroy(ehci, qh);
 		return NULL;
 	}
 
@@ -1003,7 +1002,6 @@ static void qh_link_async (struct ehci_h
 	head->qh_next.qh = qh;
 	head->hw->hw_next = dma;
 
-	qh_get(qh);
 	qh->xacterrs = 0;
 	qh->qh_state = QH_STATE_LINKED;
 	/* qtd completions reported later by interrupt */
@@ -1090,7 +1088,7 @@ static struct ehci_qh *qh_append_tds (
 			wmb ();
 			dummy->hw_token = token;
 
-			urb->hcpriv = qh_get (qh);
+			urb->hcpriv = qh;
 		}
 	}
 	return qh;
@@ -1167,7 +1165,6 @@ static void end_unlink_async (struct ehc
 	// qh->hw_next = cpu_to_hc32(qh->qh_dma);
 	qh->qh_state = QH_STATE_IDLE;
 	qh->qh_next.qh = NULL;
-	qh_put (qh);			// refcount from reclaim
 
 	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
 	next = qh->reclaim;
@@ -1186,7 +1183,6 @@ static void end_unlink_async (struct ehc
 				&& ehci->async->qh_next.qh == NULL)
 			timer_action (ehci, TIMER_ASYNC_OFF);
 	}
-	qh_put(qh);			/* refcount from async list */
 
 	if (next) {
 		ehci->reclaim = NULL;
@@ -1230,7 +1226,7 @@ static void start_unlink_async (struct e
 	}
 
 	qh->qh_state = QH_STATE_UNLINK;
-	ehci->reclaim = qh = qh_get (qh);
+	ehci->reclaim = qh;
 
 	prev = ehci->async;
 	while (prev->qh_next.qh != qh)
@@ -1283,12 +1279,10 @@ static void scan_async (struct ehci_hcd
 			 * gets unlinked then ehci->qh_scan_next is adjusted
 			 * in start_unlink_async().
 			 */
-			qh = qh_get(qh);
 			temp = qh_completions(ehci, qh);
 			if (qh->needs_rescan)
 				unlink_async(ehci, qh);
 			qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;
-			qh_put(qh);
 			if (temp != 0)
 				goto rescan;
 		}
Index: usb-3.4/drivers/usb/host/ehci-sched.c
===================================================================
--- usb-3.4.orig/drivers/usb/host/ehci-sched.c
+++ usb-3.4/drivers/usb/host/ehci-sched.c
@@ -606,7 +606,6 @@ static int qh_link_periodic (struct ehci
 	}
 	qh->qh_state = QH_STATE_LINKED;
 	qh->xacterrs = 0;
-	qh_get (qh);
 
 	/* update per-qh bandwidth for usbfs */
 	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period
@@ -650,7 +649,6 @@ static int qh_unlink_periodic(struct ehc
 	/* qh->qh_next still "live" to HC */
 	qh->qh_state = QH_STATE_UNLINK;
 	qh->qh_next.ptr = NULL;
-	qh_put (qh);
 
 	/* maybe turn off periodic schedule */
 	return disable_periodic(ehci);
@@ -2340,7 +2338,7 @@ restart:
 			switch (hc32_to_cpu(ehci, type)) {
 			case Q_TYPE_QH:
 				/* handle any completions */
-				temp.qh = qh_get (q.qh);
+				temp.qh = q.qh;
 				type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next);
 				q = q.qh->qh_next;
 				if (temp.qh->stamp != ehci->periodic_stamp) {
@@ -2351,7 +2349,6 @@ restart:
 							temp.qh->needs_rescan))
 						intr_deschedule(ehci, temp.qh);
 				}
-				qh_put (temp.qh);
 				break;
 			case Q_TYPE_FSTN:
 				/* for "save place" FSTNs, look at QH entries


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux