Commit b375a049 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

[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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent a4e62832
Loading
Loading
Loading
Loading
+4 −4
Original line number Original line Diff line number Diff line
@@ -1010,7 +1010,7 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
	sc->last_pipe = sc->send_bulk_pipe;
	sc->last_pipe = sc->send_bulk_pipe;
	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
	    bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
	    bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
	sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
	sc->work_urb.transfer_flags = 0;


	/* Fill what we shouldn't be filling, because usb-storage did so. */
	/* Fill what we shouldn't be filling, because usb-storage did so. */
	sc->work_urb.actual_length = 0;
	sc->work_urb.actual_length = 0;
@@ -1395,7 +1395,7 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
	usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
	usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
	    page_address(sg->page) + sg->offset, sg->length,
	    page_address(sg->page) + sg->offset, sg->length,
	    ub_urb_complete, sc);
	    ub_urb_complete, sc);
	sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
	sc->work_urb.transfer_flags = 0;
	sc->work_urb.actual_length = 0;
	sc->work_urb.actual_length = 0;
	sc->work_urb.error_count = 0;
	sc->work_urb.error_count = 0;
	sc->work_urb.status = 0;
	sc->work_urb.status = 0;
@@ -1442,7 +1442,7 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
	sc->last_pipe = sc->recv_bulk_pipe;
	sc->last_pipe = sc->recv_bulk_pipe;
	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
	    &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
	    &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
	sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
	sc->work_urb.transfer_flags = 0;
	sc->work_urb.actual_length = 0;
	sc->work_urb.actual_length = 0;
	sc->work_urb.error_count = 0;
	sc->work_urb.error_count = 0;
	sc->work_urb.status = 0;
	sc->work_urb.status = 0;
@@ -1563,7 +1563,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,


	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
	    (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
	    (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
	sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
	sc->work_urb.transfer_flags = 0;
	sc->work_urb.actual_length = 0;
	sc->work_urb.actual_length = 0;
	sc->work_urb.error_count = 0;
	sc->work_urb.error_count = 0;
	sc->work_urb.status = 0;
	sc->work_urb.status = 0;
+2 −11
Original line number Original line Diff line number Diff line
@@ -267,7 +267,7 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
                      frame, IRDA_USB_SPEED_MTU,
                      frame, IRDA_USB_SPEED_MTU,
                      speed_bulk_callback, self);
                      speed_bulk_callback, self);
	urb->transfer_buffer_length = USB_IRDA_HEADER;
	urb->transfer_buffer_length = USB_IRDA_HEADER;
	urb->transfer_flags = URB_ASYNC_UNLINK;
	urb->transfer_flags = 0;


	/* Irq disabled -> GFP_ATOMIC */
	/* Irq disabled -> GFP_ATOMIC */
	if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) {
	if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) {
@@ -401,15 +401,12 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
                      skb->data, IRDA_SKB_MAX_MTU,
                      skb->data, IRDA_SKB_MAX_MTU,
                      write_bulk_callback, skb);
                      write_bulk_callback, skb);
	urb->transfer_buffer_length = skb->len;
	urb->transfer_buffer_length = skb->len;
	/* Note : unlink *must* be Asynchronous because of the code in 
	 * irda_usb_net_timeout() -> call in irq - Jean II */
	urb->transfer_flags = URB_ASYNC_UNLINK;
	/* This flag (URB_ZERO_PACKET) indicates that what we send is not
	/* This flag (URB_ZERO_PACKET) indicates that what we send is not
	 * a continuous stream of data but separate packets.
	 * a continuous stream of data but separate packets.
	 * In this case, the USB layer will insert an empty USB frame (TD)
	 * In this case, the USB layer will insert an empty USB frame (TD)
	 * after each of our packets that is exact multiple of the frame size.
	 * after each of our packets that is exact multiple of the frame size.
	 * This is how the dongle will detect the end of packet - Jean II */
	 * This is how the dongle will detect the end of packet - Jean II */
	urb->transfer_flags |= URB_ZERO_PACKET;
	urb->transfer_flags = URB_ZERO_PACKET;


	/* Generate min turn time. FIXME: can we do better than this? */
	/* Generate min turn time. FIXME: can we do better than this? */
	/* Trying to a turnaround time at this level is trying to measure
	/* Trying to a turnaround time at this level is trying to measure
@@ -630,8 +627,6 @@ static void irda_usb_net_timeout(struct net_device *netdev)
			 * in completion handler, because urb->status will
			 * in completion handler, because urb->status will
			 * be -ENOENT. We will fix that at the next watchdog,
			 * be -ENOENT. We will fix that at the next watchdog,
			 * leaving more time to USB to recover...
			 * leaving more time to USB to recover...
			 * Also, we are in interrupt, so we need to have
			 * URB_ASYNC_UNLINK to work properly...
			 * Jean II */
			 * Jean II */
			done = 1;
			done = 1;
			break;
			break;
