diff options
author | Johan Hovold <jhovold@gmail.com> | 2013-07-26 05:55:18 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-26 17:14:09 -0400 |
commit | 40c24f2893ba0ba7df485871f6aac0c197ceef5b (patch) | |
tree | 78cfddeb2394b1a61988e85ed592f3497d9f8b54 /drivers/usb | |
parent | d8a083cc746664916d9d36ed9e4d08a29525f245 (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.c | 75 |
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 | ||
190 | static int device_type; | ||
191 | |||
192 | static const struct usb_device_id id_table[] = { | 190 | static 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 | ||
834 | static 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 | ||
2204 | static int mos7840_calc_num_ports(struct usb_serial *serial) | 2190 | static 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 | 2220 | out: |
2229 | device_type = MOSCHIP_DEVICE_ID_7820; | 2221 | usb_set_serial_data(serial, (void *)device_type); |
2230 | } | 2222 | |
2223 | return 0; | ||
2224 | } | ||
2225 | |||
2226 | static 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) | |||
2240 | static int mos7840_port_probe(struct usb_serial_port *port) | 2236 | static 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, |