Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bbcb2b90 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman
Browse files

USB: serial: allow drivers to define bulk buffer sizes



Allow drivers to define custom bulk in/out buffer sizes in struct
usb_serial_driver. If not set, fall back to the default buffer size
which matches the endpoint size.

Three drivers are currently freeing the pre-allocated buffers and
allocating larger ones to achieve this at port probe (ftdi_sio) or even
at port open (ipaq and iuu_phoenix), which needless to say is suboptimal.

Signed-off-by: default avatarJohan Hovold <jhovold@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 317149c6
Loading
Loading
Loading
Loading
+1 −15
Original line number Diff line number Diff line
@@ -768,9 +768,6 @@ static const char *ftdi_chip_name[] = {
};


/* Constants for read urb and write urb */
#define BUFSZ 512

/* Used for TIOCMIWAIT */
#define FTDI_STATUS_B0_MASK	(FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
#define FTDI_STATUS_B1_MASK	(FTDI_RS_BI)
@@ -821,6 +818,7 @@ static struct usb_serial_driver ftdi_sio_device = {
	.usb_driver = 		&ftdi_driver,
	.id_table =		id_table_combined,
	.num_ports =		1,
	.bulk_in_size =		512,
	.probe =		ftdi_sio_probe,
	.port_probe =		ftdi_sio_port_probe,
	.port_remove =		ftdi_sio_port_remove,
@@ -1552,18 +1550,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
	if (quirk && quirk->port_probe)
		quirk->port_probe(priv);

	/* Increase the size of read buffers */
	kfree(port->bulk_in_buffer);
	port->bulk_in_buffer = kmalloc(BUFSZ, GFP_KERNEL);
	if (!port->bulk_in_buffer) {
		kfree(priv);
		return -ENOMEM;
	}
	if (port->read_urb) {
		port->read_urb->transfer_buffer = port->bulk_in_buffer;
		port->read_urb->transfer_buffer_length = BUFSZ;
	}

	priv->port = port;

	/* Free port's existing write urb and transfer buffer. */
+2 −26
Original line number Diff line number Diff line
@@ -571,6 +571,8 @@ static struct usb_serial_driver ipaq_device = {
	.description =		"PocketPC PDA",
	.usb_driver = 		&ipaq_driver,
	.id_table =		ipaq_id_table,
	.bulk_in_size =		URBDATA_SIZE,
	.bulk_out_size =	URBDATA_SIZE,
	.open =			ipaq_open,
	.close =		ipaq_close,
	.attach =		ipaq_startup,
@@ -628,32 +630,6 @@ static int ipaq_open(struct tty_struct *tty,
		priv->free_len += PACKET_SIZE;
	}

	/*
	 * Lose the small buffers usbserial provides. Make larger ones.
	 */

	kfree(port->bulk_in_buffer);
	kfree(port->bulk_out_buffer);
	/* make sure the generic serial code knows */
	port->bulk_out_buffer = NULL;

	port->bulk_in_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
	if (port->bulk_in_buffer == NULL)
		goto enomem;

	port->bulk_out_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
	if (port->bulk_out_buffer == NULL) {
		/* the buffer is useless, free it */
		kfree(port->bulk_in_buffer);
		port->bulk_in_buffer = NULL;
		goto enomem;
	}
	port->read_urb->transfer_buffer = port->bulk_in_buffer;
	port->write_urb->transfer_buffer = port->bulk_out_buffer;
	port->read_urb->transfer_buffer_length = URBDATA_SIZE;
	port->bulk_out_size = port->write_urb->transfer_buffer_length
							= URBDATA_SIZE;

	msleep(1000*initial_wait);

	/*
+2 −28
Original line number Diff line number Diff line
@@ -1044,34 +1044,6 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
	if (buf == NULL)
		return -ENOMEM;

	/* fixup the endpoint buffer size */
	kfree(port->bulk_out_buffer);
	port->bulk_out_buffer = kmalloc(512, GFP_KERNEL);
	port->bulk_out_size = 512;
	kfree(port->bulk_in_buffer);
	port->bulk_in_buffer = kmalloc(512, GFP_KERNEL);
	port->bulk_in_size = 512;

	if (!port->bulk_out_buffer || !port->bulk_in_buffer) {
		kfree(port->bulk_out_buffer);
		kfree(port->bulk_in_buffer);
		kfree(buf);
		return -ENOMEM;
	}

	usb_fill_bulk_urb(port->write_urb, port->serial->dev,
			  usb_sndbulkpipe(port->serial->dev,
					  port->bulk_out_endpointAddress),
			  port->bulk_out_buffer, 512,
			  NULL, NULL);


	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
			  usb_rcvbulkpipe(port->serial->dev,
					  port->bulk_in_endpointAddress),
			  port->bulk_in_buffer, 512,
			  NULL, NULL);

	priv->poll = 0;

	/* initialize writebuf */
@@ -1277,6 +1249,8 @@ static struct usb_serial_driver iuu_device = {
		   },
	.id_table = id_table,
	.num_ports = 1,
	.bulk_in_size = 512,
	.bulk_out_size = 512,
	.port_probe = iuu_create_sysfs_attrs,
	.port_remove = iuu_remove_sysfs_attrs,
	.open = iuu_open,
+6 −2
Original line number Diff line number Diff line
@@ -901,6 +901,8 @@ int usb_serial_probe(struct usb_interface *interface,
			dev_err(&interface->dev, "No free urbs available\n");
			goto probe_error;
		}
		buffer_size = serial->type->bulk_in_size;
		if (!buffer_size)
			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
		port->bulk_in_size = buffer_size;
		port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
@@ -927,6 +929,8 @@ int usb_serial_probe(struct usb_interface *interface,
		}
		if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
			goto probe_error;
		buffer_size = serial->type->bulk_out_size;
		if (!buffer_size)
			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
		port->bulk_out_size = buffer_size;
		port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
+5 −0
Original line number Diff line number Diff line
@@ -179,6 +179,8 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
 * @id_table: pointer to a list of usb_device_id structures that define all
 *	of the devices this structure can support.
 * @num_ports: the number of different ports this device will have.
 * @bulk_in_size: bytes to allocate for bulk-in buffer (0 = end-point size)
 * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size)
 * @calc_num_ports: pointer to a function to determine how many ports this
 *	device has dynamically.  It will be called after the probe()
 *	callback is called, but before attach()
@@ -223,6 +225,9 @@ struct usb_serial_driver {
	struct usb_dynids	dynids;
	int			max_in_flight_urbs;

	size_t			bulk_in_size;
	size_t			bulk_out_size;

	int (*probe)(struct usb_serial *serial, const struct usb_device_id *id);
	int (*attach)(struct usb_serial *serial);
	int (*calc_num_ports) (struct usb_serial *serial);