diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 12:09:47 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 12:09:47 -0800 | 
| commit | 55b81e6f2795484ea8edf5805c95c007cacfa736 (patch) | |
| tree | c3724975107857fcc03b5dd649c462e4f72397be /drivers/usb/serial/generic.c | |
| parent | 5983faf942f260023e547f3c5f38c1033c35cc9b (diff) | |
| parent | 08e87d0d773dc9ca5faf4c3306e238ed0ea129b0 (diff) | |
| download | olio-linux-3.10-55b81e6f2795484ea8edf5805c95c007cacfa736.tar.xz olio-linux-3.10-55b81e6f2795484ea8edf5805c95c007cacfa736.zip  | |
Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (232 commits)
  USB: Add USB-ID for Multiplex RC serial adapter to cp210x.c
  xhci: Clean up 32-bit build warnings.
  USB: update documentation for usbmon
  usb: usb-storage doesn't support dynamic id currently, the patch disables the feature to fix an oops
  drivers/usb/class/cdc-acm.c: clear dangling pointer
  drivers/usb/dwc3/dwc3-pci.c: introduce missing kfree
  drivers/usb/host/isp1760-if.c: introduce missing kfree
  usb: option: add ZD Incorporated HSPA modem
  usb: ch9: fix up MaxStreams helper
  USB: usb-skeleton.c: cleanup open_count
  USB: usb-skeleton.c: fix open/disconnect race
  xhci: Properly handle COMP_2ND_BW_ERR
  USB: remove dead code from suspend/resume path
  USB: add quirk for another camera
  drivers: usb: wusbcore: Fix dependency for USB_WUSB
  xhci: Better debugging for critical host errors.
  xhci: Be less verbose during URB cancellation.
  xhci: Remove debugging about ring structure allocation.
  xhci: Remove debugging about toggling cycle bits.
  xhci: Remove debugging for individual transfers.
  ...
Diffstat (limited to 'drivers/usb/serial/generic.c')
| -rw-r--r-- | drivers/usb/serial/generic.c | 83 | 
1 files changed, 62 insertions, 21 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index e4db5ad2bc5..f7403576f99 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -1,7 +1,7 @@  /*   * USB Serial Converter Generic functions   * - * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com) + * Copyright (C) 2010 - 2011 Johan Hovold (jhovold@gmail.com)   * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)   *   *	This program is free software; you can redistribute it and/or @@ -132,7 +132,7 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port  	/* if we have a bulk endpoint, start reading from it */  	if (port->bulk_in_size) -		result = usb_serial_generic_submit_read_urb(port, GFP_KERNEL); +		result = usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);  	return result;  } @@ -157,8 +157,10 @@ static void generic_cleanup(struct usb_serial_port *port)  			kfifo_reset_out(&port->write_fifo);  			spin_unlock_irqrestore(&port->lock, flags);  		} -		if (port->bulk_in_size) -			usb_kill_urb(port->read_urb); +		if (port->bulk_in_size) { +			for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) +				usb_kill_urb(port->read_urbs[i]); +		}  	}  } @@ -308,19 +310,52 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)  	return chars;  } -int usb_serial_generic_submit_read_urb(struct usb_serial_port *port, +static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port, +						int index, gfp_t mem_flags) +{ +	int res; + +	if (!test_and_clear_bit(index, &port->read_urbs_free)) +		return 0; + +	dbg("%s - port %d, urb %d\n", __func__, port->number, index); + +	res = usb_submit_urb(port->read_urbs[index], mem_flags); +	if (res) { +		if (res != -EPERM) { +			dev_err(&port->dev, +					"%s - usb_submit_urb failed: %d\n", +					__func__, res); +		} +		set_bit(index, &port->read_urbs_free); +		return res; +	} + +	return 0; +} + +int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port,  					gfp_t mem_flags)  { -	int result; +	int res; +	int i; -	result = usb_submit_urb(port->read_urb, mem_flags); -	if (result && result != -EPERM) { -		dev_err(&port->dev, "%s - error submitting urb: %d\n", -							__func__, result); +	dbg("%s - port %d", __func__, port->number); + +	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) { +		res = usb_serial_generic_submit_read_urb(port, i, mem_flags); +		if (res) +			goto err;  	} -	return result; + +	return 0; +err: +	for (; i >= 0; --i) +		usb_kill_urb(port->read_urbs[i]); + +	return res;  } -EXPORT_SYMBOL_GPL(usb_serial_generic_submit_read_urb); +EXPORT_SYMBOL_GPL(usb_serial_generic_submit_read_urbs);  void usb_serial_generic_process_read_urb(struct urb *urb)  { @@ -356,14 +391,19 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)  {  	struct usb_serial_port *port = urb->context;  	unsigned char *data = urb->transfer_buffer; -	int status = urb->status;  	unsigned long flags; +	int i; -	dbg("%s - port %d", __func__, port->number); +	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) { +		if (urb == port->read_urbs[i]) +			break; +	} +	set_bit(i, &port->read_urbs_free); -	if (unlikely(status != 0)) { -		dbg("%s - nonzero read bulk status received: %d", -		    __func__, status); +	dbg("%s - port %d, urb %d, len %d\n", __func__, port->number, i, +							urb->actual_length); +	if (urb->status) { +		dbg("%s - non-zero urb status: %d\n", __func__, urb->status);  		return;  	} @@ -376,7 +416,7 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)  	port->throttled = port->throttle_req;  	if (!port->throttled) {  		spin_unlock_irqrestore(&port->lock, flags); -		usb_serial_generic_submit_read_urb(port, GFP_ATOMIC); +		usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC);  	} else  		spin_unlock_irqrestore(&port->lock, flags);  } @@ -443,7 +483,7 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)  	spin_unlock_irq(&port->lock);  	if (was_throttled) -		usb_serial_generic_submit_read_urb(port, GFP_KERNEL); +		usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);  }  EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle); @@ -509,8 +549,9 @@ int usb_serial_generic_resume(struct usb_serial *serial)  		if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))  			continue; -		if (port->read_urb) { -			r = usb_submit_urb(port->read_urb, GFP_NOIO); +		if (port->bulk_in_size) { +			r = usb_serial_generic_submit_read_urbs(port, +								GFP_NOIO);  			if (r < 0)  				c++;  		}  |