mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 17:12:06 +00:00
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:
commit
c47055e943
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user