Hi, this proved harder than it looks like. I can use cdc-acm over ohci with this patch. So what do you think?
Regards Oliver -- diff -urp linux-2.6.22rc6vanilla/include/linux/usb.h linux-2.6.22-rc6-storage/include/linux/usb.h --- linux-2.6.22rc6vanilla/include/linux/usb.h 2007-06-29 13:33:17.000000000 +0200 +++ linux-2.6.22-rc6-storage/include/linux/usb.h 2007-06-27 14:41:59.000000000 +0200 @@ -1128,9 +1128,9 @@ struct urb /* private: usb core and host controller only fields in the urb */ struct kref kref; /* reference count of the URB */ spinlock_t lock; /* lock for the URB */ - void *hcpriv; /* private data for host controller */ atomic_t use_count; /* concurrent submissions counter */ u8 reject; /* submissions will fail */ + struct usb_hcd *rh_handed_over; /* public: documented fields in the urb that can be used by drivers */ struct list_head urb_list; /* list head for use by the urb's @@ -1152,7 +1152,7 @@ struct urb int error_count; /* (return) number of ISO errors */ void *context; /* (in) context for completion */ usb_complete_t complete; /* (in) completion routine */ - struct usb_iso_packet_descriptor iso_frame_desc[0]; + struct usb_iso_packet_descriptor *iso_frames; /* (in) ISO ONLY */ }; @@ -1263,7 +1263,14 @@ static inline void usb_fill_int_urb (str } extern void usb_init_urb(struct urb *urb); -extern struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags); +extern struct urb *usb_alloc_urb(struct usb_device *dev, + int pipe, + size_t buffer_length, + int type, + unsigned int iso_packets, + long transfer_flags, + int interval, + gfp_t mem_flags); extern void usb_free_urb(struct urb *urb); #define usb_put_urb usb_free_urb extern struct urb *usb_get_urb(struct urb *urb); diff -urp linux-2.6.22rc6vanilla/drivers/usb/core/devio.c linux-2.6.22-rc6-storage/drivers/usb/core/devio.c --- linux-2.6.22rc6vanilla/drivers/usb/core/devio.c 2007-06-29 13:33:00.000000000 +0200 +++ linux-2.6.22-rc6-storage/drivers/usb/core/devio.c 2007-06-27 14:27:35.000000000 +0200 @@ -207,14 +207,14 @@ err: * async list handling */ -static struct async *alloc_async(unsigned int numisoframes) +static struct async *alloc_async(struct usb_device *dev, int pipe, size_t buffer_length, int type, unsigned int numisoframes, int interval) { unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor); struct async *as = kzalloc(assize, GFP_KERNEL); if (!as) return NULL; - as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL); + as->urb = usb_alloc_urb(dev, pipe, buffer_length, type, numisoframes, 0, interval, GFP_KERNEL); if (!as->urb) { kfree(as); return NULL; @@ -909,7 +909,7 @@ static int proc_do_submiturb(struct dev_ struct async *as; struct usb_ctrlrequest *dr = NULL; unsigned int u, totlen, isofrmlen; - int ret, ifnum = -1; + int ret, pipe, interval, ifnum = -1; if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK| URB_NO_FSBR|URB_ZERO_PACKET)) @@ -1027,7 +1027,15 @@ static int proc_do_submiturb(struct dev_ default: return -EINVAL; } - if (!(as = alloc_async(uurb->number_of_packets))) { + + if (uurb->type == USBDEVFS_URB_TYPE_ISO || + ps->dev->speed == USB_SPEED_HIGH) + interval = 1 << min(15, ep->desc.bInterval - 1); + else + interval = ep->desc.bInterval; + + pipe = (uurb->type << 30) | __create_pipe(ps->dev, uurb->endpoint & 0xf) | (uurb->endpoint & USB_DIR_IN); + if (!(as = alloc_async(ps->dev, pipe, uurb->buffer_length, uurb->type, uurb->number_of_packets, interval))) { kfree(isopkt); kfree(dr); return -ENOMEM; @@ -1038,23 +1046,16 @@ static int proc_do_submiturb(struct dev_ free_async(as); return -ENOMEM; } - as->urb->dev = ps->dev; - as->urb->pipe = (uurb->type << 30) | __create_pipe(ps->dev, uurb->endpoint & 0xf) | (uurb->endpoint & USB_DIR_IN); - as->urb->transfer_flags = uurb->flags; + as->urb->transfer_buffer_length = uurb->buffer_length; as->urb->setup_packet = (unsigned char*)dr; as->urb->start_frame = uurb->start_frame; as->urb->number_of_packets = uurb->number_of_packets; - if (uurb->type == USBDEVFS_URB_TYPE_ISO || - ps->dev->speed == USB_SPEED_HIGH) - as->urb->interval = 1 << min(15, ep->desc.bInterval - 1); - else - as->urb->interval = ep->desc.bInterval; as->urb->context = as; as->urb->complete = async_completed; for (totlen = u = 0; u < uurb->number_of_packets; u++) { - as->urb->iso_frame_desc[u].offset = totlen; - as->urb->iso_frame_desc[u].length = isopkt[u].length; + as->urb->iso_frames[u].offset = totlen; + as->urb->iso_frames[u].length = isopkt[u].length; totlen += isopkt[u].length; } kfree(isopkt); @@ -1128,10 +1129,10 @@ static int processcompl(struct async *as if (usb_pipeisoc(urb->pipe)) { for (i = 0; i < urb->number_of_packets; i++) { - if (put_user(urb->iso_frame_desc[i].actual_length, + if (put_user(urb->iso_frames[i].actual_length, &userurb->iso_frame_desc[i].actual_length)) return -EFAULT; - if (put_user(urb->iso_frame_desc[i].status, + if (put_user(urb->iso_frames[i].status, &userurb->iso_frame_desc[i].status)) return -EFAULT; } @@ -1242,10 +1243,10 @@ static int processcompl_compat(struct as if (usb_pipeisoc(urb->pipe)) { for (i = 0; i < urb->number_of_packets; i++) { - if (put_user(urb->iso_frame_desc[i].actual_length, + if (put_user(urb->iso_frames[i].actual_length, &userurb->iso_frame_desc[i].actual_length)) return -EFAULT; - if (put_user(urb->iso_frame_desc[i].status, + if (put_user(urb->iso_frames[i].status, &userurb->iso_frame_desc[i].status)) return -EFAULT; } diff -urp linux-2.6.22rc6vanilla/drivers/usb/core/hcd.c linux-2.6.22-rc6-storage/drivers/usb/core/hcd.c --- linux-2.6.22rc6vanilla/drivers/usb/core/hcd.c 2007-06-29 13:33:00.000000000 +0200 +++ linux-2.6.22-rc6-storage/drivers/usb/core/hcd.c 2007-06-27 14:40:59.000000000 +0200 @@ -563,7 +563,7 @@ void usb_hcd_poll_rh_status(struct usb_h hcd->poll_pending = 0; hcd->status_urb = NULL; urb->status = 0; - urb->hcpriv = NULL; + urb->rh_handed_over = NULL; urb->actual_length = length; memcpy(urb->transfer_buffer, buffer, length); } else /* urb has been unlinked */ @@ -611,7 +611,7 @@ static int rh_queue_status (struct usb_h retval = -EINVAL; } else { hcd->status_urb = urb; - urb->hcpriv = hcd; /* indicate it's queued */ + urb->rh_handed_over = hcd; /* indicate it's queued */ if (!hcd->uses_new_polling) mod_timer (&hcd->rh_timer, jiffies + @@ -654,7 +654,7 @@ static int usb_rh_urb_dequeue (struct us spin_lock (&hcd_root_hub_lock); if (urb == hcd->status_urb) { hcd->status_urb = NULL; - urb->hcpriv = NULL; + urb->rh_handed_over = NULL; } else urb = NULL; /* wasn't fully queued */ spin_unlock (&hcd_root_hub_lock); Nur in linux-2.6.22-rc6-storage/drivers/usb/core: hcd.c~. diff -urp linux-2.6.22rc6vanilla/drivers/usb/core/hcd.h linux-2.6.22-rc6-storage/drivers/usb/core/hcd.h --- linux-2.6.22rc6vanilla/drivers/usb/core/hcd.h 2007-06-29 13:33:00.000000000 +0200 +++ linux-2.6.22-rc6-storage/drivers/usb/core/hcd.h 2007-06-28 09:52:42.000000000 +0200 @@ -188,6 +188,18 @@ struct hc_driver { gfp_t mem_flags); int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb); + int (*urb_compute_space) (struct usb_hcd *hcd, + struct usb_device *dev, + int pipe, + size_t buffer_length, + int type, + unsigned int iso_packets, + int transfer_flags); + int (*urb_init) (struct usb_hcd *hcd, + struct urb *urb, + int memory, + gfp_t mem_flags); + /* hw synch, freeing endpoint resources that urb_dequeue can't */ void (*endpoint_disable)(struct usb_hcd *hcd, struct usb_host_endpoint *ep); diff -urp linux-2.6.22rc6vanilla/drivers/usb/core/hub.c linux-2.6.22-rc6-storage/drivers/usb/core/hub.c --- linux-2.6.22rc6vanilla/drivers/usb/core/hub.c 2007-06-29 13:33:00.000000000 +0200 +++ linux-2.6.22-rc6-storage/drivers/usb/core/hub.c 2007-06-27 14:32:53.000000000 +0200 @@ -818,7 +818,7 @@ static int hub_configure(struct usb_hub if (maxp > sizeof(*hub->buffer)) maxp = sizeof(*hub->buffer); - hub->urb = usb_alloc_urb(0, GFP_KERNEL); + hub->urb = usb_alloc_urb(hdev, pipe, maxp, PIPE_INTERRUPT, 0, URB_NO_TRANSFER_DMA_MAP, endpoint->bInterval, GFP_KERNEL); if (!hub->urb) { message = "couldn't allocate interrupt urb"; ret = -ENOMEM; @@ -828,7 +828,6 @@ static int hub_configure(struct usb_hub usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq, hub, endpoint->bInterval); hub->urb->transfer_dma = hub->buffer_dma; - hub->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* maybe cycle the hub leds */ if (hub->has_indicators && blinkenlights) diff -urp linux-2.6.22rc6vanilla/drivers/usb/core/message.c linux-2.6.22-rc6-storage/drivers/usb/core/message.c --- linux-2.6.22rc6vanilla/drivers/usb/core/message.c 2007-06-29 13:33:00.000000000 +0200 +++ linux-2.6.22-rc6-storage/drivers/usb/core/message.c 2007-06-29 14:37:57.000000000 +0200 @@ -77,7 +77,7 @@ static int usb_internal_control_msg(stru int retv; int length; - urb = usb_alloc_urb(0, GFP_NOIO); + urb = usb_alloc_urb(usb_dev, pipe, len, PIPE_CONTROL, 0, 0, 0, GFP_NOIO); if (!urb) return -ENOMEM; @@ -85,6 +85,7 @@ static int usb_internal_control_msg(stru len, usb_api_blocking_completion, NULL); retv = usb_start_wait_urb(urb, timeout, &length); + if (retv < 0) return retv; else @@ -209,23 +210,31 @@ int usb_bulk_msg(struct usb_device *usb_ { struct urb *urb; struct usb_host_endpoint *ep; + int is_int, interval = 0; ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out) [usb_pipeendpoint(pipe)]; if (!ep || len < 0) return -EINVAL; - urb = usb_alloc_urb(0, GFP_KERNEL); + is_int = (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT; + if (is_int) { + interval = ep->desc.bInterval; + pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); + } + + urb = usb_alloc_urb(usb_dev, pipe, len, + is_int ? PIPE_INTERRUPT : PIPE_BULK, + 0, 0, interval, GFP_KERNEL); if (!urb) return -ENOMEM; - if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_INT) { - pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); + if (is_int) usb_fill_int_urb(urb, usb_dev, pipe, data, len, usb_api_blocking_completion, NULL, ep->desc.bInterval); - } else + else usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, usb_api_blocking_completion, NULL); @@ -391,22 +400,6 @@ int usb_sg_init ( for (i = 0; i < io->entries; i++) { unsigned len; - io->urbs [i] = usb_alloc_urb (0, mem_flags); - if (!io->urbs [i]) { - io->entries = i; - goto nomem; - } - - io->urbs [i]->dev = NULL; - io->urbs [i]->pipe = pipe; - io->urbs [i]->interval = period; - io->urbs [i]->transfer_flags = urb_flags; - - io->urbs [i]->complete = sg_complete; - io->urbs [i]->context = io; - io->urbs [i]->status = -EINPROGRESS; - io->urbs [i]->actual_length = 0; - /* * Some systems need to revert to PIO when DMA is temporarily * unavailable. For their sakes, both transfer_buffer and @@ -439,6 +432,22 @@ int usb_sg_init ( io->entries = i + 1; } io->urbs [i]->transfer_buffer_length = len; + + io->urbs [i] = usb_alloc_urb (dev, pipe, len, PIPE_BULK, 0, urb_flags, 0, mem_flags); + if (!io->urbs [i]) { + io->entries = i; + goto nomem; + } + + io->urbs [i]->dev = NULL; + io->urbs [i]->interval = period; + + io->urbs [i]->complete = sg_complete; + io->urbs [i]->context = io; + io->urbs [i]->status = -EINPROGRESS; + io->urbs [i]->actual_length = 0; + + } io->urbs [--i]->transfer_flags &= ~URB_NO_INTERRUPT; @@ -628,6 +637,7 @@ int usb_get_descriptor(struct usb_device USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, (type << 8) + index, 0, buf, size, USB_CTRL_GET_TIMEOUT); + if (result == 0 || result == -EPIPE) continue; if (result > 1 && ((u8 *)buf)[1] != type) { @@ -864,6 +874,7 @@ int usb_get_device_descriptor(struct usb if (size > sizeof(*desc)) return -EINVAL; + desc = kmalloc(sizeof(*desc), GFP_NOIO); if (!desc) return -ENOMEM; diff -urp linux-2.6.22rc6vanilla/drivers/usb/core/urb.c linux-2.6.22-rc6-storage/drivers/usb/core/urb.c --- linux-2.6.22rc6vanilla/drivers/usb/core/urb.c 2007-06-29 13:28:31.000000000 +0200 +++ linux-2.6.22-rc6-storage/drivers/usb/core/urb.c 2007-06-28 09:53:02.000000000 +0200 @@ -11,6 +11,7 @@ static void urb_destroy(struct kref *kref) { struct urb *urb = to_urb(kref); + kfree(urb->iso_frames); kfree(urb); } @@ -53,18 +54,47 @@ void usb_init_urb(struct urb *urb) * * The driver must call usb_free_urb() when it is finished with the urb. */ -struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags) +struct urb *usb_alloc_urb(struct usb_device *dev, + int pipe, + size_t buffer_length, + int type, + unsigned int iso_packets, + long transfer_flags, + int interval, + gfp_t mem_flags) { struct urb *urb; + struct usb_iso_packet_descriptor *frames = NULL; + struct usb_hcd *hcd = bus_to_hcd(dev->bus); + int space; - urb = kmalloc(sizeof(struct urb) + - iso_packets * sizeof(struct usb_iso_packet_descriptor), - mem_flags); + space = (hcd->driver->urb_compute_space) (hcd, dev, pipe, buffer_length, type, iso_packets, transfer_flags); + if (space < 0) + return NULL; + + if (iso_packets) { + frames = kmalloc(iso_packets * sizeof(struct usb_iso_packet_descriptor), mem_flags); + if (!frames) + return NULL; + } + + urb = kmalloc(space, mem_flags); if (!urb) { err("alloc_urb: kmalloc failed"); + kfree(frames); return NULL; } usb_init_urb(urb); + urb->dev = dev; + urb->pipe = pipe; + urb->iso_frames = frames; + urb->transfer_flags = transfer_flags; + urb->interval = interval; + if (0 > (hcd->driver->urb_init)(hcd, urb, space, mem_flags)) { + kfree(urb); + kfree(frames); + return NULL; + } return urb; } @@ -223,7 +253,7 @@ int usb_submit_urb(struct urb *urb, gfp_ struct usb_device *dev; int is_out; - if (!urb || urb->hcpriv || !urb->complete) + if (!urb || !urb->complete) return -EINVAL; if (!(dev = urb->dev) || (dev->state < USB_STATE_DEFAULT) || @@ -278,11 +308,11 @@ int usb_submit_urb(struct urb *urb, gfp_ if (urb->number_of_packets <= 0) return -EINVAL; for (n = 0; n < urb->number_of_packets; n++) { - len = urb->iso_frame_desc[n].length; + len = urb->iso_frames[n].length; if (len < 0 || len > max) return -EMSGSIZE; - urb->iso_frame_desc[n].status = -EXDEV; - urb->iso_frame_desc[n].actual_length = 0; + urb->iso_frames[n].status = -EXDEV; + urb->iso_frames[n].actual_length = 0; } } diff -urp linux-2.6.22rc6vanilla/drivers/usb/host/ohci.h linux-2.6.22-rc6-storage/drivers/usb/host/ohci.h --- linux-2.6.22rc6vanilla/drivers/usb/host/ohci.h 2007-06-29 13:28:34.000000000 +0200 +++ linux-2.6.22-rc6-storage/drivers/usb/host/ohci.h 2007-06-28 09:46:55.000000000 +0200 @@ -326,6 +326,7 @@ struct ohci_regs { typedef struct urb_priv { struct ed *ed; u16 length; // # tds in this request + u16 alloc_length; u16 td_cnt; // tds already serviced struct list_head pending; struct td *td [0]; // all TDs in this request @@ -401,6 +402,11 @@ struct ohci_hcd { }; +struct ohci_urb { + struct urb urb; + urb_priv_t hcpriv; +}; + /* convert between an hcd pointer and the corresponding ohci_hcd */ static inline struct ohci_hcd *hcd_to_ohci (struct usb_hcd *hcd) { diff -urp linux-2.6.22rc6vanilla/drivers/usb/host/ohci-hcd.c linux-2.6.22-rc6-storage/drivers/usb/host/ohci-hcd.c --- linux-2.6.22rc6vanilla/drivers/usb/host/ohci-hcd.c 2007-06-29 13:33:00.000000000 +0200 +++ linux-2.6.22-rc6-storage/drivers/usb/host/ohci-hcd.c 2007-06-29 09:07:15.000000000 +0200 @@ -53,7 +53,7 @@ /*-------------------------------------------------------------------------*/ -#undef OHCI_VERBOSE_DEBUG /* not always helpful */ +#define OHCI_VERBOSE_DEBUG /* not always helpful */ /* For initializing controller (mask in an HCFS mode too) */ #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR @@ -113,6 +113,82 @@ MODULE_PARM_DESC (no_handshake, "true (n /*-------------------------------------------------------------------------*/ +static int ohci_urb_compute_space(struct usb_hcd *hcd, + struct usb_device *dev, + int pipe, + size_t buffer_length, + int type, + unsigned int iso_packets, + int transfer_flags) +{ + int size = 0; + + /* for the private part of the URB we need the number of TDs (size) */ + switch (type) { + case PIPE_CONTROL: + /* td_submit_urb() doesn't yet handle these */ + if (buffer_length > 4096) + return -EMSGSIZE; + + /* 1 TD for setup, 1 for ACK, plus ... */ + size = 2; + /* FALLTHROUGH */ + // case PIPE_INTERRUPT: + // case PIPE_BULK: + default: + /* one TD for every 4096 Bytes (can be upto 8K) */ + size += buffer_length / 4096; + /* ... and for any remaining bytes ... */ + if ((buffer_length % 4096) != 0) + size++; + /* ... and maybe a zero length packet to wrap it up */ + if (size == 0) + size++; + else if ((transfer_flags & URB_ZERO_PACKET) != 0 + && (buffer_length + % usb_maxpacket (dev, pipe, + usb_pipeout (pipe))) == 0) + size++; + break; + case PIPE_ISOCHRONOUS: /* number of packets from URB */ + size = iso_packets; + break; + } + return size * sizeof(struct td) + sizeof(struct ohci_urb); +} + +static int ohci_urb_init(struct usb_hcd *hcd, + struct urb *urb, + int memory, + gfp_t mem_flags) +{ + struct ohci_urb *ou = (struct ohci_urb *)urb; + struct usb_host_endpoint *ep; + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + struct ed *ed; + int i, size; + + size = ou->hcpriv.alloc_length = (memory - sizeof(struct ohci_urb)) / sizeof(struct td); + + ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out) + [usb_pipeendpoint(urb->pipe)]; + /* every endpoint has an ed, locate and maybe (re)initialize it */ + if (! (ed = ed_get (ohci, ep, urb->dev, urb->pipe, urb->interval))) + return -ENOMEM; + ou->hcpriv.ed = ed; + + /* allocate the TDs (deferring hash chain updates) */ + for (i = 0; i < size; i++) { + ou->hcpriv.td[i] = td_alloc(ohci, mem_flags); + if (!ou->hcpriv.td[i]) { + urb_free_priv(ohci, &ou->hcpriv); + return -ENOMEM; + } + } + + return 0; +} + /* * queue up an urb for anything except the root hub */ @@ -123,20 +199,18 @@ static int ohci_urb_enqueue ( gfp_t mem_flags ) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); - struct ed *ed; - urb_priv_t *urb_priv; + urb_priv_t *urb_priv = &(((struct ohci_urb *)urb)->hcpriv); + struct ed *ed = urb_priv->ed; unsigned int pipe = urb->pipe; - int i, size = 0; + int size = 0; unsigned long flags; int retval = 0; + u16 orig = urb_priv->alloc_length; #ifdef OHCI_VERBOSE_DEBUG urb_print (urb, "SUB", usb_pipein (pipe)); #endif - /* every endpoint has a ed, locate and maybe (re)initialize it */ - if (! (ed = ed_get (ohci, ep, urb->dev, pipe, urb->interval))) - return -ENOMEM; /* for the private part of the URB we need the number of TDs (size) */ switch (ed->type) { @@ -170,26 +244,17 @@ static int ohci_urb_enqueue ( break; } + if (size > orig) + return -EMSGSIZE; + BUG_ON(ed == NULL); + /* allocate the private part of the URB */ - urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (struct td *), - mem_flags); - if (!urb_priv) - return -ENOMEM; - memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *)); + memset (urb_priv, 0, sizeof (urb_priv_t)); INIT_LIST_HEAD (&urb_priv->pending); + urb_priv->alloc_length = orig; urb_priv->length = size; urb_priv->ed = ed; - /* allocate the TDs (deferring hash chain updates) */ - for (i = 0; i < size; i++) { - urb_priv->td [i] = td_alloc (ohci, mem_flags); - if (!urb_priv->td [i]) { - urb_priv->length = i; - urb_free_priv (ohci, urb_priv); - return -ENOMEM; - } - } - spin_lock_irqsave (&ohci->lock, flags); /* don't submit to a dead HC */ @@ -206,7 +271,6 @@ static int ohci_urb_enqueue ( spin_lock (&urb->lock); if (urb->status != -EINPROGRESS) { spin_unlock (&urb->lock); - urb->hcpriv = urb_priv; finish_urb (ohci, urb); retval = 0; goto fail; @@ -237,14 +301,11 @@ static int ohci_urb_enqueue ( * enable that part of the schedule, if needed * and update count of queued periodic urbs */ - urb->hcpriv = urb_priv; td_submit_urb (ohci, urb); fail0: spin_unlock (&urb->lock); fail: - if (retval) - urb_free_priv (ohci, urb_priv); spin_unlock_irqrestore (&ohci->lock, flags); return retval; } @@ -257,7 +318,8 @@ fail: */ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) { - struct ohci_hcd *ohci = hcd_to_ohci (hcd); + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + struct ohci_urb *ourb = (struct ohci_urb *)urb; unsigned long flags; #ifdef OHCI_VERBOSE_DEBUG @@ -272,18 +334,15 @@ static int ohci_urb_dequeue (struct usb_ * handed to us, flag it for unlink and giveback, and force * some upcoming INTR_SF to call finish_unlinks() */ - urb_priv = urb->hcpriv; - if (urb_priv) { - if (urb_priv->ed->state == ED_OPER) - start_ed_unlink (ohci, urb_priv->ed); - } + urb_priv = &ourb->hcpriv; + if (urb_priv->ed->state == ED_OPER) + start_ed_unlink (ohci, urb_priv->ed); } else { /* * with HC dead, we won't respect hc queue pointers * any more ... just clean up every urb's memory. */ - if (urb->hcpriv) - finish_urb (ohci, urb); + finish_urb(ohci, urb); } spin_unlock_irqrestore (&ohci->lock, flags); return 0; diff -urp linux-2.6.22rc6vanilla/drivers/usb/host/ohci-pci.c linux-2.6.22-rc6-storage/drivers/usb/host/ohci-pci.c --- linux-2.6.22rc6vanilla/drivers/usb/host/ohci-pci.c 2007-06-29 13:33:01.000000000 +0200 +++ linux-2.6.22-rc6-storage/drivers/usb/host/ohci-pci.c 2007-06-27 17:36:59.000000000 +0200 @@ -281,6 +281,8 @@ static const struct hc_driver ohci_pci_h .urb_enqueue = ohci_urb_enqueue, .urb_dequeue = ohci_urb_dequeue, .endpoint_disable = ohci_endpoint_disable, + .urb_compute_space = ohci_urb_compute_space, + .urb_init = ohci_urb_init, /* * scheduling support diff -urp linux-2.6.22rc6vanilla/drivers/usb/host/ohci-q.c linux-2.6.22-rc6-storage/drivers/usb/host/ohci-q.c --- linux-2.6.22rc6vanilla/drivers/usb/host/ohci-q.c 2007-02-04 19:44:54.000000000 +0100 +++ linux-2.6.22-rc6-storage/drivers/usb/host/ohci-q.c 2007-06-29 14:36:25.000000000 +0200 @@ -11,21 +11,20 @@ static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv) { - int last = urb_priv->length - 1; + int last = urb_priv->alloc_length - 1; if (last >= 0) { int i; struct td *td; for (i = 0; i <= last; i++) { - td = urb_priv->td [i]; + td = urb_priv->td[i]; if (td) - td_free (hc, td); + td_free(hc, td); } } list_del (&urb_priv->pending); - kfree (urb_priv); } /*-------------------------------------------------------------------------*/ @@ -40,11 +39,9 @@ finish_urb (struct ohci_hcd *ohci, struc __releases(ohci->lock) __acquires(ohci->lock) { + //struct ohci_urb *ourb = (struct ohci_urb *)urb; // ASSERT (urb->hcpriv != 0); - urb_free_priv (ohci, urb->hcpriv); - urb->hcpriv = NULL; - spin_lock (&urb->lock); if (likely (urb->status == -EINPROGRESS)) urb->status = 0; @@ -507,8 +504,9 @@ td_fill (struct ohci_hcd *ohci, u32 info dma_addr_t data, int len, struct urb *urb, int index) { + struct ohci_urb *ourb = (struct ohci_urb *)urb; struct td *td, *td_pt; - struct urb_priv *urb_priv = urb->hcpriv; + struct urb_priv *urb_priv = &ourb->hcpriv; int is_iso = info & TD_ISO; int hash; @@ -531,7 +529,6 @@ td_fill (struct ohci_hcd *ohci, u32 info /* use this td as the next dummy */ td_pt = urb_priv->td [index]; - /* fill the old dummy TD */ td = urb_priv->td [index] = urb_priv->ed->dummy; urb_priv->ed->dummy = td_pt; @@ -543,7 +540,6 @@ td_fill (struct ohci_hcd *ohci, u32 info td->data_dma = data; if (!len) data = 0; - td->hwINFO = cpu_to_hc32 (ohci, info); if (is_iso) { td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000); @@ -558,15 +554,12 @@ td_fill (struct ohci_hcd *ohci, u32 info else td->hwBE = 0; td->hwNextTD = cpu_to_hc32 (ohci, td_pt->td_dma); - /* append to queue */ list_add_tail (&td->td_list, &td->ed->td_list); - /* hash it for later reverse mapping */ hash = TD_HASH_FUNC (td->td_dma); td->td_hash = ohci->td_hash [hash]; ohci->td_hash [hash] = td; - /* HC might read the TD (or cachelines) right away ... */ wmb (); td->ed->hwTailP = td->hwNextTD; @@ -583,7 +576,8 @@ static void td_submit_urb ( struct ohci_hcd *ohci, struct urb *urb ) { - struct urb_priv *urb_priv = urb->hcpriv; + struct ohci_urb *ourb = (struct ohci_urb *)urb; + struct urb_priv *urb_priv = &ourb->hcpriv; dma_addr_t data; int data_len = urb->transfer_buffer_length; int cnt = 0; @@ -686,8 +680,8 @@ static void td_submit_urb ( frame += cnt * urb->interval; frame &= 0xffff; td_fill (ohci, TD_CC | TD_ISO | frame, - data + urb->iso_frame_desc [cnt].offset, - urb->iso_frame_desc [cnt].length, urb, cnt); + data + urb->iso_frames[cnt].offset, + urb->iso_frames[cnt].length, urb, cnt); } periodic = ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs++ == 0 && ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0; @@ -732,7 +726,7 @@ static void td_done (struct ohci_hcd *oh return; if (usb_pipeout (urb->pipe)) - dlen = urb->iso_frame_desc [td->index].length; + dlen = urb->iso_frames[td->index].length; else { /* short reads are always OK for ISO */ if (cc == TD_DATAUNDERRUN) @@ -740,8 +734,8 @@ static void td_done (struct ohci_hcd *oh dlen = tdPSW & 0x3ff; } urb->actual_length += dlen; - urb->iso_frame_desc [td->index].actual_length = dlen; - urb->iso_frame_desc [td->index].status = cc_to_error [cc]; + urb->iso_frames[td->index].actual_length = dlen; + urb->iso_frames[td->index].status = cc_to_error [cc]; if (cc != TD_CC_NOERROR) ohci_vdbg (ohci, @@ -967,12 +961,14 @@ rescan_this: list_for_each_safe (entry, tmp, &ed->td_list) { struct td *td; struct urb *urb; + struct ohci_urb *ourb; urb_priv_t *urb_priv; __hc32 savebits; td = list_entry (entry, struct td, td_list); urb = td->urb; - urb_priv = td->urb->hcpriv; + ourb = (struct ohci_urb *)urb; + urb_priv = &ourb->hcpriv; if (urb->status == -EINPROGRESS) { prev = &td->hwNextTD; @@ -1075,7 +1071,7 @@ dl_done_list (struct ohci_hcd *ohci) while (td) { struct td *td_next = td->next_dl_td; struct urb *urb = td->urb; - urb_priv_t *urb_priv = urb->hcpriv; + urb_priv_t *urb_priv = &(((struct ohci_urb *)urb)->hcpriv); struct ed *ed = td->ed; /* update URB's length and status from TD */ diff -urp linux-2.6.22rc6vanilla/drivers/usb/class/cdc-acm.c linux-2.6.22-rc6-storage/drivers/usb/class/cdc-acm.c --- linux-2.6.22rc6vanilla/drivers/usb/class/cdc-acm.c 2007-06-29 13:33:00.000000000 +0200 +++ linux-2.6.22-rc6-storage/drivers/usb/class/cdc-acm.c 2007-06-28 16:20:49.000000000 +0200 @@ -989,7 +989,14 @@ skip_normal_probe: goto alloc_fail4; } - acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); + acm->ctrlurb = usb_alloc_urb(usb_dev, + usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress), + ctrlsize, + PIPE_INTERRUPT, + 0, + URB_NO_TRANSFER_DMA_MAP, + epctrl->bInterval, + GFP_KERNEL); if (!acm->ctrlurb) { dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)"); goto alloc_fail5; @@ -997,7 +1004,15 @@ skip_normal_probe: for (i = 0; i < num_rx_buf; i++) { struct acm_ru *rcv = &(acm->ru[i]); - if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) { + if (!(rcv->urb = usb_alloc_urb(usb_dev, + acm->rx_endpoint, + acm->readsize, + PIPE_BULK, + 0, + URB_NO_TRANSFER_DMA_MAP, + 0, + GFP_KERNEL + ))) { dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)"); goto alloc_fail7; } @@ -1013,7 +1028,14 @@ skip_normal_probe: goto alloc_fail7; } } - acm->writeurb = usb_alloc_urb(0, GFP_KERNEL); + acm->writeurb = usb_alloc_urb(usb_dev, + usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), + acm->writesize, + PIPE_BULK, + 0, + URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP, + 0, + GFP_KERNEL); if (!acm->writeurb) { dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)"); goto alloc_fail7; ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel