USB: UHCI: Add support for big endian descriptors

This patch adds support for universal host controllers that use
big endian descriptors. Support for BE descriptors requires a non-PCI
host controller. For kernels with PCI-only UHCI there should be no
change in behaviour.

This patch tries to replicate the technique used to support BE descriptors
in the EHCI HCD. Parts added to uhci-hcd.h are basically copy'n'paste from
ehci.h.

Signed-off-by: Jan Andersson <jan@gaisler.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index f882a84..fc0b0da 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -37,7 +37,8 @@
 	}
 }
 
-static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space)
+static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf,
+			int len, int space)
 {
 	char *out = buf;
 	char *spid;
@@ -47,8 +48,9 @@
 	if (len < 160)
 		return 0;
 
-	status = td_status(td);
-	out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td, le32_to_cpu(td->link));
+	status = td_status(uhci, td);
+	out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td,
+		hc32_to_cpu(uhci, td->link));
 	out += sprintf(out, "e%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
 		((status >> 27) & 3),
 		(status & TD_CTRL_SPD) ?      "SPD " : "",
@@ -63,7 +65,7 @@
 		(status & TD_CTRL_BITSTUFF) ? "BitStuff " : "",
 		status & 0x7ff);
 
-	token = td_token(td);
+	token = td_token(uhci, td);
 	switch (uhci_packetid(token)) {
 		case USB_PID_SETUP:
 			spid = "SETUP";
@@ -86,12 +88,13 @@
 		(token >> 8) & 127,
 		(token & 0xff),
 		spid);
-	out += sprintf(out, "(buf=%08x)\n", le32_to_cpu(td->buffer));
+	out += sprintf(out, "(buf=%08x)\n", hc32_to_cpu(uhci, td->buffer));
 
 	return out - buf;
 }
 
-static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
+static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp,
+			char *buf, int len, int space)
 {
 	char *out = buf;
 	struct uhci_td *td;
@@ -130,9 +133,10 @@
 		if (urbp->qh->type != USB_ENDPOINT_XFER_ISOC &&
 				(++i <= 10 || debug > 2)) {
 			out += sprintf(out, "%*s%d: ", space + 2, "", i);
-			out += uhci_show_td(td, out, len - (out - buf), 0);
+			out += uhci_show_td(uhci, td, out,
+					len - (out - buf), 0);
 		} else {
-			if (td_status(td) & TD_CTRL_ACTIVE)
+			if (td_status(uhci, td) & TD_CTRL_ACTIVE)
 				++nactive;
 			else
 				++ninactive;
@@ -151,7 +155,7 @@
 {
 	char *out = buf;
 	int i, nurbs;
-	__le32 element = qh_element(qh);
+	__hc32 element = qh_element(qh);
 	char *qtype;
 
 	/* Try to make sure there's enough memory */
@@ -168,7 +172,8 @@
 
 	out += sprintf(out, "%*s[%p] %s QH link (%08x) element (%08x)\n",
 			space, "", qh, qtype,
-			le32_to_cpu(qh->link), le32_to_cpu(element));
+			hc32_to_cpu(uhci, qh->link),
+			hc32_to_cpu(uhci, element));
 	if (qh->type == USB_ENDPOINT_XFER_ISOC)
 		out += sprintf(out, "%*s    period %d phase %d load %d us, "
 				"frame %x desc [%p]\n",
@@ -178,22 +183,22 @@
 		out += sprintf(out, "%*s    period %d phase %d load %d us\n",
 				space, "", qh->period, qh->phase, qh->load);
 
-	if (element & UHCI_PTR_QH)
+	if (element & UHCI_PTR_QH(uhci))
 		out += sprintf(out, "%*s  Element points to QH (bug?)\n", space, "");
 
-	if (element & UHCI_PTR_DEPTH)
+	if (element & UHCI_PTR_DEPTH(uhci))
 		out += sprintf(out, "%*s  Depth traverse\n", space, "");
 
-	if (element & cpu_to_le32(8))
+	if (element & cpu_to_hc32(uhci, 8))
 		out += sprintf(out, "%*s  Bit 3 set (bug?)\n", space, "");
 
-	if (!(element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH)))
+	if (!(element & ~(UHCI_PTR_QH(uhci) | UHCI_PTR_DEPTH(uhci))))
 		out += sprintf(out, "%*s  Element is NULL (bug?)\n", space, "");
 
 	if (list_empty(&qh->queue)) {
 		out += sprintf(out, "%*s  queue is empty\n", space, "");
 		if (qh == uhci->skel_async_qh)
-			out += uhci_show_td(uhci->term_td, out,
+			out += uhci_show_td(uhci, uhci->term_td, out,
 					len - (out - buf), 0);
 	} else {
 		struct urb_priv *urbp = list_entry(qh->queue.next,
@@ -201,13 +206,13 @@
 		struct uhci_td *td = list_entry(urbp->td_list.next,
 				struct uhci_td, list);
 
-		if (element != LINK_TO_TD(td))
+		if (element != LINK_TO_TD(uhci, td))
 			out += sprintf(out, "%*s Element != First TD\n",
 					space, "");
 		i = nurbs = 0;
 		list_for_each_entry(urbp, &qh->queue, node) {
 			if (++i <= 10)
-				out += uhci_show_urbp(urbp, out,
+				out += uhci_show_urbp(uhci, urbp, out,
 						len - (out - buf), space + 2);
 			else
 				++nurbs;
@@ -219,7 +224,8 @@
 
 	if (qh->dummy_td) {
 		out += sprintf(out, "%*s  Dummy TD\n", space, "");
-		out += uhci_show_td(qh->dummy_td, out, len - (out - buf), 0);
+		out += uhci_show_td(uhci, qh->dummy_td, out,
+				len - (out - buf), 0);
 	}
 
 	return out - buf;
@@ -346,8 +352,8 @@
 	struct uhci_td *td;
 	struct list_head *tmp, *head;
 	int nframes, nerrs;
-	__le32 link;
-	__le32 fsbr_link;
+	__hc32 link;
+	__hc32 fsbr_link;
 
 	static const char * const qh_names[] = {
 		"unlink", "iso", "int128", "int64", "int32", "int16",
@@ -375,7 +381,7 @@
 	nframes = 10;
 	nerrs = 0;
 	for (i = 0; i < UHCI_NUMFRAMES; ++i) {
-		__le32 qh_dma;
+		__hc32 qh_dma;
 
 		j = 0;
 		td = uhci->frame_cpu[i];
@@ -385,7 +391,7 @@
 
 		if (nframes > 0) {
 			out += sprintf(out, "- Frame %d -> (%08x)\n",
-					i, le32_to_cpu(link));
+					i, hc32_to_cpu(uhci, link));
 			j = 1;
 		}
 
@@ -394,7 +400,7 @@
 		do {
 			td = list_entry(tmp, struct uhci_td, fl_list);
 			tmp = tmp->next;
-			if (link != LINK_TO_TD(td)) {
+			if (link != LINK_TO_TD(uhci, td)) {
 				if (nframes > 0)
 					out += sprintf(out, "    link does "
 						"not match list entry!\n");
@@ -402,7 +408,7 @@
 					++nerrs;
 			}
 			if (nframes > 0)
-				out += uhci_show_td(td, out,
+				out += uhci_show_td(uhci, td, out,
 						len - (out - buf), 4);
 			link = td->link;
 		} while (tmp != head);
@@ -414,11 +420,12 @@
 				if (!j) {
 					out += sprintf(out,
 						"- Frame %d -> (%08x)\n",
-						i, le32_to_cpu(link));
+						i, hc32_to_cpu(uhci, link));
 					j = 1;
 				}
 				out += sprintf(out, "   link does not match "
-					"QH (%08x)!\n", le32_to_cpu(qh_dma));
+					"QH (%08x)!\n",
+					hc32_to_cpu(uhci, qh_dma));
 			} else
 				++nerrs;
 		}
@@ -439,11 +446,11 @@
 
 		/* Last QH is the Terminating QH, it's different */
 		if (i == SKEL_TERM) {
-			if (qh_element(qh) != LINK_TO_TD(uhci->term_td))
+			if (qh_element(qh) != LINK_TO_TD(uhci, uhci->term_td))
 				out += sprintf(out, "    skel_term_qh element is not set to term_td!\n");
 			link = fsbr_link;
 			if (!link)
-				link = LINK_TO_QH(uhci->skel_term_qh);
+				link = LINK_TO_QH(uhci, uhci->skel_term_qh);
 			goto check_qh_link;
 		}
 
@@ -457,20 +464,20 @@
 				out += uhci_show_qh(uhci, qh, out,
 						len - (out - buf), 4);
 			if (!fsbr_link && qh->skel >= SKEL_FSBR)
-				fsbr_link = LINK_TO_QH(qh);
+				fsbr_link = LINK_TO_QH(uhci, qh);
 		}
 		if ((cnt -= 10) > 0)
 			out += sprintf(out, "    Skipped %d QHs\n", cnt);
 
-		link = UHCI_PTR_TERM;
+		link = UHCI_PTR_TERM(uhci);
 		if (i <= SKEL_ISO)
 			;
 		else if (i < SKEL_ASYNC)
-			link = LINK_TO_QH(uhci->skel_async_qh);
+			link = LINK_TO_QH(uhci, uhci->skel_async_qh);
 		else if (!uhci->fsbr_is_on)
 			;
 		else
-			link = LINK_TO_QH(uhci->skel_term_qh);
+			link = LINK_TO_QH(uhci, uhci->skel_term_qh);
 check_qh_link:
 		if (qh->link != link)
 			out += sprintf(out, "    last QH not linked to next skeleton!\n");