[PATCH] USB: URB_ASYNC_UNLINK flag removed from the kernel

29 July 2005, Cambridge, MA:

This afternoon Alan Stern submitted a patch to remove the URB_ASYNC_UNLINK
flag from the Linux kernel.  Mr. Stern explained, "This flag is a relic
from an earlier, less-well-designed system.  For over a year it hasn't
been used for anything other than printing warning messages."

An anonymous spokesman for the Linux kernel development community
commented, "This is exactly the sort of thing we see happening all the
time.  As the kernel evolves, support for old techniques and old code can
be jettisoned and replaced by newer, better approaches.  Proprietary
operating systems do not have the freedom or flexibility to change so
quickly."

Mr. Stern, a staff member at Harvard University's Rowland Institute who
works on Linux only as a hobby, noted that the patch (labelled as548) did
not update two files, keyspan.c and option.c, in the USB drivers' "serial"
subdirectory.  "Those files need more extensive changes," he remarked.
"They examine the status field of several URBs at times when they're not
supposed to.  That will need to be fixed before the URB_ASYNC_UNLINK flag
is removed."

Greg Kroah-Hartman, the kernel maintainer responsible for overseeing all
of Linux's USB drivers, did not respond to our inquiries or return our
calls.  His only comment was "Applied, thanks."

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 8e184e2..79861ee 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -715,13 +715,11 @@
 			usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
 			instance->rcv_buf, PAGE_SIZE,
 			cxacru_blocking_completion, &instance->rcv_done, 1);
-	instance->rcv_urb->transfer_flags |= URB_ASYNC_UNLINK;
 
 	usb_fill_int_urb(instance->snd_urb,
 			usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD),
 			instance->snd_buf, PAGE_SIZE,
 			cxacru_blocking_completion, &instance->snd_done, 4);
-	instance->snd_urb->transfer_flags |= URB_ASYNC_UNLINK;
 
 	init_MUTEX(&instance->cm_serialize);
 
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 88d1b37..7419724 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -48,7 +48,6 @@
 
 	init_completion(&done); 	
 	urb->context = &done;
-	urb->transfer_flags |= URB_ASYNC_UNLINK;
 	urb->actual_length = 0;
 	status = usb_submit_urb(urb, GFP_NOIO);
 
@@ -357,8 +356,7 @@
 	if (!io->urbs)
 		goto nomem;
 
-	urb_flags = URB_ASYNC_UNLINK | URB_NO_TRANSFER_DMA_MAP
-			| URB_NO_INTERRUPT;
+	urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
 	if (usb_pipein (pipe))
 		urb_flags |= URB_SHORT_NOT_OK;
 
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index c0feee2..c846fef 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -309,9 +309,8 @@
 	unsigned int	allowed;
 
 	/* enforce simple/standard policy */
-	allowed = URB_ASYNC_UNLINK;	// affects later unlinks
-	allowed |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
-	allowed |= URB_NO_INTERRUPT;
+	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
+			URB_NO_INTERRUPT);
 	switch (temp) {
 	case PIPE_BULK:
 		if (is_out)
@@ -400,14 +399,8 @@
  * canceled (rather than any other code) and will quickly be removed
  * from host controller data structures.
  *
- * In the past, clearing the URB_ASYNC_UNLINK transfer flag for the
- * URB indicated that the request was synchronous.  This usage is now
- * deprecated; if the flag is clear the call will be forwarded to
- * usb_kill_urb() and the return value will be 0.  In the future, drivers
- * should call usb_kill_urb() directly for synchronous unlinking.
- *
- * When the URB_ASYNC_UNLINK transfer flag for the URB is set, this
- * request is asynchronous.  Success is indicated by returning -EINPROGRESS,
+ * This request is always asynchronous.
+ * Success is indicated by returning -EINPROGRESS,
  * at which time the URB will normally have been unlinked but not yet
  * given back to the device driver.  When it is called, the completion
  * function will see urb->status == -ECONNRESET.  Failure is indicated
@@ -453,17 +446,6 @@
 {
 	if (!urb)
 		return -EINVAL;
-	if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) {
-#ifdef CONFIG_DEBUG_KERNEL
-		if (printk_ratelimit()) {
-			printk(KERN_NOTICE "usb_unlink_urb() is deprecated for "
-				"synchronous unlinks.  Use usb_kill_urb() instead.\n");
-			WARN_ON(1);
-		}
-#endif
-		usb_kill_urb(urb);
-		return 0;
-	}
 	if (!(urb->dev && urb->dev->bus && urb->dev->bus->op))
 		return -ENODEV;
 	return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET);
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 719c031..1ab95d2 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1688,7 +1688,7 @@
 			usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0,
 					 hid_irq_in, hid, interval);
 			hid->urbin->transfer_dma = hid->inbuf_dma;
-			hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
+			hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 		} else {
 			if (hid->urbout)
 				continue;
@@ -1698,7 +1698,7 @@
 			usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
 					 hid_irq_out, hid, interval);
 			hid->urbout->transfer_dma = hid->outbuf_dma;
-			hid->urbout->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
+			hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 		}
 	}
 
@@ -1750,7 +1750,7 @@
 			     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_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | URB_ASYNC_UNLINK);
