USB-serial updates for 5.16-rc1

Here are the USB-serial updates for 5.16-rc1, including:
 
  - conversions of usb_control_msg() calls to use the new wrappers where
    appropriate
  - fix of the keyspan probe error handling after a low-order allocation
    failure (e.g. due to fault injection)
  - allow hung up ports to be runtime suspended
 
 Included are also some related clean ups.
 
 All have been in linux-next with no reported issues.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQQHbPq+cpGvN/peuzMLxc3C7H1lCAUCYXuuDwAKCRALxc3C7H1l
 CNStAP4ubIEo6iYNF1N9FvkyvIDIlsSF8GOzXpT433cY0jQjxgD+LhzgIbtDi6SI
 6Rt91qPdkf+eAsHTLDFjEygigjtinww=
 =HGXC
 -----END PGP SIGNATURE-----

Merge tag 'usb-serial-5.16-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next

Johan writes:

USB-serial updates for 5.16-rc1

Here are the USB-serial updates for 5.16-rc1, including:

 - conversions of usb_control_msg() calls to use the new wrappers where
   appropriate
 - fix of the keyspan probe error handling after a low-order allocation
   failure (e.g. due to fault injection)
 - allow hung up ports to be runtime suspended

Included are also some related clean ups.

All have been in linux-next with no reported issues.

* tag 'usb-serial-5.16-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial:
  USB: serial: keyspan: fix memleak on probe errors
  USB: serial: cp210x: use usb_control_msg_recv() and usb_control_msg_send()
  USB: serial: ch314: use usb_control_msg_recv()
  USB: serial: kl5kusb105: drop line-status helper
  USB: serial: kl5kusb105: simplify line-status handling
  USB: serial: kl5kusb105: clean up line-status handling
  USB: serial: kl5kusb105: use usb_control_msg_recv() and usb_control_msg_send()
  USB: serial: keyspan_pda: use usb_control_msg_recv()
  USB: serial: ftdi_sio: use usb_control_msg_recv()
  USB: serial: f81232: use usb_control_msg_recv() and usb_control_msg_send()
  USB: serial: allow hung up ports to be suspended
  USB: serial: clean up core error labels
This commit is contained in:
Greg Kroah-Hartman 2021-10-29 16:56:03 +02:00
commit c47055e943
8 changed files with 215 additions and 384 deletions

View File

@ -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,

View File

@ -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)

View File

@ -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;
}

View File

@ -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_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;
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];
}
kfree(buf);
usb_autopm_put_interface(serial->interface);
return result;

View File

@ -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;

View File

@ -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;
u8 data;
data = kmalloc(1, GFP_KERNEL);
if (!data)
return -ENOMEM;
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;
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;
kfree(data);
return rc;
}

View File

@ -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);
dev_dbg(&port->dev, "read status %02x %02x\n",
status_buf[0], status_buf[1]);
*line_state_p = klsi_105_status2linestate(status);
return rc;
}
kfree(status_buf);
return rc;
le16_to_cpus(&status);
dev_dbg(&port->dev, "read status %04x\n", status);
*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)

View File

@ -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;
}