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>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJXNhM9AAoJEEEN5E/e4bSV1YwQAJc/CSQyi2pHkP/2p5IcWX5s
 74ld8tdY/07ZO8HEyfn1PBPJF60naOfsG90rf7jKqmOoMLUfCPM3CFt26bPllKGN
 T5YEpBp1INdZQpRP/HRvGLg6iW6vqb2oGK+fBXyNGp5ZVHaDVuYdT3HVZmDcfY1e
 DKtkuI8eCwKbQrVxsLu2DvxA4+l/OxRMwZKAlAGFtRIs+Im1++JTL4PLKsMEvkf2
 ztkDM3piBkTKEIpekrRBAL2MqMugwjCIyd3Dz/yJ96RIhcXASc26nLSRVFRJ5x6a
 oKG19WmNVxk7LWuI6j4b5BSuLfbWsKUDlEQufLt+mkDBbVIf+kAX9901V5SG8S33
 2J1fyTNzHXktdKCEOy4xT6EDQ9wgWt/1JMCCOQhb8rRR/MYVAoEyAPUCO2AHhOZY
 1HwYpbM2DHBWYcMU+jx1yXyfQMlG2Hs6wjfebKbb5GBCBa0PmdgbSzTS+8jX81uC
 du5qkgAtN2SJWk+tVU+CUncQMe9u7zJo+8vDweqVW5M5rR6XW9Zq4LkrscUbzrgo
 USNRQjrXn4Y5W5MaDXRFT/6LoL09FCnbOdJk7EuiAZr4+Z/AxpBuIg5hDY3+RF+V
 u6J3ada1EUpy53+iYmsIE7uWsx3YrqT3RyGuvZyXKYW71u7SXWiaar3riQG3a6W+
 L4zd2DdmgrpYxFAzijpI
 =8igx
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Greg Kroah-Hartman 2016-05-14 11:25:35 +02:00
commit 60d5794fe5
9 changed files with 231 additions and 90 deletions

View File

