linux/drivers/usb/serial
Bjørn Mork 954c3f8a5f USB: serial: Enforce USB driver and USB serial driver match
We need to make sure that the USB serial driver we find
matches the USB driver whose probe we are currently
executing. Otherwise we will end up with USB serial
devices bound to the correct serial driver but wrong
USB driver.

An example of such cross-probing, where the usbserial_generic
USB driver has found the sierra serial driver:

May 29 18:26:15 nemi kernel: [ 4442.559246] usbserial_generic 4-4:1.0: Sierra USB modem converter detected
May 29 18:26:20 nemi kernel: [ 4447.556747] usbserial_generic 4-4:1.2: Sierra USB modem converter detected
May 29 18:26:25 nemi kernel: [ 4452.557288] usbserial_generic 4-4:1.3: Sierra USB modem converter detected

sysfs view of the same problem:

bjorn@nemi:~$ ls -l /sys/bus/usb/drivers/sierra/
total 0
--w------- 1 root root 4096 May 29 18:23 bind
lrwxrwxrwx 1 root root    0 May 29 18:23 module -> ../../../../module/usbserial
--w------- 1 root root 4096 May 29 18:23 uevent
--w------- 1 root root 4096 May 29 18:23 unbind
bjorn@nemi:~$ ls -l /sys/bus/usb-serial/drivers/sierra/
total 0
--w------- 1 root root 4096 May 29 18:23 bind
lrwxrwxrwx 1 root root    0 May 29 18:23 module -> ../../../../module/sierra
-rw-r--r-- 1 root root 4096 May 29 18:23 new_id
lrwxrwxrwx 1 root root    0 May 29 18:32 ttyUSB0 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb4/4-4/4-4:1.0/ttyUSB0
lrwxrwxrwx 1 root root    0 May 29 18:32 ttyUSB1 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb4/4-4/4-4:1.2/ttyUSB1
lrwxrwxrwx 1 root root    0 May 29 18:32 ttyUSB2 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb4/4-4/4-4:1.3/ttyUSB2
--w------- 1 root root 4096 May 29 18:23 uevent
--w------- 1 root root 4096 May 29 18:23 unbind

bjorn@nemi:~$ ls -l /sys/bus/usb/drivers/usbserial_generic/
total 0
lrwxrwxrwx 1 root root    0 May 29 18:33 4-4:1.0 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb4/4-4/4-4:1.0
lrwxrwxrwx 1 root root    0 May 29 18:33 4-4:1.2 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb4/4-4/4-4:1.2
lrwxrwxrwx 1 root root    0 May 29 18:33 4-4:1.3 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb4/4-4/4-4:1.3
--w------- 1 root root 4096 May 29 18:33 bind
lrwxrwxrwx 1 root root    0 May 29 18:33 module -> ../../../../module/usbserial
--w------- 1 root root 4096 May 29 18:22 uevent
--w------- 1 root root 4096 May 29 18:33 unbind
bjorn@nemi:~$ ls -l /sys/bus/usb-serial/drivers/generic/
total 0
--w------- 1 root root 4096 May 29 18:33 bind
lrwxrwxrwx 1 root root    0 May 29 18:33 module -> ../../../../module/usbserial
-rw-r--r-- 1 root root 4096 May 29 18:33 new_id
--w------- 1 root root 4096 May 29 18:22 uevent
--w------- 1 root root 4096 May 29 18:33 unbind

So we end up with a mismatch between the USB driver and the
USB serial driver.  The reason for the above is simple: The
USB driver probe will succeed if *any* registered serial
driver matches, and will use that serial driver for all
serial driver functions.

This makes ref counting go wrong. We count the USB driver
as used, but not the USB serial driver.  This may result
in Oops'es as demonstrated by Johan Hovold <jhovold@gmail.com>:

[11811.646396] drivers/usb/serial/usb-serial.c: get_free_serial 1
[11811.646443] drivers/usb/serial/usb-serial.c: get_free_serial - minor base = 0
[11811.646460] drivers/usb/serial/usb-serial.c: usb_serial_probe - registering ttyUSB0
[11811.646766] usb 6-1: pl2303 converter now attached to ttyUSB0
[11812.264197] USB Serial deregistering driver FTDI USB Serial Device
[11812.264865] usbcore: deregistering interface driver ftdi_sio
[11812.282180] USB Serial deregistering driver pl2303
[11812.283141] pl2303 ttyUSB0: pl2303 converter now disconnected from ttyUSB0
[11812.283272] usbcore: deregistering interface driver pl2303
[11812.301056] USB Serial deregistering driver generic
[11812.301186] usbcore: deregistering interface driver usbserial_generic
[11812.301259] drivers/usb/serial/usb-serial.c: usb_serial_disconnect
[11812.301823] BUG: unable to handle kernel paging request at f8e7438c
[11812.301845] IP: [<f8e38445>] usb_serial_disconnect+0xb5/0x100 [usbserial]
[11812.301871] *pde = 357ef067 *pte = 00000000
[11812.301957] Oops: 0000 [#1] PREEMPT SMP
[11812.301983] Modules linked in: usbserial(-) [last unloaded: pl2303]
[11812.302008]
[11812.302019] Pid: 1323, comm: modprobe Tainted: G        W    3.4.0-rc7+ #101 Dell Inc. Vostro 1520/0T816J
[11812.302115] EIP: 0060:[<f8e38445>] EFLAGS: 00010246 CPU: 1
[11812.302130] EIP is at usb_serial_disconnect+0xb5/0x100 [usbserial]
[11812.302141] EAX: f508a180 EBX: f508a180 ECX: 00000000 EDX: f8e74300
[11812.302151] ESI: f5050800 EDI: 00000001 EBP: f5141e78 ESP: f5141e58
[11812.302160]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
[11812.302170] CR0: 8005003b CR2: f8e7438c CR3: 34848000 CR4: 000007d0
[11812.302180] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[11812.302189] DR6: ffff0ff0 DR7: 00000400
[11812.302199] Process modprobe (pid: 1323, ti=f5140000 task=f61e2bc0 task.ti=f5140000)
[11812.302209] Stack:
[11812.302216]  f8e3be0f f8e3b29c f8e3ae00 00000000 f513641c f5136400 f513641c f507a540
[11812.302325]  f5141e98 c133d2c1 00000000 00000000 f509c400 f513641c f507a590 f5136450
[11812.302372]  f5141ea8 c12f0344 f513641c f507a590 f5141ebc c12f0c67 00000000 f507a590
[11812.302419] Call Trace:
[11812.302439]  [<c133d2c1>] usb_unbind_interface+0x51/0x190
[11812.302456]  [<c12f0344>] __device_release_driver+0x64/0xb0
[11812.302469]  [<c12f0c67>] driver_detach+0x97/0xa0
[11812.302483]  [<c12f001c>] bus_remove_driver+0x6c/0xe0
[11812.302500]  [<c145938d>] ? __mutex_unlock_slowpath+0xcd/0x140
[11812.302514]  [<c12f0ff9>] driver_unregister+0x49/0x80
[11812.302528]  [<c1457df6>] ? printk+0x1d/0x1f
[11812.302540]  [<c133c50d>] usb_deregister+0x5d/0xb0
[11812.302557]  [<f8e37c55>] ? usb_serial_deregister+0x45/0x50 [usbserial]
[11812.302575]  [<f8e37c8d>] usb_serial_deregister_drivers+0x2d/0x40 [usbserial]
[11812.302593]  [<f8e3a6e2>] usb_serial_generic_deregister+0x12/0x20 [usbserial]
[11812.302611]  [<f8e3acf0>] usb_serial_exit+0x8/0x32 [usbserial]
[11812.302716]  [<c1080b48>] sys_delete_module+0x158/0x260
[11812.302730]  [<c110594e>] ? mntput+0x1e/0x30
[11812.302746]  [<c145c3c3>] ? sysenter_exit+0xf/0x18
[11812.302746]  [<c107777c>] ? trace_hardirqs_on_caller+0xec/0x170
[11812.302746]  [<c145c390>] sysenter_do_call+0x12/0x36
[11812.302746] Code: 24 02 00 00 e8 dd f3 20 c8 f6 86 74 02 00 00 02 74 b4 8d 86 4c 02 00 00 47 e8 78 55 4b c8 0f b6 43 0e 39 f8 7f a9 8b 53 04 89 d8 <ff> 92 8c 00 00 00 89 d8 e8 0e ff ff ff 8b 45 f0 c7 44 24 04 2f
[11812.302746] EIP: [<f8e38445>] usb_serial_disconnect+0xb5/0x100 [usbserial] SS:ESP 0068:f5141e58
[11812.302746] CR2: 00000000f8e7438c

Fix by only evaluating serial drivers pointing back to the
USB driver we are currently probing.  This still allows two
or more drivers to match the same device, running their
serial driver probes to sort out which one to use.

Cc: stable@vger.kernel.org # 3.0, 3.2, 3.3, 3.4
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Reviewed-by: Felipe Balbi <balbi@ti.com>
Tested-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2012-06-13 14:01:56 -07:00
..
aircable.c USB: aircable.c: remove dbg() usage 2012-05-15 16:27:08 -07:00
ark3116.c USB: ark3116.c: remove dbg() usage 2012-05-15 16:27:11 -07:00
belkin_sa.c USB: belkin_sa.c: remove dbg() usage 2012-05-15 16:27:11 -07:00
belkin_sa.h USB: belkin_sa.h: checkpatch cleanups 2010-05-20 13:21:46 -07:00
bus.c USB: add read support to usb-serial/../new_id 2012-05-14 09:30:40 -07:00
ch341.c USB: serial: ch341: make the reset_resume callback actually work. 2012-05-16 08:36:13 -07:00
console.c USB: console.c: remove err() usage 2012-04-20 16:53:58 -07:00
cp210x.c USB: serial: cp210x: add Optris MS Pro usb id 2012-06-12 16:05:59 -07:00
cyberjack.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
cypress_m8.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
cypress_m8.h USB: cypress_m8.h: checkpatch cleanups 2010-05-20 13:21:46 -07:00
digi_acceleport.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
empeg.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
ezusb_convert.pl
ezusb.c USB: ezusb.c: remove dbg() tracing calls 2012-05-03 16:44:02 -07:00
f81232.c USB: f81232.c: remove dbg() usage 2012-05-15 16:27:17 -07:00
ftdi_sio_ids.h USB: ftdi-sio: Add support for RT Systems USB-RTS01 serial adapter 2012-06-12 16:05:44 -07:00
ftdi_sio.c USB: ftdi-sio: Add support for RT Systems USB-RTS01 serial adapter 2012-06-12 16:05:44 -07:00
ftdi_sio.h USB: ftdi_sio: add support for FT-X series devices 2012-03-14 15:43:05 -07:00
funsoft.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
garmin_gps.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
generic.c USB: generic.c: remove dbg() usage 2012-05-15 16:27:18 -07:00
hp4x.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
io_16654.h
io_edgeport.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
io_edgeport.h Fix common misspellings 2011-03-31 11:26:23 -03:00
io_ionsp.h USB: io_edgeport: checkpatch cleanups 2010-05-20 13:21:47 -07:00
io_tables.h USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
io_ti.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
io_ti.h USB: io_edgeport: checkpatch cleanups 2010-05-20 13:21:47 -07:00
io_usbvend.h USB: io_edgeport: checkpatch cleanups 2010-05-20 13:21:47 -07:00
ipaq.c USB: ipaq.c: remove dbg() usage 2012-05-15 16:27:20 -07:00
ipw.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
ir-usb.c USB: ir-usb.c: remove dbg() usage 2012-05-15 16:27:23 -07:00
iuu_phoenix.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
iuu_phoenix.h
Kconfig USB: serial: add quatech2 usb to serial driver 2012-05-10 12:46:20 -07:00
keyspan_pda.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
keyspan_usa26msg.h
keyspan_usa28msg.h
keyspan_usa49msg.h
keyspan_usa67msg.h
keyspan_usa90msg.h
keyspan.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
keyspan.h USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
kl5kusb105.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
kl5kusb105.h USB: kl5kusb105.h: checkpatch cleanups 2010-05-20 13:21:47 -07:00
kobil_sct.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
kobil_sct.h USB: kobil_sct.h: checkpatch cleanups 2010-05-20 13:21:47 -07:00
Makefile USB: serial: add quatech2 usb to serial driver 2012-05-10 12:46:20 -07:00
Makefile-keyspan_pda_fw
mct_u232.c USB: mct_u232: Fix incorrect TIOCMSET return 2012-06-12 16:09:49 -07:00
mct_u232.h Update broken web addresses in the kernel. 2010-10-18 11:03:14 +02:00
metro-usb.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
mos7720.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
mos7840.c USB: mos7840: Fix compilation of usb serial driver 2012-06-12 16:09:50 -07:00
moto_modem.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
navman.c USB: navman.c: remove dbg() usage 2012-05-15 16:27:25 -07:00
omninet.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
opticon.c USB: serial: opticon: hook up suspend/resume callbacks 2012-05-10 14:35:21 -07:00
option.c USB: option: add more YUGA device ids 2012-06-12 16:25:01 -07:00
oti6858.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
oti6858.h
pl2303.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
pl2303.h USB: serial: pl2303: rm duplicate id 2011-11-15 10:06:15 -08:00
qcaux.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
qcserial.c USB: qcserial: Add Sierra Wireless device IDs 2012-06-12 16:05:44 -07:00
quatech2.c USB: serial: add copyright and license to quatech2 2012-05-10 14:05:01 -07:00
safe_serial.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
siemens_mpi.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
sierra.c USB: serial: sierra: Add support for Sierra Wireless AirCard 320U modem 2012-06-12 16:05:59 -07:00
spcp8x5.c USB: spcp8x5.c: remove dbg() usage 2012-05-15 16:27:30 -07:00
ssu100.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
symbolserial.c USB: symbolserial.c: remove dbg() usage 2012-05-15 16:27:32 -07:00
ti_usb_3410_5052.c USB: serial: ti_usb_3410_5052: Add support for the FRI2 serial console 2012-05-11 15:14:07 -07:00
ti_usb_3410_5052.h USB: serial: ti_usb_3410_5052: Add support for the FRI2 serial console 2012-05-11 15:14:07 -07:00
usb_debug.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
usb_wwan.c USB: usb_wwan.c: remove dbg() tracing calls 2012-05-03 16:45:00 -07:00
usb-serial.c USB: serial: Enforce USB driver and USB serial driver match 2012-06-13 14:01:56 -07:00
usb-wwan.h tty: remove filp from the USB tty ioctls 2011-02-17 11:59:14 -08:00
visor.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
visor.h USB: visor.h: checkpatch cleanups 2010-05-20 13:21:47 -07:00
vivopay-serial.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
whiteheat.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00
whiteheat.h
zio.c USB: serial: rework usb_serial_register/deregister_drivers() 2012-05-08 15:46:14 -07:00