Browse Source

Merge tag 'usb-serial-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next

Johan writes:

USB-serial updates for v4.13-rc1

Here are the USB-serial updates for 4.13, including support for
manipulating the modem-control signals of qcserial devices, propagation
of errnos after late probe errors from usb-serial core, and a couple of
clean ups.

All have been in linux-next with no reported issues.

Signed-off-by: Johan Hovold <johan@kernel.org>
Greg Kroah-Hartman 8 years ago
parent
commit
0e4b470c0a
3 changed files with 146 additions and 105 deletions
  1. 2 0
      drivers/usb/serial/qcserial.c
  2. 3 3
      drivers/usb/serial/upd78f0730.c
  3. 141 102
      drivers/usb/serial/usb-serial.c

+ 2 - 0
drivers/usb/serial/qcserial.c

@@ -454,6 +454,8 @@ static struct usb_serial_driver qcdevice = {
 	.write		     = usb_wwan_write,
 	.write		     = usb_wwan_write,
 	.write_room	     = usb_wwan_write_room,
 	.write_room	     = usb_wwan_write_room,
 	.chars_in_buffer     = usb_wwan_chars_in_buffer,
 	.chars_in_buffer     = usb_wwan_chars_in_buffer,
+	.tiocmget            = usb_wwan_tiocmget,
+	.tiocmset            = usb_wwan_tiocmset,
 	.attach              = qc_attach,
 	.attach              = qc_attach,
 	.release	     = qc_release,
 	.release	     = qc_release,
 	.port_probe          = usb_wwan_port_probe,
 	.port_probe          = usb_wwan_port_probe,

+ 3 - 3
drivers/usb/serial/upd78f0730.c

@@ -288,7 +288,7 @@ static void upd78f0730_dtr_rts(struct usb_serial_port *port, int on)
 static speed_t upd78f0730_get_baud_rate(struct tty_struct *tty)
 static speed_t upd78f0730_get_baud_rate(struct tty_struct *tty)
 {
 {
 	const speed_t baud_rate = tty_get_baud_rate(tty);
 	const speed_t baud_rate = tty_get_baud_rate(tty);
-	const speed_t supported[] = {
+	static const speed_t supported[] = {
 		0, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 153600
 		0, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 153600
 	};
 	};
 	int i;
 	int i;
@@ -384,7 +384,7 @@ static void upd78f0730_set_termios(struct tty_struct *tty,
 
 
 static int upd78f0730_open(struct tty_struct *tty, struct usb_serial_port *port)
 static int upd78f0730_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
 {
-	struct upd78f0730_open_close request = {
+	static const struct upd78f0730_open_close request = {
 		.opcode = UPD78F0730_CMD_OPEN_CLOSE,
 		.opcode = UPD78F0730_CMD_OPEN_CLOSE,
 		.state = UPD78F0730_PORT_OPEN
 		.state = UPD78F0730_PORT_OPEN
 	};
 	};
@@ -402,7 +402,7 @@ static int upd78f0730_open(struct tty_struct *tty, struct usb_serial_port *port)
 
 
 static void upd78f0730_close(struct usb_serial_port *port)
 static void upd78f0730_close(struct usb_serial_port *port)
 {
 {
-	struct upd78f0730_open_close request = {
+	static const struct upd78f0730_open_close request = {
 		.opcode = UPD78F0730_CMD_OPEN_CLOSE,
 		.opcode = UPD78F0730_CMD_OPEN_CLOSE,
 		.state = UPD78F0730_PORT_CLOSE
 		.state = UPD78F0730_PORT_CLOSE
 	};
 	};

+ 141 - 102
drivers/usb/serial/usb-serial.c

@@ -742,6 +742,124 @@ static void find_endpoints(struct usb_serial *serial,
 	}
 	}
 }
 }
 
 
+static int setup_port_bulk_in(struct usb_serial_port *port,
+					struct usb_endpoint_descriptor *epd)
+{
+	struct usb_serial_driver *type = port->serial->type;
+	struct usb_device *udev = port->serial->dev;
+	int buffer_size;
+	int i;
+
+	buffer_size = max_t(int, type->bulk_in_size, usb_endpoint_maxp(epd));
+	port->bulk_in_size = buffer_size;
+	port->bulk_in_endpointAddress = epd->bEndpointAddress;
+
+	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
+		set_bit(i, &port->read_urbs_free);
+		port->read_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+		if (!port->read_urbs[i])
+			return -ENOMEM;
+		port->bulk_in_buffers[i] = kmalloc(buffer_size, GFP_KERNEL);
+		if (!port->bulk_in_buffers[i])
+			return -ENOMEM;
+		usb_fill_bulk_urb(port->read_urbs[i], udev,
+				usb_rcvbulkpipe(udev, epd->bEndpointAddress),
+				port->bulk_in_buffers[i], buffer_size,
+				type->read_bulk_callback, port);
+	}
+
+	port->read_urb = port->read_urbs[0];
+	port->bulk_in_buffer = port->bulk_in_buffers[0];
+
+	return 0;
+}
+
+static int setup_port_bulk_out(struct usb_serial_port *port,
+					struct usb_endpoint_descriptor *epd)
+{
+	struct usb_serial_driver *type = port->serial->type;
+	struct usb_device *udev = port->serial->dev;
+	int buffer_size;
+	int i;
+
+	if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
+		return -ENOMEM;
+	if (type->bulk_out_size)
+		buffer_size = type->bulk_out_size;
+	else
+		buffer_size = usb_endpoint_maxp(epd);
+	port->bulk_out_size = buffer_size;
+	port->bulk_out_endpointAddress = epd->bEndpointAddress;
+
+	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) {
+		set_bit(i, &port->write_urbs_free);
+		port->write_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+		if (!port->write_urbs[i])
+			return -ENOMEM;
+		port->bulk_out_buffers[i] = kmalloc(buffer_size, GFP_KERNEL);
+		if (!port->bulk_out_buffers[i])
+			return -ENOMEM;
+		usb_fill_bulk_urb(port->write_urbs[i], udev,
+				usb_sndbulkpipe(udev, epd->bEndpointAddress),
+				port->bulk_out_buffers[i], buffer_size,
+				type->write_bulk_callback, port);
+	}
+
+	port->write_urb = port->write_urbs[0];
+	port->bulk_out_buffer = port->bulk_out_buffers[0];
+
+	return 0;
+}
+
+static int setup_port_interrupt_in(struct usb_serial_port *port,
+					struct usb_endpoint_descriptor *epd)
+{
+	struct usb_serial_driver *type = port->serial->type;
+	struct usb_device *udev = port->serial->dev;
+	int buffer_size;
+
+	port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!port->interrupt_in_urb)
+		return -ENOMEM;
+	buffer_size = usb_endpoint_maxp(epd);
+	port->interrupt_in_endpointAddress = epd->bEndpointAddress;
+	port->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+	if (!port->interrupt_in_buffer)
+		return -ENOMEM;
+	usb_fill_int_urb(port->interrupt_in_urb, udev,
+			usb_rcvintpipe(udev, epd->bEndpointAddress),
+			port->interrupt_in_buffer, buffer_size,
+			type->read_int_callback, port,
+			epd->bInterval);
+
+	return 0;
+}
+
+static int setup_port_interrupt_out(struct usb_serial_port *port,
+					struct usb_endpoint_descriptor *epd)
+{
+	struct usb_serial_driver *type = port->serial->type;
+	struct usb_device *udev = port->serial->dev;
+	int buffer_size;
+
+	port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!port->interrupt_out_urb)
+		return -ENOMEM;
+	buffer_size = usb_endpoint_maxp(epd);
+	port->interrupt_out_size = buffer_size;
+	port->interrupt_out_endpointAddress = epd->bEndpointAddress;
+	port->interrupt_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
+	if (!port->interrupt_out_buffer)
+		return -ENOMEM;
+	usb_fill_int_urb(port->interrupt_out_urb, udev,
+			usb_sndintpipe(udev, epd->bEndpointAddress),
+			port->interrupt_out_buffer, buffer_size,
+			type->write_int_callback, port,
+			epd->bInterval);
+
+	return 0;
+}
+
 static int usb_serial_probe(struct usb_interface *interface,
 static int usb_serial_probe(struct usb_interface *interface,
 			       const struct usb_device_id *id)
 			       const struct usb_device_id *id)
 {
 {
@@ -749,13 +867,10 @@ static int usb_serial_probe(struct usb_interface *interface,
 	struct usb_device *dev = interface_to_usbdev(interface);
 	struct usb_device *dev = interface_to_usbdev(interface);
 	struct usb_serial *serial = NULL;
 	struct usb_serial *serial = NULL;
 	struct usb_serial_port *port;
 	struct usb_serial_port *port;
-	struct usb_endpoint_descriptor *endpoint;
 	struct usb_serial_endpoints *epds;
 	struct usb_serial_endpoints *epds;
 	struct usb_serial_driver *type = NULL;
 	struct usb_serial_driver *type = NULL;
 	int retval;
 	int retval;
-	int buffer_size;
 	int i;
 	int i;
-	int j;
 	int num_ports = 0;
 	int num_ports = 0;
 	unsigned char max_endpoints;
 	unsigned char max_endpoints;
 
 
@@ -847,8 +962,10 @@ static int usb_serial_probe(struct usb_interface *interface,
 	dev_dbg(ddev, "setting up %d port structure(s)\n", max_endpoints);
 	dev_dbg(ddev, "setting up %d port structure(s)\n", max_endpoints);
 	for (i = 0; i < max_endpoints; ++i) {
 	for (i = 0; i < max_endpoints; ++i) {
 		port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
 		port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
-		if (!port)
-			goto probe_error;
+		if (!port) {
+			retval = -ENOMEM;
+			goto err_free_epds;
+		}
 		tty_port_init(&port->port);
 		tty_port_init(&port->port);
 		port->port.ops = &serial_port_ops;
 		port->port.ops = &serial_port_ops;
 		port->serial = serial;
 		port->serial = serial;
@@ -867,86 +984,24 @@ static int usb_serial_probe(struct usb_interface *interface,
 
 
 	/* set up the endpoint information */
 	/* set up the endpoint information */
 	for (i = 0; i < epds->num_bulk_in; ++i) {
 	for (i = 0; i < epds->num_bulk_in; ++i) {
-		endpoint = epds->bulk_in[i];
-		port = serial->port[i];
-		buffer_size = max_t(int, serial->type->bulk_in_size,
-				usb_endpoint_maxp(endpoint));
-		port->bulk_in_size = buffer_size;
-		port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
-
-		for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) {
-			set_bit(j, &port->read_urbs_free);
-			port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
-			if (!port->read_urbs[j])
-				goto probe_error;
-			port->bulk_in_buffers[j] = kmalloc(buffer_size,
-								GFP_KERNEL);
-			if (!port->bulk_in_buffers[j])
-				goto probe_error;
-			usb_fill_bulk_urb(port->read_urbs[j], dev,
-					usb_rcvbulkpipe(dev,
-						endpoint->bEndpointAddress),
-					port->bulk_in_buffers[j], buffer_size,
-					serial->type->read_bulk_callback,
-					port);
-		}
-
-		port->read_urb = port->read_urbs[0];
-		port->bulk_in_buffer = port->bulk_in_buffers[0];
+		retval = setup_port_bulk_in(serial->port[i], epds->bulk_in[i]);
+		if (retval)
+			goto err_free_epds;
 	}
 	}
 
 
 	for (i = 0; i < epds->num_bulk_out; ++i) {
 	for (i = 0; i < epds->num_bulk_out; ++i) {
-		endpoint = epds->bulk_out[i];
-		port = serial->port[i];
-		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 = usb_endpoint_maxp(endpoint);
-		port->bulk_out_size = buffer_size;
-		port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
-
-		for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
-			set_bit(j, &port->write_urbs_free);
-			port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
-			if (!port->write_urbs[j])
-				goto probe_error;
-			port->bulk_out_buffers[j] = kmalloc(buffer_size,
-								GFP_KERNEL);
-			if (!port->bulk_out_buffers[j])
-				goto probe_error;
-			usb_fill_bulk_urb(port->write_urbs[j], dev,
-					usb_sndbulkpipe(dev,
-						endpoint->bEndpointAddress),
-					port->bulk_out_buffers[j], buffer_size,
-					serial->type->write_bulk_callback,
-					port);
-		}
-
-		port->write_urb = port->write_urbs[0];
-		port->bulk_out_buffer = port->bulk_out_buffers[0];
+		retval = setup_port_bulk_out(serial->port[i],
+				epds->bulk_out[i]);
+		if (retval)
+			goto err_free_epds;
 	}
 	}
 
 
 	if (serial->type->read_int_callback) {
 	if (serial->type->read_int_callback) {
 		for (i = 0; i < epds->num_interrupt_in; ++i) {
 		for (i = 0; i < epds->num_interrupt_in; ++i) {
-			endpoint = epds->interrupt_in[i];
-			port = serial->port[i];
-			port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!port->interrupt_in_urb)
-				goto probe_error;
-			buffer_size = usb_endpoint_maxp(endpoint);
-			port->interrupt_in_endpointAddress =
-						endpoint->bEndpointAddress;
-			port->interrupt_in_buffer = kmalloc(buffer_size,
-								GFP_KERNEL);
-			if (!port->interrupt_in_buffer)
-				goto probe_error;
-			usb_fill_int_urb(port->interrupt_in_urb, dev,
-				usb_rcvintpipe(dev,
-						endpoint->bEndpointAddress),
-				port->interrupt_in_buffer, buffer_size,
-				serial->type->read_int_callback, port,
-				endpoint->bInterval);
+			retval = setup_port_interrupt_in(serial->port[i],
+					epds->interrupt_in[i]);
+			if (retval)
+				goto err_free_epds;
 		}
 		}
 	} else if (epds->num_interrupt_in) {
 	} else if (epds->num_interrupt_in) {
 		dev_dbg(ddev, "The device claims to support interrupt in transfers, but read_int_callback is not defined\n");
 		dev_dbg(ddev, "The device claims to support interrupt in transfers, but read_int_callback is not defined\n");
@@ -954,25 +1009,10 @@ static int usb_serial_probe(struct usb_interface *interface,
 
 
 	if (serial->type->write_int_callback) {
 	if (serial->type->write_int_callback) {
 		for (i = 0; i < epds->num_interrupt_out; ++i) {
 		for (i = 0; i < epds->num_interrupt_out; ++i) {
-			endpoint = epds->interrupt_out[i];
-			port = serial->port[i];
-			port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!port->interrupt_out_urb)
-				goto probe_error;
-			buffer_size = usb_endpoint_maxp(endpoint);
-			port->interrupt_out_size = buffer_size;
-			port->interrupt_out_endpointAddress =
-						endpoint->bEndpointAddress;
-			port->interrupt_out_buffer = kmalloc(buffer_size,
-								GFP_KERNEL);
-			if (!port->interrupt_out_buffer)
-				goto probe_error;
-			usb_fill_int_urb(port->interrupt_out_urb, dev,
-				usb_sndintpipe(dev,
-						  endpoint->bEndpointAddress),
-				port->interrupt_out_buffer, buffer_size,
-				serial->type->write_int_callback, port,
-				endpoint->bInterval);
+			retval = setup_port_interrupt_out(serial->port[i],
+					epds->interrupt_out[i]);
+			if (retval)
+				goto err_free_epds;
 		}
 		}
 	} else if (epds->num_interrupt_out) {
 	} else if (epds->num_interrupt_out) {
 		dev_dbg(ddev, "The device claims to support interrupt out transfers, but write_int_callback is not defined\n");
 		dev_dbg(ddev, "The device claims to support interrupt out transfers, but write_int_callback is not defined\n");
@@ -984,7 +1024,7 @@ static int usb_serial_probe(struct usb_interface *interface,
 	if (type->attach) {
 	if (type->attach) {
 		retval = type->attach(serial);
 		retval = type->attach(serial);
 		if (retval < 0)
 		if (retval < 0)
-			goto probe_error;
+			goto err_free_epds;
 		serial->attached = 1;
 		serial->attached = 1;
 		if (retval > 0) {
 		if (retval > 0) {
 			/* quietly accept this device, but don't bind to a
 			/* quietly accept this device, but don't bind to a
@@ -996,9 +1036,10 @@ static int usb_serial_probe(struct usb_interface *interface,
 		serial->attached = 1;
 		serial->attached = 1;
 	}
 	}
 
 
-	if (allocate_minors(serial, num_ports)) {
+	retval = allocate_minors(serial, num_ports);
+	if (retval) {
 		dev_err(ddev, "No more free serial minor numbers\n");
 		dev_err(ddev, "No more free serial minor numbers\n");
-		goto probe_error;
+		goto err_free_epds;
 	}
 	}
 
 
 	/* register all of the individual ports with the driver core */
 	/* register all of the individual ports with the driver core */
@@ -1020,8 +1061,6 @@ exit:
 	module_put(type->driver.owner);
 	module_put(type->driver.owner);
 	return 0;
 	return 0;
 
 
-probe_error:
-	retval = -EIO;
 err_free_epds:
 err_free_epds:
 	kfree(epds);
 	kfree(epds);
 err_put_serial:
 err_put_serial: