diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-05-14 11:25:35 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-05-14 11:25:35 +0200 |
commit | 60d5794fe5a50d02f4a0df84b45910a4dfa8b487 (patch) | |
tree | 5c221ba843285abe809b23e4dec064ed0219a9ca /drivers/usb | |
parent | 13069bd94d559c0d91dd97341bfed9d237a5032d (diff) | |
parent | b923c6c62981cec5e2d2187fd700c2fc4386fc45 (diff) |
Merge tag 'usb-serial-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next
Johan writes:
USB-serial updates for v4.7-rc1
These updates fixes a number of issues where resources were not properly
released on probe errors. Included is also a fix for hardware
flow-control disable for cp210x.
Support for Moxa UPort 11x0 is added to the ti_usb_3410_5052 driver, and
included are also some general code clean ups.
Signed-off-by: Johan Hovold <johan@kernel.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/cp210x.c | 102 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 16 | ||||
-rw-r--r-- | drivers/usb/serial/io_edgeport.c | 56 | ||||
-rw-r--r-- | drivers/usb/serial/keyspan.c | 72 | ||||
-rw-r--r-- | drivers/usb/serial/mxuport.c | 10 | ||||
-rw-r--r-- | drivers/usb/serial/quatech2.c | 1 | ||||
-rw-r--r-- | drivers/usb/serial/ti_usb_3410_5052.c | 55 | ||||
-rw-r--r-- | drivers/usb/serial/ti_usb_3410_5052.h | 8 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 5 |
9 files changed, 233 insertions, 92 deletions
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 7c9f25e9c422..96a70789b4c2 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -331,6 +331,42 @@ struct cp210x_comm_status { */ #define PURGE_ALL 0x000f +/* CP210X_GET_FLOW/CP210X_SET_FLOW read/write these 0x10 bytes */ +struct cp210x_flow_ctl { + __le32 ulControlHandshake; + __le32 ulFlowReplace; + __le32 ulXonLimit; + __le32 ulXoffLimit; +} __packed; + +/* cp210x_flow_ctl::ulControlHandshake */ +#define CP210X_SERIAL_DTR_MASK GENMASK(1, 0) +#define CP210X_SERIAL_DTR_SHIFT(_mode) (_mode) +#define CP210X_SERIAL_CTS_HANDSHAKE BIT(3) +#define CP210X_SERIAL_DSR_HANDSHAKE BIT(4) +#define CP210X_SERIAL_DCD_HANDSHAKE BIT(5) +#define CP210X_SERIAL_DSR_SENSITIVITY BIT(6) + +/* values for cp210x_flow_ctl::ulControlHandshake::CP210X_SERIAL_DTR_MASK */ +#define CP210X_SERIAL_DTR_INACTIVE 0 +#define CP210X_SERIAL_DTR_ACTIVE 1 +#define CP210X_SERIAL_DTR_FLOW_CTL 2 + +/* cp210x_flow_ctl::ulFlowReplace */ +#define CP210X_SERIAL_AUTO_TRANSMIT BIT(0) +#define CP210X_SERIAL_AUTO_RECEIVE BIT(1) +#define CP210X_SERIAL_ERROR_CHAR BIT(2) +#define CP210X_SERIAL_NULL_STRIPPING BIT(3) +#define CP210X_SERIAL_BREAK_CHAR BIT(4) +#define CP210X_SERIAL_RTS_MASK GENMASK(7, 6) +#define CP210X_SERIAL_RTS_SHIFT(_mode) (_mode << 6) +#define CP210X_SERIAL_XOFF_CONTINUE BIT(31) + +/* values for cp210x_flow_ctl::ulFlowReplace::CP210X_SERIAL_RTS_MASK */ +#define CP210X_SERIAL_RTS_INACTIVE 0 +#define CP210X_SERIAL_RTS_ACTIVE 1 +#define CP210X_SERIAL_RTS_FLOW_CTL 2 + /* * Reads a variable-sized block of CP210X_ registers, identified by req. * Returns data into buf in native USB byte order. @@ -698,9 +734,10 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, { struct device *dev = &port->dev; unsigned int cflag; - u8 modem_ctl[16]; + struct cp210x_flow_ctl flow_ctl; u32 baud; u16 bits; + u32 ctl_hs; cp210x_read_u32_reg(port, CP210X_GET_BAUDRATE, &baud); @@ -796,9 +833,10 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, break; } - cp210x_read_reg_block(port, CP210X_GET_FLOW, modem_ctl, - sizeof(modem_ctl)); - if (modem_ctl[0] & 0x08) { + cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl, + sizeof(flow_ctl)); + ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake); + if (ctl_hs & CP210X_SERIAL_CTS_HANDSHAKE) { dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__); cflag |= CRTSCTS; } else { @@ -867,7 +905,6 @@ static void cp210x_set_termios(struct tty_struct *tty, struct device *dev = &port->dev; unsigned int cflag, old_cflag; u16 bits; - u8 modem_ctl[16]; cflag = tty->termios.c_cflag; old_cflag = old_termios->c_cflag; @@ -951,35 +988,44 @@ static void cp210x_set_termios(struct tty_struct *tty, } if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { - - /* Only bytes 0, 4 and 7 out of first 8 have functional bits */ - - cp210x_read_reg_block(port, CP210X_GET_FLOW, modem_ctl, - sizeof(modem_ctl)); - dev_dbg(dev, "%s - read modem controls = %02x .. .. .. %02x .. .. %02x\n", - __func__, modem_ctl[0], modem_ctl[4], modem_ctl[7]); - + struct cp210x_flow_ctl flow_ctl; + u32 ctl_hs; + u32 flow_repl; + + cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl, + sizeof(flow_ctl)); + ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake); + flow_repl = le32_to_cpu(flow_ctl.ulFlowReplace); + dev_dbg(dev, "%s - read ulControlHandshake=0x%08x, ulFlowReplace=0x%08x\n", + __func__, ctl_hs, flow_repl); + + ctl_hs &= ~CP210X_SERIAL_DSR_HANDSHAKE; + ctl_hs &= ~CP210X_SERIAL_DCD_HANDSHAKE; + ctl_hs &= ~CP210X_SERIAL_DSR_SENSITIVITY; + ctl_hs &= ~CP210X_SERIAL_DTR_MASK; + ctl_hs |= CP210X_SERIAL_DTR_SHIFT(CP210X_SERIAL_DTR_ACTIVE); if (cflag & CRTSCTS) { - modem_ctl[0] &= ~0x7B; - modem_ctl[0] |= 0x09; - modem_ctl[4] = 0x80; - /* FIXME - why clear reserved bits just read? */ - modem_ctl[5] = 0; - modem_ctl[6] = 0; - modem_ctl[7] = 0; + ctl_hs |= CP210X_SERIAL_CTS_HANDSHAKE; + + flow_repl &= ~CP210X_SERIAL_RTS_MASK; + flow_repl |= CP210X_SERIAL_RTS_SHIFT( + CP210X_SERIAL_RTS_FLOW_CTL); dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__); } else { - modem_ctl[0] &= ~0x7B; - modem_ctl[0] |= 0x01; - /* FIXME - OR here instead of assignment looks wrong */ - modem_ctl[4] |= 0x40; + ctl_hs &= ~CP210X_SERIAL_CTS_HANDSHAKE; + + flow_repl &= ~CP210X_SERIAL_RTS_MASK; + flow_repl |= CP210X_SERIAL_RTS_SHIFT( + CP210X_SERIAL_RTS_ACTIVE); dev_dbg(dev, "%s - flow control = NONE\n", __func__); } - dev_dbg(dev, "%s - write modem controls = %02x .. .. .. %02x .. .. %02x\n", - __func__, modem_ctl[0], modem_ctl[4], modem_ctl[7]); - cp210x_write_reg_block(port, CP210X_SET_FLOW, modem_ctl, - sizeof(modem_ctl)); + dev_dbg(dev, "%s - write ulControlHandshake=0x%08x, ulFlowReplace=0x%08x\n", + __func__, ctl_hs, flow_repl); + flow_ctl.ulControlHandshake = cpu_to_le32(ctl_hs); + flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl); + cp210x_write_reg_block(port, CP210X_SET_FLOW, &flow_ctl, + sizeof(flow_ctl)); } } diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3a814e802dee..00820809139a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -93,27 +93,27 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial); static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); -static struct ftdi_sio_quirk ftdi_jtag_quirk = { +static const struct ftdi_sio_quirk ftdi_jtag_quirk = { .probe = ftdi_jtag_probe, }; -static struct ftdi_sio_quirk ftdi_NDI_device_quirk = { +static const struct ftdi_sio_quirk ftdi_NDI_device_quirk = { .probe = ftdi_NDI_device_setup, }; -static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { +static const struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { .port_probe = ftdi_USB_UIRT_setup, }; -static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { +static const struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { .port_probe = ftdi_HE_TIRA1_setup, }; -static struct ftdi_sio_quirk ftdi_stmclite_quirk = { +static const struct ftdi_sio_quirk ftdi_stmclite_quirk = { .probe = ftdi_stmclite_probe, }; -static struct ftdi_sio_quirk ftdi_8u2232c_quirk = { +static const struct ftdi_sio_quirk ftdi_8u2232c_quirk = { .probe = ftdi_8u2232c_probe, }; @@ -1775,7 +1775,7 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) static int ftdi_sio_probe(struct usb_serial *serial, const struct usb_device_id *id) { - struct ftdi_sio_quirk *quirk = + const struct ftdi_sio_quirk *quirk = (struct ftdi_sio_quirk *)id->driver_info; if (quirk && quirk->probe) { @@ -1792,7 +1792,7 @@ static int ftdi_sio_probe(struct usb_serial *serial, static int ftdi_sio_port_probe(struct usb_serial_port *port) { struct ftdi_private *priv; - struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial); + const struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial); priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index f3007ecdd1b4..11c05ce2f35f 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -2849,14 +2849,16 @@ static int edge_startup(struct usb_serial *serial) /* not set up yet, so do it now */ edge_serial->interrupt_read_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!edge_serial->interrupt_read_urb) - return -ENOMEM; + if (!edge_serial->interrupt_read_urb) { + response = -ENOMEM; + break; + } edge_serial->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!edge_serial->interrupt_in_buffer) { - usb_free_urb(edge_serial->interrupt_read_urb); - return -ENOMEM; + response = -ENOMEM; + break; } edge_serial->interrupt_in_endpoint = endpoint->bEndpointAddress; @@ -2884,14 +2886,16 @@ static int edge_startup(struct usb_serial *serial) /* not set up yet, so do it now */ edge_serial->read_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!edge_serial->read_urb) - return -ENOMEM; + if (!edge_serial->read_urb) { + response = -ENOMEM; + break; + } edge_serial->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!edge_serial->bulk_in_buffer) { - usb_free_urb(edge_serial->read_urb); - return -ENOMEM; + response = -ENOMEM; + break; } edge_serial->bulk_in_endpoint = endpoint->bEndpointAddress; @@ -2917,9 +2921,22 @@ static int edge_startup(struct usb_serial *serial) } } - if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) { - dev_err(ddev, "Error - the proper endpoints were not found!\n"); - return -ENODEV; + if (response || !interrupt_in_found || !bulk_in_found || + !bulk_out_found) { + if (!response) { + dev_err(ddev, "expected endpoints not found\n"); + response = -ENODEV; + } + + usb_free_urb(edge_serial->interrupt_read_urb); + kfree(edge_serial->interrupt_in_buffer); + + usb_free_urb(edge_serial->read_urb); + kfree(edge_serial->bulk_in_buffer); + + kfree(edge_serial); + + return response; } /* start interrupt read for this edgeport this interrupt will @@ -2942,16 +2959,9 @@ static void edge_disconnect(struct usb_serial *serial) { struct edgeport_serial *edge_serial = usb_get_serial_data(serial); - /* stop reads and writes on all ports */ - /* free up our endpoint stuff */ if (edge_serial->is_epic) { usb_kill_urb(edge_serial->interrupt_read_urb); - usb_free_urb(edge_serial->interrupt_read_urb); - kfree(edge_serial->interrupt_in_buffer); - usb_kill_urb(edge_serial->read_urb); - usb_free_urb(edge_serial->read_urb); - kfree(edge_serial->bulk_in_buffer); } } @@ -2964,6 +2974,16 @@ static void edge_release(struct usb_serial *serial) { struct edgeport_serial *edge_serial = usb_get_serial_data(serial); + if (edge_serial->is_epic) { + usb_kill_urb(edge_serial->interrupt_read_urb); + usb_free_urb(edge_serial->interrupt_read_urb); + kfree(edge_serial->interrupt_in_buffer); + + usb_kill_urb(edge_serial->read_urb); + usb_free_urb(edge_serial->read_urb); + kfree(edge_serial->bulk_in_buffer); + } + kfree(edge_serial); } diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index b6bd8e4a6486..1f9414bdd649 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -255,7 +255,7 @@ static int keyspan_write(struct tty_struct *tty, return count; } - dev_dbg(&port->dev, "%s - endpoint %d flip %d\n", + dev_dbg(&port->dev, "%s - endpoint %x flip %d\n", __func__, usb_pipeendpoint(this_urb->pipe), flip); if (this_urb->status == -EINPROGRESS) { @@ -300,7 +300,7 @@ static void usa26_indat_callback(struct urb *urb) endpoint = usb_pipeendpoint(urb->pipe); if (status) { - dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n", + dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n", __func__, status, endpoint); return; } @@ -393,7 +393,8 @@ static void usa26_instat_callback(struct urb *urb) serial = urb->context; if (status) { - dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n", + __func__, status); return; } if (urb->actual_length != 9) { @@ -452,7 +453,7 @@ static void usa28_indat_callback(struct urb *urb) do { if (status) { - dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n", + dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n", __func__, status, usb_pipeendpoint(urb->pipe)); return; } @@ -511,7 +512,8 @@ static void usa28_instat_callback(struct urb *urb) serial = urb->context; if (status) { - dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n", + __func__, status); return; } @@ -591,7 +593,8 @@ static void usa49_instat_callback(struct urb *urb) serial = urb->context; if (status) { - dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n", + __func__, status); return; } @@ -646,7 +649,7 @@ static void usa49_indat_callback(struct urb *urb) endpoint = usb_pipeendpoint(urb->pipe); if (status) { - dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n", + dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n", __func__, status, endpoint); return; } @@ -698,7 +701,8 @@ static void usa49wg_indat_callback(struct urb *urb) serial = urb->context; if (status) { - dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n", + __func__, status); return; } @@ -774,8 +778,8 @@ static void usa90_indat_callback(struct urb *urb) endpoint = usb_pipeendpoint(urb->pipe); if (status) { - dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n", - __func__, status, endpoint); + dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n", + __func__, status, endpoint); return; } @@ -847,7 +851,8 @@ static void usa90_instat_callback(struct urb *urb) serial = urb->context; if (status) { - dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n", + __func__, status); return; } if (urb->actual_length < 14) { @@ -912,7 +917,8 @@ static void usa67_instat_callback(struct urb *urb) serial = urb->context; if (status) { - dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n", + __func__, status); return; } @@ -1082,12 +1088,6 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port) return 0; } -static inline void stop_urb(struct urb *urb) -{ - if (urb && urb->status == -EINPROGRESS) - usb_kill_urb(urb); -} - static void keyspan_dtr_rts(struct usb_serial_port *port, int on) { struct keyspan_port_private *p_priv = usb_get_serial_port_data(port); @@ -1114,10 +1114,10 @@ static void keyspan_close(struct usb_serial_port *port) p_priv->out_flip = 0; p_priv->in_flip = 0; - stop_urb(p_priv->inack_urb); + usb_kill_urb(p_priv->inack_urb); for (i = 0; i < 2; i++) { - stop_urb(p_priv->in_urbs[i]); - stop_urb(p_priv->out_urbs[i]); + usb_kill_urb(p_priv->in_urbs[i]); + usb_kill_urb(p_priv->out_urbs[i]); } } @@ -1221,8 +1221,8 @@ static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *se if (ep->bEndpointAddress == endpoint) return ep; } - dev_warn(&serial->interface->dev, "found no endpoint descriptor for " - "endpoint %x\n", endpoint); + dev_warn(&serial->interface->dev, "found no endpoint descriptor for endpoint %x\n", + endpoint); return NULL; } @@ -1237,7 +1237,8 @@ static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint, if (endpoint == -1) return NULL; /* endpoint not needed */ - dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d.\n", __func__, endpoint); + dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %x\n", + __func__, endpoint); urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ if (!urb) return NULL; @@ -1572,7 +1573,8 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, return -1; } - dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe)); + dev_dbg(&port->dev, "%s - endpoint %x\n", + __func__, usb_pipeendpoint(this_urb->pipe)); /* Save reset port val for resend. Don't overwrite resend for open/close condition. */ @@ -1838,7 +1840,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, return -1; } - dev_dbg(&port->dev, "%s - endpoint %d (%d)\n", + dev_dbg(&port->dev, "%s - endpoint %x (%d)\n", __func__, usb_pipeendpoint(this_urb->pipe), device_port); /* Save reset port val for resend. @@ -2365,9 +2367,9 @@ static void keyspan_disconnect(struct usb_serial *serial) s_priv = usb_get_serial_data(serial); - stop_urb(s_priv->instat_urb); - stop_urb(s_priv->glocont_urb); - stop_urb(s_priv->indat_urb); + usb_kill_urb(s_priv->instat_urb); + usb_kill_urb(s_priv->glocont_urb); + usb_kill_urb(s_priv->indat_urb); } static void keyspan_release(struct usb_serial *serial) @@ -2376,6 +2378,10 @@ static void keyspan_release(struct usb_serial *serial) s_priv = usb_get_serial_data(serial); + /* Make sure to unlink the URBs submitted in attach. */ + usb_kill_urb(s_priv->instat_urb); + usb_kill_urb(s_priv->indat_urb); + usb_free_urb(s_priv->instat_urb); usb_free_urb(s_priv->indat_urb); usb_free_urb(s_priv->glocont_urb); @@ -2491,11 +2497,11 @@ static int keyspan_port_remove(struct usb_serial_port *port) p_priv = usb_get_serial_port_data(port); - stop_urb(p_priv->inack_urb); - stop_urb(p_priv->outcont_urb); + usb_kill_urb(p_priv->inack_urb); + usb_kill_urb(p_priv->outcont_urb); for (i = 0; i < 2; i++) { - stop_urb(p_priv->in_urbs[i]); - stop_urb(p_priv->out_urbs[i]); + usb_kill_urb(p_priv->in_urbs[i]); + usb_kill_urb(p_priv->out_urbs[i]); } usb_free_urb(p_priv->inack_urb); diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c index 31a8b47f1ac6..c6596cbcc4b6 100644 --- a/drivers/usb/serial/mxuport.c +++ b/drivers/usb/serial/mxuport.c @@ -1259,6 +1259,15 @@ static int mxuport_attach(struct usb_serial *serial) return 0; } +static void mxuport_release(struct usb_serial *serial) +{ + struct usb_serial_port *port0 = serial->port[0]; + struct usb_serial_port *port1 = serial->port[1]; + + usb_serial_generic_close(port1); + usb_serial_generic_close(port0); +} + static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port) { struct mxuport_port *mxport = usb_get_serial_port_data(port); @@ -1361,6 +1370,7 @@ static struct usb_serial_driver mxuport_device = { .probe = mxuport_probe, .port_probe = mxuport_port_probe, .attach = mxuport_attach, + .release = mxuport_release, .calc_num_ports = mxuport_calc_num_ports, .open = mxuport_open, .close = mxuport_close, diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 2df8ad5ede89..85acb50a7ee2 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -141,6 +141,7 @@ static void qt2_release(struct usb_serial *serial) serial_priv = usb_get_serial_data(serial); + usb_kill_urb(serial_priv->read_urb); usb_free_urb(serial_priv->read_urb); kfree(serial_priv->read_buffer); kfree(serial_priv); diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 2694df2f4559..e7dbbef2af2a 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -80,6 +80,7 @@ struct ti_device { int td_open_port_count; struct usb_serial *td_serial; int td_is_3410; + bool td_rs485_only; int td_urb_error; }; @@ -160,6 +161,11 @@ static const struct usb_device_id ti_id_table_3410[] = { { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) }, { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, { USB_DEVICE(HONEYWELL_VENDOR_ID, HONEYWELL_HGI80_PRODUCT_ID) }, + { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1110_PRODUCT_ID) }, + { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1130_PRODUCT_ID) }, + { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1131_PRODUCT_ID) }, + { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1150_PRODUCT_ID) }, + { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1151_PRODUCT_ID) }, { } /* terminator */ }; @@ -193,6 +199,11 @@ static const struct usb_device_id ti_id_table_combined[] = { { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) }, { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, { USB_DEVICE(HONEYWELL_VENDOR_ID, HONEYWELL_HGI80_PRODUCT_ID) }, + { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1110_PRODUCT_ID) }, + { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1130_PRODUCT_ID) }, + { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1131_PRODUCT_ID) }, + { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1150_PRODUCT_ID) }, + { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1151_PRODUCT_ID) }, { } /* terminator */ }; @@ -277,6 +288,11 @@ MODULE_FIRMWARE("mts_gsm.fw"); MODULE_FIRMWARE("mts_edge.fw"); MODULE_FIRMWARE("mts_mt9234mu.fw"); MODULE_FIRMWARE("mts_mt9234zba.fw"); +MODULE_FIRMWARE("moxa/moxa-1110.fw"); +MODULE_FIRMWARE("moxa/moxa-1130.fw"); +MODULE_FIRMWARE("moxa/moxa-1131.fw"); +MODULE_FIRMWARE("moxa/moxa-1150.fw"); +MODULE_FIRMWARE("moxa/moxa-1151.fw"); module_param(closing_wait, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(closing_wait, @@ -292,6 +308,9 @@ static int ti_startup(struct usb_serial *serial) { struct ti_device *tdev; struct usb_device *dev = serial->dev; + struct usb_host_interface *cur_altsetting; + int num_endpoints; + u16 vid, pid; int status; dev_dbg(&dev->dev, @@ -315,8 +334,22 @@ static int ti_startup(struct usb_serial *serial) dev_dbg(&dev->dev, "%s - device type is %s\n", __func__, tdev->td_is_3410 ? "3410" : "5052"); - /* if we have only 1 configuration, download firmware */ - if (dev->descriptor.bNumConfigurations == 1) { + vid = le16_to_cpu(dev->descriptor.idVendor); + pid = le16_to_cpu(dev->descriptor.idProduct); + if (vid == MXU1_VENDOR_ID) { + switch (pid) { + case MXU1_1130_PRODUCT_ID: + case MXU1_1131_PRODUCT_ID: + tdev->td_rs485_only = true; + break; + } + } + + cur_altsetting = serial->interface->cur_altsetting; + num_endpoints = cur_altsetting->desc.bNumEndpoints; + + /* if we have only 1 configuration and 1 endpoint, download firmware */ + if (dev->descriptor.bNumConfigurations == 1 && num_endpoints == 1) { status = ti_download_firmware(tdev); if (status != 0) @@ -371,7 +404,11 @@ static int ti_port_probe(struct usb_serial_port *port) port->port.closing_wait = msecs_to_jiffies(10 * closing_wait); tport->tp_port = port; tport->tp_tdev = usb_get_serial_data(port->serial); - tport->tp_uart_mode = 0; /* default is RS232 */ + + if (tport->tp_tdev->td_rs485_only) + tport->tp_uart_mode = TI_UART_485_RECEIVER_DISABLED; + else + tport->tp_uart_mode = TI_UART_232; usb_set_serial_port_data(port, tport); @@ -1450,6 +1487,16 @@ static int ti_download_firmware(struct ti_device *tdev) const struct firmware *fw_p; char buf[32]; + if (le16_to_cpu(dev->descriptor.idVendor) == MXU1_VENDOR_ID) { + snprintf(buf, + sizeof(buf), + "moxa/moxa-%04x.fw", + le16_to_cpu(dev->descriptor.idProduct)); + + status = request_firmware(&fw_p, buf, &dev->dev); + goto check_firmware; + } + /* try ID specific firmware first, then try generic firmware */ sprintf(buf, "ti_usb-v%04x-p%04x.fw", le16_to_cpu(dev->descriptor.idVendor), @@ -1487,6 +1534,8 @@ static int ti_download_firmware(struct ti_device *tdev) } status = request_firmware(&fw_p, buf, &dev->dev); } + +check_firmware: if (status) { dev_err(&dev->dev, "%s - firmware not found\n", __func__); return -ENOENT; diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h index 98f35c656c02..bbfd3a184600 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.h +++ b/drivers/usb/serial/ti_usb_3410_5052.h @@ -60,6 +60,14 @@ #define HONEYWELL_VENDOR_ID 0x10ac #define HONEYWELL_HGI80_PRODUCT_ID 0x0102 /* Honeywell HGI80 */ +/* Moxa UPORT 11x0 vendor and product IDs */ +#define MXU1_VENDOR_ID 0x110a +#define MXU1_1110_PRODUCT_ID 0x1110 +#define MXU1_1130_PRODUCT_ID 0x1130 +#define MXU1_1131_PRODUCT_ID 0x1131 +#define MXU1_1150_PRODUCT_ID 0x1150 +#define MXU1_1151_PRODUCT_ID 0x1151 + /* Commands */ #define TI_GET_VERSION 0x01 #define TI_GET_PORT_STATUS 0x02 diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 46f1f13b41f1..4d2b310de55d 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -96,7 +96,8 @@ static int allocate_minors(struct usb_serial *serial, int num_ports) mutex_lock(&table_lock); for (i = 0; i < num_ports; ++i) { port = serial->port[i]; - minor = idr_alloc(&serial_minors, port, 0, 0, GFP_KERNEL); + minor = idr_alloc(&serial_minors, port, 0, + USB_SERIAL_TTY_MINORS, GFP_KERNEL); if (minor < 0) goto error; port->minor = minor; @@ -815,7 +816,7 @@ static int usb_serial_probe(struct usb_interface *interface, } } -#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE) +#if IS_ENABLED(CONFIG_USB_SERIAL_PL2303) /* BEGIN HORRIBLE HACK FOR PL2303 */ /* this is needed due to the looney way its endpoints are set up */ if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) && |