[PATCH v2] EHCI: split ehci_qh structure into hw and sw parts

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

 



Have to send v2 version again, fixed a qh_destroy issue.

>From bd43fff4f26616f3abe58deffeafac3e05aea4c5 Mon Sep 17 00:00:00 2001
From: Alek Du <alek.du@xxxxxxxxx>
Date: Wed, 10 Jun 2009 11:53:59 +0800
Subject: [PATCH] EHCI: split ehci_qh structure into hw and sw parts

The ehci_qh structure merged hw and sw together which is not good:
1. If HCD has local SRAM, the sw part will consume it too, and it won't
   bring any benefit.
2. For non-x86 system, the entire ehci_qh is uncachable, actually we
   only need the hw part to be uncacheable. Split them will give the sw
   part cacheable feature.

Signed-off-by: Alek Du <alek.du@xxxxxxxxx>
---
 drivers/usb/host/ehci-dbg.c   |   18 +++---
 drivers/usb/host/ehci-hcd.c   |   46 ++++++++-------
 drivers/usb/host/ehci-hub.c   |    5 +-
 drivers/usb/host/ehci-mem.c   |   50 ++++++++++------
 drivers/usb/host/ehci-q.c     |  131 +++++++++++++++++++++--------------------
 drivers/usb/host/ehci-sched.c |  118 +++++++++++++++++++------------------
 drivers/usb/host/ehci.h       |    9 +++-
 7 files changed, 203 insertions(+), 174 deletions(-)

diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 7f4ace7..e54bd3c 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -429,7 +429,7 @@ static void qh_lines (
 	next += temp;
 
 	/* hc may be modifying the list as we read it ... */
-	list_for_each (entry, &qh->qtd_list) {
+	list_for_each(entry, &qh->sw->qtd_list) {
 		td = list_entry (entry, struct ehci_qtd, qtd_list);
 		scratch = hc32_to_cpup(ehci, &td->hw_token);
 		mark = ' ';
@@ -495,14 +495,15 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
 	 * one QH per line, and TDs we know about
 	 */
 	spin_lock_irqsave (&ehci->lock, flags);
-	for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)
+	for (qh = ehci->async->sw->qh_next.qh; size > 0 && qh;
+						qh = qh->sw->qh_next.qh)
 		qh_lines (ehci, qh, &next, &size);
 	if (ehci->reclaim && size > 0) {
 		temp = scnprintf (next, size, "\nreclaim =\n");
 		size -= temp;
 		next += temp;
 
-		for (qh = ehci->reclaim; size > 0 && qh; qh = qh->reclaim)
+		for (qh = ehci->reclaim; size > 0 && qh; qh = qh->sw->reclaim)
 			qh_lines (ehci, qh, &next, &size);
 	}
 	spin_unlock_irqrestore (&ehci->lock, flags);
@@ -553,7 +554,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
 			switch (hc32_to_cpu(ehci, tag)) {
 			case Q_TYPE_QH:
 				temp = scnprintf (next, size, " qh%d-%04x/%p",
-						p.qh->period,
+						p.qh->sw->period,
 						hc32_to_cpup(ehci,
 								&p.qh->hw_info2)
 							/* uframe masks */
@@ -565,7 +566,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
 				for (temp = 0; temp < seen_count; temp++) {
 					if (seen [temp].ptr != p.ptr)
 						continue;
-					if (p.qh->qh_next.ptr) {
+					if (p.qh->sw->qh_next.ptr) {
 						temp = scnprintf (next, size,
 							" ...");
 						size -= temp;
@@ -583,7 +584,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
 					/* count tds, get ep direction */
 					temp = 0;
 					list_for_each_entry (qtd,
-							&p.qh->qtd_list,
+							&p.qh->sw->qtd_list,
 							qtd_list) {
 						temp++;
 						switch (0x03 & (hc32_to_cpu(
@@ -600,7 +601,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
 						speed_char (scratch),
 						scratch & 0x007f,
 						(scratch >> 8) & 0x000f, type,
-						p.qh->usecs, p.qh->c_usecs,
+						p.qh->sw->usecs,
+						p.qh->sw->c_usecs,
 						temp,
 						0x7ff & (scratch >> 16));
 
@@ -610,7 +612,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
 					temp = 0;
 				if (p.qh) {
 					tag = Q_NEXT_TYPE(ehci, p.qh->hw_next);
-					p = p.qh->qh_next;
+					p = p.qh->sw->qh_next;
 				}
 				break;
 			case Q_TYPE_FSTN:
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 36cedc9..d7ba228 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -452,7 +452,7 @@ static void ehci_work (struct ehci_hcd *ehci)
 	 * such lossage has been observed on both VT6202 and VT8235.
 	 */
 	if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
-			(ehci->async->qh_next.ptr != NULL ||
+			(ehci->async->sw->qh_next.ptr != NULL ||
 			 ehci->periodic_sched != 0))
 		timer_action (ehci, TIMER_IO_WATCHDOG);
 }
@@ -545,13 +545,14 @@ static int ehci_init(struct usb_hcd *hcd)
 	 * its dummy is used in hw_alt_next of many tds, to prevent the qh
 	 * from automatically advancing to the next td after short reads.
 	 */
-	ehci->async->qh_next.qh = NULL;
-	ehci->async->hw_next = QH_NEXT(ehci, ehci->async->qh_dma);
+	ehci->async->sw->qh_next.qh = NULL;
+	ehci->async->hw_next = QH_NEXT(ehci, ehci->async->sw->qh_dma);
 	ehci->async->hw_info1 = cpu_to_hc32(ehci, QH_HEAD);
 	ehci->async->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
 	ehci->async->hw_qtd_next = EHCI_LIST_END(ehci);
-	ehci->async->qh_state = QH_STATE_LINKED;
-	ehci->async->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma);
+	ehci->async->sw->qh_state = QH_STATE_LINKED;
+	ehci->async->hw_alt_next =
+				QTD_NEXT(ehci, ehci->async->sw->dummy->qtd_dma);
 
 	/* clear interrupt enables, set irq latency */
 	if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
@@ -605,7 +606,8 @@ static int ehci_run (struct usb_hcd *hcd)
 		return retval;
 	}
 	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
-	ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);
+	ehci_writel(ehci, (u32)ehci->async->sw->qh_dma,
+						&ehci->regs->async_next);
 
 	/*
 	 * hcc_params controls whether ehci->regs->segment must (!!!)
@@ -853,7 +855,7 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 		end_unlink_async(ehci);
 
 	/* if it's not linked then there's nothing to do */
-	if (qh->qh_state != QH_STATE_LINKED)
+	if (qh->sw->qh_state != QH_STATE_LINKED)
 		;
 
 	/* defer till later if busy */
@@ -861,11 +863,11 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 		struct ehci_qh		*last;
 
 		for (last = ehci->reclaim;
-				last->reclaim;
-				last = last->reclaim)
+				last->sw->reclaim;
+				last = last->sw->reclaim)
 			continue;
-		qh->qh_state = QH_STATE_UNLINK_WAIT;
-		last->reclaim = qh;
+		qh->sw->qh_state = QH_STATE_UNLINK_WAIT;
+		last->sw->reclaim = qh;
 
 	/* start IAA cycle */
 	} else
@@ -895,7 +897,7 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 		qh = (struct ehci_qh *) urb->hcpriv;
 		if (!qh)
 			break;
-		switch (qh->qh_state) {
+		switch (qh->sw->qh_state) {
 		case QH_STATE_LINKED:
 		case QH_STATE_COMPLETING:
 			unlink_async(ehci, qh);
@@ -914,7 +916,7 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 		qh = (struct ehci_qh *) urb->hcpriv;
 		if (!qh)
 			break;
-		switch (qh->qh_state) {
+		switch (qh->sw->qh_state) {
 		case QH_STATE_LINKED:
 			intr_deschedule (ehci, qh);
 			/* FALL THROUGH */
@@ -923,12 +925,12 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 			break;
 		default:
 			ehci_dbg (ehci, "bogus qh %p state %d\n",
-					qh, qh->qh_state);
+					qh, qh->sw->qh_state);
 			goto done;
 		}
 
 		/* reschedule QH iff another request is queued */
-		if (!list_empty (&qh->qtd_list)
+		if (!list_empty(&qh->sw->qtd_list)
 				&& HC_IS_RUNNING (hcd->state)) {
 			rc = qh_schedule(ehci, qh);
 
@@ -986,12 +988,12 @@ rescan:
 	}
 
 	if (!HC_IS_RUNNING (hcd->state))
-		qh->qh_state = QH_STATE_IDLE;
-	switch (qh->qh_state) {
+		qh->sw->qh_state = QH_STATE_IDLE;
+	switch (qh->sw->qh_state) {
 	case QH_STATE_LINKED:
-		for (tmp = ehci->async->qh_next.qh;
+		for (tmp = ehci->async->sw->qh_next.qh;
 				tmp && tmp != qh;
-				tmp = tmp->qh_next.qh)
+				tmp = tmp->sw->qh_next.qh)
 			continue;
 		/* periodic qh self-unlinks on empty */
 		if (!tmp)
@@ -1005,7 +1007,7 @@ idle_timeout:
 		schedule_timeout_uninterruptible(1);
 		goto rescan;
 	case QH_STATE_IDLE:		/* fully unlinked */
-		if (list_empty (&qh->qtd_list)) {
+		if (list_empty(&qh->sw->qtd_list)) {
 			qh_put (qh);
 			break;
 		}
@@ -1016,8 +1018,8 @@ nogood:
 		 * that's not our job.  just leak this memory.
 		 */
 		ehci_err (ehci, "qh %p (#%02x) state %d%s\n",
-			qh, ep->desc.bEndpointAddress, qh->qh_state,
-			list_empty (&qh->qtd_list) ? "" : "(has tds)");
+			qh, ep->desc.bEndpointAddress, qh->sw->qh_state,
+			list_empty(&qh->sw->qtd_list) ? "" : "(has tds)");
 		break;
 	}
 	ep->hcpriv = NULL;
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 97a53a4..ce04e05 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -222,7 +222,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 	/* re-init operational registers */
 	ehci_writel(ehci, 0, &ehci->regs->segment);
 	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
-	ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
+	ehci_writel(ehci, (u32) ehci->async->sw->qh_dma,
+					&ehci->regs->async_next);
 
 	/* restore CMD_RUN, framelist size, and irq threshold */
 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
@@ -267,7 +268,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 (ehci->async->sw->qh_next.qh)
 		temp |= CMD_ASE;
 	if (ehci->periodic_sched)
 		temp |= CMD_PSE;
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 10d5291..9bb222c 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -66,16 +66,19 @@ static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
 
 static void qh_destroy(struct ehci_qh *qh)
 {
-	struct ehci_hcd *ehci = qh->ehci;
+	struct ehci_hcd *ehci = qh->sw->ehci;
+	dma_addr_t qh_dma;
 
 	/* clean qtds first, and know this is not linked */
-	if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) {
+	if (!list_empty(&qh->sw->qtd_list) || qh->sw->qh_next.ptr) {
 		ehci_dbg (ehci, "unused qh not empty!\n");
 		BUG ();
 	}
-	if (qh->dummy)
-		ehci_qtd_free (ehci, qh->dummy);
-	dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
+	if (qh->sw->dummy)
+		ehci_qtd_free(ehci, qh->sw->dummy);
+	qh_dma = qh->sw->qh_dma;
+	kfree(qh->sw);
+	dma_pool_free(ehci->qh_pool, qh, qh_dma);
 }
 
 static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
@@ -86,36 +89,47 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
 	qh = (struct ehci_qh *)
 		dma_pool_alloc (ehci->qh_pool, flags, &dma);
 	if (!qh)
-		return qh;
+		goto done;
 
 	memset (qh, 0, sizeof *qh);
-	qh->refcount = 1;
-	qh->ehci = ehci;
-	qh->qh_dma = dma;
-	// INIT_LIST_HEAD (&qh->qh_list);
-	INIT_LIST_HEAD (&qh->qtd_list);
+	qh->sw = (struct ehci_qh_sw *)
+		kzalloc(sizeof *qh->sw, GFP_ATOMIC);
+	if (qh->sw == NULL) {
+		ehci_err(ehci, "can not alloc ehci_qh_sw\n");
+		goto failed;
+	}
+	qh->sw->refcount = 1;
+	qh->sw->ehci = ehci;
+	qh->sw->qh_dma = dma;
+	/* INIT_LIST_HEAD(&qh->sw->qh_list); */
+	INIT_LIST_HEAD(&qh->sw->qtd_list);
 
 	/* dummy td enables safe urb queuing */
-	qh->dummy = ehci_qtd_alloc (ehci, flags);
-	if (qh->dummy == NULL) {
+	qh->sw->dummy = ehci_qtd_alloc(ehci, flags);
+	if (qh->sw->dummy == NULL) {
 		ehci_dbg (ehci, "no dummy td\n");
-		dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
-		qh = NULL;
+		goto failed1;
 	}
+done:
 	return qh;
+failed1:
+	kfree(qh->sw);
+failed:
+	dma_pool_free(ehci->qh_pool, qh, dma);
+	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++;
+	WARN_ON(!qh->sw->refcount);
+	qh->sw->refcount++;
 	return qh;
 }
 
 static inline void qh_put (struct ehci_qh *qh)
 {
-	if (!--qh->refcount)
+	if (!--qh->sw->refcount)
 		qh_destroy(qh);
 }
 
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 1976b1b..bc7d0f6 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -88,7 +88,7 @@ static inline void
 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);
+	BUG_ON(qh->sw->qh_state != QH_STATE_IDLE);
 
 	qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
 	qh->hw_alt_next = EHCI_LIST_END(ehci);
@@ -103,9 +103,9 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
 
 		is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
 		epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f;
-		if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
+		if (unlikely(!usb_gettoggle(qh->sw->dev, epnum, is_out))) {
 			qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
-			usb_settoggle (qh->dev, epnum, is_out, 1);
+			usb_settoggle(qh->sw->dev, epnum, is_out, 1);
 		}
 	}
 
@@ -123,10 +123,10 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
 	struct ehci_qtd *qtd;
 
-	if (list_empty (&qh->qtd_list))
-		qtd = qh->dummy;
+	if (list_empty(&qh->sw->qtd_list))
+		qtd = qh->sw->dummy;
 	else {
-		qtd = list_entry (qh->qtd_list.next,
+		qtd = list_entry(qh->sw->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)
@@ -279,7 +279,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
 static unsigned
 qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	struct ehci_qtd		*last = NULL, *end = qh->dummy;
+	struct ehci_qtd		*last = NULL, *end = qh->sw->dummy;
 	struct list_head	*entry, *tmp;
 	int			last_status = -EINPROGRESS;
 	int			stopped;
@@ -287,7 +287,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	u8			state;
 	__le32			halt = HALT_BIT(ehci);
 
-	if (unlikely (list_empty (&qh->qtd_list)))
+	if (unlikely(list_empty(&qh->sw->qtd_list)))
 		return count;
 
 	/* completions (or tasks on other cpus) must never clobber HALT
@@ -296,8 +296,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	 *
 	 * NOTE:  unlinking expects to be done in queue order.
 	 */
-	state = qh->qh_state;
-	qh->qh_state = QH_STATE_COMPLETING;
+	state = qh->sw->qh_state;
+	qh->sw->qh_state = QH_STATE_COMPLETING;
 	stopped = (state == QH_STATE_IDLE);
 
 	/* remove de-activated QTDs from front of queue.
@@ -305,7 +305,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	 * then let the queue advance.
 	 * if queue is stopped, handles unlinks.
 	 */
-	list_for_each_safe (entry, tmp, &qh->qtd_list) {
+	list_for_each_safe(entry, tmp, &qh->sw->qtd_list) {
 		struct ehci_qtd	*qtd;
 		struct urb	*urb;
 		u32		token = 0;
@@ -346,12 +346,12 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 				 */
 				if ((token & QTD_STS_XACT) &&
 						QTD_CERR(token) == 0 &&
-						--qh->xacterrs > 0 &&
+						--qh->sw->xacterrs > 0 &&
 						!urb->unlinked) {
 					ehci_dbg(ehci,
 	"detected XactErr len %zu/%zu retry %d\n",
 	qtd->length - QTD_LENGTH(token), qtd->length,
-	QH_XACTERR_MAX - qh->xacterrs);
+	QH_XACTERR_MAX - qh->sw->xacterrs);
 
 					/* reset the token in the qtd and the
 					 * qh overlay (which still contains
@@ -440,7 +440,7 @@ halt:
 		/* if we're removing something not at the queue head,
 		 * patch the hardware queue pointer.
 		 */
-		if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
+		if (stopped && qtd->qtd_list.prev != &qh->sw->qtd_list) {
 			last = list_entry (qtd->qtd_list.prev,
 					struct ehci_qtd, qtd_list);
 			last->hw_next = qtd->hw_next;
@@ -451,7 +451,7 @@ halt:
 		last = qtd;
 
 		/* reinit the xacterr counter for the next qtd */
-		qh->xacterrs = QH_XACTERR_MAX;
+		qh->sw->xacterrs = QH_XACTERR_MAX;
 	}
 
 	/* last urb's completion might still need calling */
@@ -462,7 +462,7 @@ halt:
 	}
 
 	/* restore original state; caller must unlink or relink */
-	qh->qh_state = state;
+	qh->sw->qh_state = state;
 
 	/* be sure the hardware's done with the qh before refreshing
 	 * it after fault cleanup, or recovering from silicon wrongly
@@ -733,17 +733,17 @@ qh_make (
 	 * For control/bulk requests, the HC or TT handles these.
 	 */
 	if (type == PIPE_INTERRUPT) {
-		qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
+		qh->sw->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
 				is_input, 0,
 				hb_mult(maxp) * max_packet(maxp)));
-		qh->start = NO_FRAME;
+		qh->sw->start = NO_FRAME;
 
 		if (urb->dev->speed == USB_SPEED_HIGH) {
-			qh->c_usecs = 0;
-			qh->gap_uf = 0;
+			qh->sw->c_usecs = 0;
+			qh->sw->gap_uf = 0;
 
-			qh->period = urb->interval >> 3;
-			if (qh->period == 0 && urb->interval != 1) {
+			qh->sw->period = urb->interval >> 3;
+			if (qh->sw->period == 0 && urb->interval != 1) {
 				/* NOTE interval 2 or 4 uframes could work.
 				 * But interval 1 scheduling is simpler, and
 				 * includes high bandwidth.
@@ -756,28 +756,28 @@ qh_make (
 			int		think_time;
 
 			/* gap is f(FS/LS transfer times) */
-			qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed,
+			qh->sw->gap_uf = 1 + usb_calc_bus_time(urb->dev->speed,
 					is_input, 0, maxp) / (125 * 1000);
 
 			/* FIXME this just approximates SPLIT/CSPLIT times */
 			if (is_input) {		// SPLIT, gap, CSPLIT+DATA
-				qh->c_usecs = qh->usecs + HS_USECS (0);
-				qh->usecs = HS_USECS (1);
+				qh->sw->c_usecs = qh->sw->usecs + HS_USECS(0);
+				qh->sw->usecs = HS_USECS(1);
 			} else {		// SPLIT+DATA, gap, CSPLIT
-				qh->usecs += HS_USECS (1);
-				qh->c_usecs = HS_USECS (0);
+				qh->sw->usecs += HS_USECS(1);
+				qh->sw->c_usecs = HS_USECS(0);
 			}
 
 			think_time = tt ? tt->think_time : 0;
-			qh->tt_usecs = NS_TO_US (think_time +
+			qh->sw->tt_usecs = NS_TO_US(think_time +
 					usb_calc_bus_time (urb->dev->speed,
 					is_input, 0, max_packet (maxp)));
-			qh->period = urb->interval;
+			qh->sw->period = urb->interval;
 		}
 	}
 
 	/* support for tt scheduling, and access to toggles */
-	qh->dev = urb->dev;
+	qh->sw->dev = urb->dev;
 
 	/* using TT? */
 	switch (urb->dev->speed) {
@@ -847,7 +847,7 @@ done:
 	/* NOTE:  if (PIPE_INTERRUPT) { scheduler sets s-mask } */
 
 	/* init as live, toggle clear, advance to dummy */
-	qh->qh_state = QH_STATE_IDLE;
+	qh->sw->qh_state = QH_STATE_IDLE;
 	qh->hw_info1 = cpu_to_hc32(ehci, info1);
 	qh->hw_info2 = cpu_to_hc32(ehci, info2);
 	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
@@ -861,13 +861,13 @@ done:
 
 static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	__hc32		dma = QH_NEXT(ehci, qh->qh_dma);
+	__hc32		dma = QH_NEXT(ehci, qh->sw->qh_dma);
 	struct ehci_qh	*head;
 
 	/* (re)start the async schedule? */
 	head = ehci->async;
 	timer_action_done (ehci, TIMER_ASYNC_OFF);
-	if (!head->qh_next.qh) {
+	if (!head->sw->qh_next.qh) {
 		u32	cmd = ehci_readl(ehci, &ehci->regs->command);
 
 		if (!(cmd & CMD_ASE)) {
@@ -882,19 +882,19 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	}
 
 	/* clear halt and/or toggle; and maybe recover from silicon quirk */
-	if (qh->qh_state == QH_STATE_IDLE)
+	if (qh->sw->qh_state == QH_STATE_IDLE)
 		qh_refresh (ehci, qh);
 
 	/* splice right after start */
-	qh->qh_next = head->qh_next;
+	qh->sw->qh_next = head->sw->qh_next;
 	qh->hw_next = head->hw_next;
 	wmb ();
 
-	head->qh_next.qh = qh;
+	head->sw->qh_next.qh = qh;
 	head->hw_next = dma;
 
-	qh->xacterrs = QH_XACTERR_MAX;
-	qh->qh_state = QH_STATE_LINKED;
+	qh->sw->xacterrs = QH_XACTERR_MAX;
+	qh->sw->qh_state = QH_STATE_LINKED;
 	/* qtd completions reported later by interrupt */
 }
 
@@ -956,7 +956,7 @@ static struct ehci_qh *qh_append_tds (
 			token = qtd->hw_token;
 			qtd->hw_token = HALT_BIT(ehci);
 			wmb ();
-			dummy = qh->dummy;
+			dummy = qh->sw->dummy;
 
 			dma = dummy->qtd_dma;
 			*dummy = *qtd;
@@ -964,14 +964,14 @@ static struct ehci_qh *qh_append_tds (
 
 			list_del (&qtd->qtd_list);
 			list_add (&dummy->qtd_list, qtd_list);
-			list_splice_tail(qtd_list, &qh->qtd_list);
+			list_splice_tail(qtd_list, &qh->sw->qtd_list);
 
 			ehci_qtd_init(ehci, qtd, qtd->qtd_dma);
-			qh->dummy = qtd;
+			qh->sw->dummy = qtd;
 
 			/* hc must see the new dummy at list end */
 			dma = qtd->qtd_dma;
-			qtd = list_entry (qh->qtd_list.prev,
+			qtd = list_entry(qh->sw->qtd_list.prev,
 					struct ehci_qtd, qtd_list);
 			qtd->hw_next = QTD_NEXT(ehci, dma);
 
@@ -1032,7 +1032,7 @@ submit_async (
 	/* Control/bulk operations through TTs don't need scheduling,
 	 * the HC and TT handle it when the TT has a buffer ready.
 	 */
-	if (likely (qh->qh_state == QH_STATE_IDLE))
+	if (likely(qh->sw->qh_state == QH_STATE_IDLE))
 		qh_link_async (ehci, qh_get (qh));
  done:
 	spin_unlock_irqrestore (&ehci->lock, flags);
@@ -1052,19 +1052,19 @@ static void end_unlink_async (struct ehci_hcd *ehci)
 
 	iaa_watchdog_done(ehci);
 
-	// qh->hw_next = cpu_to_hc32(qh->qh_dma);
-	qh->qh_state = QH_STATE_IDLE;
-	qh->qh_next.qh = NULL;
+	/* qh->hw_next = cpu_to_hc32(qh->sw->qh_dma); */
+	qh->sw->qh_state = QH_STATE_IDLE;
+	qh->sw->qh_next.qh = NULL;
 	qh_put (qh);			// refcount from reclaim
 
 	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
-	next = qh->reclaim;
+	next = qh->sw->reclaim;
 	ehci->reclaim = next;
-	qh->reclaim = NULL;
+	qh->sw->reclaim = NULL;
 
 	qh_completions (ehci, qh);
 
-	if (!list_empty (&qh->qtd_list)
+	if (!list_empty(&qh->sw->qtd_list)
 			&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
 		qh_link_async (ehci, qh);
 	else {
@@ -1074,7 +1074,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)
+				&& ehci->async->sw->qh_next.qh == NULL)
 			timer_action (ehci, TIMER_ASYNC_OFF);
 	}
 
@@ -1095,8 +1095,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 #ifdef DEBUG
 	assert_spin_locked(&ehci->lock);
 	if (ehci->reclaim
-			|| (qh->qh_state != QH_STATE_LINKED
-				&& qh->qh_state != QH_STATE_UNLINK_WAIT)
+			|| (qh->sw->qh_state != QH_STATE_LINKED
+				&& qh->sw->qh_state != QH_STATE_UNLINK_WAIT)
 			)
 		BUG ();
 #endif
@@ -1116,20 +1116,20 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 		return;
 	}
 
-	qh->qh_state = QH_STATE_UNLINK;
+	qh->sw->qh_state = QH_STATE_UNLINK;
 	ehci->reclaim = qh = qh_get (qh);
 
 	prev = ehci->async;
-	while (prev->qh_next.qh != qh)
-		prev = prev->qh_next.qh;
+	while (prev->sw->qh_next.qh != qh)
+		prev = prev->sw->qh_next.qh;
 
 	prev->hw_next = qh->hw_next;
-	prev->qh_next = qh->qh_next;
+	prev->sw->qh_next = qh->sw->qh_next;
 	wmb ();
 
 	/* If the controller isn't running, we don't have to wait for it */
 	if (unlikely(!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) {
-		/* if (unlikely (qh->reclaim != 0))
+		/* if (unlikely (qh->sw->reclaim != 0))
 		 *	this will recurse, probably not much
 		 */
 		end_unlink_async (ehci);
@@ -1152,12 +1152,12 @@ 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 = ehci->async->sw->qh_next.qh;
 	if (likely (qh != NULL)) {
 		do {
 			/* clean any finished work for this qh */
-			if (!list_empty (&qh->qtd_list)
-					&& qh->stamp != ehci->stamp) {
+			if (!list_empty(&qh->sw->qtd_list)
+					&& qh->sw->stamp != ehci->stamp) {
 				int temp;
 
 				/* unlinks could happen here; completion
@@ -1166,7 +1166,7 @@ rescan:
 				 * qhs we already finished (no looping).
 				 */
 				qh = qh_get (qh);
-				qh->stamp = ehci->stamp;
+				qh->sw->stamp = ehci->stamp;
 				temp = qh_completions (ehci, qh);
 				qh_put (qh);
 				if (temp != 0) {
@@ -1180,17 +1180,18 @@ rescan:
 			 * doesn't stay idle for long.
 			 * (plus, avoids some kind of re-activation race.)
 			 */
-			if (list_empty(&qh->qtd_list)
-					&& qh->qh_state == QH_STATE_LINKED) {
+			if (list_empty(&qh->sw->qtd_list)
+				&& qh->sw->qh_state == QH_STATE_LINKED) {
 				if (!ehci->reclaim
-					&& ((ehci->stamp - qh->stamp) & 0x1fff)
+					&& ((ehci->stamp - qh->sw->stamp)
+						& 0x1fff)
 						>= (EHCI_SHRINK_FRAMES * 8))
 					start_unlink_async(ehci, qh);
 				else
 					action = TIMER_ASYNC_SHRINK;
 			}
 
-			qh = qh->qh_next.qh;
+			qh = qh->sw->qh_next.qh;
 		} while (qh);
 	}
 	if (action == TIMER_ASYNC_SHRINK)
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 556d0ec..cce6f32 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 &periodic->qh->sw->qh_next;
 	case Q_TYPE_FSTN:
 		return &periodic->fstn->fstn_next;
 	case Q_TYPE_ITD:
@@ -99,13 +99,13 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
 		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;
+				usecs += q->qh->sw->usecs;
 			/* ... or C-mask? */
 			if (q->qh->hw_info2 & cpu_to_hc32(ehci,
 					1 << (8 + uframe)))
-				usecs += q->qh->c_usecs;
+				usecs += q->qh->sw->c_usecs;
 			hw_p = &q->qh->hw_next;
-			q = &q->qh->qh_next;
+			q = &q->qh->sw->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)) {
+			if (same_tt(dev, q->qh->sw->dev)) {
 				uf = tt_start_uframe(ehci, q->qh->hw_info2);
-				tt_usecs[uf] += q->qh->tt_usecs;
+				tt_usecs[uf] += q->qh->sw->tt_usecs;
 			}
 			hw_p = &q->qh->hw_next;
-			q = &q->qh->qh_next;
+			q = &q->qh->sw->qh_next;
 			continue;
 		case Q_TYPE_SITD:
 			if (same_tt(dev, q->sitd->urb->dev)) {
@@ -385,7 +385,7 @@ 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, here.qh->sw->dev)) {
 					u32		mask;
 
 					mask = hc32_to_cpu(ehci,
@@ -396,7 +396,7 @@ static int tt_no_collision (
 						break;
 				}
 				type = Q_NEXT_TYPE(ehci, here.qh->hw_next);
-				here = here.qh->qh_next;
+				here = here.qh->sw->qh_next;
 				continue;
 			case Q_TYPE_SITD:
 				if (same_tt (dev, here.sitd->urb->dev)) {
@@ -494,18 +494,18 @@ static int disable_periodic (struct ehci_hcd *ehci)
 static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
 	unsigned	i;
-	unsigned	period = qh->period;
+	unsigned	period = qh->sw->period;
 
-	dev_dbg (&qh->dev->dev,
+	dev_dbg(&qh->sw->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),
-		qh, qh->start, qh->usecs, qh->c_usecs);
+		qh, qh->sw->start, qh->sw->usecs, qh->sw->c_usecs);
 
 	/* high bandwidth, or otherwise every microframe */
 	if (period == 0)
 		period = 1;
 
-	for (i = qh->start; i < ehci->periodic_size; i += period) {
+	for (i = qh->sw->start; i < ehci->periodic_size; i += period) {
 		union ehci_shadow	*prev = &ehci->pshadow[i];
 		__hc32			*hw_p = &ehci->periodic[i];
 		union ehci_shadow	here = *prev;
@@ -525,29 +525,29 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
 		 * enables sharing interior tree nodes
 		 */
 		while (here.ptr && qh != here.qh) {
-			if (qh->period > here.qh->period)
+			if (qh->sw->period > here.qh->sw->period)
 				break;
-			prev = &here.qh->qh_next;
+			prev = &here.qh->sw->qh_next;
 			hw_p = &here.qh->hw_next;
 			here = *prev;
 		}
 		/* link in this qh, unless some earlier pass did that */
 		if (qh != here.qh) {
-			qh->qh_next = here;
+			qh->sw->qh_next = here;
 			if (here.qh)
 				qh->hw_next = *hw_p;
 			wmb ();
 			prev->qh = qh;
-			*hw_p = QH_NEXT (ehci, qh->qh_dma);
+			*hw_p = QH_NEXT(ehci, qh->sw->qh_dma);
 		}
 	}
-	qh->qh_state = QH_STATE_LINKED;
+	qh->sw->qh_state = QH_STATE_LINKED;
 	qh_get (qh);
 
 	/* update per-qh bandwidth for usbfs */
-	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period
-		? ((qh->usecs + qh->c_usecs) / qh->period)
-		: (qh->usecs * 8);
+	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->sw->period
+		? ((qh->sw->usecs + qh->sw->c_usecs) / qh->sw->period)
+		: (qh->sw->usecs * 8);
 
 	/* maybe enable periodic schedule processing */
 	return enable_periodic(ehci);
@@ -566,26 +566,27 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
 	//   qh->hw_info1 |= cpu_to_hc32(1 << 7 /* "ignore" */);
 
 	/* high bandwidth, or otherwise part of every microframe */
-	if ((period = qh->period) == 0)
+	period = qh->sw->period;
+	if (period == 0)
 		period = 1;
 
-	for (i = qh->start; i < ehci->periodic_size; i += period)
+	for (i = qh->sw->start; i < ehci->periodic_size; i += period)
 		periodic_unlink (ehci, i, qh);
 
 	/* update per-qh bandwidth for usbfs */
-	ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->period
-		? ((qh->usecs + qh->c_usecs) / qh->period)
-		: (qh->usecs * 8);
+	ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->sw->period
+		? ((qh->sw->usecs + qh->sw->c_usecs) / qh->sw->period)
+		: (qh->sw->usecs * 8);
 
-	dev_dbg (&qh->dev->dev,
+	dev_dbg(&qh->sw->dev->dev,
 		"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
-		qh->period,
+		qh->sw->period,
 		hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
-		qh, qh->start, qh->usecs, qh->c_usecs);
+		qh, qh->sw->start, qh->sw->usecs, qh->sw->c_usecs);
 
-	/* qh->qh_next still "live" to HC */
-	qh->qh_state = QH_STATE_UNLINK;
-	qh->qh_next.ptr = NULL;
+	/* qh->sw->qh_next still "live" to HC */
+	qh->sw->qh_state = QH_STATE_UNLINK;
+	qh->sw->qh_next.ptr = NULL;
 	qh_put (qh);
 
 	/* maybe turn off periodic schedule */
@@ -603,7 +604,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	 * expect khubd to clean up after any CSPLITs we won't issue.
 	 * active high speed queues may need bigger delays...
 	 */
-	if (list_empty (&qh->qtd_list)
+	if (list_empty(&qh->sw->qtd_list)
 			|| (cpu_to_hc32(ehci, QH_CMASK)
 					& qh->hw_info2) != 0)
 		wait = 2;
@@ -611,7 +612,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 		wait = 55;	/* worst case: 3 * 1024 */
 
 	udelay (wait);
-	qh->qh_state = QH_STATE_IDLE;
+	qh->sw->qh_state = QH_STATE_IDLE;
 	qh->hw_next = EHCI_LIST_END(ehci);
 	wmb ();
 }
@@ -675,26 +676,26 @@ static int check_intr_schedule (
 	int		retval = -ENOSPC;
 	u8		mask = 0;
 
-	if (qh->c_usecs && uframe >= 6)		/* FSTN territory? */
+	if (qh->sw->c_usecs && uframe >= 6)		/* FSTN territory? */
 		goto done;
 
-	if (!check_period (ehci, frame, uframe, qh->period, qh->usecs))
+	if (!check_period(ehci, frame, uframe, qh->sw->period, qh->sw->usecs))
 		goto done;
-	if (!qh->c_usecs) {
+	if (!qh->sw->c_usecs) {
 		retval = 0;
 		*c_maskp = 0;
 		goto done;
 	}
 
 #ifdef CONFIG_USB_EHCI_TT_NEWSCHED
-	if (tt_available (ehci, qh->period, qh->dev, frame, uframe,
-				qh->tt_usecs)) {
+	if (tt_available(ehci, qh->sw->period, qh->sw->dev, frame, uframe,
+				qh->sw->tt_usecs)) {
 		unsigned i;
 
 		/* TODO : this may need FSTN for SSPLIT in uframe 5. */
 		for (i=uframe+1; i<8 && i<uframe+4; i++)
-			if (!check_period (ehci, frame, i,
-						qh->period, qh->c_usecs))
+			if (!check_period(ehci, frame, i,
+					qh->sw->period, qh->sw->c_usecs))
 				goto done;
 			else
 				mask |= 1 << i;
@@ -711,16 +712,16 @@ static int check_intr_schedule (
 	 * NOTE:  both SPLIT and CSPLIT could be checked in just
 	 * one smart pass...
 	 */
-	mask = 0x03 << (uframe + qh->gap_uf);
+	mask = 0x03 << (uframe + qh->sw->gap_uf);
 	*c_maskp = cpu_to_hc32(ehci, mask << 8);
 
 	mask |= 1 << uframe;
-	if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) {
-		if (!check_period (ehci, frame, uframe + qh->gap_uf + 1,
-					qh->period, qh->c_usecs))
+	if (tt_no_collision(ehci, qh->sw->period, qh->sw->dev, frame, mask)) {
+		if (!check_period(ehci, frame, uframe + qh->sw->gap_uf + 1,
+					qh->sw->period, qh->sw->c_usecs))
 			goto done;
-		if (!check_period (ehci, frame, uframe + qh->gap_uf,
-					qh->period, qh->c_usecs))
+		if (!check_period(ehci, frame, uframe + qh->sw->gap_uf,
+					qh->sw->period, qh->sw->c_usecs))
 			goto done;
 		retval = 0;
 	}
@@ -737,14 +738,14 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
 	int		status;
 	unsigned	uframe;
 	__hc32		c_mask;
-	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
+	unsigned	frame;	/* 0..(qh->sw->period - 1), or NO_FRAME */
 
 	qh_refresh(ehci, qh);
 	qh->hw_next = EHCI_LIST_END(ehci);
-	frame = qh->start;
+	frame = qh->sw->start;
 
 	/* reuse the previous schedule slots, if we can */
-	if (frame < qh->period) {
+	if (frame < qh->sw->period) {
 		uframe = ffs(hc32_to_cpup(ehci, &qh->hw_info2) & QH_SMASK);
 		status = check_intr_schedule (ehci, frame, --uframe,
 				qh, &c_mask);
@@ -759,8 +760,8 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
 	 */
 	if (status) {
 		/* "normal" case, uframing flexible except with splits */
-		if (qh->period) {
-			frame = qh->period - 1;
+		if (qh->sw->period) {
+			frame = qh->sw->period - 1;
 			do {
 				for (uframe = 0; uframe < 8; uframe++) {
 					status = check_intr_schedule (ehci,
@@ -771,18 +772,18 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
 				}
 			} while (status && frame--);
 
-		/* qh->period == 0 means every uframe */
+		/* qh->sw->period == 0 means every uframe */
 		} else {
 			frame = 0;
 			status = check_intr_schedule (ehci, 0, 0, qh, &c_mask);
 		}
 		if (status)
 			goto done;
-		qh->start = frame;
+		qh->sw->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
+		qh->hw_info2 |= qh->sw->period
 			? cpu_to_hc32(ehci, 1 << uframe)
 			: cpu_to_hc32(ehci, QH_SMASK);
 		qh->hw_info2 |= c_mask;
@@ -828,7 +829,7 @@ static int intr_submit (
 		status = -ENOMEM;
 		goto done;
 	}
-	if (qh->qh_state == QH_STATE_IDLE) {
+	if (qh->sw->qh_state == QH_STATE_IDLE) {
 		if ((status = qh_schedule (ehci, qh)) != 0)
 			goto done;
 	}
@@ -2182,9 +2183,10 @@ restart:
 				/* handle any completions */
 				temp.qh = qh_get (q.qh);
 				type = Q_NEXT_TYPE(ehci, q.qh->hw_next);
-				q = q.qh->qh_next;
+				q = q.qh->sw->qh_next;
 				modified = qh_completions (ehci, temp.qh);
-				if (unlikely (list_empty (&temp.qh->qtd_list)))
+				if (unlikely(
+					list_empty(&temp.qh->sw->qtd_list)))
 					intr_deschedule (ehci, temp.qh);
 				qh_put (temp.qh);
 				break;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index c36d22a..5e4b52c 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -298,6 +298,8 @@ union ehci_shadow {
  * These appear in both the async and (for interrupt) periodic schedules.
  */
 
+struct ehci_qh_sw;
+
 struct ehci_qh {
 	/* first part defined by EHCI spec */
 	__hc32			hw_next;	/* see EHCI 3.6.1 */
@@ -319,6 +321,11 @@ struct ehci_qh {
 	__hc32			hw_buf_hi [5];
 
 	/* the rest is HCD-private */
+	struct	ehci_qh_sw	*sw;
+} __attribute__ ((aligned(32)));
+
+/* HCD private (software) part */
+struct ehci_qh_sw {
 	dma_addr_t		qh_dma;		/* address of qh */
 	union ehci_shadow	qh_next;	/* ptr to qh; or periodic */
 	struct list_head	qtd_list;	/* sw qtd list */
@@ -355,7 +362,7 @@ struct ehci_qh {
 	unsigned short		start;		/* where polling starts */
 #define NO_FRAME ((unsigned short)~0)			/* pick new start */
 	struct usb_device	*dev;		/* access to TT */
-} __attribute__ ((aligned (32)));
+};
 
 /*-------------------------------------------------------------------------*/
 
-- 
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