diff options
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 47 |
1 files changed, 43 insertions, 4 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 3873660d821..941c2d409f8 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -289,7 +289,7 @@ static void serial_down(struct tty_port *tport) * The console is magical. Do not hang up the console hardware * or there will be tears. */ - if (port->console) + if (port->port.console) return; if (drv->close) drv->close(port); @@ -328,7 +328,7 @@ static void serial_cleanup(struct tty_struct *tty) /* The console is magical. Do not hang up the console hardware * or there will be tears. */ - if (port->console) + if (port->port.console) return; dbg("%s - port %d", __func__, port->number); @@ -548,8 +548,12 @@ static void usb_serial_port_work(struct work_struct *work) static void kill_traffic(struct usb_serial_port *port) { + int i; + usb_kill_urb(port->read_urb); usb_kill_urb(port->write_urb); + for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) + usb_kill_urb(port->write_urbs[i]); /* * This is tricky. * Some drivers submit the read_urb in the @@ -568,6 +572,7 @@ static void kill_traffic(struct usb_serial_port *port) static void port_release(struct device *dev) { struct usb_serial_port *port = to_usb_serial_port(dev); + int i; dbg ("%s - %s", __func__, dev_name(dev)); @@ -582,6 +587,10 @@ static void port_release(struct device *dev) usb_free_urb(port->write_urb); usb_free_urb(port->interrupt_in_urb); usb_free_urb(port->interrupt_out_urb); + for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) { + usb_free_urb(port->write_urbs[i]); + kfree(port->bulk_out_buffers[i]); + } kfifo_free(&port->write_fifo); kfree(port->bulk_in_buffer); kfree(port->bulk_out_buffer); @@ -901,7 +910,9 @@ int usb_serial_probe(struct usb_interface *interface, dev_err(&interface->dev, "No free urbs available\n"); goto probe_error; } - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + 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; port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); @@ -918,6 +929,8 @@ int usb_serial_probe(struct usb_interface *interface, } for (i = 0; i < num_bulk_out; ++i) { + int j; + endpoint = bulk_out_endpoint[i]; port = serial->port[i]; port->write_urb = usb_alloc_urb(0, GFP_KERNEL); @@ -927,7 +940,9 @@ int usb_serial_probe(struct usb_interface *interface, } if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL)) goto probe_error; - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + 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; port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); @@ -941,6 +956,28 @@ int usb_serial_probe(struct usb_interface *interface, endpoint->bEndpointAddress), port->bulk_out_buffer, buffer_size, serial->type->write_bulk_callback, port); + 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]) { + dev_err(&interface->dev, + "No free urbs available\n"); + goto probe_error; + } + port->bulk_out_buffers[j] = kmalloc(buffer_size, + GFP_KERNEL); + if (!port->bulk_out_buffers[j]) { + dev_err(&interface->dev, + "Couldn't allocate bulk_out_buffer\n"); + 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); + } } if (serial->type->read_int_callback) { @@ -1294,6 +1331,8 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, write_bulk_callback); set_to_generic_if_null(device, disconnect); set_to_generic_if_null(device, release); + set_to_generic_if_null(device, process_read_urb); + set_to_generic_if_null(device, prepare_write_buffer); } int usb_serial_register(struct usb_serial_driver *driver) |