@@ -1008,9 +1003,7 @@ static int irda_usb_net_close(struct net_device *netdev)
		}
		}
	}
	}
	/* Cancel Tx and speed URB - need to be synchronous to avoid races */
	/* Cancel Tx and speed URB - need to be synchronous to avoid races */
	self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
	usb_kill_urb(self->tx_urb);
	usb_kill_urb(self->tx_urb);
	self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
	usb_kill_urb(self->speed_urb);
	usb_kill_urb(self->speed_urb);


	/* Stop and remove instance of IrLAP */
	/* Stop and remove instance of IrLAP */
@@ -1521,9 +1514,7 @@ static void irda_usb_disconnect(struct usb_interface *intf)
			usb_kill_urb(self->rx_urb[i]);
			usb_kill_urb(self->rx_urb[i]);
		/* Cancel Tx and speed URB.
		/* Cancel Tx and speed URB.
		 * Toggle flags to make sure it's synchronous. */
		 * Toggle flags to make sure it's synchronous. */
		self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
		usb_kill_urb(self->tx_urb);
		usb_kill_urb(self->tx_urb);
		self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
		usb_kill_urb(self->speed_urb);
		usb_kill_urb(self->speed_urb);
	}
	}


+0 −2
Original line number Original line Diff line number Diff line
@@ -715,13 +715,11 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
			usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
			usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
			instance->rcv_buf, PAGE_SIZE,
			instance->rcv_buf, PAGE_SIZE,
			cxacru_blocking_completion, &instance->rcv_done, 1);
			cxacru_blocking_completion, &instance->rcv_done, 1);
	instance->rcv_urb->transfer_flags |= URB_ASYNC_UNLINK;


	usb_fill_int_urb(instance->snd_urb,
	usb_fill_int_urb(instance->snd_urb,
			usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD),
			usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD),
			instance->snd_buf, PAGE_SIZE,
			instance->snd_buf, PAGE_SIZE,
			cxacru_blocking_completion, &instance->snd_done, 4);
			cxacru_blocking_completion, &instance->snd_done, 4);
	instance->snd_urb->transfer_flags |= URB_ASYNC_UNLINK;


	init_MUTEX(&instance->cm_serialize);
	init_MUTEX(&instance->cm_serialize);


+1 −3
Original line number Original line Diff line number Diff line
@@ -48,7 +48,6 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)


	init_completion(&done); 	
	init_completion(&done); 	
	urb->context = &done;
	urb->context = &done;
	urb->transfer_flags |= URB_ASYNC_UNLINK;
	urb->actual_length = 0;
	urb->actual_length = 0;
	status = usb_submit_urb(urb, GFP_NOIO);
	status = usb_submit_urb(urb, GFP_NOIO);


@@ -357,8 +356,7 @@ int usb_sg_init (
	if (!io->urbs)
	if (!io->urbs)
		goto nomem;
		goto nomem;


	urb_flags = URB_ASYNC_UNLINK | URB_NO_TRANSFER_DMA_MAP
	urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
			| URB_NO_INTERRUPT;
	if (usb_pipein (pipe))
	if (usb_pipein (pipe))
		urb_flags |= URB_SHORT_NOT_OK;
		urb_flags |= URB_SHORT_NOT_OK;


+4 −22
Original line number Original line Diff line number Diff line
@@ -309,9 +309,8 @@ int usb_submit_urb(struct urb *urb, unsigned mem_flags)
	unsigned int	allowed;
	unsigned int	allowed;


	/* enforce simple/standard policy */
	/* 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_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
			URB_NO_INTERRUPT);
	allowed |= URB_NO_INTERRUPT;
	switch (temp) {
	switch (temp) {
	case PIPE_BULK:
	case PIPE_BULK:
		if (is_out)
		if (is_out)
@@ -400,14 +399,8 @@ int usb_submit_urb(struct urb *urb, unsigned mem_flags)
 * canceled (rather than any other code) and will quickly be removed
 * canceled (rather than any other code) and will quickly be removed
 * from host controller data structures.
 * from host controller data structures.
 *
 *
 * In the past, clearing the URB_ASYNC_UNLINK transfer flag for the
 * This request is always asynchronous.
 * URB indicated that the request was synchronous.  This usage is now
 * Success is indicated by returning -EINPROGRESS,
 * 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,
 * at which time the URB will normally have been unlinked but not yet
 * 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
 * given back to the device driver.  When it is called, the completion
 * function will see urb->status == -ECONNRESET.  Failure is indicated
 * function will see urb->status == -ECONNRESET.  Failure is indicated
@@ -453,17 +446,6 @@ int usb_unlink_urb(struct urb *urb)
{
{
	if (!urb)
	if (!urb)
		return -EINVAL;
		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))
	if (!(urb->dev && urb->dev->bus && urb->dev->bus->op))
		return -ENODEV;
		return -ENODEV;
	return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET);
	return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET);
Loading