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

Commit 40c24f28 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman
Browse files

USB: mos7840: fix device-type detection



Fix race in device-type detection introduced by commit 0eafe4de ("USB:
serial: mos7840: add support for MCS7810 devices") which used a static
variable to hold the device type.

Move type detection to probe and use serial data to store the device
type.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarJohan Hovold <jhovold@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d8a083cc
Loading
Loading
Loading
Loading
+35 −40
Original line number Original line Diff line number Diff line
@@ -187,8 +187,6 @@ enum mos7840_flag {
	MOS7840_FLAG_CTRL_BUSY,
	MOS7840_FLAG_CTRL_BUSY,
};
};


static int device_type;

static const struct usb_device_id id_table[] = {
static const struct usb_device_id id_table[] = {
	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
@@ -830,18 +828,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
/************************************************************************/
/************************************************************************/
/*       D R I V E R  T T Y  I N T E R F A C E  F U N C T I O N S       */
/*       D R I V E R  T T Y  I N T E R F A C E  F U N C T I O N S       */
/************************************************************************/
/************************************************************************/
#ifdef MCSSerialProbe
static int mos7840_serial_probe(struct usb_serial *serial,
				const struct usb_device_id *id)
{

	/*need to implement the mode_reg reading and updating\
	   structures usb_serial_ device_type\
	   (i.e num_ports, num_bulkin,bulkout etc) */
	/* Also we can update the changes  attach */
	return 1;
}
#endif


/*****************************************************************************
/*****************************************************************************
 * mos7840_open
 * mos7840_open
@@ -2201,38 +2187,48 @@ static int mos7810_check(struct usb_serial *serial)
	return 0;
	return 0;
}
}


static int mos7840_calc_num_ports(struct usb_serial *serial)
static int mos7840_probe(struct usb_serial *serial,
				const struct usb_device_id *id)
{
{
	__u16 data = 0x00;
	u16 product = serial->dev->descriptor.idProduct;
	u8 *buf;
	u8 *buf;
	int mos7840_num_ports;
	int device_type;

	if (product == MOSCHIP_DEVICE_ID_7810 ||
		product == MOSCHIP_DEVICE_ID_7820) {
		device_type = product;
		goto out;
	}


	buf = kzalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
	buf = kzalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
	if (buf) {
	if (!buf)
		return -ENOMEM;

	usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
	usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
			MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, buf,
			MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, buf,
			VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
			VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
		data = *buf;
		kfree(buf);
	}


	if (serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7810 ||
		serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7820) {
		device_type = serial->dev->descriptor.idProduct;
	} else {
	/* For a MCS7840 device GPIO0 must be set to 1 */
	/* For a MCS7840 device GPIO0 must be set to 1 */
		if ((data & 0x01) == 1)
	if (buf[0] & 0x01)
		device_type = MOSCHIP_DEVICE_ID_7840;
		device_type = MOSCHIP_DEVICE_ID_7840;
	else if (mos7810_check(serial))
	else if (mos7810_check(serial))
		device_type = MOSCHIP_DEVICE_ID_7810;
		device_type = MOSCHIP_DEVICE_ID_7810;
	else
	else
		device_type = MOSCHIP_DEVICE_ID_7820;
		device_type = MOSCHIP_DEVICE_ID_7820;

	kfree(buf);
out:
	usb_set_serial_data(serial, (void *)device_type);

	return 0;
}
}


static int mos7840_calc_num_ports(struct usb_serial *serial)
{
	int device_type = (int)usb_get_serial_data(serial);
	int mos7840_num_ports;

	mos7840_num_ports = (device_type >> 4) & 0x000F;
	mos7840_num_ports = (device_type >> 4) & 0x000F;
	serial->num_bulk_in = mos7840_num_ports;
	serial->num_bulk_out = mos7840_num_ports;
	serial->num_ports = mos7840_num_ports;


	return mos7840_num_ports;
	return mos7840_num_ports;
}
}
@@ -2240,6 +2236,7 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)
static int mos7840_port_probe(struct usb_serial_port *port)
static int mos7840_port_probe(struct usb_serial_port *port)
{
{
	struct usb_serial *serial = port->serial;
	struct usb_serial *serial = port->serial;
	int device_type = (int)usb_get_serial_data(serial);
	struct moschip_port *mos7840_port;
	struct moschip_port *mos7840_port;
	int status;
	int status;
	int pnum;
	int pnum;
@@ -2496,9 +2493,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
	.throttle = mos7840_throttle,
	.throttle = mos7840_throttle,
	.unthrottle = mos7840_unthrottle,
	.unthrottle = mos7840_unthrottle,
	.calc_num_ports = mos7840_calc_num_ports,
	.calc_num_ports = mos7840_calc_num_ports,
#ifdef MCSSerialProbe
	.probe = mos7840_probe,
	.probe = mos7840_serial_probe,
#endif
	.ioctl = mos7840_ioctl,
	.ioctl = mos7840_ioctl,
	.set_termios = mos7840_set_termios,
	.set_termios = mos7840_set_termios,
	.break_ctl = mos7840_break,
	.break_ctl = mos7840_break,