[PATCH 202/205] USB: UHCI: Add support for big endian descriptors

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

 



From: Jan Andersson <jan@xxxxxxxxxxx>

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@xxxxxxxxxxx>
Acked-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
---
 drivers/usb/host/Kconfig      |    4 +
 drivers/usb/host/uhci-debug.c |   71 ++++++++++++----------
 drivers/usb/host/uhci-hcd.c   |   16 +++---
 drivers/usb/host/uhci-hcd.h   |   90 +++++++++++++++++++++++-----
 drivers/usb/host/uhci-q.c     |  131 +++++++++++++++++++++--------------------
 5 files changed, 192 insertions(+), 120 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index ce9e22b..5844248 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -420,6 +420,10 @@ config USB_UHCI_BIG_ENDIAN_MMIO
 	bool
 	depends on USB_UHCI_SUPPORT_NON_PCI_HC
 
+config USB_UHCI_BIG_ENDIAN_DESC
+	bool
+	depends on USB_UHCI_SUPPORT_NON_PCI_HC
+
 config USB_FHCI_HCD
 	tristate "Freescale QE USB Host Controller support"
 	depends on USB && OF_GPIO && QE_GPIO && QUICC_ENGINE
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 void lprintk(char *buf)
 	}
 }
 
-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 @@ static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space)
 	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 @@ static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space)
 		(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 @@ static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space)
 		(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 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
 		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 @@ static int uhci_show_qh(struct uhci_hcd *uhci,
 {
 	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 @@ static int uhci_show_qh(struct uhci_hcd *uhci,
 
 	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 @@ static int uhci_show_qh(struct uhci_hcd *uhci,
 		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 @@ static int uhci_show_qh(struct uhci_hcd *uhci,
 		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 @@ static int uhci_show_qh(struct uhci_hcd *uhci,
 
 	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 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
 	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 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
 	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 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
 
 		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 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
 		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 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
 					++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 @@ check_link:
 				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 @@ check_link:
 
 		/* 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 @@ check_link:
 				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");
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 79dd822..32dec7c 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -92,7 +92,7 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
 /*
  * Calculate the link pointer DMA value for the first Skeleton QH in a frame.
  */
-static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
+static __hc32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
 {
 	int skelnum;
 
@@ -114,7 +114,7 @@ static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
 	skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
 	if (skelnum <= 1)
 		skelnum = 9;
-	return LINK_TO_QH(uhci->skelqh[skelnum]);
+	return LINK_TO_QH(uhci, uhci->skelqh[skelnum]);
 }
 
 #include "uhci-debug.c"
@@ -630,16 +630,16 @@ static int uhci_start(struct usb_hcd *hcd)
 	 * 8 Interrupt queues; link all higher int queues to int1 = async
 	 */
 	for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i)
-		uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh);
-	uhci->skel_async_qh->link = UHCI_PTR_TERM;
-	uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh);
+		uhci->skelqh[i]->link = LINK_TO_QH(uhci, uhci->skel_async_qh);
+	uhci->skel_async_qh->link = UHCI_PTR_TERM(uhci);
+	uhci->skel_term_qh->link = LINK_TO_QH(uhci, uhci->skel_term_qh);
 
 	/* This dummy TD is to work around a bug in Intel PIIX controllers */
-	uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
+	uhci_fill_td(uhci, uhci->term_td, 0, uhci_explen(0) |
 			(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
-	uhci->term_td->link = UHCI_PTR_TERM;
+	uhci->term_td->link = UHCI_PTR_TERM(uhci);
 	uhci->skel_async_qh->element = uhci->skel_term_qh->element =
-			LINK_TO_TD(uhci->term_td);
+		LINK_TO_TD(uhci, uhci->term_td);
 
 	/*
 	 * Fill the frame list: make all entries point to the proper
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 0deeab6..7af2b70 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -78,11 +78,11 @@
 #define   USBPORT1EN		0x01
 #define   USBPORT2EN		0x02
 
-#define UHCI_PTR_BITS		cpu_to_le32(0x000F)
-#define UHCI_PTR_TERM		cpu_to_le32(0x0001)
-#define UHCI_PTR_QH		cpu_to_le32(0x0002)
-#define UHCI_PTR_DEPTH		cpu_to_le32(0x0004)
-#define UHCI_PTR_BREADTH	cpu_to_le32(0x0000)
+#define UHCI_PTR_BITS(uhci)	cpu_to_hc32((uhci), 0x000F)
+#define UHCI_PTR_TERM(uhci)	cpu_to_hc32((uhci), 0x0001)
+#define UHCI_PTR_QH(uhci)	cpu_to_hc32((uhci), 0x0002)
+#define UHCI_PTR_DEPTH(uhci)	cpu_to_hc32((uhci), 0x0004)
+#define UHCI_PTR_BREADTH(uhci)	cpu_to_hc32((uhci), 0x0000)
 
 #define UHCI_NUMFRAMES		1024	/* in the frame list [array] */
 #define UHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
@@ -99,6 +99,22 @@
 
 
 /*
+ * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to
+ * __leXX (normally) or __beXX (given UHCI_BIG_ENDIAN_DESC), depending on
+ * the host controller implementation.
+ *
+ * To facilitate the strongest possible byte-order checking from "sparse"
+ * and so on, we use __leXX unless that's not practical.
+ */
+#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_DESC
+typedef __u32 __bitwise __hc32;
+typedef __u16 __bitwise __hc16;
+#else
+#define __hc32	__le32
+#define __hc16	__le16
+#endif
+
+/*
  *	Queue Headers
  */
 
@@ -130,8 +146,8 @@
 
 struct uhci_qh {
 	/* Hardware fields */
-	__le32 link;			/* Next QH in the schedule */
-	__le32 element;			/* Queue element (TD) pointer */
+	__hc32 link;			/* Next QH in the schedule */
+	__hc32 element;			/* Queue element (TD) pointer */
 
 	/* Software fields */
 	dma_addr_t dma_handle;
@@ -170,7 +186,8 @@ struct uhci_qh {
  */
 #define qh_element(qh)		ACCESS_ONCE((qh)->element)
 
-#define LINK_TO_QH(qh)		(UHCI_PTR_QH | cpu_to_le32((qh)->dma_handle))
+#define LINK_TO_QH(uhci, qh)	(UHCI_PTR_QH((uhci)) | \
+				cpu_to_hc32((uhci), (qh)->dma_handle))
 
 
 /*
@@ -207,7 +224,7 @@ struct uhci_qh {
 /*
  * for TD <info>: (a.k.a. Token)
  */
-#define td_token(td)		le32_to_cpu((td)->token)
+#define td_token(uhci, td)	hc32_to_cpu((uhci), (td)->token)
 #define TD_TOKEN_DEVADDR_SHIFT	8
 #define TD_TOKEN_TOGGLE_SHIFT	19
 #define TD_TOKEN_TOGGLE		(1 << 19)
@@ -240,10 +257,10 @@ struct uhci_qh {
  */
 struct uhci_td {
 	/* Hardware fields */
-	__le32 link;
-	__le32 status;
-	__le32 token;
-	__le32 buffer;
+	__hc32 link;
+	__hc32 status;
+	__hc32 token;
+	__hc32 buffer;
 
 	/* Software fields */
 	dma_addr_t dma_handle;
@@ -258,9 +275,10 @@ struct uhci_td {
  * We need a special accessor for the control/status word because it is
  * subject to asynchronous updates by the controller.
  */
-#define td_status(td)		le32_to_cpu(ACCESS_ONCE((td)->status))
+#define td_status(uhci, td)		hc32_to_cpu((uhci), \
+						ACCESS_ONCE((td)->status))
 
-#define LINK_TO_TD(td)		(cpu_to_le32((td)->dma_handle))
+#define LINK_TO_TD(uhci, td)		(cpu_to_hc32((uhci), (td)->dma_handle))
 
 
 /*
@@ -383,7 +401,7 @@ struct uhci_hcd {
 	spinlock_t lock;
 
 	dma_addr_t frame_dma_handle;	/* Hardware frame list */
-	__le32 *frame;
+	__hc32 *frame;
 	void **frame_cpu;		/* CPU's frame list */
 
 	enum uhci_rh_state rh_state;
@@ -412,6 +430,7 @@ struct uhci_hcd {
 	unsigned int oc_low:1;			/* OverCurrent bit active low */
 	unsigned int wait_for_hp:1;		/* Wait for HP port reset */
 	unsigned int big_endian_mmio:1;		/* Big endian registers */
+	unsigned int big_endian_desc:1;		/* Big endian descriptors */
 
 	/* Support for port suspend/resume/reset */
 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
@@ -603,4 +622,43 @@ static inline void uhci_writeb(const struct uhci_hcd *uhci, u8 val, int reg)
 }
 #endif /* CONFIG_USB_UHCI_SUPPORT_NON_PCI_HC */
 
+/*
+ * The GRLIB GRUSBHC controller can use big endian format for its descriptors.
+ *
+ * UHCI controllers accessed through PCI work normally (little-endian
+ * everywhere), so we don't bother supporting a BE-only mode.
+ */
+#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_DESC
+#define uhci_big_endian_desc(u)		((u)->big_endian_desc)
+
+/* cpu to uhci */
+static inline __hc32 cpu_to_hc32(const struct uhci_hcd *uhci, const u32 x)
+{
+	return uhci_big_endian_desc(uhci)
+		? (__force __hc32)cpu_to_be32(x)
+		: (__force __hc32)cpu_to_le32(x);
+}
+
+/* uhci to cpu */
+static inline u32 hc32_to_cpu(const struct uhci_hcd *uhci, const __hc32 x)
+{
+	return uhci_big_endian_desc(uhci)
+		? be32_to_cpu((__force __be32)x)
+		: le32_to_cpu((__force __le32)x);
+}
+
+#else
+/* cpu to uhci */
+static inline __hc32 cpu_to_hc32(const struct uhci_hcd *uhci, const u32 x)
+{
+	return cpu_to_le32(x);
+}
+
+/* uhci to cpu */
+static inline u32 hc32_to_cpu(const struct uhci_hcd *uhci, const __hc32 x)
+{
+	return le32_to_cpu(x);
+}
+#endif
+
 #endif
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index af77abb..84ed28b 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -29,12 +29,12 @@ static void uhci_set_next_interrupt(struct uhci_hcd *uhci)
 {
 	if (uhci->is_stopped)
 		mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
-	uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC);
+	uhci->term_td->status |= cpu_to_hc32(uhci, TD_CTRL_IOC);
 }
 
 static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
 {
-	uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
+	uhci->term_td->status &= ~cpu_to_hc32(uhci, TD_CTRL_IOC);
 }
 
 
@@ -53,7 +53,7 @@ static void uhci_fsbr_on(struct uhci_hcd *uhci)
 	uhci->fsbr_is_on = 1;
 	lqh = list_entry(uhci->skel_async_qh->node.prev,
 			struct uhci_qh, node);
-	lqh->link = LINK_TO_QH(uhci->skel_term_qh);
+	lqh->link = LINK_TO_QH(uhci, uhci->skel_term_qh);
 }
 
 static void uhci_fsbr_off(struct uhci_hcd *uhci)
@@ -65,7 +65,7 @@ static void uhci_fsbr_off(struct uhci_hcd *uhci)
 	uhci->fsbr_is_on = 0;
 	lqh = list_entry(uhci->skel_async_qh->node.prev,
 			struct uhci_qh, node);
-	lqh->link = UHCI_PTR_TERM;
+	lqh->link = UHCI_PTR_TERM(uhci);
 }
 
 static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
@@ -131,12 +131,12 @@ static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
 	dma_pool_free(uhci->td_pool, td, td->dma_handle);
 }
 
-static inline void uhci_fill_td(struct uhci_td *td, u32 status,
-		u32 token, u32 buffer)
+static inline void uhci_fill_td(struct uhci_hcd *uhci, struct uhci_td *td,
+		u32 status, u32 token, u32 buffer)
 {
-	td->status = cpu_to_le32(status);
-	td->token = cpu_to_le32(token);
-	td->buffer = cpu_to_le32(buffer);
+	td->status = cpu_to_hc32(uhci, status);
+	td->token = cpu_to_hc32(uhci, token);
+	td->buffer = cpu_to_hc32(uhci, buffer);
 }
 
 static void uhci_add_td_to_urbp(struct uhci_td *td, struct urb_priv *urbp)
@@ -170,11 +170,11 @@ static inline void uhci_insert_td_in_frame_list(struct uhci_hcd *uhci,
 
 		td->link = ltd->link;
 		wmb();
-		ltd->link = LINK_TO_TD(td);
+		ltd->link = LINK_TO_TD(uhci, td);
 	} else {
 		td->link = uhci->frame[framenum];
 		wmb();
-		uhci->frame[framenum] = LINK_TO_TD(td);
+		uhci->frame[framenum] = LINK_TO_TD(uhci, td);
 		uhci->frame_cpu[framenum] = td;
 	}
 }
@@ -198,7 +198,7 @@ static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci,
 			ntd = list_entry(td->fl_list.next,
 					 struct uhci_td,
 					 fl_list);
-			uhci->frame[td->frame] = LINK_TO_TD(ntd);
+			uhci->frame[td->frame] = LINK_TO_TD(uhci, ntd);
 			uhci->frame_cpu[td->frame] = ntd;
 		}
 	} else {
@@ -255,8 +255,8 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
 	memset(qh, 0, sizeof(*qh));
 	qh->dma_handle = dma_handle;
 
-	qh->element = UHCI_PTR_TERM;
-	qh->link = UHCI_PTR_TERM;
+	qh->element = UHCI_PTR_TERM(uhci);
+	qh->link = UHCI_PTR_TERM(uhci);
 
 	INIT_LIST_HEAD(&qh->queue);
 	INIT_LIST_HEAD(&qh->node);
@@ -348,9 +348,9 @@ static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh,
 
 	/* If the QH element pointer is UHCI_PTR_TERM then then currently
 	 * executing URB has already been unlinked, so this one isn't it. */
-	if (qh_element(qh) == UHCI_PTR_TERM)
+	if (qh_element(qh) == UHCI_PTR_TERM(uhci))
 		goto done;
-	qh->element = UHCI_PTR_TERM;
+	qh->element = UHCI_PTR_TERM(uhci);
 
 	/* Control pipes don't have to worry about toggles */
 	if (qh->type == USB_ENDPOINT_XFER_CONTROL)
@@ -360,7 +360,7 @@ static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh,
 	WARN_ON(list_empty(&urbp->td_list));
 	td = list_entry(urbp->td_list.next, struct uhci_td, list);
 	qh->needs_fixup = 1;
-	qh->initial_toggle = uhci_toggle(td_token(td));
+	qh->initial_toggle = uhci_toggle(td_token(uhci, td));
 
 done:
 	return ret;
@@ -370,7 +370,8 @@ done:
  * Fix up the data toggles for URBs in a queue, when one of them
  * terminates early (short transfer, error, or dequeued).
  */
-static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first)
+static void uhci_fixup_toggles(struct uhci_hcd *uhci, struct uhci_qh *qh,
+			int skip_first)
 {
 	struct urb_priv *urbp = NULL;
 	struct uhci_td *td;
@@ -384,7 +385,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first)
 
 	/* When starting with the first URB, if the QH element pointer is
 	 * still valid then we know the URB's toggles are okay. */
-	else if (qh_element(qh) != UHCI_PTR_TERM)
+	else if (qh_element(qh) != UHCI_PTR_TERM(uhci))
 		toggle = 2;
 
 	/* Fix up the toggle for the URBs in the queue.  Normally this
@@ -396,15 +397,15 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first)
 		/* If the first TD has the right toggle value, we don't
 		 * need to change any toggles in this URB */
 		td = list_entry(urbp->td_list.next, struct uhci_td, list);
-		if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) {
+		if (toggle > 1 || uhci_toggle(td_token(uhci, td)) == toggle) {
 			td = list_entry(urbp->td_list.prev, struct uhci_td,
 					list);
-			toggle = uhci_toggle(td_token(td)) ^ 1;
+			toggle = uhci_toggle(td_token(uhci, td)) ^ 1;
 
 		/* Otherwise all the toggles in the URB have to be switched */
 		} else {
 			list_for_each_entry(td, &urbp->td_list, list) {
-				td->token ^= cpu_to_le32(
+				td->token ^= cpu_to_hc32(uhci,
 							TD_TOKEN_TOGGLE);
 				toggle ^= 1;
 			}
@@ -441,7 +442,7 @@ static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
 	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
 	qh->link = pqh->link;
 	wmb();
-	pqh->link = LINK_TO_QH(qh);
+	pqh->link = LINK_TO_QH(uhci, qh);
 }
 
 /*
@@ -451,7 +452,7 @@ static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
 static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
 	struct uhci_qh *pqh;
-	__le32 link_to_new_qh;
+	__hc32 link_to_new_qh;
 
 	/* Find the predecessor QH for our new one and insert it in the list.
 	 * The list of QHs is expected to be short, so linear search won't
@@ -465,7 +466,7 @@ static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
 	/* Link it into the schedule */
 	qh->link = pqh->link;
 	wmb();
-	link_to_new_qh = LINK_TO_QH(qh);
+	link_to_new_qh = LINK_TO_QH(uhci, qh);
 	pqh->link = link_to_new_qh;
 
 	/* If this is now the first FSBR QH, link the terminating skeleton
@@ -483,13 +484,13 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 
 	/* Set the element pointer if it isn't set already.
 	 * This isn't needed for Isochronous queues, but it doesn't hurt. */
-	if (qh_element(qh) == UHCI_PTR_TERM) {
+	if (qh_element(qh) == UHCI_PTR_TERM(uhci)) {
 		struct urb_priv *urbp = list_entry(qh->queue.next,
 				struct urb_priv, node);
 		struct uhci_td *td = list_entry(urbp->td_list.next,
 				struct uhci_td, list);
 
-		qh->element = LINK_TO_TD(td);
+		qh->element = LINK_TO_TD(uhci, td);
 	}
 
 	/* Treat the queue as if it has just advanced */
@@ -533,7 +534,7 @@ static void unlink_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
 static void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
 	struct uhci_qh *pqh;
-	__le32 link_to_next_qh = qh->link;
+	__hc32 link_to_next_qh = qh->link;
 
 	pqh = list_entry(qh->node.prev, struct uhci_qh, node);
 	pqh->link = link_to_next_qh;
@@ -757,8 +758,8 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
 /*
  * Map status to standard result codes
  *
- * <status> is (td_status(td) & 0xF60000), a.k.a.
- * uhci_status_bits(td_status(td)).
+ * <status> is (td_status(uhci, td) & 0xF60000), a.k.a.
+ * uhci_status_bits(td_status(uhci, td)).
  * Note: <status> does not include the TD_CTRL_NAK bit.
  * <dir_out> is True for output TDs and False for input TDs.
  */
@@ -794,7 +795,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
 	int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);
 	int len = urb->transfer_buffer_length;
 	dma_addr_t data = urb->transfer_dma;
-	__le32 *plink;
+	__hc32 *plink;
 	struct urb_priv *urbp = urb->hcpriv;
 	int skel;
 
@@ -811,7 +812,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
 	 */
 	td = qh->dummy_td;
 	uhci_add_td_to_urbp(td, urbp);
-	uhci_fill_td(td, status, destination | uhci_explen(8),
+	uhci_fill_td(uhci, td, status, destination | uhci_explen(8),
 			urb->setup_dma);
 	plink = &td->link;
 	status |= TD_CTRL_ACTIVE;
@@ -844,14 +845,14 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
 		td = uhci_alloc_td(uhci);
 		if (!td)
 			goto nomem;
-		*plink = LINK_TO_TD(td);
+		*plink = LINK_TO_TD(uhci, td);
 
 		/* Alternate Data0/1 (start with Data1) */
 		destination ^= TD_TOKEN_TOGGLE;
 
 		uhci_add_td_to_urbp(td, urbp);
-		uhci_fill_td(td, status, destination | uhci_explen(pktsze),
-				data);
+		uhci_fill_td(uhci, td, status,
+			destination | uhci_explen(pktsze), data);
 		plink = &td->link;
 
 		data += pktsze;
@@ -864,14 +865,14 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
 	td = uhci_alloc_td(uhci);
 	if (!td)
 		goto nomem;
-	*plink = LINK_TO_TD(td);
+	*plink = LINK_TO_TD(uhci, td);
 
 	/* Change direction for the status transaction */
 	destination ^= (USB_PID_IN ^ USB_PID_OUT);
 	destination |= TD_TOKEN_TOGGLE;		/* End in Data1 */
 
 	uhci_add_td_to_urbp(td, urbp);
-	uhci_fill_td(td, status | TD_CTRL_IOC,
+	uhci_fill_td(uhci, td, status | TD_CTRL_IOC,
 			destination | uhci_explen(0), 0);
 	plink = &td->link;
 
@@ -881,11 +882,11 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
 	td = uhci_alloc_td(uhci);
 	if (!td)
 		goto nomem;
-	*plink = LINK_TO_TD(td);
+	*plink = LINK_TO_TD(uhci, td);
 
-	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
+	uhci_fill_td(uhci, td, 0, USB_PID_OUT | uhci_explen(0), 0);
 	wmb();
-	qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE);
+	qh->dummy_td->status |= cpu_to_hc32(uhci, TD_CTRL_ACTIVE);
 	qh->dummy_td = td;
 
 	/* Low-speed transfers get a different queue, and won't hog the bus.
@@ -921,7 +922,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
 	int len = urb->transfer_buffer_length;
 	int this_sg_len;
 	dma_addr_t data;
-	__le32 *plink;
+	__hc32 *plink;
 	struct urb_priv *urbp = urb->hcpriv;
 	unsigned int toggle;
 	struct scatterlist  *sg;
@@ -974,10 +975,10 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
 			td = uhci_alloc_td(uhci);
 			if (!td)
 				goto nomem;
-			*plink = LINK_TO_TD(td);
+			*plink = LINK_TO_TD(uhci, td);
 		}
 		uhci_add_td_to_urbp(td, urbp);
-		uhci_fill_td(td, status,
+		uhci_fill_td(uhci, td, status,
 				destination | uhci_explen(pktsze) |
 					(toggle << TD_TOKEN_TOGGLE_SHIFT),
 				data);
@@ -1010,10 +1011,10 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
 		td = uhci_alloc_td(uhci);
 		if (!td)
 			goto nomem;
-		*plink = LINK_TO_TD(td);
+		*plink = LINK_TO_TD(uhci, td);
 
 		uhci_add_td_to_urbp(td, urbp);
-		uhci_fill_td(td, status,
+		uhci_fill_td(uhci, td, status,
 				destination | uhci_explen(0) |
 					(toggle << TD_TOKEN_TOGGLE_SHIFT),
 				data);
@@ -1028,7 +1029,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
 	 * fast side but not enough to justify delaying an interrupt
 	 * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT
 	 * flag setting. */
-	td->status |= cpu_to_le32(TD_CTRL_IOC);
+	td->status |= cpu_to_hc32(uhci, TD_CTRL_IOC);
 
 	/*
 	 * Build the new dummy TD and activate the old one
@@ -1036,11 +1037,11 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
 	td = uhci_alloc_td(uhci);
 	if (!td)
 		goto nomem;
-	*plink = LINK_TO_TD(td);
+	*plink = LINK_TO_TD(uhci, td);
 
-	uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
+	uhci_fill_td(uhci, td, 0, USB_PID_OUT | uhci_explen(0), 0);
 	wmb();
-	qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE);
+	qh->dummy_td->status |= cpu_to_hc32(uhci, TD_CTRL_ACTIVE);
 	qh->dummy_td = td;
 
 	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
@@ -1133,7 +1134,7 @@ static int uhci_fixup_short_transfer(struct uhci_hcd *uhci,
 		 * the queue at the status stage transaction, which is
 		 * the last TD. */
 		WARN_ON(list_empty(&urbp->td_list));
-		qh->element = LINK_TO_TD(td);
+		qh->element = LINK_TO_TD(uhci, td);
 		tmp = td->list.prev;
 		ret = -EINPROGRESS;
 
@@ -1142,8 +1143,9 @@ static int uhci_fixup_short_transfer(struct uhci_hcd *uhci,
 		/* When a bulk/interrupt transfer is short, we have to
 		 * fix up the toggles of the following URBs on the queue
 		 * before restarting the queue at the next URB. */
-		qh->initial_toggle = uhci_toggle(td_token(qh->post_td)) ^ 1;
-		uhci_fixup_toggles(qh, 1);
+		qh->initial_toggle =
+			uhci_toggle(td_token(uhci, qh->post_td)) ^ 1;
+		uhci_fixup_toggles(uhci, qh, 1);
 
 		if (list_empty(&urbp->td_list))
 			td = qh->post_td;
@@ -1178,7 +1180,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
 		unsigned int ctrlstat;
 		int len;
 
-		ctrlstat = td_status(td);
+		ctrlstat = td_status(uhci, td);
 		status = uhci_status_bits(ctrlstat);
 		if (status & TD_CTRL_ACTIVE)
 			return -EINPROGRESS;
@@ -1188,7 +1190,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
 
 		if (status) {
 			ret = uhci_map_status(status,
-					uhci_packetout(td_token(td)));
+					uhci_packetout(td_token(uhci, td)));
 			if ((debug == 1 && ret != -EPIPE) || debug > 1) {
 				/* Some debugging code */
 				dev_dbg(&urb->dev->dev,
@@ -1204,7 +1206,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
 			}
 
 		/* Did we receive a short packet? */
-		} else if (len < uhci_expected_length(td_token(td))) {
+		} else if (len < uhci_expected_length(td_token(uhci, td))) {
 
 			/* For control transfers, go to the status TD if
 			 * this isn't already the last data TD */
@@ -1236,10 +1238,10 @@ err:
 	if (ret < 0) {
 		/* Note that the queue has stopped and save
 		 * the next toggle value */
-		qh->element = UHCI_PTR_TERM;
+		qh->element = UHCI_PTR_TERM(uhci);
 		qh->is_stopped = 1;
 		qh->needs_fixup = (qh->type != USB_ENDPOINT_XFER_CONTROL);
-		qh->initial_toggle = uhci_toggle(td_token(td)) ^
+		qh->initial_toggle = uhci_toggle(td_token(uhci, td)) ^
 				(ret == -EREMOTEIO);
 
 	} else		/* Short packet received */
@@ -1335,14 +1337,14 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
 			return -ENOMEM;
 
 		uhci_add_td_to_urbp(td, urbp);
-		uhci_fill_td(td, status, destination |
+		uhci_fill_td(uhci, td, status, destination |
 				uhci_explen(urb->iso_frame_desc[i].length),
 				urb->transfer_dma +
 					urb->iso_frame_desc[i].offset);
 	}
 
 	/* Set the interrupt-on-completion flag on the last packet. */
-	td->status |= cpu_to_le32(TD_CTRL_IOC);
+	td->status |= cpu_to_hc32(uhci, TD_CTRL_IOC);
 
 	/* Add the TDs to the frame list */
 	frame = urb->start_frame;
@@ -1378,7 +1380,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
 
 		uhci_remove_tds_from_frame(uhci, qh->iso_frame);
 
-		ctrlstat = td_status(td);
+		ctrlstat = td_status(uhci, td);
 		if (ctrlstat & TD_CTRL_ACTIVE) {
 			status = -EXDEV;	/* TD was added too late? */
 		} else {
@@ -1629,7 +1631,7 @@ restart:
 	 * queue, the QH can now be re-activated. */
 	if (!list_empty(&qh->queue)) {
 		if (qh->needs_fixup)
-			uhci_fixup_toggles(qh, 0);
+			uhci_fixup_toggles(uhci, qh, 0);
 
 		/* If the first URB on the queue wants FSBR but its time
 		 * limit has expired, set the next TD to interrupt on
@@ -1639,7 +1641,7 @@ restart:
 			struct uhci_td *td = list_entry(urbp->td_list.next,
 					struct uhci_td, list);
 
-			td->status |= __cpu_to_le32(TD_CTRL_IOC);
+			td->status |= cpu_to_hc32(uhci, TD_CTRL_IOC);
 		}
 
 		uhci_activate_qh(uhci, qh);
@@ -1686,7 +1688,7 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
 	} else {
 		urbp = list_entry(qh->queue.next, struct urb_priv, node);
 		td = list_entry(urbp->td_list.next, struct uhci_td, list);
-		status = td_status(td);
+		status = td_status(uhci, td);
 		if (!(status & TD_CTRL_ACTIVE)) {
 
 			/* We're okay, the queue has advanced */
@@ -1704,7 +1706,8 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
 	if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
 
 		/* Detect the Intel bug and work around it */
-		if (qh->post_td && qh_element(qh) == LINK_TO_TD(qh->post_td)) {
+		if (qh->post_td && qh_element(qh) ==
+			LINK_TO_TD(uhci, qh->post_td)) {
 			qh->element = qh->post_td->link;
 			qh->advance_jiffies = jiffies;
 			ret = 1;
-- 
1.7.4.2

--
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