diff options
author | Johan Hovold <johan@kernel.org> | 2017-06-20 13:52:02 +0300 |
---|---|---|
committer | Johan Hovold <johan@kernel.org> | 2017-06-21 10:38:58 +0300 |
commit | 45e5d4d418f37cb9b2746c1fc63ab89b7b521d78 (patch) | |
tree | 12ad91df46a64960eeca5c2e4c14635bb9550b78 /drivers/usb/serial | |
parent | 08f741a93333dc81b6d17d25f712ca167f250b1a (diff) | |
download | linux-45e5d4d418f37cb9b2746c1fc63ab89b7b521d78.tar.xz |
USB: serial: refactor port endpoint setup
Make the probe callback more readable by refactoring the port
endpoint-resource setup by adding four helper functions.
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 222 |
1 files changed, 130 insertions, 92 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index c7ca95f64edc..f68275dd1e9f 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; @@ -867,86 +982,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 probe_error; } 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)) + retval = setup_port_bulk_out(serial->port[i], + epds->bulk_out[i]); + if (retval) 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]; } 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) + retval = setup_port_interrupt_in(serial->port[i], + epds->interrupt_in[i]); + if (retval) 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); } } 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 +1007,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) + retval = setup_port_interrupt_out(serial->port[i], + epds->interrupt_out[i]); + if (retval) 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); } } 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"); |