Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6dbd682b authored by Stefan Roese's avatar Stefan Roese Committed by Greg Kroah-Hartman
Browse files

USB: EHCI support for big-endian descriptors



This patch implements supports for EHCI controllers whose in-memory
data structures are represented in big-endian format. This is needed
(unfortunately) for the AMCC PPC440EPx SoC EHCI controller; the EHCI
spec doesn't specify little-endian format, although that's what most
other implementations use.

The guts of the patch are to introduce the hc32 type and change all
references from le32 to hc32.  All access routines are converted from
cpu_to_le32(...) to cpu_to_hc32(ehci, ...) and similar for the other
"direction".  (This is the same approach used with OHCI.)

David fixed:
	Whitespace fixes; refresh against ehci cpufreq patch; move glue
	for that PPC driver to the patch adding it; fix free symbol
	capture bugs in modified "constant" macros; and make "hc32" etc
	be "le32" unless we really need the BE options, so "sparse" can
	do some real good.

Signed-off-by: default avatarStefan Roese <sr@denx.de>
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 196705c9
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -72,6 +72,11 @@ config USB_EHCI_BIG_ENDIAN_MMIO
	depends on USB_EHCI_HCD
	default n

config USB_EHCI_BIG_ENDIAN_DESC
	bool
	depends on USB_EHCI_HCD
	default n

config USB_ISP116X_HCD
	tristate "ISP116X HCD support"
	depends on USB
+85 −76
Original line number Diff line number Diff line
@@ -119,16 +119,16 @@ static void __attribute__((__unused__))
dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd)
{
	ehci_dbg(ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
		le32_to_cpup (&qtd->hw_next),
		le32_to_cpup (&qtd->hw_alt_next),
		le32_to_cpup (&qtd->hw_token),
		le32_to_cpup (&qtd->hw_buf [0]));
		hc32_to_cpup(ehci, &qtd->hw_next),
		hc32_to_cpup(ehci, &qtd->hw_alt_next),
		hc32_to_cpup(ehci, &qtd->hw_token),
		hc32_to_cpup(ehci, &qtd->hw_buf [0]));
	if (qtd->hw_buf [1])
		ehci_dbg(ehci, "  p1=%08x p2=%08x p3=%08x p4=%08x\n",
			le32_to_cpup (&qtd->hw_buf [1]),
			le32_to_cpup (&qtd->hw_buf [2]),
			le32_to_cpup (&qtd->hw_buf [3]),
			le32_to_cpup (&qtd->hw_buf [4]));
			hc32_to_cpup(ehci, &qtd->hw_buf[1]),
			hc32_to_cpup(ehci, &qtd->hw_buf[2]),
			hc32_to_cpup(ehci, &qtd->hw_buf[3]),
			hc32_to_cpup(ehci, &qtd->hw_buf[4]));
}

static void __attribute__((__unused__))
@@ -144,26 +144,27 @@ static void __attribute__((__unused__))
dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
{
	ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n",
		label, itd->frame, itd, le32_to_cpu(itd->hw_next), itd->urb);
		label, itd->frame, itd, hc32_to_cpu(ehci, itd->hw_next),
		itd->urb);
	ehci_dbg (ehci,
		"  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
		le32_to_cpu(itd->hw_transaction[0]),
		le32_to_cpu(itd->hw_transaction[1]),
		le32_to_cpu(itd->hw_transaction[2]),
		le32_to_cpu(itd->hw_transaction[3]),
		le32_to_cpu(itd->hw_transaction[4]),
		le32_to_cpu(itd->hw_transaction[5]),
		le32_to_cpu(itd->hw_transaction[6]),
		le32_to_cpu(itd->hw_transaction[7]));
		hc32_to_cpu(ehci, itd->hw_transaction[0]),
		hc32_to_cpu(ehci, itd->hw_transaction[1]),
		hc32_to_cpu(ehci, itd->hw_transaction[2]),
		hc32_to_cpu(ehci, itd->hw_transaction[3]),
		hc32_to_cpu(ehci, itd->hw_transaction[4]),
		hc32_to_cpu(ehci, itd->hw_transaction[5]),
		hc32_to_cpu(ehci, itd->hw_transaction[6]),
		hc32_to_cpu(ehci, itd->hw_transaction[7]));
	ehci_dbg (ehci,
		"  buf:   %08x %08x %08x %08x %08x %08x %08x\n",
		le32_to_cpu(itd->hw_bufp[0]),
		le32_to_cpu(itd->hw_bufp[1]),
		le32_to_cpu(itd->hw_bufp[2]),
		le32_to_cpu(itd->hw_bufp[3]),
		le32_to_cpu(itd->hw_bufp[4]),
		le32_to_cpu(itd->hw_bufp[5]),
		le32_to_cpu(itd->hw_bufp[6]));
		hc32_to_cpu(ehci, itd->hw_bufp[0]),
		hc32_to_cpu(ehci, itd->hw_bufp[1]),
		hc32_to_cpu(ehci, itd->hw_bufp[2]),
		hc32_to_cpu(ehci, itd->hw_bufp[3]),
		hc32_to_cpu(ehci, itd->hw_bufp[4]),
		hc32_to_cpu(ehci, itd->hw_bufp[5]),
		hc32_to_cpu(ehci, itd->hw_bufp[6]));
	ehci_dbg (ehci, "  index: %d %d %d %d %d %d %d %d\n",
		itd->index[0], itd->index[1], itd->index[2],
		itd->index[3], itd->index[4], itd->index[5],
@@ -174,14 +175,15 @@ static void __attribute__((__unused__))
dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd)
{
	ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n",
		label, sitd->frame, sitd, le32_to_cpu(sitd->hw_next), sitd->urb);
		label, sitd->frame, sitd, hc32_to_cpu(ehci, sitd->hw_next),
		sitd->urb);
	ehci_dbg (ehci,
		"  addr %08x sched %04x result %08x buf %08x %08x\n",
		le32_to_cpu(sitd->hw_fullspeed_ep),
		le32_to_cpu(sitd->hw_uframe),
		le32_to_cpu(sitd->hw_results),
		le32_to_cpu(sitd->hw_buf [0]),
		le32_to_cpu(sitd->hw_buf [1]));
		hc32_to_cpu(ehci, sitd->hw_fullspeed_ep),
		hc32_to_cpu(ehci, sitd->hw_uframe),
		hc32_to_cpu(ehci, sitd->hw_results),
		hc32_to_cpu(ehci, sitd->hw_buf[0]),
		hc32_to_cpu(ehci, sitd->hw_buf[1]));
}

static int __attribute__((__unused__))
@@ -267,8 +269,7 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status)
		(status & PORT_PEC) ? " PEC" : "",
		(status & PORT_PE) ? " PE" : "",
		(status & PORT_CSC) ? " CSC" : "",
		(status & PORT_CONNECT) ? " CONNECT" : ""
	    );
		(status & PORT_CONNECT) ? " CONNECT" : "");
}

#else
@@ -332,9 +333,10 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
		default: tmp = '?'; break; \
		}; tmp; })

static inline char token_mark (__le32 token)
static inline char token_mark(struct ehci_hcd *ehci, __hc32 token)
{
	__u32 v = le32_to_cpu (token);
	__u32 v = hc32_to_cpu(ehci, token);

	if (v & QTD_STS_ACTIVE)
		return '*';
	if (v & QTD_STS_HALT)
@@ -360,46 +362,48 @@ static void qh_lines (
	unsigned		size = *sizep;
	char			*next = *nextp;
	char			mark;
	u32			list_end = EHCI_LIST_END(ehci);

	if (qh->hw_qtd_next == EHCI_LIST_END)	/* NEC does this */
	if (qh->hw_qtd_next == list_end)	/* NEC does this */
		mark = '@';
	else
		mark = token_mark (qh->hw_token);
		mark = token_mark(ehci, qh->hw_token);
	if (mark == '/') {	/* qh_alt_next controls qh advance? */
		if ((qh->hw_alt_next & QTD_MASK) == ehci->async->hw_alt_next)
		if ((qh->hw_alt_next & QTD_MASK(ehci))
				== ehci->async->hw_alt_next)
			mark = '#';	/* blocked */
		else if (qh->hw_alt_next == EHCI_LIST_END)
		else if (qh->hw_alt_next == list_end)
			mark = '.';	/* use hw_qtd_next */
		/* else alt_next points to some other qtd */
	}
	scratch = le32_to_cpup (&qh->hw_info1);
	hw_curr = (mark == '*') ? le32_to_cpup (&qh->hw_current) : 0;
	scratch = hc32_to_cpup(ehci, &qh->hw_info1);
	hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &qh->hw_current) : 0;
	temp = scnprintf (next, size,
			"qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
			qh, scratch & 0x007f,
			speed_char (scratch),
			(scratch >> 8) & 0x000f,
			scratch, le32_to_cpup (&qh->hw_info2),
			le32_to_cpup (&qh->hw_token), mark,
			(__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token)
			scratch, hc32_to_cpup(ehci, &qh->hw_info2),
			hc32_to_cpup(ehci, &qh->hw_token), mark,
			(cpu_to_hc32(ehci, QTD_TOGGLE) & qh->hw_token)
				? "data1" : "data0",
			(le32_to_cpup (&qh->hw_alt_next) >> 1) & 0x0f);
			(hc32_to_cpup(ehci, &qh->hw_alt_next) >> 1) & 0x0f);
	size -= temp;
	next += temp;

	/* hc may be modifying the list as we read it ... */
	list_for_each (entry, &qh->qtd_list) {
		td = list_entry (entry, struct ehci_qtd, qtd_list);
		scratch = le32_to_cpup (&td->hw_token);
		scratch = hc32_to_cpup(ehci, &td->hw_token);
		mark = ' ';
		if (hw_curr == td->qtd_dma)
			mark = '*';
		else if (qh->hw_qtd_next == cpu_to_le32(td->qtd_dma))
		else if (qh->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma))
			mark = '+';
		else if (QTD_LENGTH (scratch)) {
			if (td->hw_alt_next == ehci->async->hw_alt_next)
				mark = '#';
			else if (td->hw_alt_next != EHCI_LIST_END)
			else if (td->hw_alt_next != list_end)
				mark = '/';
		}
		temp = snprintf (next, size,
@@ -490,7 +494,7 @@ show_periodic (struct class_device *class_dev, char *buf)
	unsigned		temp, size, seen_count;
	char			*next;
	unsigned		i;
	__le32			tag;
	__hc32			tag;

	if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC)))
		return 0;
