USB-serial updates for v4.19-rc1
Here are the USB-serial updates for 4.19-rc1, including: - gpio support for CP2102N devices - improved line-speed handling for cp210x - conversion to spin_lock_irqsave() in completion handlers - dropped kl5kusb105 support from the kl5kusb105 driver (sic!) Included are also various lower-priority fixes and clean ups. All but the final commit have been in linux-next, and with no reported issues. Signed-off-by: Johan Hovold <johan@kernel.org> -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEHszNKQClByu0A+9RQQ3kT97htJUFAltSEpQRHGpvaGFuQGtl cm5lbC5vcmcACgkQQQ3kT97htJUXJA//UaE1M6D5LefGKEitn1CMMqaCxc6M4U/y PyuGnGds22VXYgscQlur++bhetJ12qGWoo8r1IOl4QgZl5dWOISx19F5kgMXBMr7 GKEPraRCdxCvZ4RSKbjinlUIjFBij131doI2NIOP6lVdbnwA+z0fX5OH6zAf61p2 Tr/aNyJmN2eIJJx+ez7PszEB3pczWNpv7uP7tmoZ/cmyLdpRYYJzsaSv4I0KA4dz d87IQ9G2eG1BGbs3cYN7fUwwNhcsKG7wfonXMfQPEENdyPWdle7sh/EiubRlquv4 I7xs8+E5zDKChrwavbMQr4uCmXf3L1O7Ueev9718pHzYkQTfxiCvAqt6nhlmkyEx yZdo3DncTMGT3A8/MZk3C66I30xul8z7BH2X0DVXr8yeV4ZN17u7F65Qzyr5Tmni aUYPXaov6JuyLtIBNii3cXMtMuG9ghJoEbXZ2U9DcCFuYeDW6xJuTUd0sKmctTWa htXgW9lvndw0C3ojTXgp6dT2KQyEYhKDM6qdgVhoZV2x4M2XErEMSxTTIm0nlG7O dnrIT3q+iqarxU4vBC6doOq7vbQP5L7UPfpYJcD/AqMvjLX0ZEFInKz+eI2KLUg0 MM8DatTs6z80lClKfKmpNw/bWWcUdKyH9acFXvjrflwwMU2hqsJB9RcsN0d4ppNL QtaT/uY6zls= =0ukW -----END PGP SIGNATURE----- Merge tag 'usb-serial-4.19-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next Johan writes: USB-serial updates for v4.19-rc1 Here are the USB-serial updates for 4.19-rc1, including: - gpio support for CP2102N devices - improved line-speed handling for cp210x - conversion to spin_lock_irqsave() in completion handlers - dropped kl5kusb105 support from the kl5kusb105 driver (sic!) Included are also various lower-priority fixes and clean ups. All but the final commit have been in linux-next, and with no reported issues. Signed-off-by: Johan Hovold <johan@kernel.org>
This commit is contained in:
commit
78fbe864c3
|
@ -418,15 +418,6 @@ Current status:
|
|||
why it is wise to cut down on the rate used is wise for large
|
||||
transfers until this is settled.
|
||||
|
||||
Options supported:
|
||||
If this driver is compiled as a module you can pass the following
|
||||
options to it:
|
||||
debug - extra verbose debugging info
|
||||
(default: 0; nonzero enables)
|
||||
use_lowlatency - use low_latency flag to speed up tty layer
|
||||
when reading from the device.
|
||||
(default: 0; nonzero enables)
|
||||
|
||||
See http://www.uuhaus.de/linux/palmconnect.html for up-to-date
|
||||
information on this driver.
|
||||
|
||||
|
|
|
@ -239,11 +239,14 @@ MODULE_DEVICE_TABLE(usb, id_table);
|
|||
struct cp210x_serial_private {
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
struct gpio_chip gc;
|
||||
u8 config;
|
||||
u8 gpio_mode;
|
||||
bool gpio_registered;
|
||||
u8 gpio_pushpull;
|
||||
u8 gpio_altfunc;
|
||||
u8 gpio_input;
|
||||
#endif
|
||||
u8 partnum;
|
||||
speed_t max_speed;
|
||||
bool use_actual_rate;
|
||||
};
|
||||
|
||||
struct cp210x_port_private {
|
||||
|
@ -356,6 +359,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
|
|||
#define CONTROL_WRITE_RTS 0x0200
|
||||
|
||||
/* CP210X_VENDOR_SPECIFIC values */
|
||||
#define CP210X_READ_2NCONFIG 0x000E
|
||||
#define CP210X_READ_LATCH 0x00C2
|
||||
#define CP210X_GET_PARTNUM 0x370B
|
||||
#define CP210X_GET_PORTCONFIG 0x370C
|
||||
|
@ -369,6 +373,9 @@ static struct usb_serial_driver * const serial_drivers[] = {
|
|||
#define CP210X_PARTNUM_CP2104 0x04
|
||||
#define CP210X_PARTNUM_CP2105 0x05
|
||||
#define CP210X_PARTNUM_CP2108 0x08
|
||||
#define CP210X_PARTNUM_CP2102N_QFN28 0x20
|
||||
#define CP210X_PARTNUM_CP2102N_QFN24 0x21
|
||||
#define CP210X_PARTNUM_CP2102N_QFN20 0x22
|
||||
#define CP210X_PARTNUM_UNKNOWN 0xFF
|
||||
|
||||
/* CP210X_GET_COMM_STATUS returns these 0x13 bytes */
|
||||
|
@ -462,6 +469,12 @@ struct cp210x_config {
|
|||
#define CP2105_GPIO1_RXLED_MODE BIT(1)
|
||||
#define CP2105_GPIO1_RS485_MODE BIT(2)
|
||||
|
||||
/* CP2102N configuration array indices */
|
||||
#define CP210X_2NCONFIG_CONFIG_VERSION_IDX 2
|
||||
#define CP210X_2NCONFIG_GPIO_MODE_IDX 581
|
||||
#define CP210X_2NCONFIG_GPIO_RSTLATCH_IDX 587
|
||||
#define CP210X_2NCONFIG_GPIO_CONTROL_IDX 600
|
||||
|
||||
/* CP210X_VENDOR_SPECIFIC, CP210X_WRITE_LATCH call writes these 0x2 bytes. */
|
||||
struct cp210x_gpio_write {
|
||||
u8 mask;
|
||||
|
@ -767,48 +780,6 @@ static int cp210x_get_line_ctl(struct usb_serial_port *port, u16 *ctl)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* cp210x_quantise_baudrate
|
||||
* Quantises the baud rate as per AN205 Table 1
|
||||
*/
|
||||
static unsigned int cp210x_quantise_baudrate(unsigned int baud)
|
||||
{
|
||||
if (baud <= 300)
|
||||
baud = 300;
|
||||
else if (baud <= 600) baud = 600;
|
||||
else if (baud <= 1200) baud = 1200;
|
||||
else if (baud <= 1800) baud = 1800;
|
||||
else if (baud <= 2400) baud = 2400;
|
||||
else if (baud <= 4000) baud = 4000;
|
||||
else if (baud <= 4803) baud = 4800;
|
||||
else if (baud <= 7207) baud = 7200;
|
||||
else if (baud <= 9612) baud = 9600;
|
||||
else if (baud <= 14428) baud = 14400;
|
||||
else if (baud <= 16062) baud = 16000;
|
||||
else if (baud <= 19250) baud = 19200;
|
||||
else if (baud <= 28912) baud = 28800;
|
||||
else if (baud <= 38601) baud = 38400;
|
||||
else if (baud <= 51558) baud = 51200;
|
||||
else if (baud <= 56280) baud = 56000;
|
||||
else if (baud <= 58053) baud = 57600;
|
||||
else if (baud <= 64111) baud = 64000;
|
||||
else if (baud <= 77608) baud = 76800;
|
||||
else if (baud <= 117028) baud = 115200;
|
||||
else if (baud <= 129347) baud = 128000;
|
||||
else if (baud <= 156868) baud = 153600;
|
||||
else if (baud <= 237832) baud = 230400;
|
||||
else if (baud <= 254234) baud = 250000;
|
||||
else if (baud <= 273066) baud = 256000;
|
||||
else if (baud <= 491520) baud = 460800;
|
||||
else if (baud <= 567138) baud = 500000;
|
||||
else if (baud <= 670254) baud = 576000;
|
||||
else if (baud < 1000000)
|
||||
baud = 921600;
|
||||
else if (baud > 2000000)
|
||||
baud = 2000000;
|
||||
return baud;
|
||||
}
|
||||
|
||||
static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
{
|
||||
int result;
|
||||
|
@ -1028,6 +999,75 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
|
|||
*cflagp = cflag;
|
||||
}
|
||||
|
||||
struct cp210x_rate {
|
||||
speed_t rate;
|
||||
speed_t high;
|
||||
};
|
||||
|
||||
static const struct cp210x_rate cp210x_an205_table1[] = {
|
||||
{ 300, 300 },
|
||||
{ 600, 600 },
|
||||
{ 1200, 1200 },
|
||||
{ 1800, 1800 },
|
||||
{ 2400, 2400 },
|
||||
{ 4000, 4000 },
|
||||
{ 4800, 4803 },
|
||||
{ 7200, 7207 },
|
||||
{ 9600, 9612 },
|
||||
{ 14400, 14428 },
|
||||
{ 16000, 16062 },
|
||||
{ 19200, 19250 },
|
||||
{ 28800, 28912 },
|
||||
{ 38400, 38601 },
|
||||
{ 51200, 51558 },
|
||||
{ 56000, 56280 },
|
||||
{ 57600, 58053 },
|
||||
{ 64000, 64111 },
|
||||
{ 76800, 77608 },
|
||||
{ 115200, 117028 },
|
||||
{ 128000, 129347 },
|
||||
{ 153600, 156868 },
|
||||
{ 230400, 237832 },
|
||||
{ 250000, 254234 },
|
||||
{ 256000, 273066 },
|
||||
{ 460800, 491520 },
|
||||
{ 500000, 567138 },
|
||||
{ 576000, 670254 },
|
||||
{ 921600, UINT_MAX }
|
||||
};
|
||||
|
||||
/*
|
||||
* Quantises the baud rate as per AN205 Table 1
|
||||
*/
|
||||
static speed_t cp210x_get_an205_rate(speed_t baud)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cp210x_an205_table1); ++i) {
|
||||
if (baud <= cp210x_an205_table1[i].high)
|
||||
break;
|
||||
}
|
||||
|
||||
return cp210x_an205_table1[i].rate;
|
||||
}
|
||||
|
||||
static speed_t cp210x_get_actual_rate(struct usb_serial *serial, speed_t baud)
|
||||
{
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
unsigned int prescale = 1;
|
||||
unsigned int div;
|
||||
|
||||
baud = clamp(baud, 300u, priv->max_speed);
|
||||
|
||||
if (baud <= 365)
|
||||
prescale = 4;
|
||||
|
||||
div = DIV_ROUND_CLOSEST(48000000, 2 * prescale * baud);
|
||||
baud = 48000000 / (2 * prescale * div);
|
||||
|
||||
return baud;
|
||||
}
|
||||
|
||||
/*
|
||||
* CP2101 supports the following baud rates:
|
||||
*
|
||||
|
@ -1057,16 +1097,24 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
|
|||
static void cp210x_change_speed(struct tty_struct *tty,
|
||||
struct usb_serial_port *port, struct ktermios *old_termios)
|
||||
{
|
||||
struct usb_serial *serial = port->serial;
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
u32 baud;
|
||||
|
||||
baud = tty->termios.c_ospeed;
|
||||
|
||||
/* This maps the requested rate to a rate valid on cp2102 or cp2103,
|
||||
* or to an arbitrary rate in [1M,2M].
|
||||
/*
|
||||
* This maps the requested rate to the actual rate, a valid rate on
|
||||
* cp2102 or cp2103, or to an arbitrary rate in [1M, max_speed].
|
||||
*
|
||||
* NOTE: B0 is not implemented.
|
||||
*/
|
||||
baud = cp210x_quantise_baudrate(baud);
|
||||
if (priv->use_actual_rate)
|
||||
baud = cp210x_get_actual_rate(serial, baud);
|
||||
else if (baud < 1000000)
|
||||
baud = cp210x_get_an205_rate(baud);
|
||||
else if (baud > priv->max_speed)
|
||||
baud = priv->max_speed;
|
||||
|
||||
dev_dbg(&port->dev, "%s - setting baud rate to %u\n", __func__, baud);
|
||||
if (cp210x_write_u32_reg(port, CP210X_SET_BAUDRATE, baud)) {
|
||||
|
@ -1288,17 +1336,8 @@ static int cp210x_gpio_request(struct gpio_chip *gc, unsigned int offset)
|
|||
struct usb_serial *serial = gpiochip_get_data(gc);
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
|
||||
switch (offset) {
|
||||
case 0:
|
||||
if (priv->config & CP2105_GPIO0_TXLED_MODE)
|
||||
return -ENODEV;
|
||||
break;
|
||||
case 1:
|
||||
if (priv->config & (CP2105_GPIO1_RXLED_MODE |
|
||||
CP2105_GPIO1_RS485_MODE))
|
||||
return -ENODEV;
|
||||
break;
|
||||
}
|
||||
if (priv->gpio_altfunc & BIT(offset))
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1306,10 +1345,15 @@ static int cp210x_gpio_request(struct gpio_chip *gc, unsigned int offset)
|
|||
static int cp210x_gpio_get(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct usb_serial *serial = gpiochip_get_data(gc);
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
u8 req_type = REQTYPE_DEVICE_TO_HOST;
|
||||
int result;
|
||||
u8 buf;
|
||||
|
||||
result = cp210x_read_vendor_block(serial, REQTYPE_INTERFACE_TO_HOST,
|
||||
if (priv->partnum == CP210X_PARTNUM_CP2105)
|
||||
req_type = REQTYPE_INTERFACE_TO_HOST;
|
||||
|
||||
result = cp210x_read_vendor_block(serial, req_type,
|
||||
CP210X_READ_LATCH, &buf, sizeof(buf));
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
@ -1320,7 +1364,9 @@ static int cp210x_gpio_get(struct gpio_chip *gc, unsigned int gpio)
|
|||
static void cp210x_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
|
||||
{
|
||||
struct usb_serial *serial = gpiochip_get_data(gc);
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
struct cp210x_gpio_write buf;
|
||||
int result;
|
||||
|
||||
if (value == 1)
|
||||
buf.state = BIT(gpio);
|
||||
|
@ -1329,25 +1375,68 @@ static void cp210x_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
|
|||
|
||||
buf.mask = BIT(gpio);
|
||||
|
||||
cp210x_write_vendor_block(serial, REQTYPE_HOST_TO_INTERFACE,
|
||||
CP210X_WRITE_LATCH, &buf, sizeof(buf));
|
||||
if (priv->partnum == CP210X_PARTNUM_CP2105) {
|
||||
result = cp210x_write_vendor_block(serial,
|
||||
REQTYPE_HOST_TO_INTERFACE,
|
||||
CP210X_WRITE_LATCH, &buf,
|
||||
sizeof(buf));
|
||||
} else {
|
||||
u16 wIndex = buf.state << 8 | buf.mask;
|
||||
|
||||
result = usb_control_msg(serial->dev,
|
||||
usb_sndctrlpipe(serial->dev, 0),
|
||||
CP210X_VENDOR_SPECIFIC,
|
||||
REQTYPE_HOST_TO_DEVICE,
|
||||
CP210X_WRITE_LATCH,
|
||||
wIndex,
|
||||
NULL, 0, USB_CTRL_SET_TIMEOUT);
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
dev_err(&serial->interface->dev, "failed to set GPIO value: %d\n",
|
||||
result);
|
||||
}
|
||||
}
|
||||
|
||||
static int cp210x_gpio_direction_get(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
/* Hardware does not support an input mode */
|
||||
return 0;
|
||||
struct usb_serial *serial = gpiochip_get_data(gc);
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
|
||||
return priv->gpio_input & BIT(gpio);
|
||||
}
|
||||
|
||||
static int cp210x_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
/* Hardware does not support an input mode */
|
||||
return -ENOTSUPP;
|
||||
struct usb_serial *serial = gpiochip_get_data(gc);
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
|
||||
if (priv->partnum == CP210X_PARTNUM_CP2105) {
|
||||
/* hardware does not support an input mode */
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
/* push-pull pins cannot be changed to be inputs */
|
||||
if (priv->gpio_pushpull & BIT(gpio))
|
||||
return -EINVAL;
|
||||
|
||||
/* make sure to release pin if it is being driven low */
|
||||
cp210x_gpio_set(gc, gpio, 1);
|
||||
|
||||
priv->gpio_input |= BIT(gpio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cp210x_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio,
|
||||
int value)
|
||||
{
|
||||
struct usb_serial *serial = gpiochip_get_data(gc);
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
|
||||
priv->gpio_input &= ~BIT(gpio);
|
||||
cp210x_gpio_set(gc, gpio, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1360,11 +1449,11 @@ static int cp210x_gpio_set_config(struct gpio_chip *gc, unsigned int gpio,
|
|||
|
||||
/* Succeed only if in correct mode (this can't be set at runtime) */
|
||||
if ((param == PIN_CONFIG_DRIVE_PUSH_PULL) &&
|
||||
(priv->gpio_mode & BIT(gpio)))
|
||||
(priv->gpio_pushpull & BIT(gpio)))
|
||||
return 0;
|
||||
|
||||
if ((param == PIN_CONFIG_DRIVE_OPEN_DRAIN) &&
|
||||
!(priv->gpio_mode & BIT(gpio)))
|
||||
!(priv->gpio_pushpull & BIT(gpio)))
|
||||
return 0;
|
||||
|
||||
return -ENOTSUPP;
|
||||
|
@ -1377,12 +1466,13 @@ static int cp210x_gpio_set_config(struct gpio_chip *gc, unsigned int gpio,
|
|||
* this driver that provide GPIO do so in a way that does not impact other
|
||||
* signals and are thus expected to have very different initialisation.
|
||||
*/
|
||||
static int cp2105_shared_gpio_init(struct usb_serial *serial)
|
||||
static int cp2105_gpioconf_init(struct usb_serial *serial)
|
||||
{
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
struct cp210x_pin_mode mode;
|
||||
struct cp210x_config config;
|
||||
u8 intf_num = cp210x_interface_num(serial);
|
||||
u8 iface_config;
|
||||
int result;
|
||||
|
||||
result = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST,
|
||||
|
@ -1399,20 +1489,26 @@ static int cp2105_shared_gpio_init(struct usb_serial *serial)
|
|||
|
||||
/* 2 banks of GPIO - One for the pins taken from each serial port */
|
||||
if (intf_num == 0) {
|
||||
if (mode.eci == CP210X_PIN_MODE_MODEM)
|
||||
if (mode.eci == CP210X_PIN_MODE_MODEM) {
|
||||
/* mark all GPIOs of this interface as reserved */
|
||||
priv->gpio_altfunc = 0xff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
priv->config = config.eci_cfg;
|
||||
priv->gpio_mode = (u8)((le16_to_cpu(config.gpio_mode) &
|
||||
iface_config = config.eci_cfg;
|
||||
priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) &
|
||||
CP210X_ECI_GPIO_MODE_MASK) >>
|
||||
CP210X_ECI_GPIO_MODE_OFFSET);
|
||||
priv->gc.ngpio = 2;
|
||||
} else if (intf_num == 1) {
|
||||
if (mode.sci == CP210X_PIN_MODE_MODEM)
|
||||
if (mode.sci == CP210X_PIN_MODE_MODEM) {
|
||||
/* mark all GPIOs of this interface as reserved */
|
||||
priv->gpio_altfunc = 0xff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
priv->config = config.sci_cfg;
|
||||
priv->gpio_mode = (u8)((le16_to_cpu(config.gpio_mode) &
|
||||
iface_config = config.sci_cfg;
|
||||
priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) &
|
||||
CP210X_SCI_GPIO_MODE_MASK) >>
|
||||
CP210X_SCI_GPIO_MODE_OFFSET);
|
||||
priv->gc.ngpio = 3;
|
||||
|
@ -1420,6 +1516,125 @@ static int cp2105_shared_gpio_init(struct usb_serial *serial)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* mark all pins which are not in GPIO mode */
|
||||
if (iface_config & CP2105_GPIO0_TXLED_MODE) /* GPIO 0 */
|
||||
priv->gpio_altfunc |= BIT(0);
|
||||
if (iface_config & (CP2105_GPIO1_RXLED_MODE | /* GPIO 1 */
|
||||
CP2105_GPIO1_RS485_MODE))
|
||||
priv->gpio_altfunc |= BIT(1);
|
||||
|
||||
/* driver implementation for CP2105 only supports outputs */
|
||||
priv->gpio_input = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cp2102n_gpioconf_init(struct usb_serial *serial)
|
||||
{
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
const u16 config_size = 0x02a6;
|
||||
u8 gpio_rst_latch;
|
||||
u8 config_version;
|
||||
u8 gpio_pushpull;
|
||||
u8 *config_buf;
|
||||
u8 gpio_latch;
|
||||
u8 gpio_ctrl;
|
||||
int result;
|
||||
u8 i;
|
||||
|
||||
/*
|
||||
* Retrieve device configuration from the device.
|
||||
* The array received contains all customization settings done at the
|
||||
* factory/manufacturer. Format of the array is documented at the
|
||||
* time of writing at:
|
||||
* https://www.silabs.com/community/interface/knowledge-base.entry.html/2017/03/31/cp2102n_setconfig-xsfa
|
||||
*/
|
||||
config_buf = kmalloc(config_size, GFP_KERNEL);
|
||||
if (!config_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
result = cp210x_read_vendor_block(serial,
|
||||
REQTYPE_DEVICE_TO_HOST,
|
||||
CP210X_READ_2NCONFIG,
|
||||
config_buf,
|
||||
config_size);
|
||||
if (result < 0) {
|
||||
kfree(config_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
config_version = config_buf[CP210X_2NCONFIG_CONFIG_VERSION_IDX];
|
||||
gpio_pushpull = config_buf[CP210X_2NCONFIG_GPIO_MODE_IDX];
|
||||
gpio_ctrl = config_buf[CP210X_2NCONFIG_GPIO_CONTROL_IDX];
|
||||
gpio_rst_latch = config_buf[CP210X_2NCONFIG_GPIO_RSTLATCH_IDX];
|
||||
|
||||
kfree(config_buf);
|
||||
|
||||
/* Make sure this is a config format we understand. */
|
||||
if (config_version != 0x01)
|
||||
return -ENOTSUPP;
|
||||
|
||||
/*
|
||||
* We only support 4 GPIOs even on the QFN28 package, because
|
||||
* config locations of GPIOs 4-6 determined using reverse
|
||||
* engineering revealed conflicting offsets with other
|
||||
* documented functions. So we'll just play it safe for now.
|
||||
*/
|
||||
priv->gc.ngpio = 4;
|
||||
|
||||
/*
|
||||
* Get default pin states after reset. Needed so we can determine
|
||||
* the direction of an open-drain pin.
|
||||
*/
|
||||
gpio_latch = (gpio_rst_latch >> 3) & 0x0f;
|
||||
|
||||
/* 0 indicates open-drain mode, 1 is push-pull */
|
||||
priv->gpio_pushpull = (gpio_pushpull >> 3) & 0x0f;
|
||||
|
||||
/* 0 indicates GPIO mode, 1 is alternate function */
|
||||
priv->gpio_altfunc = (gpio_ctrl >> 2) & 0x0f;
|
||||
|
||||
/*
|
||||
* The CP2102N does not strictly has input and output pin modes,
|
||||
* it only knows open-drain and push-pull modes which is set at
|
||||
* factory. An open-drain pin can function both as an
|
||||
* input or an output. We emulate input mode for open-drain pins
|
||||
* by making sure they are not driven low, and we do not allow
|
||||
* push-pull pins to be set as an input.
|
||||
*/
|
||||
for (i = 0; i < priv->gc.ngpio; ++i) {
|
||||
/*
|
||||
* Set direction to "input" iff pin is open-drain and reset
|
||||
* value is 1.
|
||||
*/
|
||||
if (!(priv->gpio_pushpull & BIT(i)) && (gpio_latch & BIT(i)))
|
||||
priv->gpio_input |= BIT(i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cp210x_gpio_init(struct usb_serial *serial)
|
||||
{
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
int result;
|
||||
|
||||
switch (priv->partnum) {
|
||||
case CP210X_PARTNUM_CP2105:
|
||||
result = cp2105_gpioconf_init(serial);
|
||||
break;
|
||||
case CP210X_PARTNUM_CP2102N_QFN28:
|
||||
case CP210X_PARTNUM_CP2102N_QFN24:
|
||||
case CP210X_PARTNUM_CP2102N_QFN20:
|
||||
result = cp2102n_gpioconf_init(serial);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
priv->gc.label = "cp210x";
|
||||
priv->gc.request = cp210x_gpio_request;
|
||||
priv->gc.get_direction = cp210x_gpio_direction_get;
|
||||
|
@ -1452,7 +1667,7 @@ static void cp210x_gpio_remove(struct usb_serial *serial)
|
|||
|
||||
#else
|
||||
|
||||
static int cp2105_shared_gpio_init(struct usb_serial *serial)
|
||||
static int cp210x_gpio_init(struct usb_serial *serial)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -1497,6 +1712,50 @@ static int cp210x_port_remove(struct usb_serial_port *port)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void cp210x_init_max_speed(struct usb_serial *serial)
|
||||
{
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
bool use_actual_rate = false;
|
||||
speed_t max;
|
||||
|
||||
switch (priv->partnum) {
|
||||
case CP210X_PARTNUM_CP2101:
|
||||
max = 921600;
|
||||
break;
|
||||
case CP210X_PARTNUM_CP2102:
|
||||
case CP210X_PARTNUM_CP2103:
|
||||
max = 1000000;
|
||||
break;
|
||||
case CP210X_PARTNUM_CP2104:
|
||||
use_actual_rate = true;
|
||||
max = 2000000;
|
||||
break;
|
||||
case CP210X_PARTNUM_CP2108:
|
||||
max = 2000000;
|
||||
break;
|
||||
case CP210X_PARTNUM_CP2105:
|
||||
if (cp210x_interface_num(serial) == 0) {
|
||||
use_actual_rate = true;
|
||||
max = 2000000; /* ECI */
|
||||
} else {
|
||||
max = 921600; /* SCI */
|
||||
}
|
||||
break;
|
||||
case CP210X_PARTNUM_CP2102N_QFN28:
|
||||
case CP210X_PARTNUM_CP2102N_QFN24:
|
||||
case CP210X_PARTNUM_CP2102N_QFN20:
|
||||
use_actual_rate = true;
|
||||
max = 3000000;
|
||||
break;
|
||||
default:
|
||||
max = 2000000;
|
||||
break;
|
||||
}
|
||||
|
||||
priv->max_speed = max;
|
||||
priv->use_actual_rate = use_actual_rate;
|
||||
}
|
||||
|
||||
static int cp210x_attach(struct usb_serial *serial)
|
||||
{
|
||||
int result;
|
||||
|
@ -1517,12 +1776,12 @@ static int cp210x_attach(struct usb_serial *serial)
|
|||
|
||||
usb_set_serial_data(serial, priv);
|
||||
|
||||
if (priv->partnum == CP210X_PARTNUM_CP2105) {
|
||||
result = cp2105_shared_gpio_init(serial);
|
||||
if (result < 0) {
|
||||
dev_err(&serial->interface->dev,
|
||||
"GPIO initialisation failed, continuing without GPIO support\n");
|
||||
}
|
||||
cp210x_init_max_speed(serial);
|
||||
|
||||
result = cp210x_gpio_init(serial);
|
||||
if (result < 0) {
|
||||
dev_err(&serial->interface->dev, "GPIO initialisation failed: %d\n",
|
||||
result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -255,6 +255,7 @@ static void cyberjack_read_int_callback(struct urb *urb)
|
|||
struct device *dev = &port->dev;
|
||||
unsigned char *data = urb->transfer_buffer;
|
||||
int status = urb->status;
|
||||
unsigned long flags;
|
||||
int result;
|
||||
|
||||
/* the urb might have been killed. */
|
||||
|
@ -270,13 +271,13 @@ static void cyberjack_read_int_callback(struct urb *urb)
|
|||
/* This is a announcement of coming bulk_ins. */
|
||||
unsigned short size = ((unsigned short)data[3]<<8)+data[2]+3;
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
old_rdtodo = priv->rdtodo;
|
||||
|
||||
if (old_rdtodo > SHRT_MAX - size) {
|
||||
dev_dbg(dev, "To many bulk_in urbs to do.\n");
|
||||
spin_unlock(&priv->lock);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
|
@ -285,7 +286,7 @@ static void cyberjack_read_int_callback(struct urb *urb)
|
|||
|
||||
dev_dbg(dev, "%s - rdtodo: %d\n", __func__, priv->rdtodo);
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
if (!old_rdtodo) {
|
||||
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
|
||||
|
@ -309,6 +310,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb)
|
|||
struct cyberjack_private *priv = usb_get_serial_port_data(port);
|
||||
struct device *dev = &port->dev;
|
||||
unsigned char *data = urb->transfer_buffer;
|
||||
unsigned long flags;
|
||||
short todo;
|
||||
int result;
|
||||
int status = urb->status;
|
||||
|
@ -325,7 +327,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb)
|
|||
tty_flip_buffer_push(&port->port);
|
||||
}
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* Reduce urbs to do by one. */
|
||||
priv->rdtodo -= urb->actual_length;
|
||||
|
@ -334,7 +336,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb)
|
|||
priv->rdtodo = 0;
|
||||
todo = priv->rdtodo;
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
dev_dbg(dev, "%s - rdtodo: %d\n", __func__, todo);
|
||||
|
||||
|
@ -354,6 +356,7 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
|
|||
struct cyberjack_private *priv = usb_get_serial_port_data(port);
|
||||
struct device *dev = &port->dev;
|
||||
int status = urb->status;
|
||||
unsigned long flags;
|
||||
|
||||
set_bit(0, &port->write_urbs_free);
|
||||
if (status) {
|
||||
|
@ -362,7 +365,7 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
|
|||
return;
|
||||
}
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* only do something if we have more data to send */
|
||||
if (priv->wrfilled) {
|
||||
|
@ -406,7 +409,7 @@ static void cyberjack_write_bulk_callback(struct urb *urb)
|
|||
}
|
||||
|
||||
exit:
|
||||
spin_unlock(&priv->lock);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
usb_serial_port_softint(port);
|
||||
}
|
||||
|
||||
|
|
|
@ -984,6 +984,7 @@ static void digi_write_bulk_callback(struct urb *urb)
|
|||
struct usb_serial *serial;
|
||||
struct digi_port *priv;
|
||||
struct digi_serial *serial_priv;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
int status = urb->status;
|
||||
|
||||
|
@ -1004,15 +1005,15 @@ static void digi_write_bulk_callback(struct urb *urb)
|
|||
/* handle oob callback */
|
||||
if (priv->dp_port_num == serial_priv->ds_oob_port_num) {
|
||||
dev_dbg(&port->dev, "digi_write_bulk_callback: oob callback\n");
|
||||
spin_lock(&priv->dp_port_lock);
|
||||
spin_lock_irqsave(&priv->dp_port_lock, flags);
|
||||
priv->dp_write_urb_in_use = 0;
|
||||
wake_up_interruptible(&port->write_wait);
|
||||
spin_unlock(&priv->dp_port_lock);
|
||||
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* try to send any buffered data on this port */
|
||||
spin_lock(&priv->dp_port_lock);
|
||||
spin_lock_irqsave(&priv->dp_port_lock, flags);
|
||||
priv->dp_write_urb_in_use = 0;
|
||||
if (priv->dp_out_buf_len > 0) {
|
||||
*((unsigned char *)(port->write_urb->transfer_buffer))
|
||||
|
@ -1035,7 +1036,7 @@ static void digi_write_bulk_callback(struct urb *urb)
|
|||
/* lost the race in write_chan(). */
|
||||
schedule_work(&priv->dp_wakeup_work);
|
||||
|
||||
spin_unlock(&priv->dp_port_lock);
|
||||
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
|
||||
if (ret && ret != -EPERM)
|
||||
dev_err_console(port,
|
||||
"%s: usb_submit_urb failed, ret=%d, port=%d\n",
|
||||
|
@ -1381,11 +1382,12 @@ static int digi_read_inb_callback(struct urb *urb)
|
|||
struct usb_serial_port *port = urb->context;
|
||||
struct digi_port *priv = usb_get_serial_port_data(port);
|
||||
unsigned char *buf = urb->transfer_buffer;
|
||||
unsigned long flags;
|
||||
int opcode;
|
||||
int len;
|
||||
int port_status;
|
||||
unsigned char *data;
|
||||
int flag, throttled;
|
||||
int tty_flag, throttled;
|
||||
|
||||
/* short/multiple packet check */
|
||||
if (urb->actual_length < 2) {
|
||||
|
@ -1407,7 +1409,7 @@ static int digi_read_inb_callback(struct urb *urb)
|
|||
return -1;
|
||||
}
|
||||
|
||||
spin_lock(&priv->dp_port_lock);
|
||||
spin_lock_irqsave(&priv->dp_port_lock, flags);
|
||||
|
||||
/* check for throttle; if set, do not resubmit read urb */
|
||||
/* indicate the read chain needs to be restarted on unthrottle */
|
||||
|
@ -1421,7 +1423,7 @@ static int digi_read_inb_callback(struct urb *urb)
|
|||
data = &buf[3];
|
||||
|
||||
/* get flag from port_status */
|
||||
flag = 0;
|
||||
tty_flag = 0;
|
||||
|
||||
/* overrun is special, not associated with a char */
|
||||
if (port_status & DIGI_OVERRUN_ERROR)
|
||||
|
@ -1430,21 +1432,21 @@ static int digi_read_inb_callback(struct urb *urb)
|
|||
/* break takes precedence over parity, */
|
||||
/* which takes precedence over framing errors */
|
||||
if (port_status & DIGI_BREAK_ERROR)
|
||||
flag = TTY_BREAK;
|
||||
tty_flag = TTY_BREAK;
|
||||
else if (port_status & DIGI_PARITY_ERROR)
|
||||
flag = TTY_PARITY;
|
||||
tty_flag = TTY_PARITY;
|
||||
else if (port_status & DIGI_FRAMING_ERROR)
|
||||
flag = TTY_FRAME;
|
||||
tty_flag = TTY_FRAME;
|
||||
|
||||
/* data length is len-1 (one byte of len is port_status) */
|
||||
--len;
|
||||
if (len > 0) {
|
||||
tty_insert_flip_string_fixed_flag(&port->port, data,
|
||||
flag, len);
|
||||
tty_flag, len);
|
||||
tty_flip_buffer_push(&port->port);
|
||||
}
|
||||
}
|
||||
spin_unlock(&priv->dp_port_lock);
|
||||
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
|
||||
|
||||
if (opcode == DIGI_CMD_RECEIVE_DISABLE)
|
||||
dev_dbg(&port->dev, "%s: got RECEIVE_DISABLE\n", __func__);
|
||||
|
@ -1474,6 +1476,7 @@ static int digi_read_oob_callback(struct urb *urb)
|
|||
struct digi_port *priv = usb_get_serial_port_data(port);
|
||||
unsigned char *buf = urb->transfer_buffer;
|
||||
int opcode, line, status, val;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
unsigned int rts;
|
||||
|
||||
|
@ -1506,7 +1509,7 @@ static int digi_read_oob_callback(struct urb *urb)
|
|||
rts = C_CRTSCTS(tty);
|
||||
|
||||
if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
|
||||
spin_lock(&priv->dp_port_lock);
|
||||
spin_lock_irqsave(&priv->dp_port_lock, flags);
|
||||
/* convert from digi flags to termiox flags */
|
||||
if (val & DIGI_READ_INPUT_SIGNALS_CTS) {
|
||||
priv->dp_modem_signals |= TIOCM_CTS;
|
||||
|
@ -1530,12 +1533,12 @@ static int digi_read_oob_callback(struct urb *urb)
|
|||
else
|
||||
priv->dp_modem_signals &= ~TIOCM_CD;
|
||||
|
||||
spin_unlock(&priv->dp_port_lock);
|
||||
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
|
||||
} else if (opcode == DIGI_CMD_TRANSMIT_IDLE) {
|
||||
spin_lock(&priv->dp_port_lock);
|
||||
spin_lock_irqsave(&priv->dp_port_lock, flags);
|
||||
priv->dp_transmit_idle = 1;
|
||||
wake_up_interruptible(&priv->dp_transmit_idle_wait);
|
||||
spin_unlock(&priv->dp_port_lock);
|
||||
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
|
||||
} else if (opcode == DIGI_CMD_IFLUSH_FIFO) {
|
||||
wake_up_interruptible(&priv->dp_flush_wait);
|
||||
}
|
||||
|
|
|
@ -648,6 +648,7 @@ static void edge_interrupt_callback(struct urb *urb)
|
|||
struct usb_serial_port *port;
|
||||
unsigned char *data = urb->transfer_buffer;
|
||||
int length = urb->actual_length;
|
||||
unsigned long flags;
|
||||
int bytes_avail;
|
||||
int position;
|
||||
int txCredits;
|
||||
|
@ -679,7 +680,7 @@ static void edge_interrupt_callback(struct urb *urb)
|
|||
if (length > 1) {
|
||||
bytes_avail = data[0] | (data[1] << 8);
|
||||
if (bytes_avail) {
|
||||
spin_lock(&edge_serial->es_lock);
|
||||
spin_lock_irqsave(&edge_serial->es_lock, flags);
|
||||
edge_serial->rxBytesAvail += bytes_avail;
|
||||
dev_dbg(dev,
|
||||
"%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d\n",
|
||||
|
@ -702,7 +703,8 @@ static void edge_interrupt_callback(struct urb *urb)
|
|||
edge_serial->read_in_progress = false;
|
||||
}
|
||||
}
|
||||
spin_unlock(&edge_serial->es_lock);
|
||||
spin_unlock_irqrestore(&edge_serial->es_lock,
|
||||
flags);
|
||||
}
|
||||
}
|
||||
/* grab the txcredits for the ports if available */
|
||||
|
@ -715,9 +717,11 @@ static void edge_interrupt_callback(struct urb *urb)
|
|||
port = edge_serial->serial->port[portNumber];
|
||||
edge_port = usb_get_serial_port_data(port);
|
||||
if (edge_port->open) {
|
||||
spin_lock(&edge_port->ep_lock);
|
||||
spin_lock_irqsave(&edge_port->ep_lock,
|
||||
flags);
|
||||
edge_port->txCredits += txCredits;
|
||||
spin_unlock(&edge_port->ep_lock);
|
||||
spin_unlock_irqrestore(&edge_port->ep_lock,
|
||||
flags);
|
||||
dev_dbg(dev, "%s - txcredits for port%d = %d\n",
|
||||
__func__, portNumber,
|
||||
edge_port->txCredits);
|
||||
|
@ -758,6 +762,7 @@ static void edge_bulk_in_callback(struct urb *urb)
|
|||
int retval;
|
||||
__u16 raw_data_length;
|
||||
int status = urb->status;
|
||||
unsigned long flags;
|
||||
|
||||
if (status) {
|
||||
dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n",
|
||||
|
@ -777,7 +782,7 @@ static void edge_bulk_in_callback(struct urb *urb)
|
|||
|
||||
usb_serial_debug_data(dev, __func__, raw_data_length, data);
|
||||
|
||||
spin_lock(&edge_serial->es_lock);
|
||||
spin_lock_irqsave(&edge_serial->es_lock, flags);
|
||||
|
||||
/* decrement our rxBytes available by the number that we just got */
|
||||
edge_serial->rxBytesAvail -= raw_data_length;
|
||||
|
@ -801,7 +806,7 @@ static void edge_bulk_in_callback(struct urb *urb)
|
|||
edge_serial->read_in_progress = false;
|
||||
}
|
||||
|
||||
spin_unlock(&edge_serial->es_lock);
|
||||
spin_unlock_irqrestore(&edge_serial->es_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1729,6 +1729,7 @@ static void edge_bulk_in_callback(struct urb *urb)
|
|||
struct edgeport_port *edge_port = urb->context;
|
||||
struct device *dev = &edge_port->port->dev;
|
||||
unsigned char *data = urb->transfer_buffer;
|
||||
unsigned long flags;
|
||||
int retval = 0;
|
||||
int port_number;
|
||||
int status = urb->status;
|
||||
|
@ -1780,13 +1781,13 @@ static void edge_bulk_in_callback(struct urb *urb)
|
|||
|
||||
exit:
|
||||
/* continue read unless stopped */
|
||||
spin_lock(&edge_port->ep_lock);
|
||||
spin_lock_irqsave(&edge_port->ep_lock, flags);
|
||||
if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING)
|
||||
retval = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
else if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPING)
|
||||
edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPED;
|
||||
|
||||
spin_unlock(&edge_port->ep_lock);
|
||||
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
|
||||
if (retval)
|
||||
dev_err(dev, "%s - usb_submit_urb failed with result %d\n", __func__, retval);
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ irda_usb_find_class_desc(struct usb_serial *serial, unsigned int ifnum)
|
|||
0, ifnum, desc, sizeof(*desc), 1000);
|
||||
|
||||
dev_dbg(&serial->dev->dev, "%s - ret=%d\n", __func__, ret);
|
||||
if (ret < sizeof(*desc)) {
|
||||
if (ret < (int)sizeof(*desc)) {
|
||||
dev_dbg(&serial->dev->dev,
|
||||
"%s - class descriptor read %s (%d)\n", __func__,
|
||||
(ret < 0) ? "failed" : "too short", ret);
|
||||
|
|
|
@ -58,7 +58,6 @@ struct iuu_private {
|
|||
u8 *buf; /* used for initialize speed */
|
||||
u8 len;
|
||||
int vcc; /* vcc (either 3 or 5 V) */
|
||||
u32 baud;
|
||||
u32 boost;
|
||||
u32 clk;
|
||||
};
|
||||
|
@ -963,9 +962,6 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
struct iuu_private *priv = usb_get_serial_port_data(port);
|
||||
|
||||
baud = tty->termios.c_ospeed;
|
||||
tty->termios.c_ispeed = baud;
|
||||
/* Re-encode speed */
|
||||
tty_encode_baud_rate(tty, baud, baud);
|
||||
|
||||
dev_dbg(dev, "%s - baud %d\n", __func__, baud);
|
||||
usb_clear_halt(serial->dev, port->write_urb->pipe);
|
||||
|
@ -991,7 +987,6 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
if (boost < 100)
|
||||
boost = 100;
|
||||
priv->boost = boost;
|
||||
priv->baud = baud;
|
||||
switch (clockmode) {
|
||||
case 2: /* 3.680 Mhz */
|
||||
priv->clk = IUU_CLK_3680000;
|
||||
|
|
|
@ -67,7 +67,6 @@ static int klsi_105_prepare_write_buffer(struct usb_serial_port *port,
|
|||
*/
|
||||
static const struct usb_device_id id_table[] = {
|
||||
{ USB_DEVICE(PALMCONNECT_VID, PALMCONNECT_PID) },
|
||||
{ USB_DEVICE(KLSI_VID, KLSI_KL5KUSB105D_PID) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
#define PALMCONNECT_VID 0x0830
|
||||
#define PALMCONNECT_PID 0x0080
|
||||
|
||||
#define KLSI_VID 0x05e9
|
||||
#define KLSI_KL5KUSB105D_PID 0x00c0
|
||||
|
||||
/* Vendor commands: */
|
||||
|
||||
|
||||
|
|
|
@ -190,8 +190,10 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
KOBIL_TIMEOUT
|
||||
);
|
||||
dev_dbg(dev, "%s - Send get_HW_version URB returns: %i\n", __func__, result);
|
||||
dev_dbg(dev, "Hardware version: %i.%i.%i\n", transfer_buffer[0],
|
||||
transfer_buffer[1], transfer_buffer[2]);
|
||||
if (result >= 3) {
|
||||
dev_dbg(dev, "Hardware version: %i.%i.%i\n", transfer_buffer[0],
|
||||
transfer_buffer[1], transfer_buffer[2]);
|
||||
}
|
||||
|
||||
/* get firmware version */
|
||||
result = usb_control_msg(port->serial->dev,
|
||||
|
@ -205,8 +207,10 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
KOBIL_TIMEOUT
|
||||
);
|
||||
dev_dbg(dev, "%s - Send get_FW_version URB returns: %i\n", __func__, result);
|
||||
dev_dbg(dev, "Firmware version: %i.%i.%i\n", transfer_buffer[0],
|
||||
transfer_buffer[1], transfer_buffer[2]);
|
||||
if (result >= 3) {
|
||||
dev_dbg(dev, "Firmware version: %i.%i.%i\n", transfer_buffer[0],
|
||||
transfer_buffer[1], transfer_buffer[2]);
|
||||
}
|
||||
|
||||
if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
|
||||
priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
|
||||
|
@ -393,12 +397,20 @@ static int kobil_tiocmget(struct tty_struct *tty)
|
|||
transfer_buffer_length,
|
||||
KOBIL_TIMEOUT);
|
||||
|
||||
dev_dbg(&port->dev, "%s - Send get_status_line_state URB returns: %i. Statusline: %02x\n",
|
||||
__func__, result, transfer_buffer[0]);
|
||||
dev_dbg(&port->dev, "Send get_status_line_state URB returns: %i\n",
|
||||
result);
|
||||
if (result < 1) {
|
||||
if (result >= 0)
|
||||
result = -EIO;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
dev_dbg(&port->dev, "Statusline: %02x\n", transfer_buffer[0]);
|
||||
|
||||
result = 0;
|
||||
if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0)
|
||||
result = TIOCM_DSR;
|
||||
out_free:
|
||||
kfree(transfer_buffer);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -340,14 +340,15 @@ static void async_complete(struct urb *urb)
|
|||
{
|
||||
struct urbtracker *urbtrack = urb->context;
|
||||
int status = urb->status;
|
||||
unsigned long flags;
|
||||
|
||||
if (unlikely(status))
|
||||
dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __func__, status);
|
||||
|
||||
/* remove the urbtracker from the active_urbs list */
|
||||
spin_lock(&urbtrack->mos_parport->listlock);
|
||||
spin_lock_irqsave(&urbtrack->mos_parport->listlock, flags);
|
||||
list_del(&urbtrack->urblist_entry);
|
||||
spin_unlock(&urbtrack->mos_parport->listlock);
|
||||
spin_unlock_irqrestore(&urbtrack->mos_parport->listlock, flags);
|
||||
kref_put(&urbtrack->ref_count, destroy_urbtracker);
|
||||
}
|
||||
|
||||
|
@ -1526,8 +1527,6 @@ static void change_port_settings(struct tty_struct *tty,
|
|||
struct usb_serial *serial;
|
||||
int baud;
|
||||
unsigned cflag;
|
||||
unsigned iflag;
|
||||
__u8 mask = 0xff;
|
||||
__u8 lData;
|
||||
__u8 lParity;
|
||||
__u8 lStop;
|
||||
|
@ -1551,23 +1550,19 @@ static void change_port_settings(struct tty_struct *tty,
|
|||
lParity = 0x00; /* No parity */
|
||||
|
||||
cflag = tty->termios.c_cflag;
|
||||
iflag = tty->termios.c_iflag;
|
||||
|
||||
/* Change the number of bits */
|
||||
switch (cflag & CSIZE) {
|
||||
case CS5:
|
||||
lData = UART_LCR_WLEN5;
|
||||
mask = 0x1f;
|
||||
break;
|
||||
|
||||
case CS6:
|
||||
lData = UART_LCR_WLEN6;
|
||||
mask = 0x3f;
|
||||
break;
|
||||
|
||||
case CS7:
|
||||
lData = UART_LCR_WLEN7;
|
||||
mask = 0x7f;
|
||||
break;
|
||||
default:
|
||||
case CS8:
|
||||
|
@ -1685,11 +1680,8 @@ static void mos7720_set_termios(struct tty_struct *tty,
|
|||
struct usb_serial_port *port, struct ktermios *old_termios)
|
||||
{
|
||||
int status;
|
||||
struct usb_serial *serial;
|
||||
struct moschip_port *mos7720_port;
|
||||
|
||||
serial = port->serial;
|
||||
|
||||
mos7720_port = usb_get_serial_port_data(port);
|
||||
|
||||
if (mos7720_port == NULL)
|
||||
|
|
|
@ -805,18 +805,19 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
|
|||
struct moschip_port *mos7840_port;
|
||||
struct usb_serial_port *port;
|
||||
int status = urb->status;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
mos7840_port = urb->context;
|
||||
port = mos7840_port->port;
|
||||
spin_lock(&mos7840_port->pool_lock);
|
||||
spin_lock_irqsave(&mos7840_port->pool_lock, flags);
|
||||
for (i = 0; i < NUM_URBS; i++) {
|
||||
if (urb == mos7840_port->write_urb_pool[i]) {
|
||||
mos7840_port->busy[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&mos7840_port->pool_lock);
|
||||
spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
|
||||
|
||||
if (status) {
|
||||
dev_dbg(&port->dev, "nonzero write bulk status received:%d\n", status);
|
||||
|
|
|
@ -194,7 +194,7 @@ static inline int qt2_getregister(struct usb_device *dev,
|
|||
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
QT_SET_GET_REGISTER, 0xc0, reg,
|
||||
uart, data, sizeof(*data), QT2_USB_TIMEOUT);
|
||||
if (ret < sizeof(*data)) {
|
||||
if (ret < (int)sizeof(*data)) {
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
}
|
||||
|
@ -621,16 +621,17 @@ static void qt2_write_bulk_callback(struct urb *urb)
|
|||
{
|
||||
struct usb_serial_port *port;
|
||||
struct qt2_port_private *port_priv;
|
||||
unsigned long flags;
|
||||
|
||||
port = urb->context;
|
||||
port_priv = usb_get_serial_port_data(port);
|
||||
|
||||
spin_lock(&port_priv->urb_lock);
|
||||
spin_lock_irqsave(&port_priv->urb_lock, flags);
|
||||
|
||||
port_priv->urb_in_use = false;
|
||||
usb_serial_port_softint(port);
|
||||
|
||||
spin_unlock(&port_priv->urb_lock);
|
||||
spin_unlock_irqrestore(&port_priv->urb_lock, flags);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -409,6 +409,7 @@ static void sierra_outdat_callback(struct urb *urb)
|
|||
struct sierra_port_private *portdata = usb_get_serial_port_data(port);
|
||||
struct sierra_intf_private *intfdata;
|
||||
int status = urb->status;
|
||||
unsigned long flags;
|
||||
|
||||
intfdata = usb_get_serial_data(port->serial);
|
||||
|
||||
|
@ -419,12 +420,12 @@ static void sierra_outdat_callback(struct urb *urb)
|
|||
dev_dbg(&port->dev, "%s - nonzero write bulk status "
|
||||
"received: %d\n", __func__, status);
|
||||
|
||||
spin_lock(&portdata->lock);
|
||||
spin_lock_irqsave(&portdata->lock, flags);
|
||||
--portdata->outstanding_urbs;
|
||||
spin_unlock(&portdata->lock);
|
||||
spin_lock(&intfdata->susp_lock);
|
||||
spin_unlock_irqrestore(&portdata->lock, flags);
|
||||
spin_lock_irqsave(&intfdata->susp_lock, flags);
|
||||
--intfdata->in_flight;
|
||||
spin_unlock(&intfdata->susp_lock);
|
||||
spin_unlock_irqrestore(&intfdata->susp_lock, flags);
|
||||
|
||||
usb_serial_port_softint(port);
|
||||
}
|
||||
|
@ -770,9 +771,9 @@ static void sierra_close(struct usb_serial_port *port)
|
|||
kfree(urb->transfer_buffer);
|
||||
usb_free_urb(urb);
|
||||
usb_autopm_put_interface_async(serial->interface);
|
||||
spin_lock(&portdata->lock);
|
||||
spin_lock_irq(&portdata->lock);
|
||||
portdata->outstanding_urbs--;
|
||||
spin_unlock(&portdata->lock);
|
||||
spin_unlock_irq(&portdata->lock);
|
||||
}
|
||||
|
||||
sierra_stop_rx_urbs(port);
|
||||
|
|
|
@ -104,7 +104,7 @@ static inline int ssu100_getregister(struct usb_device *dev,
|
|||
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
QT_SET_GET_REGISTER, 0xc0, reg,
|
||||
uart, data, sizeof(*data), 300);
|
||||
if (ret < sizeof(*data)) {
|
||||
if (ret < (int)sizeof(*data)) {
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ static void symbol_int_callback(struct urb *urb)
|
|||
struct symbol_private *priv = usb_get_serial_port_data(port);
|
||||
unsigned char *data = urb->transfer_buffer;
|
||||
int status = urb->status;
|
||||
unsigned long flags;
|
||||
int result;
|
||||
int data_length;
|
||||
|
||||
|
@ -73,7 +74,7 @@ static void symbol_int_callback(struct urb *urb)
|
|||
}
|
||||
|
||||
exit:
|
||||
spin_lock(&priv->lock);
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* Continue trying to always read if we should */
|
||||
if (!priv->throttled) {
|
||||
|
@ -84,7 +85,7 @@ static void symbol_int_callback(struct urb *urb)
|
|||
__func__, result);
|
||||
} else
|
||||
priv->actually_throttled = true;
|
||||
spin_unlock(&priv->lock);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
|
|
|
@ -1215,6 +1215,7 @@ static void ti_bulk_in_callback(struct urb *urb)
|
|||
struct usb_serial_port *port = tport->tp_port;
|
||||
struct device *dev = &urb->dev->dev;
|
||||
int status = urb->status;
|
||||
unsigned long flags;
|
||||
int retval = 0;
|
||||
|
||||
switch (status) {
|
||||
|
@ -1247,20 +1248,20 @@ static void ti_bulk_in_callback(struct urb *urb)
|
|||
__func__);
|
||||
else
|
||||
ti_recv(port, urb->transfer_buffer, urb->actual_length);
|
||||
spin_lock(&tport->tp_lock);
|
||||
spin_lock_irqsave(&tport->tp_lock, flags);
|
||||
port->icount.rx += urb->actual_length;
|
||||
spin_unlock(&tport->tp_lock);
|
||||
spin_unlock_irqrestore(&tport->tp_lock, flags);
|
||||
}
|
||||
|
||||
exit:
|
||||
/* continue to read unless stopping */
|
||||
spin_lock(&tport->tp_lock);
|
||||
spin_lock_irqsave(&tport->tp_lock, flags);
|
||||
if (tport->tp_read_urb_state == TI_READ_URB_RUNNING)
|
||||
retval = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
else if (tport->tp_read_urb_state == TI_READ_URB_STOPPING)
|
||||
tport->tp_read_urb_state = TI_READ_URB_STOPPED;
|
||||
|
||||
spin_unlock(&tport->tp_lock);
|
||||
spin_unlock_irqrestore(&tport->tp_lock, flags);
|
||||
if (retval)
|
||||
dev_err(dev, "%s - resubmit read urb failed, %d\n",
|
||||
__func__, retval);
|
||||
|
|
|
@ -326,6 +326,7 @@ static void usb_wwan_outdat_callback(struct urb *urb)
|
|||
struct usb_serial_port *port;
|
||||
struct usb_wwan_port_private *portdata;
|
||||
struct usb_wwan_intf_private *intfdata;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
port = urb->context;
|
||||
|
@ -334,9 +335,9 @@ static void usb_wwan_outdat_callback(struct urb *urb)
|
|||
usb_serial_port_softint(port);
|
||||
usb_autopm_put_interface_async(port->serial->interface);
|
||||
portdata = usb_get_serial_port_data(port);
|
||||
spin_lock(&intfdata->susp_lock);
|
||||
spin_lock_irqsave(&intfdata->susp_lock, flags);
|
||||
intfdata->in_flight--;
|
||||
spin_unlock(&intfdata->susp_lock);
|
||||
spin_unlock_irqrestore(&intfdata->susp_lock, flags);
|
||||
|
||||
for (i = 0; i < N_OUT_URB; ++i) {
|
||||
if (portdata->out_urbs[i] == urb) {
|
||||
|
|
Loading…
Reference in New Issue