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. ehci-hcd.h needed to be rearranged due to added dependencies on uhci_hcd struct. Signed-off-by: Jan Andersson <jan@xxxxxxxxxxx> --- 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 | 380 ++++++++++++++++++++++++----------------- drivers/usb/host/uhci-q.c | 131 +++++++------- 5 files changed, 345 insertions(+), 257 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 04e241f..50aa4a8 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -78,18 +78,222 @@ #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_NUMFRAMES 1024 /* in the frame list [array] */ #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ #define CAN_SCHEDULE_FRAMES 1000 /* how far in the future frames * can be scheduled */ #define MAX_PHASE 32 /* Periodic scheduling length */ +#define UHCI_NUM_SKELQH 11 /* See Skeleton Queue Headers below */ + + +/* + * __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. + */ +#if defined(CONFIG_USB_UHCI_BIG_ENDIAN_DESC) +typedef __u32 __bitwise __hc32; +typedef __u16 __bitwise __hc16; +#else +#define __hc32 __le32 +#define __hc16 __le16 +#endif + +/* + * The UHCI controller and root hub + */ + +/* + * States for the root hub: + * + * To prevent "bouncing" in the presence of electrical noise, + * when there are no devices attached we delay for 1 second in the + * RUNNING_NODEVS state before switching to the AUTO_STOPPED state. + * + * (Note that the AUTO_STOPPED state won't be necessary once the hub + * driver learns to autosuspend.) + */ +enum uhci_rh_state { + /* In the following states the HC must be halted. + * These two must come first. */ + UHCI_RH_RESET, + UHCI_RH_SUSPENDED, + + UHCI_RH_AUTO_STOPPED, + UHCI_RH_RESUMING, + + /* In this state the HC changes from running to halted, + * so it can legally appear either way. */ + UHCI_RH_SUSPENDING, + + /* In the following states it's an error if the HC is halted. + * These two must come last. */ + UHCI_RH_RUNNING, /* The normal state */ + UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */ +}; + +/* + * The full UHCI controller information: + */ +struct uhci_hcd { + + /* debugfs */ + struct dentry *dentry; + + /* Grabbed from PCI */ + unsigned long io_addr; + + /* Used when registers are memory mapped */ + void __iomem *regs; + + struct dma_pool *qh_pool; + struct dma_pool *td_pool; + + struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ + struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QHs */ + struct uhci_qh *next_qh; /* Next QH to scan */ + + spinlock_t lock; + + dma_addr_t frame_dma_handle; /* Hardware frame list */ + __hc32 *frame; + void **frame_cpu; /* CPU's frame list */ + + enum uhci_rh_state rh_state; + unsigned long auto_stop_time; /* When to AUTO_STOP */ + + unsigned int frame_number; /* As of last check */ + unsigned int is_stopped; +#define UHCI_IS_STOPPED 9999 /* Larger than a frame # */ + unsigned int last_iso_frame; /* Frame of last scan */ + unsigned int cur_iso_frame; /* Frame for current scan */ + + unsigned int scan_in_progress:1; /* Schedule scan is running */ + unsigned int need_rescan:1; /* Redo the schedule scan */ + unsigned int dead:1; /* Controller has died */ + unsigned int RD_enable:1; /* Suspended root hub with + Resume-Detect interrupts + enabled */ + unsigned int is_initialized:1; /* Data structure is usable */ + unsigned int fsbr_is_on:1; /* FSBR is turned on */ + unsigned int fsbr_is_wanted:1; /* Does any URB want FSBR? */ + unsigned int fsbr_expiring:1; /* FSBR is timing out */ + + struct timer_list fsbr_timer; /* For turning off FBSR */ + + /* Silicon quirks */ + unsigned int oc_low:1; /* OverCurrent bit active low */ + unsigned int wait_for_hp:1; /* Wait for HP port reset */ + unsigned int big_endian_desc:1; /* Big endian descriptors */ + + /* Support for port suspend/resume/reset */ + unsigned long port_c_suspend; /* Bit-arrays of ports */ + unsigned long resuming_ports; + unsigned long ports_timeout; /* Time to stop signalling */ + + struct list_head idle_qh_list; /* Where the idle QHs live */ + + int rh_numports; /* Number of root-hub ports */ + + wait_queue_head_t waitqh; /* endpoint_disable waiters */ + int num_waiting; /* Number of waiters */ + + int total_load; /* Sum of array values */ + short load[MAX_PHASE]; /* Periodic allocations */ + + /* Reset host controller */ + void (*reset_hc) (struct uhci_hcd *uhci); + int (*check_and_reset_hc) (struct uhci_hcd *uhci); + /* configure_hc should perform arch specific settings, if needed */ + void (*configure_hc) (struct uhci_hcd *uhci); + /* Check for broken resume detect interrupts */ + int (*resume_detect_interrupts_are_broken) (struct uhci_hcd *uhci); + /* Check for broken global suspend */ + int (*global_suspend_mode_is_broken) (struct uhci_hcd *uhci); + + /* Functions used for accessing host controller registers */ + u32 (*ureadl) (const struct uhci_hcd *uhci, int reg); + void (*uwritel) (const struct uhci_hcd *uhci, u32 val, int reg); + u16 (*ureadw) (const struct uhci_hcd *uhci, int reg); + void (*uwritew) (const struct uhci_hcd *uhci, u16 val, int reg); + u8 (*ureadb) (const struct uhci_hcd *uhci, int reg); + void (*uwriteb) (const struct uhci_hcd *uhci, u8 val, int reg); +}; + +/* Convert between a usb_hcd pointer and the corresponding uhci_hcd */ +static inline struct uhci_hcd *hcd_to_uhci(struct usb_hcd *hcd) +{ + return (struct uhci_hcd *) (hcd->hcd_priv); +} +static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci) +{ + return container_of((void *) uhci, struct usb_hcd, hcd_priv); +} + +#define uhci_dev(u) (uhci_to_hcd(u)->self.controller) + + +/* + * 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. + */ +#if defined(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); +} + +static inline u32 hc32_to_cpup(const struct uhci_hcd *uhci, const __hc32 *x) +{ + return uhci_big_endian_desc(uhci) + ? be32_to_cpup((__force __be32 *)x) + : le32_to_cpup((__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); +} + +static inline u32 hc32_to_cpup(const struct uhci_hcd *uhci, const __hc32 *x) +{ + return le32_to_cpup(x); +} +#endif + +#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) + /* When no queues need Full-Speed Bandwidth Reclamation, * delay this long before turning FSBR off */ #define FSBR_OFF_DELAY msecs_to_jiffies(10) @@ -130,8 +334,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; @@ -168,14 +372,16 @@ struct uhci_qh { * We need a special accessor for the element pointer because it is * subject to asynchronous updates by the controller. */ -static inline __le32 qh_element(struct uhci_qh *qh) { - __le32 element = qh->element; +static inline __hc32 qh_element(struct uhci_qh *qh) +{ + __hc32 element = qh->element; barrier(); return 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)) /* @@ -212,7 +418,7 @@ static inline __le32 qh_element(struct uhci_qh *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) @@ -245,10 +451,10 @@ static inline __le32 qh_element(struct uhci_qh *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; @@ -263,14 +469,15 @@ struct uhci_td { * We need a special accessor for the control/status word because it is * subject to asynchronous updates by the controller. */ -static inline u32 td_status(struct uhci_td *td) { - __le32 status = td->status; +static inline u32 td_status(const struct uhci_hcd *uhci, struct uhci_td *td) +{ + __hc32 status = td->status; barrier(); - return le32_to_cpu(status); + return hc32_to_cpu(uhci, 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)) /* @@ -318,7 +525,6 @@ static inline u32 td_status(struct uhci_td *td) { * appears on the schedule. */ -#define UHCI_NUM_SKELQH 11 #define SKEL_UNLINK 0 #define skel_unlink_qh skelqh[SKEL_UNLINK] #define SKEL_ISO 1 @@ -336,138 +542,6 @@ static inline u32 td_status(struct uhci_td *td) { #define SKEL_FSBR SKEL_FS_CONTROL #define SKEL_BULK 22 -/* - * The UHCI controller and root hub - */ - -/* - * States for the root hub: - * - * To prevent "bouncing" in the presence of electrical noise, - * when there are no devices attached we delay for 1 second in the - * RUNNING_NODEVS state before switching to the AUTO_STOPPED state. - * - * (Note that the AUTO_STOPPED state won't be necessary once the hub - * driver learns to autosuspend.) - */ -enum uhci_rh_state { - /* In the following states the HC must be halted. - * These two must come first. */ - UHCI_RH_RESET, - UHCI_RH_SUSPENDED, - - UHCI_RH_AUTO_STOPPED, - UHCI_RH_RESUMING, - - /* In this state the HC changes from running to halted, - * so it can legally appear either way. */ - UHCI_RH_SUSPENDING, - - /* In the following states it's an error if the HC is halted. - * These two must come last. */ - UHCI_RH_RUNNING, /* The normal state */ - UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */ -}; - -/* - * The full UHCI controller information: - */ -struct uhci_hcd { - - /* debugfs */ - struct dentry *dentry; - - /* Grabbed from PCI */ - unsigned long io_addr; - - /* Used when registers are memory mapped */ - void __iomem *regs; - - struct dma_pool *qh_pool; - struct dma_pool *td_pool; - - struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ - struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QHs */ - struct uhci_qh *next_qh; /* Next QH to scan */ - - spinlock_t lock; - - dma_addr_t frame_dma_handle; /* Hardware frame list */ - __le32 *frame; - void **frame_cpu; /* CPU's frame list */ - - enum uhci_rh_state rh_state; - unsigned long auto_stop_time; /* When to AUTO_STOP */ - - unsigned int frame_number; /* As of last check */ - unsigned int is_stopped; -#define UHCI_IS_STOPPED 9999 /* Larger than a frame # */ - unsigned int last_iso_frame; /* Frame of last scan */ - unsigned int cur_iso_frame; /* Frame for current scan */ - - unsigned int scan_in_progress:1; /* Schedule scan is running */ - unsigned int need_rescan:1; /* Redo the schedule scan */ - unsigned int dead:1; /* Controller has died */ - unsigned int RD_enable:1; /* Suspended root hub with - Resume-Detect interrupts - enabled */ - unsigned int is_initialized:1; /* Data structure is usable */ - unsigned int fsbr_is_on:1; /* FSBR is turned on */ - unsigned int fsbr_is_wanted:1; /* Does any URB want FSBR? */ - unsigned int fsbr_expiring:1; /* FSBR is timing out */ - - struct timer_list fsbr_timer; /* For turning off FBSR */ - - /* Silicon quirks */ - unsigned int oc_low:1; /* OverCurrent bit active low */ - unsigned int wait_for_hp:1; /* Wait for HP port reset */ - - /* Support for port suspend/resume/reset */ - unsigned long port_c_suspend; /* Bit-arrays of ports */ - unsigned long resuming_ports; - unsigned long ports_timeout; /* Time to stop signalling */ - - struct list_head idle_qh_list; /* Where the idle QHs live */ - - int rh_numports; /* Number of root-hub ports */ - - wait_queue_head_t waitqh; /* endpoint_disable waiters */ - int num_waiting; /* Number of waiters */ - - int total_load; /* Sum of array values */ - short load[MAX_PHASE]; /* Periodic allocations */ - - /* Reset host controller */ - void (*reset_hc) (struct uhci_hcd *uhci); - int (*check_and_reset_hc) (struct uhci_hcd *uhci); - /* configure_hc should perform arch specific settings, if needed */ - void (*configure_hc) (struct uhci_hcd *uhci); - /* Check for broken resume detect interrupts */ - int (*resume_detect_interrupts_are_broken) (struct uhci_hcd *uhci); - /* Check for broken global suspend */ - int (*global_suspend_mode_is_broken) (struct uhci_hcd *uhci); - - /* Functions used for accessing host controller registers */ - u32 (*ureadl) (const struct uhci_hcd *uhci, int reg); - void (*uwritel) (const struct uhci_hcd *uhci, u32 val, int reg); - u16 (*ureadw) (const struct uhci_hcd *uhci, int reg); - void (*uwritew) (const struct uhci_hcd *uhci, u16 val, int reg); - u8 (*ureadb) (const struct uhci_hcd *uhci, int reg); - void (*uwriteb) (const struct uhci_hcd *uhci, u8 val, int reg); -}; - -/* Convert between a usb_hcd pointer and the corresponding uhci_hcd */ -static inline struct uhci_hcd *hcd_to_uhci(struct usb_hcd *hcd) -{ - return (struct uhci_hcd *) (hcd->hcd_priv); -} -static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci) -{ - return container_of((void *) uhci, struct usb_hcd, hcd_priv); -} - -#define uhci_dev(u) (uhci_to_hcd(u)->self.controller) - /* Utility macro for comparing frame numbers */ #define uhci_frame_before_eq(f1, f2) (0 <= (int) ((f2) - (f1))) 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.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