USB: serial: add generic wait_until_sent implementation
Add generic wait_until_sent implementation which polls for empty hardware buffers using the new port-operation tx_empty. The generic implementation will be used for all sub-drivers that implement tx_empty but does not define wait_until_sent. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
					parent
					
						
							
								0693196fe7
							
						
					
				
			
			
				commit
				
					
						dcf0105039
					
				
			
		
					 3 changed files with 36 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -253,6 +253,37 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(usb_serial_generic_chars_in_buffer);
 | 
			
		||||
 | 
			
		||||
void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout)
 | 
			
		||||
{
 | 
			
		||||
	struct usb_serial_port *port = tty->driver_data;
 | 
			
		||||
	unsigned int bps;
 | 
			
		||||
	unsigned long period;
 | 
			
		||||
	unsigned long expire;
 | 
			
		||||
 | 
			
		||||
	bps = tty_get_baud_rate(tty);
 | 
			
		||||
	if (!bps)
 | 
			
		||||
		bps = 9600;	/* B0 */
 | 
			
		||||
	/*
 | 
			
		||||
	 * Use a poll-period of roughly the time it takes to send one
 | 
			
		||||
	 * character or at least one jiffy.
 | 
			
		||||
	 */
 | 
			
		||||
	period = max_t(unsigned long, (10 * HZ / bps), 1);
 | 
			
		||||
	period = min_t(unsigned long, period, timeout);
 | 
			
		||||
 | 
			
		||||
	dev_dbg(&port->dev, "%s - timeout = %u ms, period = %u ms\n",
 | 
			
		||||
					__func__, jiffies_to_msecs(timeout),
 | 
			
		||||
					jiffies_to_msecs(period));
 | 
			
		||||
	expire = jiffies + timeout;
 | 
			
		||||
	while (!port->serial->type->tx_empty(port)) {
 | 
			
		||||
		schedule_timeout_interruptible(period);
 | 
			
		||||
		if (signal_pending(current))
 | 
			
		||||
			break;
 | 
			
		||||
		if (time_after(jiffies, expire))
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(usb_serial_generic_wait_until_sent);
 | 
			
		||||
 | 
			
		||||
static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
 | 
			
		||||
						int index, gfp_t mem_flags)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1333,6 +1333,8 @@ static void usb_serial_operations_init(struct usb_serial_driver *device)
 | 
			
		|||
	set_to_generic_if_null(device, close);
 | 
			
		||||
	set_to_generic_if_null(device, write_room);
 | 
			
		||||
	set_to_generic_if_null(device, chars_in_buffer);
 | 
			
		||||
	if (device->tx_empty)
 | 
			
		||||
		set_to_generic_if_null(device, wait_until_sent);
 | 
			
		||||
	set_to_generic_if_null(device, read_bulk_callback);
 | 
			
		||||
	set_to_generic_if_null(device, write_bulk_callback);
 | 
			
		||||
	set_to_generic_if_null(device, process_read_urb);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -269,6 +269,7 @@ struct usb_serial_driver {
 | 
			
		|||
	void (*break_ctl)(struct tty_struct *tty, int break_state);
 | 
			
		||||
	int  (*chars_in_buffer)(struct tty_struct *tty);
 | 
			
		||||
	void (*wait_until_sent)(struct tty_struct *tty, long timeout);
 | 
			
		||||
	bool (*tx_empty)(struct usb_serial_port *port);
 | 
			
		||||
	void (*throttle)(struct tty_struct *tty);
 | 
			
		||||
	void (*unthrottle)(struct tty_struct *tty);
 | 
			
		||||
	int  (*tiocmget)(struct tty_struct *tty);
 | 
			
		||||
| 
						 | 
				
			
			@ -328,6 +329,8 @@ extern void usb_serial_generic_close(struct usb_serial_port *port);
 | 
			
		|||
extern int usb_serial_generic_resume(struct usb_serial *serial);
 | 
			
		||||
extern int usb_serial_generic_write_room(struct tty_struct *tty);
 | 
			
		||||
extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);
 | 
			
		||||
extern void usb_serial_generic_wait_until_sent(struct tty_struct *tty,
 | 
			
		||||
								long timeout);
 | 
			
		||||
extern void usb_serial_generic_read_bulk_callback(struct urb *urb);
 | 
			
		||||
extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
 | 
			
		||||
extern void usb_serial_generic_throttle(struct tty_struct *tty);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue