Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29ce32ec authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

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

Merge tag 'usb-serial-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial

 into usb-next

Johan writes:

USB-serial updates for v4.15-rc1

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

 - three fixes for longstanding issues in garmin_gps and metro-usb which
   could lead to NULL-pointer dereferences and memory leaks

 - a workaround for broken f81534 firmware-handling of overruns

 - f81534 break support, and

 - conversion to timer_setup()

Included are also various clean ups and a new qcserial device id.

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

Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
parents dc586a60 7c36e6e1
Loading
Loading
Loading
Loading
+84 −6
Original line number Diff line number Diff line
@@ -39,9 +39,11 @@
#define F81534_UART_OFFSET		0x10
#define F81534_DIVISOR_LSB_REG		(0x00 + F81534_UART_BASE_ADDRESS)
#define F81534_DIVISOR_MSB_REG		(0x01 + F81534_UART_BASE_ADDRESS)
#define F81534_INTERRUPT_ENABLE_REG	(0x01 + F81534_UART_BASE_ADDRESS)
#define F81534_FIFO_CONTROL_REG		(0x02 + F81534_UART_BASE_ADDRESS)
#define F81534_LINE_CONTROL_REG		(0x03 + F81534_UART_BASE_ADDRESS)
#define F81534_MODEM_CONTROL_REG	(0x04 + F81534_UART_BASE_ADDRESS)
#define F81534_LINE_STATUS_REG		(0x05 + F81534_UART_BASE_ADDRESS)
#define F81534_MODEM_STATUS_REG		(0x06 + F81534_UART_BASE_ADDRESS)
#define F81534_CONFIG1_REG		(0x09 + F81534_UART_BASE_ADDRESS)

