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)
