aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2007-07-09 15:03:08 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-12 19:34:40 -0400
commit0ffbbe25a73db12792a05f725aa39f8a5de2c882 (patch)
tree1ffc276b87738797558df1ed41e397450659f61e /drivers/usb
parenta69228deefea57ca27c17a196e5727b091c6d323 (diff)
USB: ftdi_sio: fix oops due to processing workarounds too early
Fix an oops that happens in relation with applying work arounds for buggy ftdi_sio devices. The quirks were handled too early because due to changes in the initialisation of usb serial devices the device was not fully initialised when the old hook was called. Addresses bug 8564 Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/ftdi_sio.c104
1 files changed, 44 insertions, 60 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 4066a468118a..7b1673a44077 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -271,26 +271,58 @@ static int debug;
271static __u16 vendor = FTDI_VID; 271static __u16 vendor = FTDI_VID;
272static __u16 product; 272static __u16 product;
273 273
274struct ftdi_private {
275 ftdi_chip_type_t chip_type;
276 /* type of the device, either SIO or FT8U232AM */
277 int baud_base; /* baud base clock for divisor setting */
278 int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
279 __u16 last_set_data_urb_value ;
280 /* the last data state set - needed for doing a break */
281 int write_offset; /* This is the offset in the usb data block to write the serial data -
282 * it is different between devices
283 */
284 int flags; /* some ASYNC_xxxx flags are supported */
285 unsigned long last_dtr_rts; /* saved modem control outputs */
286 wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
287 char prev_status, diff_status; /* Used for TIOCMIWAIT */
288 __u8 rx_flags; /* receive state flags (throttling) */
289 spinlock_t rx_lock; /* spinlock for receive state */
290 struct delayed_work rx_work;
291 struct usb_serial_port *port;
292 int rx_processed;
293 unsigned long rx_bytes;
294
295 __u16 interface; /* FT2232C port interface (0 for FT232/245) */
296
297 int force_baud; /* if non-zero, force the baud rate to this value */
298 int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */
299
300 spinlock_t tx_lock; /* spinlock for transmit state */
301 unsigned long tx_bytes;
302 unsigned long tx_outstanding_bytes;
303 unsigned long tx_outstanding_urbs;
304};
305
274/* struct ftdi_sio_quirk is used by devices requiring special attention. */ 306/* struct ftdi_sio_quirk is used by devices requiring special attention. */
275struct ftdi_sio_quirk { 307struct ftdi_sio_quirk {
276 int (*probe)(struct usb_serial *); 308 int (*probe)(struct usb_serial *);
277 void (*setup)(struct usb_serial *); /* Special settings during startup. */ 309 void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */
278}; 310};
279 311
280static int ftdi_olimex_probe (struct usb_serial *serial); 312static int ftdi_olimex_probe (struct usb_serial *serial);
281static void ftdi_USB_UIRT_setup (struct usb_serial *serial); 313static void ftdi_USB_UIRT_setup (struct ftdi_private *priv);
282static void ftdi_HE_TIRA1_setup (struct usb_serial *serial); 314static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv);
283 315
284static struct ftdi_sio_quirk ftdi_olimex_quirk = { 316static struct ftdi_sio_quirk ftdi_olimex_quirk = {
285 .probe = ftdi_olimex_probe, 317 .probe = ftdi_olimex_probe,
286}; 318};
287 319
288static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { 320static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
289 .setup = ftdi_USB_UIRT_setup, 321 .port_probe = ftdi_USB_UIRT_setup,
290}; 322};
291 323
292static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { 324static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
293 .setup = ftdi_HE_TIRA1_setup, 325 .port_probe = ftdi_HE_TIRA1_setup,
294}; 326};
295 327
296/* 328/*
@@ -567,38 +599,6 @@ static const char *ftdi_chip_name[] = {
567#define THROTTLED 0x01 599#define THROTTLED 0x01
568#define ACTUALLY_THROTTLED 0x02 600#define ACTUALLY_THROTTLED 0x02
569 601
570struct ftdi_private {
571 ftdi_chip_type_t chip_type;
572 /* type of the device, either SIO or FT8U232AM */
573 int baud_base; /* baud base clock for divisor setting */
574 int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
575 __u16 last_set_data_urb_value ;
576 /* the last data state set - needed for doing a break */
577 int write_offset; /* This is the offset in the usb data block to write the serial data -
578 * it is different between devices
579 */
580 int flags; /* some ASYNC_xxxx flags are supported */
581 unsigned long last_dtr_rts; /* saved modem control outputs */
582 wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
583 char prev_status, diff_status; /* Used for TIOCMIWAIT */
584 __u8 rx_flags; /* receive state flags (throttling) */
585 spinlock_t rx_lock; /* spinlock for receive state */
586 struct delayed_work rx_work;
587 struct usb_serial_port *port;
588 int rx_processed;
589 unsigned long rx_bytes;
590
591 __u16 interface; /* FT2232C port interface (0 for FT232/245) */
592
593 int force_baud; /* if non-zero, force the baud rate to this value */
594 int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */
595
596 spinlock_t tx_lock; /* spinlock for transmit state */
597 unsigned long tx_bytes;
598 unsigned long tx_outstanding_bytes;
599 unsigned long tx_outstanding_urbs;
600};
601
602/* Used for TIOCMIWAIT */ 602/* Used for TIOCMIWAIT */
603#define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD) 603#define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
604#define FTDI_STATUS_B1_MASK (FTDI_RS_BI) 604#define FTDI_STATUS_B1_MASK (FTDI_RS_BI)
@@ -609,7 +609,6 @@ struct ftdi_private {
609 609
610/* function prototypes for a FTDI serial converter */ 610/* function prototypes for a FTDI serial converter */
611static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); 611static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id);
612static int ftdi_sio_attach (struct usb_serial *serial);
613static void ftdi_shutdown (struct usb_serial *serial); 612static void ftdi_shutdown (struct usb_serial *serial);
614static int ftdi_sio_port_probe (struct usb_serial_port *port); 613static int ftdi_sio_port_probe (struct usb_serial_port *port);
615static int ftdi_sio_port_remove (struct usb_serial_port *port); 614static int ftdi_sio_port_remove (struct usb_serial_port *port);
@@ -663,7 +662,6 @@ static struct usb_serial_driver ftdi_sio_device = {
663 .ioctl = ftdi_ioctl, 662 .ioctl = ftdi_ioctl,
664 .set_termios = ftdi_set_termios, 663 .set_termios = ftdi_set_termios,
665 .break_ctl = ftdi_break_ctl, 664 .break_ctl = ftdi_break_ctl,
666 .attach = ftdi_sio_attach,
667 .shutdown = ftdi_shutdown, 665 .shutdown = ftdi_shutdown,
668}; 666};
669 667
@@ -1200,6 +1198,8 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id
1200static int ftdi_sio_port_probe(struct usb_serial_port *port) 1198static int ftdi_sio_port_probe(struct usb_serial_port *port)
1201{ 1199{
1202 struct ftdi_private *priv; 1200 struct ftdi_private *priv;
1201 struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
1202
1203 1203
1204 dbg("%s",__FUNCTION__); 1204 dbg("%s",__FUNCTION__);
1205 1205
@@ -1216,6 +1216,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
1216 than queue a task to deliver them */ 1216 than queue a task to deliver them */
1217 priv->flags = ASYNC_LOW_LATENCY; 1217 priv->flags = ASYNC_LOW_LATENCY;
1218 1218
1219 if (quirk && quirk->port_probe)
1220 quirk->port_probe(priv);
1221
1219 /* Increase the size of read buffers */ 1222 /* Increase the size of read buffers */
1220 kfree(port->bulk_in_buffer); 1223 kfree(port->bulk_in_buffer);
1221 port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL); 1224 port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL);
@@ -1246,29 +1249,13 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
1246 return 0; 1249 return 0;
1247} 1250}
1248 1251
1249/* attach subroutine */
1250static int ftdi_sio_attach (struct usb_serial *serial)
1251{
1252 /* Check for device requiring special set up. */
1253 struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial);
1254
1255 if (quirk && quirk->setup)
1256 quirk->setup(serial);
1257
1258 return 0;
1259} /* ftdi_sio_attach */
1260
1261
1262/* Setup for the USB-UIRT device, which requires hardwired 1252/* Setup for the USB-UIRT device, which requires hardwired
1263 * baudrate (38400 gets mapped to 312500) */ 1253 * baudrate (38400 gets mapped to 312500) */
1264/* Called from usbserial:serial_probe */ 1254/* Called from usbserial:serial_probe */
1265static void ftdi_USB_UIRT_setup (struct usb_serial *serial) 1255static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
1266{ 1256{
1267 struct ftdi_private *priv;
1268
1269 dbg("%s",__FUNCTION__); 1257 dbg("%s",__FUNCTION__);
1270 1258
1271 priv = usb_get_serial_port_data(serial->port[0]);
1272 priv->flags |= ASYNC_SPD_CUST; 1259 priv->flags |= ASYNC_SPD_CUST;
1273 priv->custom_divisor = 77; 1260 priv->custom_divisor = 77;
1274 priv->force_baud = B38400; 1261 priv->force_baud = B38400;
@@ -1276,13 +1263,10 @@ static void ftdi_USB_UIRT_setup (struct usb_serial *serial)
1276 1263
1277/* Setup for the HE-TIRA1 device, which requires hardwired 1264/* Setup for the HE-TIRA1 device, which requires hardwired
1278 * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */ 1265 * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */
1279static void ftdi_HE_TIRA1_setup (struct usb_serial *serial) 1266static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
1280{ 1267{
1281 struct ftdi_private *priv;
1282
1283 dbg("%s",__FUNCTION__); 1268 dbg("%s",__FUNCTION__);
1284 1269
1285 priv = usb_get_serial_port_data(serial->port[0]);
1286 priv->flags |= ASYNC_SPD_CUST; 1270 priv->flags |= ASYNC_SPD_CUST;
1287 priv->custom_divisor = 240; 1271 priv->custom_divisor = 240;
1288 priv->force_baud = B38400; 1272 priv->force_baud = B38400;