[PATCH 4/4 v3] EHCI: split ehci_qh - core part changes

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

 



>From 475e0d8b2865b03a5f62840d0ff0551124f4106b Mon Sep 17 00:00:00 2001
From: Alek Du <alek.du@xxxxxxxxx>
Date: Tue, 23 Jun 2009 19:05:31 +0800
Subject: [PATCH] EHCI: Split ehci_qh - core part changes

The most significant changes are here ...

Signed-off-by: Alek Du <alek.du@xxxxxxxxx>
---
 drivers/usb/host/ehci-hub.c   |    2 +-
 drivers/usb/host/ehci-q.c     |   55 +++++++++++++-------------
 drivers/usb/host/ehci-sched.c |   86 +++++++++++++++++++++--------------------
 3 files changed, 73 insertions(+), 70 deletions(-)

diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index f46ad27..e90b190 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -267,7 +267,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 
 	/* maybe re-activate the schedule(s) */
 	temp = 0;
-	if (ehci->async->qh_next.qh)
+	if (SH_HW(&ehci->async->qh_next))
 		temp |= CMD_ASE;
 	if (ehci->periodic_sched)
 		temp |= CMD_PSE;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 3192f68..d293784 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -90,12 +90,12 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
 	/* writes to an active overlay are unsafe */
 	BUG_ON(qh->qh_state != QH_STATE_IDLE);
 
-	qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
-	qh->hw_alt_next = EHCI_LIST_END(ehci);
+	HW(qh)->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
+	HW(qh)->hw_alt_next = EHCI_LIST_END(ehci);
 
 	/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
 	wmb ();
-	qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
+	HW(qh)->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
 }
 
 /* if it weren't for a common silicon quirk (writing the dummy into the qh
@@ -113,7 +113,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
 		qtd = list_entry (qh->qtd_list.next,
 				struct ehci_qtd, qtd_list);
 		/* first qtd may already be partially processed */
-		if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw_current)
+		if (cpu_to_hc32(ehci, qtd->qtd_dma) == HW(qh)->hw_current)
 			qtd = NULL;
 	}
 
@@ -215,7 +215,7 @@ __acquires(ehci->lock)
 		struct ehci_qh	*qh = (struct ehci_qh *) urb->hcpriv;
 
 		/* S-mask in a QH means it's an interrupt urb */
-		if ((qh->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) {
+		if ((HW(qh)->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) {
 
 			/* ... update hc-wide periodic stats (for usbfs) */
 			ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
@@ -348,7 +348,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 					qtd->hw_token = cpu_to_hc32(ehci,
 							token);
 					wmb();
-					qh->hw_token = cpu_to_hc32(ehci, token);
+					HW(qh)->hw_token =
+						cpu_to_hc32(ehci, token);
 					goto retry_xacterr;
 				}
 				stopped = 1;
@@ -391,16 +392,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 			/* qh unlinked; token in overlay may be most current */
 			if (state == QH_STATE_IDLE
 					&& cpu_to_hc32(ehci, qtd->qtd_dma)
-						== qh->hw_current)
-				token = hc32_to_cpu(ehci, qh->hw_token);
+						== HW(qh)->hw_current)
+				token = hc32_to_cpu(ehci, HW(qh)->hw_token);
 
 			/* force halt for unlinked or blocked qh, so we'll
 			 * patch the qh later and so that completions can't
 			 * activate it while we "know" it's stopped.
 			 */
-			if ((halt & qh->hw_token) == 0) {
+			if ((halt & HW(qh)->hw_token) == 0) {
 halt:
-				qh->hw_token |= halt;
+				HW(qh)->hw_token |= halt;
 				wmb ();
 			}
 		}
@@ -452,7 +453,7 @@ halt:
 	 * it after fault cleanup, or recovering from silicon wrongly
 	 * overlaying the dummy qtd (which reduces DMA chatter).
 	 */
-	if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) {
+	if (stopped != 0 || HW(qh)->hw_qtd_next == EHCI_LIST_END(ehci)) {
 		switch (state) {
 		case QH_STATE_IDLE:
 			qh_refresh(ehci, qh);
@@ -470,7 +471,7 @@ halt:
 			 * except maybe high bandwidth ...
 			 */
 			if ((cpu_to_hc32(ehci, QH_SMASK)
-					& qh->hw_info2) != 0) {
+					& HW(qh)->hw_info2) != 0) {
 				intr_deschedule (ehci, qh);
 				(void) qh_schedule (ehci, qh);
 			} else
@@ -591,7 +592,7 @@ qh_urb_transaction (
 		 * (this will usually be overridden later.)
 		 */
 		if (is_input)
-			qtd->hw_alt_next = ehci->async->hw_alt_next;
+			qtd->hw_alt_next = HW(ehci->async)->hw_alt_next;
 
 		/* qh makes control packets use qtd toggle; maybe switch it */
 		if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
@@ -832,8 +833,8 @@ done:
 
 	/* init as live, toggle clear, advance to dummy */
 	qh->qh_state = QH_STATE_IDLE;
-	qh->hw_info1 = cpu_to_hc32(ehci, info1);
-	qh->hw_info2 = cpu_to_hc32(ehci, info2);
+	HW(qh)->hw_info1 = cpu_to_hc32(ehci, info1);
+	HW(qh)->hw_info2 = cpu_to_hc32(ehci, info2);
 	qh_refresh (ehci, qh);
 	return qh;
 }
@@ -850,7 +851,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	/* (re)start the async schedule? */
 	head = ehci->async;
 	timer_action_done (ehci, TIMER_ASYNC_OFF);
-	if (!head->qh_next.qh) {
+	if (!SH_HW(&head->qh_next)) {
 		u32	cmd = ehci_readl(ehci, &ehci->regs->command);
 
 		if (!(cmd & CMD_ASE)) {
@@ -870,11 +871,11 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 	/* splice right after start */
 	qh->qh_next = head->qh_next;
-	qh->hw_next = head->hw_next;
+	HW(qh)->hw_next = HW(head)->hw_next;
 	wmb ();
 
-	head->qh_next.qh = qh;
-	head->hw_next = dma;
+	SH_HW(&head->qh_next) = HW(qh);
+	HW(head)->hw_next = dma;
 
 	qh->xacterrs = QH_XACTERR_MAX;
 	qh->qh_state = QH_STATE_LINKED;
@@ -920,7 +921,7 @@ static struct ehci_qh *qh_append_tds (
 
                         /* usb_reset_device() briefly reverts to address 0 */
                         if (usb_pipedevice (urb->pipe) == 0)
-                                qh->hw_info1 &= ~qh_addr_mask;
+				HW(qh)->hw_info1 &= ~qh_addr_mask;
 		}
 
 		/* just one way to queue requests: swap with the dummy qtd.
@@ -1037,7 +1038,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)
 
 	// qh->hw_next = cpu_to_hc32(qh->qh_dma);
 	qh->qh_state = QH_STATE_IDLE;
-	qh->qh_next.qh = NULL;
+	SH_HW(&qh->qh_next) = NULL;
 	qh_put (qh);			// refcount from reclaim
 
 	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
@@ -1057,7 +1058,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)
 		 * active but idle for a while once it empties.
 		 */
 		if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)
-				&& ehci->async->qh_next.qh == NULL)
+				&& SH_HW(&ehci->async->qh_next) == NULL)
 			timer_action (ehci, TIMER_ASYNC_OFF);
 	}
 
@@ -1103,10 +1104,10 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	ehci->reclaim = qh = qh_get (qh);
 
 	prev = ehci->async;
-	while (prev->qh_next.qh != qh)
-		prev = prev->qh_next.qh;
+	while (SH_QH(&prev->qh_next) != qh)
+		prev = SH_QH(&prev->qh_next);
 
-	prev->hw_next = qh->hw_next;
+	HW(prev)->hw_next = HW(qh)->hw_next;
 	prev->qh_next = qh->qh_next;
 	wmb ();
 
@@ -1135,7 +1136,7 @@ static void scan_async (struct ehci_hcd *ehci)
 	ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
 	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
 rescan:
-	qh = ehci->async->qh_next.qh;
+	qh = SH_QH(&ehci->async->qh_next);
 	if (likely (qh != NULL)) {
 		do {
 			/* clean any finished work for this qh */
@@ -1173,7 +1174,7 @@ rescan:
 					action = TIMER_ASYNC_SHRINK;
 			}
 
-			qh = qh->qh_next.qh;
+			qh = SH_QH(&qh->qh_next);
 		} while (qh);
 	}
 	if (action == TIMER_ASYNC_SHRINK)
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 9d1babc..d9d4eca 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -49,7 +49,7 @@ periodic_next_shadow(struct ehci_hcd *ehci, union ehci_shadow *periodic,
 {
 	switch (hc32_to_cpu(ehci, tag)) {
 	case Q_TYPE_QH:
-		return &periodic->qh->qh_next;
+		return &SH_QH(periodic)->qh_next;
 	case Q_TYPE_FSTN:
 		return &periodic->fstn->fstn_next;
 	case Q_TYPE_ITD:
@@ -98,14 +98,14 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
 		switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) {
 		case Q_TYPE_QH:
 			/* is it in the S-mask? */
-			if (q->qh->hw_info2 & cpu_to_hc32(ehci, 1 << uframe))
-				usecs += q->qh->usecs;
+			if (SH_HW(q)->hw_info2 & cpu_to_hc32(ehci, 1 << uframe))
+				usecs += SH_QH(q)->usecs;
 			/* ... or C-mask? */
-			if (q->qh->hw_info2 & cpu_to_hc32(ehci,
+			if (SH_HW(q)->hw_info2 & cpu_to_hc32(ehci,
 					1 << (8 + uframe)))
-				usecs += q->qh->c_usecs;
-			hw_p = &q->qh->hw_next;
-			q = &q->qh->qh_next;
+				usecs += SH_QH(q)->c_usecs;
+			hw_p = &SH_HW(q)->hw_next;
+			q = &SH_QH(q)->qh_next;
 			break;
 		// case Q_TYPE_FSTN:
 		default:
@@ -236,12 +236,12 @@ periodic_tt_usecs (
 			q = &q->itd->itd_next;
 			continue;
 		case Q_TYPE_QH:
-			if (same_tt(dev, q->qh->dev)) {
-				uf = tt_start_uframe(ehci, q->qh->hw_info2);
-				tt_usecs[uf] += q->qh->tt_usecs;
+			if (same_tt(dev, SH_QH(q)->dev)) {
+				uf = tt_start_uframe(ehci, SH_HW(q)->hw_info2);
+				tt_usecs[uf] += SH_QH(q)->tt_usecs;
 			}
-			hw_p = &q->qh->hw_next;
-			q = &q->qh->qh_next;
+			hw_p = &SH_HW(q)->hw_next;
+			q = &SH_QH(q)->qh_next;
 			continue;
 		case Q_TYPE_SITD:
 			if (same_tt(dev, q->sitd->urb->dev)) {
@@ -385,18 +385,18 @@ static int tt_no_collision (
 				here = here.itd->itd_next;
 				continue;
 			case Q_TYPE_QH:
-				if (same_tt (dev, here.qh->dev)) {
+				if (same_tt(dev, SH_QH(&here)->dev)) {
 					u32		mask;
 
 					mask = hc32_to_cpu(ehci,
-							here.qh->hw_info2);
+							SH_HW(&here)->hw_info2);
 					/* "knows" no gap is needed */
 					mask |= mask >> 8;
 					if (mask & uf_mask)
 						break;
 				}
-				type = Q_NEXT_TYPE(ehci, here.qh->hw_next);
-				here = here.qh->qh_next;
+				type = Q_NEXT_TYPE(ehci, SH_HW(&here)->hw_next);
+				here = SH_QH(&here)->qh_next;
 				continue;
 			case Q_TYPE_SITD:
 				if (same_tt (dev, here.sitd->urb->dev)) {
@@ -498,7 +498,8 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 	dev_dbg (&qh->dev->dev,
 		"link qh%d-%04x/%p start %d [%d/%d us]\n",
-		period, hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
+		period, hc32_to_cpup(ehci, &HW(qh)->hw_info2)
+			& (QH_CMASK | QH_SMASK),
 		qh, qh->start, qh->usecs, qh->c_usecs);
 
 	/* high bandwidth, or otherwise every microframe */
@@ -517,27 +518,27 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
 			if (type == cpu_to_hc32(ehci, Q_TYPE_QH))
 				break;
 			prev = periodic_next_shadow(ehci, prev, type);
-			hw_p = &here.qh->hw_next;
+			hw_p = &SH_HW(&here)->hw_next;
 			here = *prev;
 		}
 
 		/* sorting each branch by period (slow-->fast)
 		 * enables sharing interior tree nodes
 		 */
-		while (here.ptr && qh != here.qh) {
-			if (qh->period > here.qh->period)
+		while (here.ptr && HW(qh) != SH_HW(&here)) {
+			if (qh->period > SH_QH(&here)->period)
 				break;
-			prev = &here.qh->qh_next;
-			hw_p = &here.qh->hw_next;
+			prev = &SH_QH(&here)->qh_next;
+			hw_p = &SH_HW(&here)->hw_next;
 			here = *prev;
 		}
 		/* link in this qh, unless some earlier pass did that */
-		if (qh != here.qh) {
+		if (HW(qh) != SH_HW(&here)) {
 			qh->qh_next = here;
-			if (here.qh)
-				qh->hw_next = *hw_p;
+			if (SH_HW(&here))
+				HW(qh)->hw_next = *hw_p;
 			wmb ();
-			prev->qh = qh;
+			SH_HW(prev) = HW(qh);
 			*hw_p = QH_NEXT (ehci, qh->qh_dma);
 		}
 	}
@@ -570,7 +571,7 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
 		period = 1;
 
 	for (i = qh->start; i < ehci->periodic_size; i += period)
-		periodic_unlink (ehci, i, qh);
+		periodic_unlink(ehci, i, HW(qh));
 
 	/* update per-qh bandwidth for usbfs */
 	ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->period
@@ -580,7 +581,7 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
 	dev_dbg (&qh->dev->dev,
 		"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
 		qh->period,
-		hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
+		hc32_to_cpup(ehci, &HW(qh)->hw_info2) & (QH_CMASK | QH_SMASK),
 		qh, qh->start, qh->usecs, qh->c_usecs);
 
 	/* qh->qh_next still "live" to HC */
@@ -605,14 +606,14 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	 */
 	if (list_empty (&qh->qtd_list)
 			|| (cpu_to_hc32(ehci, QH_CMASK)
-					& qh->hw_info2) != 0)
+					& HW(qh)->hw_info2) != 0)
 		wait = 2;
 	else
 		wait = 55;	/* worst case: 3 * 1024 */
 
 	udelay (wait);
 	qh->qh_state = QH_STATE_IDLE;
-	qh->hw_next = EHCI_LIST_END(ehci);
+	HW(qh)->hw_next = EHCI_LIST_END(ehci);
 	wmb ();
 }
 
@@ -740,12 +741,12 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
 	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
 
 	qh_refresh(ehci, qh);
-	qh->hw_next = EHCI_LIST_END(ehci);
+	HW(qh)->hw_next = EHCI_LIST_END(ehci);
 	frame = qh->start;
 
 	/* reuse the previous schedule slots, if we can */
 	if (frame < qh->period) {
-		uframe = ffs(hc32_to_cpup(ehci, &qh->hw_info2) & QH_SMASK);
+		uframe = ffs(hc32_to_cpup(ehci, &HW(qh)->hw_info2) & QH_SMASK);
 		status = check_intr_schedule (ehci, frame, --uframe,
 				qh, &c_mask);
 	} else {
@@ -783,11 +784,11 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
 		qh->start = frame;
 
 		/* reset S-frame and (maybe) C-frame masks */
-		qh->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
-		qh->hw_info2 |= qh->period
+		HW(qh)->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
+		HW(qh)->hw_info2 |= qh->period
 			? cpu_to_hc32(ehci, 1 << uframe)
 			: cpu_to_hc32(ehci, QH_SMASK);
-		qh->hw_info2 |= c_mask;
+		HW(qh)->hw_info2 |= c_mask;
 	} else
 		ehci_dbg (ehci, "reused qh %p schedule\n", qh);
 
@@ -2182,13 +2183,14 @@ restart:
 			switch (hc32_to_cpu(ehci, type)) {
 			case Q_TYPE_QH:
 				/* handle any completions */
-				temp.qh = qh_get (q.qh);
-				type = Q_NEXT_TYPE(ehci, q.qh->hw_next);
-				q = q.qh->qh_next;
-				modified = qh_completions (ehci, temp.qh);
-				if (unlikely (list_empty (&temp.qh->qtd_list)))
-					intr_deschedule (ehci, temp.qh);
-				qh_put (temp.qh);
+				SH_HW(&temp) = HW(qh_get(SH_QH(&q)));
+				type = Q_NEXT_TYPE(ehci, SH_HW(&q)->hw_next);
+				q = SH_QH(&q)->qh_next;
+				modified = qh_completions(ehci, SH_QH(&temp));
+				if (unlikely(list_empty(
+						&SH_QH(&temp)->qtd_list)))
+					intr_deschedule(ehci, SH_QH(&temp));
+				qh_put(SH_QH(&temp));
 				break;
 			case Q_TYPE_FSTN:
 				/* for "save place" FSTNs, look at QH entries
-- 
1.6.0.4
--
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