diff options
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/ch341.c | 85 | ||||
-rw-r--r-- | drivers/usb/serial/cp210x.c | 109 | ||||
-rw-r--r-- | drivers/usb/serial/f81232.c | 96 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 53 | ||||
-rw-r--r-- | drivers/usb/serial/keyspan.c | 15 | ||||
-rw-r--r-- | drivers/usb/serial/keyspan_pda.c | 67 | ||||
-rw-r--r-- | drivers/usb/serial/kl5kusb105.c | 115 | ||||
-rw-r--r-- | drivers/usb/serial/option.c | 8 | ||||
-rw-r--r-- | drivers/usb/serial/qcserial.c | 1 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 59 |
10 files changed, 224 insertions, 384 deletions
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 2db917eab799..29f4b87a9e74 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -131,17 +131,11 @@ static int ch341_control_in(struct usb_device *dev, dev_dbg(&dev->dev, "%s - (%02x,%04x,%04x,%u)\n", __func__, request, value, index, bufsize); - r = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - value, index, buf, bufsize, DEFAULT_TIMEOUT); - if (r < (int)bufsize) { - if (r >= 0) { - dev_err(&dev->dev, - "short control message received (%d < %u)\n", - r, bufsize); - r = -EIO; - } - + r = usb_control_msg_recv(dev, 0, request, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + value, index, buf, bufsize, DEFAULT_TIMEOUT, + GFP_KERNEL); + if (r) { dev_err(&dev->dev, "failed to receive control message: %d\n", r); return r; @@ -287,24 +281,19 @@ static int ch341_set_handshake(struct usb_device *dev, u8 control) static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv) { const unsigned int size = 2; - char *buffer; + u8 buffer[2]; int r; unsigned long flags; - buffer = kmalloc(size, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - r = ch341_control_in(dev, CH341_REQ_READ_REG, 0x0706, 0, buffer, size); - if (r < 0) - goto out; + if (r) + return r; spin_lock_irqsave(&priv->lock, flags); priv->msr = (~(*buffer)) & CH341_BITS_MODEM_STAT; spin_unlock_irqrestore(&priv->lock, flags); -out: kfree(buffer); - return r; + return 0; } /* -------------------------------------------------------------------------- */ @@ -312,31 +301,28 @@ out: kfree(buffer); static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) { const unsigned int size = 2; - char *buffer; + u8 buffer[2]; int r; - buffer = kmalloc(size, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - /* expect two bytes 0x27 0x00 */ r = ch341_control_in(dev, CH341_REQ_READ_VERSION, 0, 0, buffer, size); - if (r < 0) - goto out; + if (r) + return r; dev_dbg(&dev->dev, "Chip version: 0x%02x\n", buffer[0]); r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT, 0, 0); if (r < 0) - goto out; + return r; r = ch341_set_baudrate_lcr(dev, priv, priv->baud_rate, priv->lcr); if (r < 0) - goto out; + return r; r = ch341_set_handshake(dev, priv->mcr); + if (r < 0) + return r; -out: kfree(buffer); - return r; + return 0; } static int ch341_detect_quirks(struct usb_serial_port *port) @@ -345,40 +331,27 @@ static int ch341_detect_quirks(struct usb_serial_port *port) struct usb_device *udev = port->serial->dev; const unsigned int size = 2; unsigned long quirks = 0; - char *buffer; + u8 buffer[2]; int r; - buffer = kmalloc(size, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - /* * A subset of CH34x devices does not support all features. The * prescaler is limited and there is no support for sending a RS232 * break condition. A read failure when trying to set up the latter is * used to detect these devices. */ - r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), CH341_REQ_READ_REG, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - CH341_REG_BREAK, 0, buffer, size, DEFAULT_TIMEOUT); + r = usb_control_msg_recv(udev, 0, CH341_REQ_READ_REG, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + CH341_REG_BREAK, 0, &buffer, size, + DEFAULT_TIMEOUT, GFP_KERNEL); if (r == -EPIPE) { dev_info(&port->dev, "break control not supported, using simulated break\n"); quirks = CH341_QUIRK_LIMITED_PRESCALER | CH341_QUIRK_SIMULATE_BREAK; r = 0; - goto out; - } - - if (r != size) { - if (r >= 0) - r = -EIO; + } else if (r) { dev_err(&port->dev, "failed to read break control: %d\n", r); - goto out; } - r = 0; -out: - kfree(buffer); - if (quirks) { dev_dbg(&port->dev, "enabling quirk flags: 0x%02lx\n", quirks); priv->quirks |= quirks; @@ -647,23 +620,19 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state) struct ch341_private *priv = usb_get_serial_port_data(port); int r; uint16_t reg_contents; - uint8_t *break_reg; + uint8_t break_reg[2]; if (priv->quirks & CH341_QUIRK_SIMULATE_BREAK) { ch341_simulate_break(tty, break_state); return; } - break_reg = kmalloc(2, GFP_KERNEL); - if (!break_reg) - return; - r = ch341_control_in(port->serial->dev, CH341_REQ_READ_REG, ch341_break_reg, 0, break_reg, 2); - if (r < 0) { + if (r) { dev_err(&port->dev, "%s - USB control read error (%d)\n", __func__, r); - goto out; + return; } dev_dbg(&port->dev, "%s - initial ch341 break register contents - reg1: %x, reg2: %x\n", __func__, break_reg[0], break_reg[1]); @@ -684,8 +653,6 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state) if (r < 0) dev_err(&port->dev, "%s - USB control write error (%d)\n", __func__, r); -out: - kfree(break_reg); } static int ch341_tiocmset(struct tty_struct *tty, diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 189279869a8b..7705328034ca 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -631,30 +631,20 @@ static int cp210x_read_reg_block(struct usb_serial_port *port, u8 req, { struct usb_serial *serial = port->serial; struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); - void *dmabuf; int result; - dmabuf = kmalloc(bufsize, GFP_KERNEL); - if (!dmabuf) - return -ENOMEM; - result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - req, REQTYPE_INTERFACE_TO_HOST, 0, - port_priv->bInterfaceNumber, dmabuf, bufsize, - USB_CTRL_GET_TIMEOUT); - if (result == bufsize) { - memcpy(buf, dmabuf, bufsize); - result = 0; - } else { + result = usb_control_msg_recv(serial->dev, 0, req, + REQTYPE_INTERFACE_TO_HOST, 0, + port_priv->bInterfaceNumber, buf, bufsize, + USB_CTRL_SET_TIMEOUT, GFP_KERNEL); + if (result) { dev_err(&port->dev, "failed get req 0x%x size %d status: %d\n", req, bufsize, result); - if (result >= 0) - result = -EIO; + return result; } - kfree(dmabuf); - - return result; + return 0; } /* @@ -672,31 +662,19 @@ static int cp210x_read_u8_reg(struct usb_serial_port *port, u8 req, u8 *val) static int cp210x_read_vendor_block(struct usb_serial *serial, u8 type, u16 val, void *buf, int bufsize) { - void *dmabuf; int result; - dmabuf = kmalloc(bufsize, GFP_KERNEL); - if (!dmabuf) - return -ENOMEM; - - result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - CP210X_VENDOR_SPECIFIC, type, val, - cp210x_interface_num(serial), dmabuf, bufsize, - USB_CTRL_GET_TIMEOUT); - if (result == bufsize) { - memcpy(buf, dmabuf, bufsize); - result = 0; - } else { + result = usb_control_msg_recv(serial->dev, 0, CP210X_VENDOR_SPECIFIC, + type, val, cp210x_interface_num(serial), buf, bufsize, + USB_CTRL_GET_TIMEOUT, GFP_KERNEL); + if (result) { dev_err(&serial->interface->dev, "failed to get vendor val 0x%04x size %d: %d\n", val, bufsize, result); - if (result >= 0) - result = -EIO; + return result; } - kfree(dmabuf); - - return result; + return 0; } /* @@ -730,21 +708,13 @@ static int cp210x_write_reg_block(struct usb_serial_port *port, u8 req, { struct usb_serial *serial = port->serial; struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); - void *dmabuf; int result; - dmabuf = kmemdup(buf, bufsize, GFP_KERNEL); - if (!dmabuf) - return -ENOMEM; - - result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - req, REQTYPE_HOST_TO_INTERFACE, 0, - port_priv->bInterfaceNumber, dmabuf, bufsize, - USB_CTRL_SET_TIMEOUT); - - kfree(dmabuf); - - if (result < 0) { + result = usb_control_msg_send(serial->dev, 0, req, + REQTYPE_HOST_TO_INTERFACE, 0, + port_priv->bInterfaceNumber, buf, bufsize, + USB_CTRL_SET_TIMEOUT, GFP_KERNEL); + if (result) { dev_err(&port->dev, "failed set req 0x%x size %d status: %d\n", req, bufsize, result); return result; @@ -773,21 +743,12 @@ static int cp210x_write_u32_reg(struct usb_serial_port *port, u8 req, u32 val) static int cp210x_write_vendor_block(struct usb_serial *serial, u8 type, u16 val, void *buf, int bufsize) { - void *dmabuf; int result; - dmabuf = kmemdup(buf, bufsize, GFP_KERNEL); - if (!dmabuf) - return -ENOMEM; - - result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - CP210X_VENDOR_SPECIFIC, type, val, - cp210x_interface_num(serial), dmabuf, bufsize, - USB_CTRL_SET_TIMEOUT); - - kfree(dmabuf); - - if (result < 0) { + result = usb_control_msg_send(serial->dev, 0, CP210X_VENDOR_SPECIFIC, + type, val, cp210x_interface_num(serial), buf, bufsize, + USB_CTRL_SET_TIMEOUT, GFP_KERNEL); + if (result) { dev_err(&serial->interface->dev, "failed to set vendor val 0x%04x size %d: %d\n", val, bufsize, result); @@ -952,29 +913,21 @@ static int cp210x_get_tx_queue_byte_count(struct usb_serial_port *port, { struct usb_serial *serial = port->serial; struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); - struct cp210x_comm_status *sts; + struct cp210x_comm_status sts; int result; - sts = kmalloc(sizeof(*sts), GFP_KERNEL); - if (!sts) - return -ENOMEM; - - result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - CP210X_GET_COMM_STATUS, REQTYPE_INTERFACE_TO_HOST, - 0, port_priv->bInterfaceNumber, sts, sizeof(*sts), - USB_CTRL_GET_TIMEOUT); - if (result == sizeof(*sts)) { - *count = le32_to_cpu(sts->ulAmountInOutQueue); - result = 0; - } else { + result = usb_control_msg_recv(serial->dev, 0, CP210X_GET_COMM_STATUS, + REQTYPE_INTERFACE_TO_HOST, 0, + port_priv->bInterfaceNumber, &sts, sizeof(sts), + USB_CTRL_GET_TIMEOUT, GFP_KERNEL); + if (result) { dev_err(&port->dev, "failed to get comm status: %d\n", result); - if (result >= 0) - result = -EIO; + return result; } - kfree(sts); + *count = le32_to_cpu(sts.ulAmountInOutQueue); - return result; + return 0; } static bool cp210x_tx_empty(struct usb_serial_port *port) diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index a7a7af8d05bf..3ad1f515fb68 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -139,67 +139,46 @@ static int calc_baud_divisor(speed_t baudrate, speed_t clockrate) static int f81232_get_register(struct usb_serial_port *port, u16 reg, u8 *val) { int status; - u8 *tmp; struct usb_device *dev = port->serial->dev; - tmp = kmalloc(sizeof(*val), GFP_KERNEL); - if (!tmp) - return -ENOMEM; - - status = usb_control_msg(dev, - usb_rcvctrlpipe(dev, 0), - F81232_REGISTER_REQUEST, - F81232_GET_REGISTER, - reg, - 0, - tmp, - sizeof(*val), - USB_CTRL_GET_TIMEOUT); - if (status != sizeof(*val)) { + status = usb_control_msg_recv(dev, + 0, + F81232_REGISTER_REQUEST, + F81232_GET_REGISTER, + reg, + 0, + val, + sizeof(*val), + USB_CTRL_GET_TIMEOUT, + GFP_KERNEL); + if (status) { dev_err(&port->dev, "%s failed status: %d\n", __func__, status); - - if (status < 0) - status = usb_translate_errors(status); - else - status = -EIO; - } else { - status = 0; - *val = *tmp; + status = usb_translate_errors(status); } - kfree(tmp); return status; } static int f81232_set_register(struct usb_serial_port *port, u16 reg, u8 val) { int status; - u8 *tmp; struct usb_device *dev = port->serial->dev; - tmp = kmalloc(sizeof(val), GFP_KERNEL); - if (!tmp) - return -ENOMEM; - - *tmp = val; - - status = usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - F81232_REGISTER_REQUEST, - F81232_SET_REGISTER, - reg, - 0, - tmp, - sizeof(val), - USB_CTRL_SET_TIMEOUT); - if (status < 0) { + status = usb_control_msg_send(dev, + 0, + F81232_REGISTER_REQUEST, + F81232_SET_REGISTER, + reg, + 0, + &val, + sizeof(val), + USB_CTRL_SET_TIMEOUT, + GFP_KERNEL); + if (status) { dev_err(&port->dev, "%s failed status: %d\n", __func__, status); status = usb_translate_errors(status); - } else { - status = 0; } - kfree(tmp); return status; } @@ -857,28 +836,22 @@ static int f81534a_ctrl_set_register(struct usb_interface *intf, u16 reg, struct usb_device *dev = interface_to_usbdev(intf); int retry = F81534A_ACCESS_REG_RETRY; int status; - u8 *tmp; - - tmp = kmemdup(val, size, GFP_KERNEL); - if (!tmp) - return -ENOMEM; while (retry--) { - status = usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - F81232_REGISTER_REQUEST, - F81232_SET_REGISTER, - reg, - 0, - tmp, - size, - USB_CTRL_SET_TIMEOUT); - if (status < 0) { + status = usb_control_msg_send(dev, + 0, + F81232_REGISTER_REQUEST, + F81232_SET_REGISTER, + reg, + 0, + val, + size, + USB_CTRL_SET_TIMEOUT, + GFP_KERNEL); + if (status) { status = usb_translate_errors(status); if (status == -EIO) continue; - } else { - status = 0; } break; @@ -889,7 +862,6 @@ static int f81534a_ctrl_set_register(struct usb_interface *intf, u16 reg, reg, status); } - kfree(tmp); return status; } diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 99d19828dae6..4edebd14ef29 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1437,27 +1437,15 @@ static int _read_latency_timer(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); struct usb_device *udev = port->serial->dev; - unsigned char *buf; + u8 buf; int rv; - buf = kmalloc(1, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - rv = usb_control_msg(udev, - usb_rcvctrlpipe(udev, 0), - FTDI_SIO_GET_LATENCY_TIMER_REQUEST, - FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, - 0, priv->interface, - buf, 1, WDR_TIMEOUT); - if (rv < 1) { - if (rv >= 0) - rv = -EIO; - } else { - rv = buf[0]; - } - - kfree(buf); + rv = usb_control_msg_recv(udev, 0, FTDI_SIO_GET_LATENCY_TIMER_REQUEST, + FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, 0, + priv->interface, &buf, 1, WDR_TIMEOUT, + GFP_KERNEL); + if (rv == 0) + rv = buf; return rv; } @@ -1852,32 +1840,21 @@ static int ftdi_read_cbus_pins(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); struct usb_serial *serial = port->serial; - unsigned char *buf; + u8 buf; int result; result = usb_autopm_get_interface(serial->interface); if (result) return result; - buf = kmalloc(1, GFP_KERNEL); - if (!buf) { - usb_autopm_put_interface(serial->interface); - return -ENOMEM; - } - - result = usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - FTDI_SIO_READ_PINS_REQUEST, - FTDI_SIO_READ_PINS_REQUEST_TYPE, 0, - priv->interface, buf, 1, WDR_TIMEOUT); - if (result < 1) { - if (result >= 0) - result = -EIO; - } else { - result = buf[0]; - } + result = usb_control_msg_recv(serial->dev, 0, + FTDI_SIO_READ_PINS_REQUEST, + FTDI_SIO_READ_PINS_REQUEST_TYPE, 0, + priv->interface, &buf, 1, WDR_TIMEOUT, + GFP_KERNEL); + if (result == 0) + result = buf; - kfree(buf); usb_autopm_put_interface(serial->interface); return result; diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 87b89c99d517..1cfcd805f286 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -2890,22 +2890,22 @@ static int keyspan_port_probe(struct usb_serial_port *port) for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) { p_priv->in_buffer[i] = kzalloc(IN_BUFLEN, GFP_KERNEL); if (!p_priv->in_buffer[i]) - goto err_in_buffer; + goto err_free_in_buffer; } for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) { p_priv->out_buffer[i] = kzalloc(OUT_BUFLEN, GFP_KERNEL); if (!p_priv->out_buffer[i]) - goto err_out_buffer; + goto err_free_out_buffer; } p_priv->inack_buffer = kzalloc(INACK_BUFLEN, GFP_KERNEL); if (!p_priv->inack_buffer) - goto err_inack_buffer; + goto err_free_out_buffer; p_priv->outcont_buffer = kzalloc(OUTCONT_BUFLEN, GFP_KERNEL); if (!p_priv->outcont_buffer) - goto err_outcont_buffer; + goto err_free_inack_buffer; p_priv->device_details = d_details; @@ -2951,15 +2951,14 @@ static int keyspan_port_probe(struct usb_serial_port *port) return 0; -err_outcont_buffer: +err_free_inack_buffer: kfree(p_priv->inack_buffer); -err_inack_buffer: +err_free_out_buffer: for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) kfree(p_priv->out_buffer[i]); -err_out_buffer: +err_free_in_buffer: for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) kfree(p_priv->in_buffer[i]); -err_in_buffer: kfree(p_priv); return -ENOMEM; diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 39b0f5f344c2..3e7628becdcd 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -77,36 +77,27 @@ static int keyspan_pda_get_write_room(struct keyspan_pda_private *priv) { struct usb_serial_port *port = priv->port; struct usb_serial *serial = port->serial; - u8 *room; + u8 room; int rc; - room = kmalloc(1, GFP_KERNEL); - if (!room) - return -ENOMEM; - - rc = usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - 6, /* write_room */ - USB_TYPE_VENDOR | USB_RECIP_INTERFACE - | USB_DIR_IN, - 0, /* value: 0 means "remaining room" */ - 0, /* index */ - room, - 1, - 2000); - if (rc != 1) { - if (rc >= 0) - rc = -EIO; + rc = usb_control_msg_recv(serial->dev, + 0, + 6, /* write_room */ + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_IN, + 0, /* value: 0 means "remaining room" */ + 0, /* index */ + &room, + 1, + 2000, + GFP_KERNEL); + if (rc) { dev_dbg(&port->dev, "roomquery failed: %d\n", rc); - goto out_free; + return rc; } - dev_dbg(&port->dev, "roomquery says %d\n", *room); - rc = *room; -out_free: - kfree(room); + dev_dbg(&port->dev, "roomquery says %d\n", room); - return rc; + return room; } static void keyspan_pda_request_unthrottle(struct work_struct *work) @@ -381,22 +372,20 @@ static int keyspan_pda_get_modem_info(struct usb_serial *serial, unsigned char *value) { int rc; - u8 *data; - - data = kmalloc(1, GFP_KERNEL); - if (!data) - return -ENOMEM; - - rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - 3, /* get pins */ - USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN, - 0, 0, data, 1, 2000); - if (rc == 1) - *value = *data; - else if (rc >= 0) - rc = -EIO; + u8 data; + + rc = usb_control_msg_recv(serial->dev, 0, + 3, /* get pins */ + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_IN, + 0, + 0, + &data, + 1, + 2000, + GFP_KERNEL); + if (rc == 0) + *value = data; - kfree(data); return rc; } diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index f1e9628a9907..edcc57bd9b5e 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -124,16 +124,18 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port, { int rc; - rc = usb_control_msg(port->serial->dev, - usb_sndctrlpipe(port->serial->dev, 0), - KL5KUSB105A_SIO_SET_DATA, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE, - 0, /* value */ - 0, /* index */ - settings, - sizeof(struct klsi_105_port_settings), - KLSI_TIMEOUT); - if (rc < 0) + rc = usb_control_msg_send(port->serial->dev, + 0, + KL5KUSB105A_SIO_SET_DATA, + USB_TYPE_VENDOR | USB_DIR_OUT | + USB_RECIP_INTERFACE, + 0, /* value */ + 0, /* index */ + settings, + sizeof(struct klsi_105_port_settings), + KLSI_TIMEOUT, + GFP_KERNEL); + if (rc) dev_err(&port->dev, "Change port settings failed (error = %d)\n", rc); @@ -145,61 +147,37 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port, return rc; } -/* translate a 16-bit status value from the device to linux's TIO bits */ -static unsigned long klsi_105_status2linestate(const __u16 status) -{ - unsigned long res = 0; - - res = ((status & KL5KUSB105A_DSR) ? TIOCM_DSR : 0) - | ((status & KL5KUSB105A_CTS) ? TIOCM_CTS : 0) - ; - - return res; -} - /* * Read line control via vendor command and return result through - * *line_state_p + * the state pointer. */ -/* It seems that the status buffer has always only 2 bytes length */ -#define KLSI_STATUSBUF_LEN 2 static int klsi_105_get_line_state(struct usb_serial_port *port, - unsigned long *line_state_p) + unsigned long *state) { + u16 status; int rc; - u8 *status_buf; - __u16 status; - - status_buf = kmalloc(KLSI_STATUSBUF_LEN, GFP_KERNEL); - if (!status_buf) - return -ENOMEM; - status_buf[0] = 0xff; - status_buf[1] = 0xff; - rc = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), - KL5KUSB105A_SIO_POLL, - USB_TYPE_VENDOR | USB_DIR_IN, - 0, /* value */ - 0, /* index */ - status_buf, KLSI_STATUSBUF_LEN, - 10000 - ); - if (rc != KLSI_STATUSBUF_LEN) { + rc = usb_control_msg_recv(port->serial->dev, 0, + KL5KUSB105A_SIO_POLL, + USB_TYPE_VENDOR | USB_DIR_IN, + 0, /* value */ + 0, /* index */ + &status, sizeof(status), + 10000, + GFP_KERNEL); + if (rc) { dev_err(&port->dev, "reading line status failed: %d\n", rc); - if (rc >= 0) - rc = -EIO; - } else { - status = get_unaligned_le16(status_buf); + return rc; + } - dev_dbg(&port->dev, "read status %02x %02x\n", - status_buf[0], status_buf[1]); + le16_to_cpus(&status); - *line_state_p = klsi_105_status2linestate(status); - } + dev_dbg(&port->dev, "read status %04x\n", status); - kfree(status_buf); - return rc; + *state = ((status & KL5KUSB105A_DSR) ? TIOCM_DSR : 0) | + ((status & KL5KUSB105A_CTS) ? TIOCM_CTS : 0); + + return 0; } @@ -245,7 +223,7 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) int retval = 0; int rc; unsigned long line_state; - struct klsi_105_port_settings *cfg; + struct klsi_105_port_settings cfg; unsigned long flags; /* Do a defined restart: @@ -255,27 +233,22 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) * Then read the modem line control and store values in * priv->line_state. */ - cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); - if (!cfg) - return -ENOMEM; - cfg->pktlen = 5; - cfg->baudrate = kl5kusb105a_sio_b9600; - cfg->databits = kl5kusb105a_dtb_8; - cfg->unknown1 = 0; - cfg->unknown2 = 1; - klsi_105_chg_port_settings(port, cfg); + cfg.pktlen = 5; + cfg.baudrate = kl5kusb105a_sio_b9600; + cfg.databits = kl5kusb105a_dtb_8; + cfg.unknown1 = 0; + cfg.unknown2 = 1; + klsi_105_chg_port_settings(port, &cfg); spin_lock_irqsave(&priv->lock, flags); - priv->cfg.pktlen = cfg->pktlen; - priv->cfg.baudrate = cfg->baudrate; - priv->cfg.databits = cfg->databits; - priv->cfg.unknown1 = cfg->unknown1; - priv->cfg.unknown2 = cfg->unknown2; + priv->cfg.pktlen = cfg.pktlen; + priv->cfg.baudrate = cfg.baudrate; + priv->cfg.databits = cfg.databits; + priv->cfg.unknown1 = cfg.unknown1; + priv->cfg.unknown2 = cfg.unknown2; spin_unlock_irqrestore(&priv->lock, flags); - kfree(cfg); - /* READ_ON and urb submission */ rc = usb_serial_generic_open(tty, port); if (rc) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6cfb5d33609f..a484ff5e4ebf 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -246,11 +246,13 @@ static void option_instat_callback(struct urb *urb); /* These Quectel products use Quectel's vendor ID */ #define QUECTEL_PRODUCT_EC21 0x0121 #define QUECTEL_PRODUCT_EC25 0x0125 +#define QUECTEL_PRODUCT_EG91 0x0191 #define QUECTEL_PRODUCT_EG95 0x0195 #define QUECTEL_PRODUCT_BG96 0x0296 #define QUECTEL_PRODUCT_EP06 0x0306 #define QUECTEL_PRODUCT_EM12 0x0512 #define QUECTEL_PRODUCT_RM500Q 0x0800 +#define QUECTEL_PRODUCT_EC200S_CN 0x6002 #define QUECTEL_PRODUCT_EC200T 0x6026 #define CMOTECH_VENDOR_ID 0x16d8 @@ -1111,6 +1113,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25, 0xff, 0xff, 0xff), .driver_info = NUMEP2 }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG91, 0xff, 0xff, 0xff), + .driver_info = NUMEP2 }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG91, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0xff, 0xff), .driver_info = NUMEP2 }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) }, @@ -1128,6 +1133,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x10), .driver_info = ZLP }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, @@ -1227,6 +1233,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1203, 0xff), /* Telit LE910Cx (RNDIS) */ .driver_info = NCTRL(2) | RSVD(3) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1204, 0xff), /* Telit LE910Cx (MBIM) */ + .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4), .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) | RSVD(3) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 83da8236e3c8..c18bf8164bc2 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -165,6 +165,7 @@ static const struct usb_device_id id_table[] = { {DEVICE_SWI(0x1199, 0x907b)}, /* Sierra Wireless EM74xx */ {DEVICE_SWI(0x1199, 0x9090)}, /* Sierra Wireless EM7565 QDL */ {DEVICE_SWI(0x1199, 0x9091)}, /* Sierra Wireless EM7565 */ + {DEVICE_SWI(0x1199, 0x90d2)}, /* Sierra Wireless EM9191 QDL */ {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 090a78c948f2..24101bd7fcad 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -208,8 +208,8 @@ void usb_serial_put(struct usb_serial *serial) * * This is the first place a new tty gets used. Hence this is where we * acquire references to the usb_serial structure and the driver module, - * where we store a pointer to the port, and where we do an autoresume. - * All these actions are reversed in serial_cleanup(). + * where we store a pointer to the port. All these actions are reversed + * in serial_cleanup(). */ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) { @@ -225,17 +225,13 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) serial = port->serial; if (!try_module_get(serial->type->driver.owner)) - goto error_module_get; - - retval = usb_autopm_get_interface(serial->interface); - if (retval) - goto error_get_interface; + goto err_put_serial; init_termios = (driver->termios[idx] == NULL); retval = tty_standard_install(driver, tty); if (retval) - goto error_init_termios; + goto err_put_module; mutex_unlock(&serial->disc_mutex); @@ -247,11 +243,9 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) return retval; - error_init_termios: - usb_autopm_put_interface(serial->interface); - error_get_interface: +err_put_module: module_put(serial->type->driver.owner); - error_module_get: +err_put_serial: usb_serial_put(serial); mutex_unlock(&serial->disc_mutex); return retval; @@ -265,10 +259,19 @@ static int serial_port_activate(struct tty_port *tport, struct tty_struct *tty) int retval; mutex_lock(&serial->disc_mutex); - if (serial->disconnected) + if (serial->disconnected) { retval = -ENODEV; - else - retval = port->serial->type->open(tty, port); + goto out_unlock; + } + + retval = usb_autopm_get_interface(serial->interface); + if (retval) + goto out_unlock; + + retval = port->serial->type->open(tty, port); + if (retval) + usb_autopm_put_interface(serial->interface); +out_unlock: mutex_unlock(&serial->disc_mutex); if (retval < 0) @@ -304,6 +307,8 @@ static void serial_port_shutdown(struct tty_port *tport) if (drv->close) drv->close(port); + + usb_autopm_put_interface(port->serial->interface); } static void serial_hangup(struct tty_struct *tty) @@ -352,8 +357,6 @@ static void serial_cleanup(struct tty_struct *tty) serial = port->serial; owner = serial->type->driver.owner; - usb_autopm_put_interface(serial->interface); - usb_serial_put(serial); module_put(owner); } @@ -1328,7 +1331,7 @@ static int __init usb_serial_init(void) result = bus_register(&usb_serial_bus_type); if (result) { pr_err("%s - registering bus driver failed\n", __func__); - goto exit_bus; + goto err_put_driver; } usb_serial_tty_driver->driver_name = "usbserial"; @@ -1346,25 +1349,23 @@ static int __init usb_serial_init(void) result = tty_register_driver(usb_serial_tty_driver); if (result) { pr_err("%s - tty_register_driver failed\n", __func__); - goto exit_reg_driver; + goto err_unregister_bus; } /* register the generic driver, if we should */ result = usb_serial_generic_register(); if (result < 0) { pr_err("%s - registering generic driver failed\n", __func__); - goto exit_generic; + goto err_unregister_driver; } return result; -exit_generic: +err_unregister_driver: tty_unregister_driver(usb_serial_tty_driver); - -exit_reg_driver: +err_unregister_bus: bus_unregister(&usb_serial_bus_type); - -exit_bus: +err_put_driver: pr_err("%s - returning with error %d\n", __func__, result); tty_driver_kref_put(usb_serial_tty_driver); return result; @@ -1509,13 +1510,13 @@ int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[] rc = usb_register(udriver); if (rc) - goto failed_usb_register; + goto err_free_driver; for (sd = serial_drivers; *sd; ++sd) { (*sd)->usb_driver = udriver; rc = usb_serial_register(*sd); if (rc) - goto failed; + goto err_deregister_drivers; } /* Now set udriver's id_table and look for matches */ @@ -1523,11 +1524,11 @@ int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[] rc = driver_attach(&udriver->drvwrap.driver); return 0; - failed: +err_deregister_drivers: while (sd-- > serial_drivers) usb_serial_deregister(*sd); usb_deregister(udriver); -failed_usb_register: +err_free_driver: kfree(udriver); return rc; } |