From 51e2f62fe79651e7ed8e16ba126a163b116fe3d7 Mon Sep 17 00:00:00 2001 From: Jan Andersson Date: Wed, 18 May 2011 10:44:51 +0200 Subject: 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 Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 71 ++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 32 deletions(-) (limited to 'drivers/usb/host/uhci-debug.c') diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index f882a84b1bbb..fc0b0daac93d 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"); -- cgit v1.2.3