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: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Johan Hovold 2013-07-26 11:55:18 +02:00 committed by Greg Kroah-Hartman
parent d8a083cc74
commit 40c24f2893
1 changed files with 35 additions and 40 deletions

View File

@ -187,8 +187,6 @@ enum mos7840_flag {
MOS7840_FLAG_CTRL_BUSY,
};
static int device_type;
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_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 */
/************************************************************************/
#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
@ -2201,38 +2187,48 @@ static int mos7810_check(struct usb_serial *serial)
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;
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);
if (buf) {
usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
if (!buf)
return -ENOMEM;
usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, buf,
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 */
if ((data & 0x01) == 1)
device_type = MOSCHIP_DEVICE_ID_7840;
else if (mos7810_check(serial))
device_type = MOSCHIP_DEVICE_ID_7810;
else
device_type = MOSCHIP_DEVICE_ID_7820;
}
/* For a MCS7840 device GPIO0 must be set to 1 */
if (buf[0] & 0x01)
device_type = MOSCHIP_DEVICE_ID_7840;
else if (mos7810_check(serial))
device_type = MOSCHIP_DEVICE_ID_7810;
else
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;
serial->num_bulk_in = mos7840_num_ports;
serial->num_bulk_out = mos7840_num_ports;
serial->num_ports = 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)
{
struct usb_serial *serial = port->serial;
int device_type = (int)usb_get_serial_data(serial);
struct moschip_port *mos7840_port;
int status;
int pnum;
@ -2496,9 +2493,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
.throttle = mos7840_throttle,
.unthrottle = mos7840_unthrottle,
.calc_num_ports = mos7840_calc_num_ports,
#ifdef MCSSerialProbe
.probe = mos7840_serial_probe,
#endif
.probe = mos7840_probe,
.ioctl = mos7840_ioctl,
.set_termios = mos7840_set_termios,
.break_ctl = mos7840_break,