Commit 78fbe864 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'usb-serial-4.19-rc1' of...

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: default avatarJohan Hovold <johan@kernel.org>
parents 500f0716 c8acfe0a
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -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.

+340 −81
Original line number Diff line number Diff line
@@ -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)
	if (priv->gpio_altfunc & BIT(offset))
		return -ENODEV;
		break;
	case 1:
		if (priv->config & (CP2105_GPIO1_RXLED_MODE |
				    CP2105_GPIO1_RS485_MODE))
			return -ENODEV;
		break;
	}

	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 */
	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);
	cp210x_init_max_speed(serial);

	result = cp210x_gpio_init(serial);
	if (result < 0) {
			dev_err(&serial->interface->dev,
				"GPIO initialisation failed, continuing without GPIO support\n");
		}
		dev_err(&serial->interface->dev, "GPIO initialisation failed: %d\n",
				result);
	}

	return 0;
+10 −7
Original line number Diff line number Diff line
@@ -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);
}

+19 −16
Original line number Diff line number Diff line
@@ -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);
		}
+11 −6
Original line number Diff line number Diff line
@@ -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);
}


Loading