diff options
Diffstat (limited to 'packages/linux/linux-rp-2.6.22/usb-ohci-hooks-r2.patch')
-rw-r--r-- | packages/linux/linux-rp-2.6.22/usb-ohci-hooks-r2.patch | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/packages/linux/linux-rp-2.6.22/usb-ohci-hooks-r2.patch b/packages/linux/linux-rp-2.6.22/usb-ohci-hooks-r2.patch new file mode 100644 index 0000000000..3656e98f0c --- /dev/null +++ b/packages/linux/linux-rp-2.6.22/usb-ohci-hooks-r2.patch @@ -0,0 +1,180 @@ +Index: linux-2.6.15/drivers/usb/host/ohci.h +=================================================================== +--- linux-2.6.15.orig/drivers/usb/host/ohci.h ++++ linux-2.6.15/drivers/usb/host/ohci.h +@@ -336,6 +336,23 @@ typedef struct urb_priv { + // sizeof (struct td) ~= 64 == 2^6 ... + #define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE) + ++struct ohci_hcd; ++ ++/* ++ * Hooks to support controllers that must resort to a PIO-ish ++ * implementation because they only dma with on-chip memory. ++ */ ++struct ohci_ops { ++ void* (*dma_pool_alloc) (struct dma_pool *pool, gfp_t mem_flags, ++ dma_addr_t *handle); ++ void (*dma_pool_free) (struct dma_pool *pool, void *vaddr, ++ dma_addr_t addr); ++ ++ void (*td_fill) (struct ohci_hcd *ohci, u32 info, dma_addr_t data, ++ int len, struct urb *urb, int index); ++ void (*td_done) (struct ohci_hcd *ohci, struct urb *urb, ++ struct td *td); ++}; + + /* + * This is the full ohci controller description +@@ -346,6 +363,7 @@ typedef struct urb_priv { + + struct ohci_hcd { + spinlock_t lock; ++ const struct ohci_ops *ops; + + /* + * I/O memory used to communicate with the HC (dma-consistent) +Index: linux-2.6.15/drivers/usb/host/ohci-mem.c +=================================================================== +--- linux-2.6.15.orig/drivers/usb/host/ohci-mem.c ++++ linux-2.6.15/drivers/usb/host/ohci-mem.c +@@ -21,10 +21,13 @@ + * No memory seen by this driver is pagable. + */ + ++static const struct ohci_ops ohci_ops; ++ + /*-------------------------------------------------------------------------*/ + + static void ohci_hcd_init (struct ohci_hcd *ohci) + { ++ ohci->ops = &ohci_ops; + ohci->next_statechange = jiffies; + spin_lock_init (&ohci->lock); + INIT_LIST_HEAD (&ohci->pending); +@@ -88,7 +91,7 @@ td_alloc (struct ohci_hcd *hc, gfp_t mem + dma_addr_t dma; + struct td *td; + +- td = dma_pool_alloc (hc->td_cache, mem_flags, &dma); ++ td = hc->ops->dma_pool_alloc (hc->td_cache, mem_flags, &dma); + if (td) { + /* in case hc fetches it, make it look dead */ + memset (td, 0, sizeof *td); +@@ -110,7 +113,7 @@ td_free (struct ohci_hcd *hc, struct td + *prev = td->td_hash; + else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0) + ohci_dbg (hc, "no hash for td %p\n", td); +- dma_pool_free (hc->td_cache, td, td->td_dma); ++ hc->ops->dma_pool_free (hc->td_cache, td, td->td_dma); + } + + /*-------------------------------------------------------------------------*/ +@@ -122,7 +125,7 @@ ed_alloc (struct ohci_hcd *hc, gfp_t mem + dma_addr_t dma; + struct ed *ed; + +- ed = dma_pool_alloc (hc->ed_cache, mem_flags, &dma); ++ ed = hc->ops->dma_pool_alloc (hc->ed_cache, mem_flags, &dma); + if (ed) { + memset (ed, 0, sizeof (*ed)); + INIT_LIST_HEAD (&ed->td_list); +@@ -134,6 +137,6 @@ ed_alloc (struct ohci_hcd *hc, gfp_t mem + static void + ed_free (struct ohci_hcd *hc, struct ed *ed) + { +- dma_pool_free (hc->ed_cache, ed, ed->dma); ++ hc->ops->dma_pool_free (hc->ed_cache, ed, ed->dma); + } + +Index: linux-2.6.15/drivers/usb/host/ohci-q.c +=================================================================== +--- linux-2.6.15.orig/drivers/usb/host/ohci-q.c ++++ linux-2.6.15/drivers/usb/host/ohci-q.c +@@ -629,7 +629,7 @@ static void td_submit_urb ( + : TD_T_TOGGLE | TD_CC | TD_DP_IN; + /* TDs _could_ transfer up to 8K each */ + while (data_len > 4096) { +- td_fill (ohci, info, data, 4096, urb, cnt); ++ ohci->ops->td_fill (ohci, info, data, 4096, urb, cnt); + data += 4096; + data_len -= 4096; + cnt++; +@@ -637,11 +637,11 @@ static void td_submit_urb ( + /* maybe avoid ED halt on final TD short read */ + if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) + info |= TD_R; +- td_fill (ohci, info, data, data_len, urb, cnt); ++ ohci->ops->td_fill (ohci, info, data, data_len, urb, cnt); + cnt++; + if ((urb->transfer_flags & URB_ZERO_PACKET) + && cnt < urb_priv->length) { +- td_fill (ohci, info, 0, 0, urb, cnt); ++ ohci->ops->td_fill (ohci, info, 0, 0, urb, cnt); + cnt++; + } + /* maybe kickstart bulk list */ +@@ -656,17 +656,18 @@ static void td_submit_urb ( + */ + case PIPE_CONTROL: + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; +- td_fill (ohci, info, urb->setup_dma, 8, urb, cnt++); ++ ohci->ops->td_fill (ohci, info, urb->setup_dma, 8, urb, cnt++); + if (data_len > 0) { + info = TD_CC | TD_R | TD_T_DATA1; + info |= is_out ? TD_DP_OUT : TD_DP_IN; + /* NOTE: mishandles transfers >8K, some >4K */ +- td_fill (ohci, info, data, data_len, urb, cnt++); ++ ohci->ops->td_fill (ohci, info, data, data_len, ++ urb, cnt++); + } + info = (is_out || data_len == 0) + ? TD_CC | TD_DP_IN | TD_T_DATA1 + : TD_CC | TD_DP_OUT | TD_T_DATA1; +- td_fill (ohci, info, data, 0, urb, cnt++); ++ ohci->ops->td_fill (ohci, info, data, 0, urb, cnt++); + /* maybe kickstart control list */ + wmb (); + ohci_writel (ohci, OHCI_CLF, &ohci->regs->cmdstatus); +@@ -685,7 +686,7 @@ static void td_submit_urb ( + // a 2^16 iso range, vs other HCs max of 2^10) + frame += cnt * urb->interval; + frame &= 0xffff; +- td_fill (ohci, TD_CC | TD_ISO | frame, ++ ohci->ops->td_fill (ohci, TD_CC | TD_ISO | frame, + data + urb->iso_frame_desc [cnt].offset, + urb->iso_frame_desc [cnt].length, urb, cnt); + } +@@ -788,6 +789,14 @@ static void td_done (struct ohci_hcd *oh + } + } + ++/* default operations for most HCs */ ++static const struct ohci_ops ohci_ops = { ++ .dma_pool_alloc = dma_pool_alloc, ++ .dma_pool_free = dma_pool_free, ++ .td_fill = td_fill, ++ .td_done = td_done, ++}; ++ + /*-------------------------------------------------------------------------*/ + + static inline struct td * +@@ -984,7 +993,7 @@ rescan_this: + *prev = td->hwNextTD | savebits; + + /* HC may have partly processed this TD */ +- td_done (ohci, urb, td); ++ ohci->ops->td_done (ohci, urb, td); + urb_priv->td_cnt++; + + /* if URB is done, clean up */ +@@ -1079,7 +1088,7 @@ dl_done_list (struct ohci_hcd *ohci, str + struct ed *ed = td->ed; + + /* update URB's length and status from TD */ +- td_done (ohci, urb, td); ++ ohci->ops->td_done (ohci, urb, td); + urb_priv->td_cnt++; + + /* If all this urb's TDs are done, call complete() */ |