ChangeSet 1.1305.7.4, 2003/06/13 16:41:21-07:00, stern@rowland.harvard.edu [PATCH] USB: Use separate transport_flags bits for transfer_dma Use separate transfer_flags bits for transfer_dma and setup_dma Documentation/usb/dma.txt | 31 ++++++++++++++++------- drivers/usb/class/usblp.c | 4 +-- drivers/usb/core/hcd.c | 20 +++++++++------ drivers/usb/core/hub.c | 2 - drivers/usb/core/message.c | 3 +- drivers/usb/core/urb.c | 2 - drivers/usb/core/usb.c | 56 +++++++++++++++++++++++++++--------------- drivers/usb/input/aiptek.c | 2 - drivers/usb/input/hid-core.c | 7 +++-- drivers/usb/input/kbtab.c | 2 - drivers/usb/input/powermate.c | 4 +-- drivers/usb/input/usbkbd.c | 5 ++- drivers/usb/input/usbmouse.c | 2 - drivers/usb/input/wacom.c | 2 - drivers/usb/input/xpad.c | 2 - drivers/usb/misc/usbtest.c | 2 - include/linux/usb.h | 51 +++++++++++++++++++++----------------- 17 files changed, 121 insertions(+), 76 deletions(-) diff -Nru a/Documentation/usb/dma.txt b/Documentation/usb/dma.txt --- a/Documentation/usb/dma.txt Wed Jun 18 11:16:00 2003 +++ b/Documentation/usb/dma.txt Wed Jun 18 11:16:00 2003 @@ -15,10 +15,12 @@ manage dma mappings for existing dma-ready buffers (see below). - URBs have an additional "transfer_dma" field, as well as a transfer_flags - bit saying if it's valid. (Control requests also needed "setup_dma".) + bit saying if it's valid. (Control requests also have "setup_dma" and a + corresponding transfer_flags bit.) -- "usbcore" will map those DMA addresses, if a DMA-aware driver didn't do it - first and set URB_NO_DMA_MAP. HCDs don't manage dma mappings for urbs. +- "usbcore" will map those DMA addresses, if a DMA-aware driver didn't do + it first and set URB_NO_TRANSFER_DMA_MAP or URB_NO_SETUP_DMA_MAP. HCDs + don't manage dma mappings for URBs. - There's a new "generic DMA API", parts of which are usable by USB device drivers. Never use dma_set_mask() on any USB interface or device; that @@ -33,8 +35,9 @@ - When you're allocating a buffer for DMA purposes anyway, use the buffer primitives. Think of them as kmalloc and kfree that give you the right kind of addresses to store in urb->transfer_buffer and urb->transfer_dma, - while guaranteeing that hidden copies through DMA "bounce" buffers won't - slow things down. You'd also set URB_NO_DMA_MAP in urb->transfer_flags: + while guaranteeing that no hidden copies through DMA "bounce" buffers will + slow things down. You'd also set URB_NO_TRANSFER_DMA_MAP in + urb->transfer_flags: void *usb_buffer_alloc (struct usb_device *dev, size_t size, int mem_flags, dma_addr_t *dma); @@ -42,10 +45,18 @@ void usb_buffer_free (struct usb_device *dev, size_t size, void *addr, dma_addr_t dma); + For control transfers you can use the buffer primitives or not for each + of the transfer buffer and setup buffer independently. Set the flag bits + URB_NO_TRANSFER_DMA_MAP and URB_NO_SETUP_DMA_MAP to indicate which + buffers you have prepared. For non-control transfers URB_NO_SETUP_DMA_MAP + is ignored. + The memory buffer returned is "dma-coherent"; sometimes you might need to force a consistent memory access ordering by using memory barriers. It's not using a streaming DMA mapping, so it's good for small transfers on - systems where the I/O would otherwise tie up an IOMMU mapping. + systems where the I/O would otherwise tie up an IOMMU mapping. (See + Documentation/DMA-mapping.txt for definitions of "coherent" and "streaming" + DMA mappings.) Asking for 1/Nth of a page (as well as asking for N pages) is reasonably space-efficient. @@ -91,7 +102,8 @@ These calls all work with initialized urbs: urb->dev, urb->pipe, urb->transfer_buffer, and urb->transfer_buffer_length must all be - valid when these calls are used: + valid when these calls are used (urb->setup_packet must be valid too + if urb is a control request): struct urb *usb_buffer_map (struct urb *urb); @@ -99,6 +111,6 @@ void usb_buffer_unmap (struct urb *urb); - The calls manage urb->transfer_dma for you, and set URB_NO_DMA_MAP so that - usbcore won't map or unmap the buffer. - + The calls manage urb->transfer_dma for you, and set URB_NO_TRANSFER_DMA_MAP + so that usbcore won't map or unmap the buffer. The same goes for + urb->setup_dma and URB_NO_SETUP_DMA_MAP for control requests. diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c --- a/drivers/usb/class/usblp.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/class/usblp.c Wed Jun 18 11:16:00 2003 @@ -858,8 +858,8 @@ } usblp->writebuf = usblp->readbuf = NULL; - usblp->writeurb->transfer_flags = URB_NO_DMA_MAP; - usblp->readurb->transfer_flags = URB_NO_DMA_MAP; + usblp->writeurb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; + usblp->readurb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; /* Malloc write & read buffers. We somewhat wastefully * malloc both regardless of bidirectionality, because the * alternate setting can be changed later via an ioctl. */ diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c --- a/drivers/usb/core/hcd.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/core/hcd.c Wed Jun 18 11:16:00 2003 @@ -1027,7 +1027,8 @@ * valid and usb_buffer_{sync,unmap}() not be needed, since * they could clobber root hub response data. */ - urb->transfer_flags |= URB_NO_DMA_MAP; + urb->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP + | URB_NO_SETUP_DMA_MAP); status = rh_urb_enqueue (hcd, urb); goto done; } @@ -1035,15 +1036,16 @@ /* lower level hcd code should use *_dma exclusively, * unless it uses pio or talks to another transport. */ - if (!(urb->transfer_flags & URB_NO_DMA_MAP) - && hcd->controller->dma_mask) { - if (usb_pipecontrol (urb->pipe)) + if (hcd->controller->dma_mask) { + if (usb_pipecontrol (urb->pipe) + && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) urb->setup_dma = dma_map_single ( hcd->controller, urb->setup_packet, sizeof (struct usb_ctrlrequest), DMA_TO_DEVICE); - if (urb->transfer_buffer_length != 0) + if (urb->transfer_buffer_length != 0 + && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) urb->transfer_dma = dma_map_single ( hcd->controller, urb->transfer_buffer, @@ -1410,12 +1412,14 @@ // It would catch exit/unlink paths for all urbs. /* lower level hcd code should use *_dma exclusively */ - if (!(urb->transfer_flags & URB_NO_DMA_MAP)) { - if (usb_pipecontrol (urb->pipe)) + if (hcd->controller->dma_mask) { + if (usb_pipecontrol (urb->pipe) + && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) pci_unmap_single (hcd->pdev, urb->setup_dma, sizeof (struct usb_ctrlrequest), PCI_DMA_TODEVICE); - if (urb->transfer_buffer_length != 0) + if (urb->transfer_buffer_length != 0 + && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) pci_unmap_single (hcd->pdev, urb->transfer_dma, urb->transfer_buffer_length, usb_pipein (urb->pipe) diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c --- a/drivers/usb/core/hub.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/core/hub.c Wed Jun 18 11:16:00 2003 @@ -461,7 +461,7 @@ usb_fill_int_urb(hub->urb, dev, pipe, *hub->buffer, maxp, hub_irq, hub, endpoint->bInterval); hub->urb->transfer_dma = hub->buffer_dma; - hub->urb->transfer_flags |= URB_NO_DMA_MAP; + hub->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; ret = usb_submit_urb(hub->urb, GFP_KERNEL); if (ret) { message = "couldn't submit status urb"; diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- a/drivers/usb/core/message.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/core/message.c Wed Jun 18 11:16:00 2003 @@ -344,7 +344,8 @@ if (!io->urbs) goto nomem; - urb_flags = URB_ASYNC_UNLINK | URB_NO_DMA_MAP | URB_NO_INTERRUPT; + urb_flags = URB_ASYNC_UNLINK | URB_NO_TRANSFER_DMA_MAP + | URB_NO_INTERRUPT; if (usb_pipein (pipe)) urb_flags |= URB_SHORT_NOT_OK; diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c --- a/drivers/usb/core/urb.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/core/urb.c Wed Jun 18 11:16:00 2003 @@ -297,7 +297,7 @@ /* enforce simple/standard policy */ allowed = URB_ASYNC_UNLINK; // affects later unlinks - allowed |= URB_NO_DMA_MAP; + allowed |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); allowed |= URB_NO_INTERRUPT; switch (temp) { case PIPE_BULK: diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/core/usb.c Wed Jun 18 11:16:00 2003 @@ -1234,7 +1234,7 @@ } /** - * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_DMA_MAP + * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP * @dev: device the buffer will be used with * @size: requested buffer size * @mem_flags: affect whether allocation may block @@ -1245,9 +1245,9 @@ * specified device. Such cpu-space buffers are returned along with the DMA * address (through the pointer provided). * - * These buffers are used with URB_NO_DMA_MAP set in urb->transfer_flags to - * avoid behaviors like using "DMA bounce buffers", or tying down I/O mapping - * hardware for long idle periods. The implementation varies between + * These buffers are used with URB_NO_xxx_DMA_MAP set in urb->transfer_flags + * to avoid behaviors like using "DMA bounce buffers", or tying down I/O + * mapping hardware for long idle periods. The implementation varies between * platforms, depending on details of how DMA will work to this device. * Using these buffers also helps prevent cacheline sharing problems on * architectures where CPU caches are not DMA-coherent. @@ -1291,17 +1291,17 @@ /** * usb_buffer_map - create DMA mapping(s) for an urb - * @urb: urb whose transfer_buffer will be mapped + * @urb: urb whose transfer_buffer/setup_packet will be mapped * * Return value is either null (indicating no buffer could be mapped), or - * the parameter. URB_NO_DMA_MAP is added to urb->transfer_flags if the - * operation succeeds. If the device is connected to this system through - * a non-DMA controller, this operation always succeeds. + * the parameter. URB_NO_TRANSFER_DMA_MAP and URB_NO_SETUP_DMA_MAP are + * added to urb->transfer_flags if the operation succeeds. If the device + * is connected to this system through a non-DMA controller, this operation + * always succeeds. * * This call would normally be used for an urb which is reused, perhaps * as the target of a large periodic transfer, with usb_buffer_dmasync() - * calls to synchronize memory and dma state. It may not be used for - * control requests. + * calls to synchronize memory and dma state. * * Reverse the effect of this call with usb_buffer_unmap(). */ @@ -1311,7 +1311,6 @@ struct device *controller; if (!urb - || usb_pipecontrol (urb->pipe) || !urb->dev || !(bus = urb->dev->bus) || !(controller = bus->controller)) @@ -1322,17 +1321,23 @@ urb->transfer_buffer, urb->transfer_buffer_length, usb_pipein (urb->pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + if (usb_pipecontrol (urb->pipe)) + urb->setup_dma = dma_map_single (controller, + urb->setup_packet, + sizeof (struct usb_ctrlrequest), + DMA_TO_DEVICE); // FIXME generic api broken like pci, can't report errors // if (urb->transfer_dma == DMA_ADDR_INVALID) return 0; } else urb->transfer_dma = ~0; - urb->transfer_flags |= URB_NO_DMA_MAP; + urb->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP + | URB_NO_SETUP_DMA_MAP); return urb; } /** * usb_buffer_dmasync - synchronize DMA and CPU view of buffer(s) - * @urb: urb whose transfer_buffer will be synchronized + * @urb: urb whose transfer_buffer/setup_packet will be synchronized */ void usb_buffer_dmasync (struct urb *urb) { @@ -1340,17 +1345,23 @@ struct device *controller; if (!urb - || !(urb->transfer_flags & URB_NO_DMA_MAP) + || !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) || !urb->dev || !(bus = urb->dev->bus) || !(controller = bus->controller)) return; - if (controller->dma_mask) + if (controller->dma_mask) { dma_sync_single (controller, urb->transfer_dma, urb->transfer_buffer_length, usb_pipein (urb->pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + if (usb_pipecontrol (urb->pipe)) + dma_sync_single (controller, + urb->setup_dma, + sizeof (struct usb_ctrlrequest), + DMA_TO_DEVICE); + } } /** @@ -1365,18 +1376,25 @@ struct device *controller; if (!urb - || !(urb->transfer_flags & URB_NO_DMA_MAP) + || !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) || !urb->dev || !(bus = urb->dev->bus) || !(controller = bus->controller)) return; - if (controller->dma_mask) + if (controller->dma_mask) { dma_unmap_single (controller, urb->transfer_dma, urb->transfer_buffer_length, usb_pipein (urb->pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); - urb->transfer_flags &= ~URB_NO_DMA_MAP; + if (usb_pipecontrol (urb->pipe)) + dma_unmap_single (controller, + urb->setup_dma, + sizeof (struct usb_ctrlrequest), + DMA_TO_DEVICE); + } + urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP + | URB_NO_SETUP_DMA_MAP); } /** @@ -1391,7 +1409,7 @@ * * The caller is responsible for placing the resulting DMA addresses from * the scatterlist into URB transfer buffer pointers, and for setting the - * URB_NO_DMA_MAP transfer flag in each of those URBs. + * URB_NO_TRANSFER_DMA_MAP transfer flag in each of those URBs. * * Top I/O rates come from queuing URBs, instead of waiting for each one * to complete before starting the next I/O. This is particularly easy diff -Nru a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c --- a/drivers/usb/input/aiptek.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/input/aiptek.c Wed Jun 18 11:16:00 2003 @@ -330,7 +330,7 @@ aiptek->data, aiptek->features->pktlen, aiptek->features->irq, aiptek, endpoint->bInterval); aiptek->irq->transfer_dma = aiptek->data_dma; - aiptek->irq->transfer_flags |= URB_NO_DMA_MAP; + aiptek->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; input_register_device(&aiptek->dev); diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c --- a/drivers/usb/input/hid-core.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/input/hid-core.c Wed Jun 18 11:16:00 2003 @@ -1510,7 +1510,7 @@ usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0, hid_irq_in, hid, endpoint->bInterval); hid->urbin->transfer_dma = hid->inbuf_dma; - hid->urbin->transfer_flags |= URB_NO_DMA_MAP; + hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; } else { if (hid->urbout) continue; @@ -1520,7 +1520,7 @@ usb_fill_bulk_urb(hid->urbout, dev, pipe, hid->outbuf, 0, hid_irq_out, hid); hid->urbout->transfer_dma = hid->outbuf_dma; - hid->urbout->transfer_flags |= URB_NO_DMA_MAP; + hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; } } @@ -1569,7 +1569,8 @@ hid->ctrlbuf, 1, hid_ctrl, hid); hid->urbctrl->setup_dma = hid->cr_dma; hid->urbctrl->transfer_dma = hid->ctrlbuf_dma; - hid->urbctrl->transfer_flags |= URB_NO_DMA_MAP; + hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP + | URB_NO_SETUP_DMA_MAP); return hid; diff -Nru a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c --- a/drivers/usb/input/kbtab.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/input/kbtab.c Wed Jun 18 11:16:00 2003 @@ -181,7 +181,7 @@ kbtab->data, 8, kbtab_irq, kbtab, endpoint->bInterval); kbtab->irq->transfer_dma = kbtab->data_dma; - kbtab->irq->transfer_flags |= URB_NO_DMA_MAP; + kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; input_register_device(&kbtab->dev); diff -Nru a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c --- a/drivers/usb/input/powermate.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/input/powermate.c Wed Jun 18 11:16:00 2003 @@ -180,7 +180,7 @@ (void *) pm->configcr, 0, 0, powermate_config_complete, pm); pm->config->setup_dma = pm->configcr_dma; - pm->config->transfer_flags |= URB_NO_DMA_MAP; + pm->config->transfer_flags |= URB_NO_SETUP_DMA_MAP; if (usb_submit_urb(pm->config, GFP_ATOMIC)) printk(KERN_ERR "powermate: usb_submit_urb(config) failed"); @@ -355,7 +355,7 @@ POWERMATE_PAYLOAD_SIZE, powermate_irq, pm, endpoint->bInterval); pm->irq->transfer_dma = pm->data_dma; - pm->irq->transfer_flags |= URB_NO_DMA_MAP; + pm->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* register our interrupt URB with the USB system */ if (usb_submit_urb(pm->irq, GFP_KERNEL)) { diff -Nru a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c --- a/drivers/usb/input/usbkbd.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/input/usbkbd.c Wed Jun 18 11:16:00 2003 @@ -282,7 +282,7 @@ kbd->new, (maxp > 8 ? 8 : maxp), usb_kbd_irq, kbd, endpoint->bInterval); kbd->irq->transfer_dma = kbd->new_dma; - kbd->irq->transfer_flags |= URB_NO_DMA_MAP; + kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE; kbd->cr->bRequest = 0x09; @@ -325,7 +325,8 @@ usb_kbd_led, kbd); kbd->led->setup_dma = kbd->cr_dma; kbd->led->transfer_dma = kbd->leds_dma; - kbd->led->transfer_flags |= URB_NO_DMA_MAP; + kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP + | URB_NO_SETUP_DMA_MAP); input_register_device(&kbd->dev); diff -Nru a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c --- a/drivers/usb/input/usbmouse.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/input/usbmouse.c Wed Jun 18 11:16:00 2003 @@ -207,7 +207,7 @@ (maxp > 8 ? 8 : maxp), usb_mouse_irq, mouse, endpoint->bInterval); mouse->irq->transfer_dma = mouse->data_dma; - mouse->irq->transfer_flags |= URB_NO_DMA_MAP; + mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; input_register_device(&mouse->dev); printk(KERN_INFO "input: %s on %s\n", mouse->name, path); diff -Nru a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c --- a/drivers/usb/input/wacom.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/input/wacom.c Wed Jun 18 11:16:00 2003 @@ -590,7 +590,7 @@ wacom->data, wacom->features->pktlen, wacom->features->irq, wacom, endpoint->bInterval); wacom->irq->transfer_dma = wacom->data_dma; - wacom->irq->transfer_flags |= URB_NO_DMA_MAP; + wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; input_register_device(&wacom->dev); diff -Nru a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c --- a/drivers/usb/input/xpad.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/input/xpad.c Wed Jun 18 11:16:00 2003 @@ -259,7 +259,7 @@ xpad->idata, XPAD_PKT_LEN, xpad_irq_in, xpad, ep_irq_in->bInterval); xpad->irq_in->transfer_dma = xpad->idata_dma; - xpad->irq_in->transfer_flags |= URB_NO_DMA_MAP; + xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; xpad->udev = udev; diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c --- a/drivers/usb/misc/usbtest.c Wed Jun 18 11:16:00 2003 +++ b/drivers/usb/misc/usbtest.c Wed Jun 18 11:16:00 2003 @@ -107,7 +107,7 @@ urb->interval = (udev->speed == USB_SPEED_HIGH) ? (INTERRUPT_RATE << 3) : INTERRUPT_RATE; - urb->transfer_flags = URB_NO_DMA_MAP; + urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; if (usb_pipein (pipe)) urb->transfer_flags |= URB_SHORT_NOT_OK; urb->transfer_buffer = usb_buffer_alloc (udev, bytes, SLAB_KERNEL, diff -Nru a/include/linux/usb.h b/include/linux/usb.h --- a/include/linux/usb.h Wed Jun 18 11:16:00 2003 +++ b/include/linux/usb.h Wed Jun 18 11:16:00 2003 @@ -492,8 +492,9 @@ */ #define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */ #define URB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame ignored */ -#define URB_NO_DMA_MAP 0x0004 /* urb->*_dma are valid on submit */ -#define URB_ASYNC_UNLINK 0x0008 /* usb_unlink_urb() returns asap */ +#define URB_NO_TRANSFER_DMA_MAP 0x0004 /* urb->transfer_dma valid on submit */ +#define URB_NO_SETUP_DMA_MAP 0x0008 /* urb->setup_dma valid on submit */ +#define URB_ASYNC_UNLINK 0x0010 /* usb_unlink_urb() returns asap */ #define URB_NO_FSBR 0x0020 /* UHCI-specific */ #define URB_ZERO_PACKET 0x0040 /* Finish bulk OUTs with short packet */ #define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */ @@ -531,14 +532,15 @@ * submission, unlinking, or operation are handled. Different * kinds of URB can use different flags. * @transfer_buffer: This identifies the buffer to (or from) which - * the I/O request will be performed (unless URB_NO_DMA_MAP is set). - * This buffer must be suitable for DMA; allocate it with kmalloc() - * or equivalent. For transfers to "in" endpoints, contents of - * this buffer will be modified. This buffer is used for data + * the I/O request will be performed (unless URB_NO_TRANSFER_DMA_MAP + * is set). This buffer must be suitable for DMA; allocate it with + * kmalloc() or equivalent. For transfers to "in" endpoints, contents + * of this buffer will be modified. This buffer is used for data * phases of control transfers. - * @transfer_dma: When transfer_flags includes URB_NO_DMA_MAP, the device - * driver is saying that it provided this DMA address, which the host - * controller driver should use instead of the transfer_buffer. + * @transfer_dma: When transfer_flags includes URB_NO_TRANSFER_DMA_MAP, + * the device driver is saying that it provided this DMA address, + * which the host controller driver should use in preference to the + * transfer_buffer. * @transfer_buffer_length: How big is transfer_buffer. The transfer may * be broken up into chunks according to the current maximum packet * size for the endpoint, which is a function of the configuration @@ -553,11 +555,10 @@ * @setup_packet: Only used for control transfers, this points to eight bytes * of setup data. Control transfers always start by sending this data * to the device. Then transfer_buffer is read or written, if needed. - * (Not used when URB_NO_DMA_MAP is set.) - * @setup_dma: For control transfers with URB_NO_DMA_MAP set, the device - * driver has provided this DMA address for the setup packet. The - * host controller driver should use this instead of setup_buffer. - * If there is a data phase, its buffer is identified by transfer_dma. + * @setup_dma: For control transfers with URB_NO_SETUP_DMA_MAP set, the + * device driver has provided this DMA address for the setup packet. + * The host controller driver should use this in preference to + * setup_packet. * @start_frame: Returns the initial frame for interrupt or isochronous * transfers. * @number_of_packets: Lists the number of ISO transfer buffers. @@ -589,13 +590,15 @@ * bounce buffer or talking to an IOMMU), * although they're cheap on commodity x86 and ppc hardware. * - * Alternatively, drivers may pass the URB_NO_DMA_MAP transfer flag, which - * tells the host controller driver that no such mapping is needed since - * the device driver is DMA-aware. For example, they might allocate a DMA - * buffer with usb_buffer_alloc(), or call usb_buffer_map(). - * When this transfer flag is provided, host controller drivers will use the - * dma addresses found in the transfer_dma and/or setup_dma fields rather than - * determing a dma address themselves. + * Alternatively, drivers may pass the URB_NO_xxx_DMA_MAP transfer flags, + * which tell the host controller driver that no such mapping is needed since + * the device driver is DMA-aware. For example, a device driver might + * allocate a DMA buffer with usb_buffer_alloc() or call usb_buffer_map(). + * When these transfer flags are provided, host controller drivers will + * attempt to use the dma addresses found in the transfer_dma and/or + * setup_dma fields rather than determining a dma address themselves. (Note + * that transfer_buffer and setup_packet must still be set because not all + * host controllers use DMA, nor do virtual root hubs). * * Initialization: * @@ -614,7 +617,11 @@ * should always terminate with a short packet, even if it means adding an * extra zero length packet. * - * Control URBs must provide a setup_packet. + * Control URBs must provide a setup_packet. The setup_packet and + * transfer_buffer may each be mapped for DMA or not, independently of + * the other. The transfer_flags bits URB_NO_TRANSFER_DMA_MAP and + * URB_NO_SETUP_DMA_MAP indicate which buffers have already been mapped. + * URB_NO_SETUP_DMA_MAP is ignored for non-control URBs. * * Interrupt UBS must provide an interval, saying how often (in milliseconds * or, for highspeed devices, 125 microsecond units)