@@ -514,18 +518,19 @@ show_periodic (struct class_device *class_dev, char *buf)
		p = ehci->pshadow [i];
		if (likely (!p.ptr))
			continue;
		tag = Q_NEXT_TYPE (ehci->periodic [i]);
		tag = Q_NEXT_TYPE(ehci, ehci->periodic [i]);

		temp = scnprintf (next, size, "%4d: ", i);
		size -= temp;
		next += temp;

		do {
			switch (tag) {
			switch (hc32_to_cpu(ehci, tag)) {
			case Q_TYPE_QH:
				temp = scnprintf (next, size, " qh%d-%04x/%p",
						p.qh->period,
						le32_to_cpup (&p.qh->hw_info2)
						hc32_to_cpup(ehci,
								&p.qh->hw_info2)
							/* uframe masks */
							& (QH_CMASK | QH_SMASK),
						p.qh);
@@ -543,7 +548,7 @@ show_periodic (struct class_device *class_dev, char *buf)
				}
				/* show more info the first time around */
				if (temp == seen_count && p.ptr) {
					u32	scratch = le32_to_cpup (
					u32	scratch = hc32_to_cpup(ehci,
							&p.qh->hw_info1);
					struct ehci_qtd	*qtd;
					char		*type = "";
@@ -554,7 +559,8 @@ show_periodic (struct class_device *class_dev, char *buf)
							&p.qh->qtd_list,
							qtd_list) {
						temp++;
						switch (0x03 & (le32_to_cpu (
						switch (0x03 & (hc32_to_cpu(
							ehci,
							qtd->hw_token) >> 8)) {
						case 0: type = "out"; continue;
						case 1: type = "in"; continue;
@@ -576,7 +582,7 @@ show_periodic (struct class_device *class_dev, char *buf)
				} else
					temp = 0;
				if (p.qh) {
					tag = Q_NEXT_TYPE (p.qh->hw_next);
					tag = Q_NEXT_TYPE(ehci, p.qh->hw_next);
					p = p.qh->qh_next;
				}
				break;
@@ -584,23 +590,23 @@ show_periodic (struct class_device *class_dev, char *buf)
				temp = scnprintf (next, size,
					" fstn-%8x/%p", p.fstn->hw_prev,
					p.fstn);
				tag = Q_NEXT_TYPE (p.fstn->hw_next);
				tag = Q_NEXT_TYPE(ehci, p.fstn->hw_next);
				p = p.fstn->fstn_next;
				break;
			case Q_TYPE_ITD:
				temp = scnprintf (next, size,
					" itd/%p", p.itd);
				tag = Q_NEXT_TYPE (p.itd->hw_next);
				tag = Q_NEXT_TYPE(ehci, p.itd->hw_next);
				p = p.itd->itd_next;
				break;
			case Q_TYPE_SITD:
				temp = scnprintf (next, size,
					" sitd%d-%04x/%p",
					p.sitd->stream->interval,
					le32_to_cpup (&p.sitd->hw_uframe)
					hc32_to_cpup(ehci, &p.sitd->hw_uframe)
						& 0x0000ffff,
					p.sitd);
				tag = Q_NEXT_TYPE (p.sitd->hw_next);
				tag = Q_NEXT_TYPE(ehci, p.sitd->hw_next);
				p = p.sitd->sitd_next;
				break;
			}
@@ -673,7 +679,8 @@ show_registers (struct class_device *class_dev, char *buf)
		unsigned	count = 256/4;

		pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
		offset = HCC_EXT_CAPS (ehci_readl(ehci, &ehci->caps->hcc_params));
		offset = HCC_EXT_CAPS(ehci_readl(ehci,
				&ehci->caps->hcc_params));
		while (offset && count--) {
			pci_read_config_dword (pdev, offset, &cap);
			switch (cap & 0xff) {
@@ -740,14 +747,16 @@ show_registers (struct class_device *class_dev, char *buf)

	for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) {
		temp = dbg_port_buf (scratch, sizeof scratch, label, i,
				ehci_readl(ehci, &ehci->regs->port_status [i - 1]));
				ehci_readl(ehci,
					&ehci->regs->port_status[i - 1]));
		temp = scnprintf (next, size, fmt, temp, scratch);
		size -= temp;
		next += temp;
		if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) {
			temp = scnprintf (next, size,
					"    debug control %08x\n",
					ehci_readl(ehci, &ehci->debug->control));
					ehci_readl(ehci,
						&ehci->debug->control));
			size -= temp;
			next += temp;
		}
+5 −5
Original line number Diff line number Diff line
@@ -526,12 +526,12 @@ static int ehci_init(struct usb_hcd *hcd)
	 * from automatically advancing to the next td after short reads.
	 */
	ehci->async->qh_next.qh = NULL;
	ehci->async->hw_next = QH_NEXT(ehci->async->qh_dma);
	ehci->async->hw_info1 = cpu_to_le32(QH_HEAD);
	ehci->async->hw_token = cpu_to_le32(QTD_STS_HALT);
	ehci->async->hw_qtd_next = EHCI_LIST_END;
	ehci->async->hw_next = QH_NEXT(ehci, ehci->async->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->async->dummy->qtd_dma);
	ehci->async->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma);

	/* clear interrupt enables, set irq latency */
	if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
+7 −6
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@
 *	  need to use dma_pool or dma_alloc_coherent
 *	- driver buffers, read/written by HC ... single shot DMA mapped
 *
 * There's also PCI "register" data, which is memory mapped.
 * There's also "register" data (e.g. PCI or SOC), which is memory mapped.
 * No memory seen by this driver is pageable.
 */

@@ -35,13 +35,14 @@

/* Allocate the key transfer structures from the previously allocated pool */

static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma)
static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd,
				  dma_addr_t dma)
{
	memset (qtd, 0, sizeof *qtd);
	qtd->qtd_dma = dma;
	qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
	qtd->hw_next = EHCI_LIST_END;
	qtd->hw_alt_next = EHCI_LIST_END;
	qtd->hw_next = EHCI_LIST_END(ehci);
	qtd->hw_alt_next = EHCI_LIST_END(ehci);
	INIT_LIST_HEAD (&qtd->qtd_list);
}

@@ -52,7 +53,7 @@ static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags)

	qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma);
	if (qtd != NULL) {
		ehci_qtd_init (qtd, dma);
		ehci_qtd_init(ehci, qtd, dma);
	}
	return qtd;
}
@@ -220,7 +221,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
		goto fail;
	}
	for (i = 0; i < ehci->periodic_size; i++)
		ehci->periodic [i] = EHCI_LIST_END;
		ehci->periodic [i] = EHCI_LIST_END(ehci);

	/* software shadow of hardware table */
	ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags);
+47 −45
Original line number Diff line number Diff line
@@ -43,15 +43,15 @@
/* fill a qtd, returning how much of the buffer we were able to queue up */

static int
qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
		int token, int maxpacket)
qtd_fill(struct ehci_hcd *ehci, struct ehci_qtd *qtd, dma_addr_t buf,
		  size_t len, int token, int maxpacket)
{
	int	i, count;
	u64	addr = buf;

	/* one buffer entry per 4K ... first might be short or unaligned */
	qtd->hw_buf [0] = cpu_to_le32 ((u32)addr);
	qtd->hw_buf_hi [0] = cpu_to_le32 ((u32)(addr >> 32));
	qtd->hw_buf[0] = cpu_to_hc32(ehci, (u32)addr);
	qtd->hw_buf_hi[0] = cpu_to_hc32(ehci, (u32)(addr >> 32));
	count = 0x1000 - (buf & 0x0fff);	/* rest of that page */
	if (likely (len < count))		/* ... iff needed */
		count = len;
@@ -62,8 +62,9 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
		/* per-qtd limit: from 16K to 20K (best alignment) */
		for (i = 1; count < len && i < 5; i++) {
			addr = buf;
			qtd->hw_buf [i] = cpu_to_le32 ((u32)addr);
			qtd->hw_buf_hi [i] = cpu_to_le32 ((u32)(addr >> 32));
			qtd->hw_buf[i] = cpu_to_hc32(ehci, (u32)addr);
			qtd->hw_buf_hi[i] = cpu_to_hc32(ehci,
					(u32)(addr >> 32));
			buf += 0x1000;
			if ((count + 0x1000) < len)
				count += 0x1000;
@@ -75,7 +76,7 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
		if (count != len)
			count -= (count % maxpacket);
	}
	qtd->hw_token = cpu_to_le32 ((count << 16) | token);
	qtd->hw_token = cpu_to_hc32(ehci, (count << 16) | token);
	qtd->length = count;

	return count;
@@ -89,28 +90,28 @@ 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 (qtd->qtd_dma);
	qh->hw_alt_next = EHCI_LIST_END;
	qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
	qh->hw_alt_next = EHCI_LIST_END(ehci);

	/* Except for control endpoints, we make hardware maintain data
	 * toggle (like OHCI) ... here (re)initialize the toggle in the QH,
	 * and set the pseudo-toggle in udev. Only usb_clear_halt() will
	 * ever clear it.
	 */
	if (!(qh->hw_info1 & cpu_to_le32(1 << 14))) {
	if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
		unsigned	is_out, epnum;

		is_out = !(qtd->hw_token & cpu_to_le32(1 << 8));
		epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f;
		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))) {
			qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE);
			qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
			usb_settoggle (qh->dev, epnum, is_out, 1);
		}
	}

	/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
	wmb ();
	qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING);
	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
@@ -128,7 +129,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_le32 (qtd->qtd_dma) == qh->hw_current)
		if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw_current)
			qtd = NULL;
	}

@@ -222,7 +223,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 & __constant_cpu_to_le32 (QH_SMASK)) != 0) {
		if ((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--;
@@ -277,7 +278,6 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
 * Chases up to qh->hw_current.  Returns number of completions called,
 * indicating how much "real" work we did.
 */
#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT)
static unsigned
qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
@@ -287,6 +287,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
	unsigned		count = 0;
	int			do_status = 0;
	u8			state;
	u32			halt = HALT_BIT(ehci);

	if (unlikely (list_empty (&qh->qtd_list)))
		return count;
@@ -334,7 +335,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)

		/* hardware copies qtd out of qh overlay */
		rmb ();
		token = le32_to_cpu (qtd->hw_token);
		token = hc32_to_cpu(ehci, qtd->hw_token);

		/* always clean up qtds the hc de-activated */
		if ((token & QTD_STS_ACTIVE) == 0) {
@@ -346,7 +347,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
			 * that silicon quirk can kick in with this dummy too.
			 */
			} else if (IS_SHORT_READ (token)
					&& !(qtd->hw_alt_next & EHCI_LIST_END)) {
					&& !(qtd->hw_alt_next
						& EHCI_LIST_END(ehci))) {
				stopped = 1;
				goto halt;
			}
@@ -378,17 +380,17 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)

			/* token in overlay may be most current */
			if (state == QH_STATE_IDLE
					&& cpu_to_le32 (qtd->qtd_dma)
					&& cpu_to_hc32(ehci, qtd->qtd_dma)
						== qh->hw_current)
				token = le32_to_cpu (qh->hw_token);
				token = hc32_to_cpu(ehci, 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_BIT & qh->hw_token) == 0) {
			if ((halt & qh->hw_token) == 0) {
halt:
				qh->hw_token |= HALT_BIT;
				qh->hw_token |= halt;
				wmb ();
			}
		}
@@ -423,7 +425,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
	 * 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) {
	if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) {
		switch (state) {
		case QH_STATE_IDLE:
			qh_refresh(ehci, qh);
@@ -432,7 +434,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
			/* should be rare for periodic transfers,
			 * except maybe high bandwidth ...
			 */
			if ((__constant_cpu_to_le32 (QH_SMASK)
			if ((cpu_to_hc32(ehci, QH_SMASK)
					& qh->hw_info2) != 0) {
				intr_deschedule (ehci, qh);
				(void) qh_schedule (ehci, qh);
@@ -506,7 +508,8 @@ qh_urb_transaction (
	is_input = usb_pipein (urb->pipe);
	if (usb_pipecontrol (urb->pipe)) {
		/* SETUP pid */
		qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest),
		qtd_fill(ehci, qtd, urb->setup_dma,
				sizeof (struct usb_ctrlrequest),
				token | (2 /* "setup" */ << 8), 8);

		/* ... and always at least one more pid */
@@ -516,7 +519,7 @@ qh_urb_transaction (
		if (unlikely (!qtd))
			goto cleanup;
		qtd->urb = urb;
		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
		qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
		list_add_tail (&qtd->qtd_list, head);

		/* for zero length DATA stages, STATUS is always IN */
@@ -543,7 +546,7 @@ qh_urb_transaction (
	for (;;) {
		int this_qtd_len;

		this_qtd_len = qtd_fill (qtd, buf, len, token, maxpacket);
		this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket);
		len -= this_qtd_len;
		buf += this_qtd_len;
		if (is_input)
@@ -561,7 +564,7 @@ qh_urb_transaction (
		if (unlikely (!qtd))
			goto cleanup;
		qtd->urb = urb;
		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
		qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
		list_add_tail (&qtd->qtd_list, head);
	}

@@ -570,7 +573,7 @@ qh_urb_transaction (
	 */
	if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
				|| usb_pipecontrol (urb->pipe)))
		qtd->hw_alt_next = EHCI_LIST_END;
		qtd->hw_alt_next = EHCI_LIST_END(ehci);

	/*
	 * control requests may need a terminating data "status" ack;
@@ -594,17 +597,17 @@ qh_urb_transaction (
			if (unlikely (!qtd))
				goto cleanup;
			qtd->urb = urb;
			qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
			qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
			list_add_tail (&qtd->qtd_list, head);

			/* never any data in such packets */
			qtd_fill (qtd, 0, 0, token, 0);
			qtd_fill(ehci, qtd, 0, 0, token, 0);
		}
	}

	/* by default, enable interrupt on urb completion */
	if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
		qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
		qtd->hw_token |= cpu_to_hc32(ehci, QTD_IOC);
	return head;

cleanup:
@@ -773,8 +776,8 @@ qh_make (

	/* init as live, toggle clear, advance to dummy */
	qh->qh_state = QH_STATE_IDLE;
	qh->hw_info1 = cpu_to_le32 (info1);
	qh->hw_info2 = cpu_to_le32 (info2);
	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);
	qh_refresh (ehci, qh);
	return qh;
@@ -786,7 +789,7 @@ qh_make (

static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
	__le32		dma = QH_NEXT (qh->qh_dma);
	__hc32		dma = QH_NEXT(ehci, qh->qh_dma);
	struct ehci_qh	*head;

	/* (re)start the async schedule? */
@@ -824,8 +827,6 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)

/*-------------------------------------------------------------------------*/

#define	QH_ADDR_MASK	__constant_cpu_to_le32(0x7f)

/*
 * For control/bulk/interrupt, return QH with these TDs appended.
 * Allocates and initializes the QH if necessary.
@@ -841,6 +842,7 @@ static struct ehci_qh *qh_append_tds (
)
{
	struct ehci_qh		*qh = NULL;
	u32			qh_addr_mask = cpu_to_hc32(ehci, 0x7f);

	qh = (struct ehci_qh *) *ptr;
	if (unlikely (qh == NULL)) {
@@ -862,7 +864,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;
                                qh->hw_info1 &= ~qh_addr_mask;
		}

		/* just one way to queue requests: swap with the dummy qtd.
@@ -871,7 +873,7 @@ static struct ehci_qh *qh_append_tds (
		if (likely (qtd != NULL)) {
			struct ehci_qtd		*dummy;
			dma_addr_t		dma;
			__le32			token;
			__hc32			token;

			/* to avoid racing the HC, use the dummy td instead of
			 * the first td of our list (becomes new dummy).  both
@@ -879,7 +881,7 @@ static struct ehci_qh *qh_append_tds (
			 * HC is allowed to fetch the old dummy (4.10.2).
			 */
			token = qtd->hw_token;
			qtd->hw_token = HALT_BIT;
			qtd->hw_token = HALT_BIT(ehci);
			wmb ();
			dummy = qh->dummy;

@@ -891,14 +893,14 @@ static struct ehci_qh *qh_append_tds (
			list_add (&dummy->qtd_list, qtd_list);
			__list_splice (qtd_list, qh->qtd_list.prev);

			ehci_qtd_init (qtd, qtd->qtd_dma);
			ehci_qtd_init(ehci, qtd, qtd->qtd_dma);
			qh->dummy = qtd;

			/* hc must see the new dummy at list end */
			dma = qtd->qtd_dma;
			qtd = list_entry (qh->qtd_list.prev,
					struct ehci_qtd, qtd_list);
			qtd->hw_next = QTD_NEXT (dma);
			qtd->hw_next = QTD_NEXT(ehci, dma);

			/* let the hc process these next qtds */
			wmb ();
@@ -974,7 +976,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)

	timer_action_done (ehci, TIMER_IAA_WATCHDOG);

	// qh->hw_next = cpu_to_le32 (qh->qh_dma);
	// 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
Loading