@@ -126,9 +128,13 @@ struct f81534_serial_private {

struct f81534_port_private {
	struct mutex mcr_mutex;
	struct mutex lcr_mutex;
	struct work_struct lsr_work;
	struct usb_serial_port *port;
	unsigned long tx_empty;
	spinlock_t msr_lock;
	u8 shadow_mcr;
	u8 shadow_lcr;
	u8 shadow_msr;
	u8 phy_num;
};
@@ -461,6 +467,7 @@ static u32 f81534_calc_baud_divisor(u32 baudrate, u32 clockrate)
static int f81534_set_port_config(struct usb_serial_port *port, u32 baudrate,
					u8 lcr)
{
	struct f81534_port_private *port_priv = usb_get_serial_port_data(port);
	u32 divisor;
	int status;
	u8 value;
@@ -489,35 +496,65 @@ static int f81534_set_port_config(struct usb_serial_port *port, u32 baudrate,
	}

	divisor = f81534_calc_baud_divisor(baudrate, F81534_MAX_BAUDRATE);

	mutex_lock(&port_priv->lcr_mutex);

	value = UART_LCR_DLAB;
	status = f81534_set_port_register(port, F81534_LINE_CONTROL_REG,
						value);
	if (status) {
		dev_err(&port->dev, "%s: set LCR failed\n", __func__);
		return status;
		goto out_unlock;
	}

	value = divisor & 0xff;
	status = f81534_set_port_register(port, F81534_DIVISOR_LSB_REG, value);
	if (status) {
		dev_err(&port->dev, "%s: set DLAB LSB failed\n", __func__);
		return status;
		goto out_unlock;
	}

	value = (divisor >> 8) & 0xff;
	status = f81534_set_port_register(port, F81534_DIVISOR_MSB_REG, value);
	if (status) {
		dev_err(&port->dev, "%s: set DLAB MSB failed\n", __func__);
		return status;
		goto out_unlock;
	}

	status = f81534_set_port_register(port, F81534_LINE_CONTROL_REG, lcr);
	value = lcr | (port_priv->shadow_lcr & UART_LCR_SBC);
	status = f81534_set_port_register(port, F81534_LINE_CONTROL_REG,
						value);
	if (status) {
		dev_err(&port->dev, "%s: set LCR failed\n", __func__);
		goto out_unlock;
	}

	port_priv->shadow_lcr = value;
out_unlock:
	mutex_unlock(&port_priv->lcr_mutex);

	return status;
}

	return 0;
static void f81534_break_ctl(struct tty_struct *tty, int break_state)
{
	struct usb_serial_port *port = tty->driver_data;
	struct f81534_port_private *port_priv = usb_get_serial_port_data(port);
	int status;

	mutex_lock(&port_priv->lcr_mutex);

	if (break_state)
		port_priv->shadow_lcr |= UART_LCR_SBC;
	else
		port_priv->shadow_lcr &= ~UART_LCR_SBC;

	status = f81534_set_port_register(port, F81534_LINE_CONTROL_REG,
					port_priv->shadow_lcr);
	if (status)
		dev_err(&port->dev, "set break failed: %d\n", status);

	mutex_unlock(&port_priv->lcr_mutex);
}

static int f81534_update_mctrl(struct usb_serial_port *port, unsigned int set,
@@ -1015,6 +1052,8 @@ static void f81534_process_per_serial_block(struct usb_serial_port *port,
				tty_insert_flip_char(&port->port, 0,
						TTY_OVERRUN);
			}

			schedule_work(&port_priv->lsr_work);
		}

		if (port->port.console && port->sysrq) {
@@ -1162,6 +1201,21 @@ static int f81534_attach(struct usb_serial *serial)
	return 0;
}

static void f81534_lsr_worker(struct work_struct *work)
{
	struct f81534_port_private *port_priv;
	struct usb_serial_port *port;
	int status;
	u8 tmp;

	port_priv = container_of(work, struct f81534_port_private, lsr_work);
	port = port_priv->port;

	status = f81534_get_port_register(port, F81534_LINE_STATUS_REG, &tmp);
	if (status)
		dev_warn(&port->dev, "read LSR failed: %d\n", status);
}

static int f81534_port_probe(struct usb_serial_port *port)
{
	struct f81534_port_private *port_priv;
@@ -1173,6 +1227,8 @@ static int f81534_port_probe(struct usb_serial_port *port)

	spin_lock_init(&port_priv->msr_lock);
	mutex_init(&port_priv->mcr_mutex);
	mutex_init(&port_priv->lcr_mutex);
	INIT_WORK(&port_priv->lsr_work, f81534_lsr_worker);

	/* Assign logic-to-phy mapping */
	ret = f81534_logic_to_phy_port(port->serial, port);
@@ -1180,10 +1236,30 @@ static int f81534_port_probe(struct usb_serial_port *port)
		return ret;

	port_priv->phy_num = ret;
	port_priv->port = port;
	usb_set_serial_port_data(port, port_priv);
	dev_dbg(&port->dev, "%s: port_number: %d, phy_num: %d\n", __func__,
			port->port_number, port_priv->phy_num);

	/*
	 * The F81532/534 will hang-up when enable LSR interrupt in IER and
	 * occur data overrun. So we'll disable the LSR interrupt in probe()
	 * and submit the LSR worker to clear LSR state when reported LSR error
	 * bit with bulk-in data in f81534_process_per_serial_block().
	 */
	ret = f81534_set_port_register(port, F81534_INTERRUPT_ENABLE_REG,
			UART_IER_RDI | UART_IER_THRI | UART_IER_MSI);
	if (ret)
		return ret;

	return 0;
}

static int f81534_port_remove(struct usb_serial_port *port)
{
	struct f81534_port_private *port_priv = usb_get_serial_port_data(port);

	flush_work(&port_priv->lsr_work);
	return 0;
}

@@ -1317,6 +1393,8 @@ static struct usb_serial_driver f81534_device = {
	.calc_num_ports =	f81534_calc_num_ports,
	.attach =		f81534_attach,
	.port_probe =		f81534_port_probe,
	.port_remove =		f81534_port_remove,
	.break_ctl =		f81534_break_ctl,
	.dtr_rts =		f81534_dtr_rts,
	.process_read_urb =	f81534_process_read_urb,
	.ioctl =		f81534_ioctl,
+35 −32
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ struct garmin_data {
	__u8   privpkt[4*6];
	spinlock_t lock;
	struct list_head pktlist;
	struct usb_anchor write_urbs;
};


@@ -875,42 +876,38 @@ static int garmin_clear(struct garmin_data *garmin_data_p)

static int garmin_init_session(struct usb_serial_port *port)
{
	struct usb_serial *serial = port->serial;
	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
	int status = 0;
	int i = 0;
	int status;
	int i;

	if (status == 0) {
	usb_kill_urb(port->interrupt_in_urb);

		dev_dbg(&serial->dev->dev, "%s - adding interrupt input\n", __func__);
	status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
		if (status)
			dev_err(&serial->dev->dev,
			  "%s - failed submitting interrupt urb, error %d\n",
							__func__, status);
	if (status) {
		dev_err(&port->dev, "failed to submit interrupt urb: %d\n",
				status);
		return status;
	}

	/*
	 * using the initialization method from gpsbabel. See comments in
	 * gpsbabel/jeeps/gpslibusb.c gusb_reset_toggles()
	 */
	if (status == 0) {
		dev_dbg(&serial->dev->dev, "%s - starting session ...\n", __func__);
	dev_dbg(&port->dev, "%s - starting session ...\n", __func__);
	garmin_data_p->state = STATE_ACTIVE;

	for (i = 0; i < 3; i++) {
			status = garmin_write_bulk(port,
					GARMIN_START_SESSION_REQ,
		status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ,
				sizeof(GARMIN_START_SESSION_REQ), 0);

		if (status < 0)
				break;
			goto err_kill_urbs;
	}

		if (status > 0)
			status = 0;
	}
	return 0;

err_kill_urbs:
	usb_kill_anchored_urbs(&garmin_data_p->write_urbs);
	usb_kill_urb(port->interrupt_in_urb);

	return status;
}
@@ -930,7 +927,6 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port)
	spin_unlock_irqrestore(&garmin_data_p->lock, flags);

	/* shutdown any bulk reads that might be going on */
	usb_kill_urb(port->write_urb);
	usb_kill_urb(port->read_urb);

	if (garmin_data_p->state == STATE_RESET)
@@ -953,7 +949,7 @@ static void garmin_close(struct usb_serial_port *port)

	/* shutdown our urbs */
	usb_kill_urb(port->read_urb);
	usb_kill_urb(port->write_urb);
	usb_kill_anchored_urbs(&garmin_data_p->write_urbs);

	/* keep reset state so we know that we must start a new session */
	if (garmin_data_p->state != STATE_RESET)
@@ -1037,12 +1033,14 @@ static int garmin_write_bulk(struct usb_serial_port *port,
	}

	/* send it down the pipe */
	usb_anchor_urb(urb, &garmin_data_p->write_urbs);
	status = usb_submit_urb(urb, GFP_ATOMIC);
	if (status) {
		dev_err(&port->dev,
		   "%s - usb_submit_urb(write bulk) failed with status = %d\n",
				__func__, status);
		count = status;
		usb_unanchor_urb(urb);
		kfree(buffer);
	}

@@ -1370,9 +1368,9 @@ static void garmin_unthrottle(struct tty_struct *tty)
 * the tty in cases where the protocol provides no own handshaking
 * to initiate the transfer.
 */
static void timeout_handler(unsigned long data)
static void timeout_handler(struct timer_list *t)
{
	struct garmin_data *garmin_data_p = (struct garmin_data *) data;
	struct garmin_data *garmin_data_p = from_timer(garmin_data_p, t, timer);

	/* send the next queued packet to the tty port */
	if (garmin_data_p->mode == MODE_NATIVE)
@@ -1391,19 +1389,23 @@ static int garmin_port_probe(struct usb_serial_port *port)
	if (!garmin_data_p)
		return -ENOMEM;

	init_timer(&garmin_data_p->timer);
	timer_setup(&garmin_data_p->timer, timeout_handler, 0);
	spin_lock_init(&garmin_data_p->lock);
	INIT_LIST_HEAD(&garmin_data_p->pktlist);
	/* garmin_data_p->timer.expires = jiffies + session_timeout; */
	garmin_data_p->timer.data = (unsigned long)garmin_data_p;
	garmin_data_p->timer.function = timeout_handler;
	garmin_data_p->port = port;
	garmin_data_p->state = 0;
	garmin_data_p->flags = 0;
	garmin_data_p->count = 0;
	init_usb_anchor(&garmin_data_p->write_urbs);
	usb_set_serial_port_data(port, garmin_data_p);

	status = garmin_init_session(port);
	if (status)
		goto err_free;

	return 0;
err_free:
	kfree(garmin_data_p);

	return status;
}
@@ -1413,6 +1415,7 @@ static int garmin_port_remove(struct usb_serial_port *port)
{
	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);

	usb_kill_anchored_urbs(&garmin_data_p->write_urbs);
	usb_kill_urb(port->interrupt_in_urb);
	del_timer_sync(&garmin_data_p->timer);
	kfree(garmin_data_p);
+1 −0
Original line number Diff line number Diff line
@@ -491,6 +491,7 @@ static void kobil_set_termios(struct tty_struct *tty,
		break;
	default:
		speed = 9600;
		/* fall through */
	case 9600:
		urb_val = SUSBCR_SBR_9600;
		break;
+26 −15
Original line number Diff line number Diff line
@@ -54,21 +54,33 @@ MODULE_DEVICE_TABLE(usb, id_table);
#define UNI_CMD_OPEN	0x80
#define UNI_CMD_CLOSE	0xFF

static inline int metrousb_is_unidirectional_mode(struct usb_serial_port *port)
static int metrousb_is_unidirectional_mode(struct usb_serial *serial)
{
	__u16 product_id = le16_to_cpu(
		port->serial->dev->descriptor.idProduct);
	u16 product_id = le16_to_cpu(serial->dev->descriptor.idProduct);

	return product_id == FOCUS_PRODUCT_ID_UNI;
}

static int metrousb_calc_num_ports(struct usb_serial *serial,
				   struct usb_serial_endpoints *epds)
{
	if (metrousb_is_unidirectional_mode(serial)) {
		if (epds->num_interrupt_out == 0) {
			dev_err(&serial->interface->dev, "interrupt-out endpoint missing\n");
			return -ENODEV;
		}
	}

	return 1;
}

static int metrousb_send_unidirectional_cmd(u8 cmd, struct usb_serial_port *port)
{
	int ret;
	int actual_len;
	u8 *buffer_cmd = NULL;

	if (!metrousb_is_unidirectional_mode(port))
	if (!metrousb_is_unidirectional_mode(port->serial))
		return 0;

	buffer_cmd = kzalloc(sizeof(cmd), GFP_KERNEL);
@@ -161,13 +173,6 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
	unsigned long flags = 0;
	int result = 0;

	/* Make sure the urb is initialized. */
	if (!port->interrupt_in_urb) {
		dev_err(&port->dev, "%s - interrupt urb not initialized\n",
			__func__);
		return -ENODEV;
	}

	/* Set the private data information for the port. */
	spin_lock_irqsave(&metro_priv->lock, flags);
	metro_priv->control_state = 0;
@@ -189,7 +194,7 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
		dev_err(&port->dev,
			"%s - failed submitting interrupt in urb, error code=%d\n",
			__func__, result);
		goto exit;
		return result;
	}

	/* Send activate cmd to device */
@@ -198,9 +203,14 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
		dev_err(&port->dev,
			"%s - failed to configure device, error code=%d\n",
			__func__, result);
		goto exit;
		goto err_kill_urb;
	}
exit:

	return 0;

err_kill_urb:
	usb_kill_urb(port->interrupt_in_urb);

	return result;
}

@@ -337,7 +347,8 @@ static struct usb_serial_driver metrousb_device = {
	},
	.description		= "Metrologic USB to Serial",
	.id_table		= id_table,
	.num_ports		= 1,
	.num_interrupt_in	= 1,
	.calc_num_ports		= metrousb_calc_num_ports,
	.open			= metrousb_open,
	.close			= metrousb_cleanup,
	.read_int_callback	= metrousb_read_int_callback,
+1 −0
Original line number Diff line number Diff line
@@ -148,6 +148,7 @@ static const struct usb_device_id id_table[] = {
	{DEVICE_SWI(0x1199, 0x68a2)},	/* Sierra Wireless MC7710 */
	{DEVICE_SWI(0x1199, 0x68c0)},	/* Sierra Wireless MC7304/MC7354 */
	{DEVICE_SWI(0x1199, 0x901c)},	/* Sierra Wireless EM7700 */
	{DEVICE_SWI(0x1199, 0x901e)},	/* Sierra Wireless EM7355 QDL */
	{DEVICE_SWI(0x1199, 0x901f)},	/* Sierra Wireless EM7355 */
	{DEVICE_SWI(0x1199, 0x9040)},	/* Sierra Wireless Modem */
	{DEVICE_SWI(0x1199, 0x9041)},	/* Sierra Wireless MC7305/MC7355 */
Loading