+	hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
 
 	return hid;
 
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 6f7994f..ae4681f 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -426,7 +426,7 @@
 
 /* cancel an urb which is submitted to the chain
    the result is 0 if the urb is cancelled, or -EINPROGRESS if
-   URB_ASYNC_UNLINK is set and the function is successfully started.
+   the function is successfully started.
 */
 static int auerchain_unlink_urb (pauerchain_t acp, struct urb * urb)
 {
@@ -515,7 +515,6 @@
         acep = acp->active;
         if (acep) {
                 urbp = acep->urbp;
-                urbp->transfer_flags &= ~URB_ASYNC_UNLINK;
                 dbg ("unlink active urb");
                 usb_kill_urb (urbp);
         }
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 2fd1226..d63ce6c 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -229,7 +229,7 @@
 	usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
 		sisusb_bulk_completeout, &sisusb->urbout_context[index]);
 
-	urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
+	urb->transfer_flags |= tflags;
 	urb->actual_length = 0;
 
 	if ((urb->transfer_dma = transfer_dma))
@@ -295,7 +295,7 @@
 	usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
 			sisusb_bulk_completein, sisusb);
 
-	urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
+	urb->transfer_flags |= tflags;
 	urb->actual_length = 0;
 
 	if ((urb->transfer_dma = transfer_dma))
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index fd7fb98..54799eb 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -986,7 +986,6 @@
 
 		u->context = &context;
 		u->complete = ctrl_complete;
-		u->transfer_flags |= URB_ASYNC_UNLINK;
 	}
 
 	/* queue the urbs */
@@ -1052,7 +1051,6 @@
 	urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size);
 	if (!urb)
 		return -ENOMEM;
-	urb->transfer_flags |= URB_ASYNC_UNLINK;
 	urb->context = &completion;
 	urb->complete = unlink1_callback;
 
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index c8be912..37ef365 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -383,7 +383,6 @@
 
 	if (urb->status == -ECONNRESET) {
 		dbg("Tx Reset.");
-		urb->transfer_flags &= ~URB_ASYNC_UNLINK;
 		urb->status = 0;
 		catc->netdev->trans_start = jiffies;
 		catc->stats.tx_errors++;
@@ -445,7 +444,6 @@
 	struct catc *catc = netdev_priv(netdev);
 
 	warn("Transmit timed out.");
-	catc->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
 	usb_unlink_urb(catc->tx_urb);
 }
 
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index 7ffa99b..e04b0ce 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -787,7 +787,6 @@
 		      kaweth_usb_transmit_complete,
 		      kaweth);
 	kaweth->end = 0;
-	kaweth->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
 
 	if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC)))
 	{
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index fcd6d3c..7484d34 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -825,7 +825,6 @@
 	pegasus_t *pegasus = netdev_priv(net);
 	if (netif_msg_timer(pegasus))
 		printk(KERN_WARNING "%s: tx timeout\n", net->name);
-	pegasus->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
 	usb_unlink_urb(pegasus->tx_urb);
 	pegasus->stats.tx_errors++;
 }
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index 59ab40e..c3d4e35 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -653,7 +653,6 @@
 {
 	rtl8150_t *dev = netdev_priv(netdev);
 	warn("%s: Tx timeout.", netdev->name);
-	dev->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
 	usb_unlink_urb(dev->tx_urb);
 	dev->stats.tx_errors++;
 }
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 4682696..3c6eef4 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -2987,7 +2987,6 @@
 
 	usb_fill_bulk_urb (urb, dev->udev, dev->in,
 		skb->data, size, rx_complete, skb);
-	urb->transfer_flags |= URB_ASYNC_UNLINK;
 
 	spin_lock_irqsave (&dev->rxq.lock, lockflags);
 
@@ -3561,7 +3560,6 @@
 
 	usb_fill_bulk_urb (urb, dev->udev, dev->out,
 			skb->data, skb->len, tx_complete, skb);
-	urb->transfer_flags |= URB_ASYNC_UNLINK;
 
 	/* don't assume the hardware handles USB_ZERO_PACKET
 	 * NOTE:  strictly conforming cdc-ether devices should expect
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
index fc01397..c4e479e 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/usb/net/zd1201.c
@@ -847,7 +847,6 @@
 		return;
 	dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n",
 	    dev->name);
-	zd->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
 	usb_unlink_urb(zd->tx_urb);
 	zd->stats.tx_errors++;
 	/* Restart the timeout to quiet the watchdog: */
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index e428751..c1ba530 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -96,8 +96,8 @@
  * or before the URB_ACTIVE bit was set.  If so, it's essential to cancel
  * the URB if it hasn't been cancelled already (i.e., if the URB_ACTIVE bit
  * is still set).  Either way, the function must then wait for the URB to
- * finish.  Note that because the URB_ASYNC_UNLINK flag is set, the URB can
- * still be in progress even after a call to usb_unlink_urb() returns.
+ * finish.  Note that the URB can still be in progress even after a call to
+ * usb_unlink_urb() returns.
  *
  * The idea is that (1) once the ABORTING or DISCONNECTING bit is set,
  * either the stop_transport() function or the submitting function
@@ -158,8 +158,7 @@
 	 * hasn't been mapped for DMA.  Yes, this is clunky, but it's
 	 * easier than always having the caller tell us whether the
 	 * transfer buffer has already been mapped. */
-	us->current_urb->transfer_flags =
-			URB_ASYNC_UNLINK | URB_NO_SETUP_DMA_MAP;
+	us->current_urb->transfer_flags = URB_NO_SETUP_DMA_MAP;
 	if (us->current_urb->transfer_buffer == us->iobuf)
 		us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	us->current_urb->transfer_dma = us->iobuf_dma;