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

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
...@@ -187,8 +187,6 @@ enum mos7840_flag { ...@@ -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) ...@@ -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) ...@@ -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)
usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), return -ENOMEM;
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 || /* For a MCS7840 device GPIO0 must be set to 1 */
serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7820) { if (buf[0] & 0x01)
device_type = serial->dev->descriptor.idProduct; device_type = MOSCHIP_DEVICE_ID_7840;
} else { else if (mos7810_check(serial))
/* For a MCS7840 device GPIO0 must be set to 1 */ device_type = MOSCHIP_DEVICE_ID_7810;
if ((data & 0x01) == 1) else
device_type = MOSCHIP_DEVICE_ID_7840; device_type = MOSCHIP_DEVICE_ID_7820;
else if (mos7810_check(serial))
device_type = MOSCHIP_DEVICE_ID_7810; kfree(buf);
else out:
device_type = MOSCHIP_DEVICE_ID_7820; 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) ...@@ -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 = { ...@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment