summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-06-28 14:02:07 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-06-28 14:02:07 +0200
commit0e4b470c0af6df6cd1456ef8482db1d07f14ae33 (patch)
treefc4e59d47fb04d4530f5b5822dcc8551ec8ecae0 /drivers/usb
parentusbip: Fix uninitialized variable bug in vhci (diff)
parentUSB: serial: propagate late probe errors (diff)
downloadlinux-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.c2
-rw-r--r--drivers/usb/serial/upd78f0730.c6
-rw-r--r--drivers/usb/serial/usb-serial.c243
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: