aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2013-07-26 05:55:18 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-26 17:14:09 -0400
commit40c24f2893ba0ba7df485871f6aac0c197ceef5b (patch)
tree78cfddeb2394b1a61988e85ed592f3497d9f8b54 /drivers/usb
parentd8a083cc746664916d9d36ed9e4d08a29525f245 (diff)
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/mos7840.c75
1 files changed, 35 insertions, 40 deletions
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 73dda1cc8028..e95d91434785 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -187,8 +187,6 @@ enum mos7840_flag {
187 MOS7840_FLAG_CTRL_BUSY, 187 MOS7840_FLAG_CTRL_BUSY,
188}; 188};
189 189
190static int device_type;
191
192static const struct usb_device_id id_table[] = { 190static const struct usb_device_id id_table[] = {
193 {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, 191 {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
194 {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, 192 {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/************************************************************************/ 828/************************************************************************/
831/* 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 */ 829/* 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 */
832/************************************************************************/ 830/************************************************************************/
833#ifdef MCSSerialProbe
834static int mos7840_serial_probe(struct usb_serial *serial,
835 const struct usb_device_id *id)
836{
837
838 /*need to implement the mode_reg reading and updating\
839 structures usb_serial_ device_type\
840 (i.e num_ports, num_bulkin,bulkout etc) */
841 /* Also we can update the changes attach */
842 return 1;
843}
844#endif
845 831
846/***************************************************************************** 832/*****************************************************************************
847 * mos7840_open 833 * mos7840_open
@@ -2201,38 +2187,48 @@ static int mos7810_check(struct usb_serial *serial)
2201 return 0; 2187 return 0;
2202} 2188}
2203 2189
2204static int mos7840_calc_num_ports(struct usb_serial *serial) 2190static int mos7840_probe(struct usb_serial *serial,
2191 const struct usb_device_id *id)
2205{ 2192{
2206 __u16 data = 0x00; 2193 u16 product = serial->dev->descriptor.idProduct;
2207 u8 *buf; 2194 u8 *buf;
2208 int mos7840_num_ports; 2195 int device_type;
2196
2197 if (product == MOSCHIP_DEVICE_ID_7810 ||
2198 product == MOSCHIP_DEVICE_ID_7820) {
2199 device_type = product;
2200 goto out;
2201 }
2209 2202
2210 buf = kzalloc(VENDOR_READ_LENGTH, GFP_KERNEL); 2203 buf = kzalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
2211 if (buf) { 2204 if (!buf)
2212 usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 2205 return -ENOMEM;
2206
2207 usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
2213 MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, buf, 2208 MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, buf,
2214 VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); 2209 VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
2215 data = *buf;
2216 kfree(buf);
2217 }
2218 2210
2219 if (serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7810 || 2211 /* For a MCS7840 device GPIO0 must be set to 1 */
2220 serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7820) { 2212 if (buf[0] & 0x01)
2221 device_type = serial->dev->descriptor.idProduct; 2213 device_type = MOSCHIP_DEVICE_ID_7840;
2222 } else { 2214 else if (mos7810_check(serial))
2223 /* For a MCS7840 device GPIO0 must be set to 1 */ 2215 device_type = MOSCHIP_DEVICE_ID_7810;
2224 if ((data & 0x01) == 1) 2216 else
2225 device_type = MOSCHIP_DEVICE_ID_7840; 2217 device_type = MOSCHIP_DEVICE_ID_7820;
2226 else if (mos7810_check(serial)) 2218
2227 device_type = MOSCHIP_DEVICE_ID_7810; 2219 kfree(buf);
2228 else 2220out:
2229 device_type = MOSCHIP_DEVICE_ID_7820; 2221 usb_set_serial_data(serial, (void *)device_type);
2230 } 2222
2223 return 0;
2224}
2225
2226static int mos7840_calc_num_ports(struct usb_serial *serial)
2227{
2228 int device_type = (int)usb_get_serial_data(serial);
2229 int mos7840_num_ports;
2231 2230
2232 mos7840_num_ports = (device_type >> 4) & 0x000F; 2231 mos7840_num_ports = (device_type >> 4) & 0x000F;
2233 serial->num_bulk_in = mos7840_num_ports;
2234 serial->num_bulk_out = mos7840_num_ports;
2235 serial->num_ports = mos7840_num_ports;
2236 2232
2237 return mos7840_num_ports; 2233 return mos7840_num_ports;
2238} 2234}
@@ -2240,6 +2236,7 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)
2240static int mos7840_port_probe(struct usb_serial_port *port) 2236static int mos7840_port_probe(struct usb_serial_port *port)
2241{ 2237{
2242 struct usb_serial *serial = port->serial; 2238 struct usb_serial *serial = port->serial;
2239 int device_type = (int)usb_get_serial_data(serial);
2243 struct moschip_port *mos7840_port; 2240 struct moschip_port *mos7840_port;
2244 int status; 2241 int status;
2245 int pnum; 2242 int pnum;
@@ -2496,9 +2493,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
2496 .throttle = mos7840_throttle, 2493 .throttle = mos7840_throttle,
2497 .unthrottle = mos7840_unthrottle, 2494 .unthrottle = mos7840_unthrottle,
2498 .calc_num_ports = mos7840_calc_num_ports, 2495 .calc_num_ports = mos7840_calc_num_ports,
2499#ifdef MCSSerialProbe 2496 .probe = mos7840_probe,
2500 .probe = mos7840_serial_probe,
2501#endif
2502 .ioctl = mos7840_ioctl, 2497 .ioctl = mos7840_ioctl,
2503 .set_termios = mos7840_set_termios, 2498 .set_termios = mos7840_set_termios,
2504 .break_ctl = mos7840_break, 2499 .break_ctl = mos7840_break,