diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-06-28 14:02:07 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-06-28 14:02:07 +0200 |
commit | 0e4b470c0af6df6cd1456ef8482db1d07f14ae33 (patch) | |
tree | fc4e59d47fb04d4530f5b5822dcc8551ec8ecae0 /drivers/usb | |
parent | usbip: Fix uninitialized variable bug in vhci (diff) | |
parent | USB: serial: propagate late probe errors (diff) | |
download | linux-0e4b470c0af6df6cd1456ef8482db1d07f14ae33.tar.xz linux-0e4b470c0af6df6cd1456ef8482db1d07f14ae33.zip |
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/qcserial.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/upd78f0730.c | 6 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 243 |
3 files changed, 146 insertions, 105 deletions
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index fd509ed6cf70..4ac137d070fb 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -454,6 +454,8 @@ static struct usb_serial_driver qcdevice = { .write = usb_wwan_write, .write_room = usb_wwan_write_room, .chars_in_buffer = usb_wwan_chars_in_buffer, + .tiocmget = usb_wwan_tiocmget, + .tiocmset = usb_wwan_tiocmset, .attach = qc_attach, .release = qc_release, .port_probe = usb_wwan_port_probe, diff --git a/drivers/usb/serial/upd78f0730.c b/drivers/usb/serial/upd78f0730.c index a028dd2310c9..6819a3486e5d 100644 --- a/drivers/usb/serial/upd78f0730.c +++ b/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) { 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 }; 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) { - struct upd78f0730_open_close request = { + static const struct upd78f0730_open_close request = { .opcode = UPD78F0730_CMD_OPEN_CLOSE, .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) { - struct upd78f0730_open_close request = { + static const struct upd78f0730_open_close request = { .opcode = UPD78F0730_CMD_OPEN_CLOSE, .state = UPD78F0730_PORT_CLOSE }; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index c7ca95f64edc..bb34f9f7eaf4 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/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, 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_serial *serial = NULL; struct usb_serial_port *port; - struct usb_endpoint_descriptor *endpoint; struct usb_serial_endpoints *epds; struct usb_serial_driver *type = NULL; int retval; - int buffer_size; int i; - int j; int num_ports = 0; 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); for (i = 0; i < max_endpoints; ++i) { 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); port->port.ops = &serial_port_ops; port->serial = serial; @@ -867,86 +984,24 @@ static int usb_serial_probe(struct usb_interface *interface, /* set up the endpoint information */ 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) { - 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) { 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) { 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) { 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) { 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) { retval = type->attach(serial); if (retval < 0) - goto probe_error; + goto err_free_epds; serial->attached = 1; if (retval > 0) { /* 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; } - if (allocate_minors(serial, num_ports)) { + retval = allocate_minors(serial, num_ports); + if (retval) { 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 */ @@ -1020,8 +1061,6 @@ exit: module_put(type->driver.owner); return 0; -probe_error: - retval = -EIO; err_free_epds: kfree(epds); err_put_serial: |