On Tue, May 22, 2012 at 02:04:37PM +0200, Jan Safrata wrote: > Running following code when 'option' driver compatible usb modem is used > > int fd = open("/dev/ttyUSB3", O_RDWR); > if (fd < 0) > exit(1) > while (1) { > fd = open("/dev/ttyUSB3", O_RDWR); > if (fd >= 0) > close(fd); > usleep(200 * 1000); > } > > and disconnecting the modem results with following oops: > > option1 ttyUSB3: GSM modem (1-port) converter now disconnected from ttyUSB3 > option 1-2.6:1.2: device disconnected > BUG: unable to handle kernel paging request at 2f406578 > IP: [<f84fd4a4>] 0xf84fd4a3 > *pdpt = 00000000366f0001 *pde = 0000000000000000 > Oops: 0000 [#1] SMP > Modules linked in: eetis_ts option usb_wwan emgd(O) backlight cfbcopyarea drm_kms_helper drm cfbimgblt cfbfillrect usbserial cdc_acm snd_hda_codec_cirrus snd_hda_intel snd_hda_codec snd_pcm snd_timer snd snd_page_alloc > > Pid: 2298, comm: modemtest Tainted: G O 3.3.6-acs4+ #6 SECO 0866 > EIP: 0060:[<f84fd4a4>] EFLAGS: 00010246 CPU: 0 > EIP is at 0xf84fd4a4 > EAX: 2f406576 EBX: f561d9c0 ECX: f41455a0 EDX: f41455a0 > ESI: f401b400 EDI: 00000000 EBP: f55e7ccc ESP: f55e7ca4 > DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 > Process modemtest (pid: 2298, ti=f55e6000 task=f6c96420 task.ti=f55e6000) > Stack: > 00000001 00000003 c152b9a0 c152b99c 00000003 00000286 f55e7cdc f401b400 > f561d9c0 00000000 f55e7cf8 f85e7c60 00000286 f401b40c f55e7cf0 f40a7600 > f41455a0 f561d9f8 f401b404 00000001 f401b40c f55e7d00 f85a7068 f55e7d20 > Call Trace: > [<f85e7c60>] usb_wwan_dtr_rts+0x60/0xa0 [usb_wwan] This is not right. You're fixing a race with disconnect in option's probe, but this indicates that there's a race with usb_wwan_dtr_rts (as well). > [<f85a7068>] 0xf85a7067 > [<c1210593>] tty_port_close_start+0xe3/0x1c0 > [<c10b74bc>] ? fasync_remove_entry+0x1c/0x90 > [<c1210d46>] tty_port_close+0x16/0x50 > [<f85a76da>] 0xf85a76d9 > [<c120817d>] ? __tty_fasync+0x5d/0x140 > [<c120946e>] tty_release+0x10e/0x4c0 > [<c1210b12>] ? tty_port_open+0xa2/0xc0 > [<f85a774a>] ? 0xf85a7749 > [<c1209b7a>] tty_open+0x35a/0x560 > [<c10acaf8>] chrdev_open+0x98/0x180 > [<c10a7652>] __dentry_open.isra.16+0x1b2/0x2a0 > [<c10a8514>] nameidata_to_filp+0x54/0x70 > [<c10aca60>] ? cdev_put+0x20/0x20 > [<c10b5677>] do_last.isra.47+0x267/0x730 > [<c10b5d04>] path_openat+0x1c4/0x310 > [<c10b5f2d>] do_filp_open+0x2d/0x80 > [<c10c0174>] ? alloc_fd+0x34/0xe0 > [<c10a8614>] do_sys_open+0xe4/0x1b0 > [<c1040000>] ? posix_timer_fn+0xc0/0xd0 > [<c10a870e>] sys_open+0x2e/0x40 > [<c13f2c10>] sysenter_do_call+0x12/0x26 > Code: ba f4 ff ff ff eb bc 55 89 e5 8d 64 24 d8 80 3d 5c 0b 50 f8 00 89 75 f8 89 5d f4 89 7d fc 8b 18 89 c6 8b 43 08 8b 53 4c 8b 40 04 <0f> b6 78 02 0f 85 9f 00 00 00 8b 4a 0c 89 f8 ba 01 00 00 00 e8 > EIP: [<f84fd4a4>] 0xf84fd4a4 SS:ESP 0068:f55e7ca4 > CR2: 000000002f406578 > ---[ end trace 3b8de3e8ffdf7ff2 ]--- > > Signed-off-by: Jan Safrata <jan.nikitenko@xxxxxxxxx> > --- > drivers/usb/serial/option.c | 6 +++++- > 1 files changed, 5 insertions(+), 1 deletions(-) > > diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c > index aac55e6..a9cccad 100644 > --- a/drivers/usb/serial/option.c > +++ b/drivers/usb/serial/option.c > @@ -1478,10 +1478,14 @@ static int option_send_setup(struct usb_serial_port *port) > struct usb_wwan_intf_private *intfdata = > (struct usb_wwan_intf_private *) serial->private; > struct usb_wwan_port_private *portdata; > - int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; > + int ifNum; > int val = 0; > dbg("%s", __func__); > > + if (serial->disconnected) > + return -ENODEV; > + > + ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; > if (is_blacklisted(ifNum, OPTION_BLACKLIST_SENDSETUP, > (struct option_blacklist_info *) intfdata->private)) { > dbg("No send_setup on blacklisted interface #%d\n", ifNum); This is not quite right. You need to use the disconnect mutex as well, e.g.: mutex_lock(&serial->disc_mutex); if (serial->disconnected) { mutex_unlock(&serial->disc_mutex); return -ENODEV; } ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; ... ret = usb_control_msg(serial->dev, ...) mutex_unlock(&serial->disc_mutex); return ret; Johan -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html