@ -331,6 +331,42 @@ struct cp210x_comm_status {
*/ */
#define PURGE_ALL 0x000f #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. * Reads a variable-sized block of CP210X_ registers, identified by req.
* Returns data into buf in native USB byte order. * 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; struct device *dev = &port->dev;
unsigned int cflag; unsigned int cflag;
u8 modem_ctl[16]; struct cp210x_flow_ctl flow_ctl;
u32 baud; u32 baud;
u16 bits; u16 bits;
u32 ctl_hs;
cp210x_read_u32_reg(port, CP210X_GET_BAUDRATE, &baud); 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; break;
} }
cp210x_read_reg_block(port, CP210X_GET_FLOW, modem_ctl, cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl,
sizeof(modem_ctl)); sizeof(flow_ctl));
if (modem_ctl[0] & 0x08) { ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake);
if (ctl_hs & CP210X_SERIAL_CTS_HANDSHAKE) {
dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__); dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__);
cflag |= CRTSCTS; cflag |= CRTSCTS;
} else { } else {
@ -867,7 +905,6 @@ static void cp210x_set_termios(struct tty_struct *tty,
struct device *dev = &port->dev; struct device *dev = &port->dev;
unsigned int cflag, old_cflag; unsigned int cflag, old_cflag;
u16 bits; u16 bits;
u8 modem_ctl[16];
cflag = tty->termios.c_cflag; cflag = tty->termios.c_cflag;
old_cflag = old_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)) { if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
struct cp210x_flow_ctl flow_ctl;
u32 ctl_hs;
u32 flow_repl;
/* Only bytes 0, 4 and 7 out of first 8 have functional bits */ cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl,
sizeof(flow_ctl));
cp210x_read_reg_block(port, CP210X_GET_FLOW, modem_ctl, ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake);
sizeof(modem_ctl)); flow_repl = le32_to_cpu(flow_ctl.ulFlowReplace);
dev_dbg(dev, "%s - read modem controls = %02x .. .. .. %02x .. .. %02x\n", dev_dbg(dev, "%s - read ulControlHandshake=0x%08x, ulFlowReplace=0x%08x\n",
__func__, modem_ctl[0], modem_ctl[4], modem_ctl[7]); __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) { if (cflag & CRTSCTS) {
modem_ctl[0] &= ~0x7B; ctl_hs |= CP210X_SERIAL_CTS_HANDSHAKE;
modem_ctl[0] |= 0x09;
modem_ctl[4] = 0x80; flow_repl &= ~CP210X_SERIAL_RTS_MASK;
/* FIXME - why clear reserved bits just read? */ flow_repl |= CP210X_SERIAL_RTS_SHIFT(
modem_ctl[5] = 0; CP210X_SERIAL_RTS_FLOW_CTL);
modem_ctl[6] = 0;
modem_ctl[7] = 0;
dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__); dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__);
} else { } else {
modem_ctl[0] &= ~0x7B; ctl_hs &= ~CP210X_SERIAL_CTS_HANDSHAKE;
modem_ctl[0] |= 0x01;
/* FIXME - OR here instead of assignment looks wrong */ flow_repl &= ~CP210X_SERIAL_RTS_MASK;
modem_ctl[4] |= 0x40; flow_repl |= CP210X_SERIAL_RTS_SHIFT(
CP210X_SERIAL_RTS_ACTIVE);
dev_dbg(dev, "%s - flow control = NONE\n", __func__); dev_dbg(dev, "%s - flow control = NONE\n", __func__);
} }
dev_dbg(dev, "%s - write modem controls = %02x .. .. .. %02x .. .. %02x\n", dev_dbg(dev, "%s - write ulControlHandshake=0x%08x, ulFlowReplace=0x%08x\n",
__func__, modem_ctl[0], modem_ctl[4], modem_ctl[7]); __func__, ctl_hs, flow_repl);
cp210x_write_reg_block(port, CP210X_SET_FLOW, modem_ctl, flow_ctl.ulControlHandshake = cpu_to_le32(ctl_hs);
sizeof(modem_ctl)); flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl);
cp210x_write_reg_block(port, CP210X_SET_FLOW, &flow_ctl,
sizeof(flow_ctl));
} }
} }

View File

@ -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_USB_UIRT_setup(struct ftdi_private *priv);
static void ftdi_HE_TIRA1_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, .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, .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, .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, .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, .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, .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, static int ftdi_sio_probe(struct usb_serial *serial,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct ftdi_sio_quirk *quirk = const struct ftdi_sio_quirk *quirk =
(struct ftdi_sio_quirk *)id->driver_info; (struct ftdi_sio_quirk *)id->driver_info;
if (quirk && quirk->probe) { 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) static int ftdi_sio_port_probe(struct usb_serial_port *port)
{ {
struct ftdi_private *priv; 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); priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);

View File

@ -2849,14 +2849,16 @@ static int edge_startup(struct usb_serial *serial)
/* not set up yet, so do it now */ /* not set up yet, so do it now */
edge_serial->interrupt_read_urb = edge_serial->interrupt_read_urb =
usb_alloc_urb(0, GFP_KERNEL); usb_alloc_urb(0, GFP_KERNEL);
if (!edge_serial->interrupt_read_urb) if (!edge_serial->interrupt_read_urb) {
return -ENOMEM; response = -ENOMEM;
break;
}
edge_serial->interrupt_in_buffer = edge_serial->interrupt_in_buffer =
kmalloc(buffer_size, GFP_KERNEL); kmalloc(buffer_size, GFP_KERNEL);
if (!edge_serial->interrupt_in_buffer) { if (!edge_serial->interrupt_in_buffer) {
usb_free_urb(edge_serial->interrupt_read_urb); response = -ENOMEM;
return -ENOMEM; break;
} }
edge_serial->interrupt_in_endpoint = edge_serial->interrupt_in_endpoint =
endpoint->bEndpointAddress; endpoint->bEndpointAddress;
@ -2884,14 +2886,16 @@ static int edge_startup(struct usb_serial *serial)
/* not set up yet, so do it now */ /* not set up yet, so do it now */
edge_serial->read_urb = edge_serial->read_urb =
usb_alloc_urb(0, GFP_KERNEL); usb_alloc_urb(0, GFP_KERNEL);
if (!edge_serial->read_urb) if (!edge_serial->read_urb) {
return -ENOMEM; response = -ENOMEM;
break;
}
edge_serial->bulk_in_buffer = edge_serial->bulk_in_buffer =
kmalloc(buffer_size, GFP_KERNEL); kmalloc(buffer_size, GFP_KERNEL);
if (!edge_serial->bulk_in_buffer) { if (!edge_serial->bulk_in_buffer) {
usb_free_urb(edge_serial->read_urb); response = -ENOMEM;
return -ENOMEM; break;
} }
edge_serial->bulk_in_endpoint = edge_serial->bulk_in_endpoint =
endpoint->bEndpointAddress; endpoint->bEndpointAddress;
@ -2917,9 +2921,22 @@ static int edge_startup(struct usb_serial *serial)
} }
} }
if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) { if (response || !interrupt_in_found || !bulk_in_found ||
dev_err(ddev, "Error - the proper endpoints were not found!\n"); !bulk_out_found) {
return -ENODEV; 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 /* 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); 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) { if (edge_serial->is_epic) {
usb_kill_urb(edge_serial->interrupt_read_urb); 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_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); 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); kfree(edge_serial);
} }

View File

@ -255,7 +255,7 @@ static int keyspan_write(struct tty_struct *tty,
return count; 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); __func__, usb_pipeendpoint(this_urb->pipe), flip);
if (this_urb->status == -EINPROGRESS) { if (this_urb->status == -EINPROGRESS) {
@ -300,7 +300,7 @@ static void usa26_indat_callback(struct urb *urb)
endpoint = usb_pipeendpoint(urb->pipe); endpoint = usb_pipeendpoint(urb->pipe);
if (status) { 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); __func__, status, endpoint);
return; return;
} }
@ -393,7 +393,8 @@ static void usa26_instat_callback(struct urb *urb)
serial = urb->context; serial = urb->context;
if (status) { 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; return;
} }
if (urb->actual_length != 9) { if (urb->actual_length != 9) {
@ -452,7 +453,7 @@ static void usa28_indat_callback(struct urb *urb)
do { do {
if (status) { 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)); __func__, status, usb_pipeendpoint(urb->pipe));
return; return;
} }
@ -511,7 +512,8 @@ static void usa28_instat_callback(struct urb *urb)
serial = urb->context; serial = urb->context;
if (status) { 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; return;
} }
@ -591,7 +593,8 @@ static void usa49_instat_callback(struct urb *urb)
serial = urb->context; serial = urb->context;
if (status) { 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; return;
} }
@ -646,7 +649,7 @@ static void usa49_indat_callback(struct urb *urb)
endpoint = usb_pipeendpoint(urb->pipe); endpoint = usb_pipeendpoint(urb->pipe);
if (status) { 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); __func__, status, endpoint);
return; return;
} }
@ -698,7 +701,8 @@ static void usa49wg_indat_callback(struct urb *urb)
serial = urb->context; serial = urb->context;
if (status) { 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; return;
} }
@ -774,8 +778,8 @@ static void usa90_indat_callback(struct urb *urb)
endpoint = usb_pipeendpoint(urb->pipe); endpoint = usb_pipeendpoint(urb->pipe);
if (status) { 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); __func__, status, endpoint);
return; return;
} }
@ -847,7 +851,8 @@ static void usa90_instat_callback(struct urb *urb)
serial = urb->context; serial = urb->context;
if (status) { 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; return;
} }
if (urb->actual_length < 14) { if (urb->actual_length < 14) {
@ -912,7 +917,8 @@ static void usa67_instat_callback(struct urb *urb)
serial = urb->context; serial = urb->context;
if (status) { 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; return;
} }
@ -1082,12 +1088,6 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
return 0; 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) static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
{ {
struct keyspan_port_private *p_priv = usb_get_serial_port_data(port); 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->out_flip = 0;
p_priv->in_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++) { for (i = 0; i < 2; i++) {
stop_urb(p_priv->in_urbs[i]); usb_kill_urb(p_priv->in_urbs[i]);
stop_urb(p_priv->out_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) if (ep->bEndpointAddress == endpoint)
return ep; return ep;
} }
dev_warn(&serial->interface->dev, "found no endpoint descriptor for " dev_warn(&serial->interface->dev, "found no endpoint descriptor for endpoint %x\n",
"endpoint %x\n", endpoint); endpoint);
return NULL; return NULL;
} }
@ -1237,7 +1237,8 @@ static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
if (endpoint == -1) if (endpoint == -1)
return NULL; /* endpoint not needed */ 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 */ urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
if (!urb) if (!urb)
return NULL; return NULL;
@ -1572,7 +1573,8 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
return -1; 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. /* Save reset port val for resend.
Don't overwrite resend for open/close condition. */ Don't overwrite resend for open/close condition. */
@ -1838,7 +1840,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
return -1; 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); __func__, usb_pipeendpoint(this_urb->pipe), device_port);
/* Save reset port val for resend. /* 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); s_priv = usb_get_serial_data(serial);
stop_urb(s_priv->instat_urb); usb_kill_urb(s_priv->instat_urb);
stop_urb(s_priv->glocont_urb); usb_kill_urb(s_priv->glocont_urb);
stop_urb(s_priv->indat_urb); usb_kill_urb(s_priv->indat_urb);
} }
static void keyspan_release(struct usb_serial *serial) 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); 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->instat_urb);
usb_free_urb(s_priv->indat_urb); usb_free_urb(s_priv->indat_urb);
usb_free_urb(s_priv->glocont_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); p_priv = usb_get_serial_port_data(port);
stop_urb(p_priv->inack_urb); usb_kill_urb(p_priv->inack_urb);
stop_urb(p_priv->outcont_urb); usb_kill_urb(p_priv->outcont_urb);
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
stop_urb(p_priv->in_urbs[i]); usb_kill_urb(p_priv->in_urbs[i]);
stop_urb(p_priv->out_urbs[i]); usb_kill_urb(p_priv->out_urbs[i]);
} }
usb_free_urb(p_priv->inack_urb); usb_free_urb(p_priv->inack_urb);

View File

@ -1259,6 +1259,15 @@ static int mxuport_attach(struct usb_serial *serial)
return 0; 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) static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port)
{ {
struct mxuport_port *mxport = usb_get_serial_port_data(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, .probe = mxuport_probe,
.port_probe = mxuport_port_probe, .port_probe = mxuport_port_probe,
.attach = mxuport_attach, .attach = mxuport_attach,
.release = mxuport_release,
.calc_num_ports = mxuport_calc_num_ports, .calc_num_ports = mxuport_calc_num_ports,
.open = mxuport_open, .open = mxuport_open,
.close = mxuport_close, .close = mxuport_close,

View File

@ -141,6 +141,7 @@ static void qt2_release(struct usb_serial *serial)
serial_priv = usb_get_serial_data(serial); serial_priv = usb_get_serial_data(serial);
usb_kill_urb(serial_priv->read_urb);
usb_free_urb(serial_priv->read_urb); usb_free_urb(serial_priv->read_urb);
kfree(serial_priv->read_buffer); kfree(serial_priv->read_buffer);
kfree(serial_priv); kfree(serial_priv);

View File

@ -80,6 +80,7 @@ struct ti_device {
int td_open_port_count; int td_open_port_count;
struct usb_serial *td_serial; struct usb_serial *td_serial;
int td_is_3410; int td_is_3410;
bool td_rs485_only;
int td_urb_error; 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(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
{ USB_DEVICE(HONEYWELL_VENDOR_ID, HONEYWELL_HGI80_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 */ { } /* 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(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
{ USB_DEVICE(HONEYWELL_VENDOR_ID, HONEYWELL_HGI80_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 */ { } /* terminator */
}; };
@ -277,6 +288,11 @@ MODULE_FIRMWARE("mts_gsm.fw");
MODULE_FIRMWARE("mts_edge.fw"); MODULE_FIRMWARE("mts_edge.fw");
MODULE_FIRMWARE("mts_mt9234mu.fw"); MODULE_FIRMWARE("mts_mt9234mu.fw");
MODULE_FIRMWARE("mts_mt9234zba.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_param(closing_wait, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(closing_wait, MODULE_PARM_DESC(closing_wait,
@ -292,6 +308,9 @@ static int ti_startup(struct usb_serial *serial)
{ {
struct ti_device *tdev; struct ti_device *tdev;
struct usb_device *dev = serial->dev; struct usb_device *dev = serial->dev;
struct usb_host_interface *cur_altsetting;
int num_endpoints;
u16 vid, pid;
int status; int status;
dev_dbg(&dev->dev, 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__, dev_dbg(&dev->dev, "%s - device type is %s\n", __func__,
tdev->td_is_3410 ? "3410" : "5052"); tdev->td_is_3410 ? "3410" : "5052");
/* if we have only 1 configuration, download firmware */ vid = le16_to_cpu(dev->descriptor.idVendor);
if (dev->descriptor.bNumConfigurations == 1) { 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); status = ti_download_firmware(tdev);
if (status != 0) 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); port->port.closing_wait = msecs_to_jiffies(10 * closing_wait);
tport->tp_port = port; tport->tp_port = port;
tport->tp_tdev = usb_get_serial_data(port->serial); 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); 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; const struct firmware *fw_p;
char buf[32]; 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 */ /* try ID specific firmware first, then try generic firmware */
sprintf(buf, "ti_usb-v%04x-p%04x.fw", sprintf(buf, "ti_usb-v%04x-p%04x.fw",
le16_to_cpu(dev->descriptor.idVendor), 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); status = request_firmware(&fw_p, buf, &dev->dev);
} }
check_firmware:
if (status) { if (status) {
dev_err(&dev->dev, "%s - firmware not found\n", __func__); dev_err(&dev->dev, "%s - firmware not found\n", __func__);
return -ENOENT; return -ENOENT;

View File

@ -60,6 +60,14 @@
#define HONEYWELL_VENDOR_ID 0x10ac #define HONEYWELL_VENDOR_ID 0x10ac
#define HONEYWELL_HGI80_PRODUCT_ID 0x0102 /* Honeywell HGI80 */ #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 */ /* Commands */
#define TI_GET_VERSION 0x01 #define TI_GET_VERSION 0x01
#define TI_GET_PORT_STATUS 0x02 #define TI_GET_PORT_STATUS 0x02

View File

@ -96,7 +96,8 @@ static int allocate_minors(struct usb_serial *serial, int num_ports)
mutex_lock(&table_lock); mutex_lock(&table_lock);
for (i = 0; i < num_ports; ++i) { for (i = 0; i < num_ports; ++i) {
port = serial->port[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) if (minor < 0)
goto error; goto error;
port->minor = minor; 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 */ /* BEGIN HORRIBLE HACK FOR PL2303 */
/* this is needed due to the looney way its endpoints are set up */ /* this is needed due to the looney way its endpoints are set up */
if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) && if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&