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/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel