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

Reply via email to