Linux: Kernel panic after unplugging touch device

Touch controllers developed by NextWindow are included in touch displays and notebooks. An example for this are the touch displays from Chilin. NextWindow provides an extra Kernel module to uses the controllers in combination with Linux. But there seems to be a bug in the current module (Version: 0.6.1.0).

Every time I turn off the monitor or unplug it from the computer the Kernel crashes. After the crash I have to reboot the computer.

An example crash output might look like this:

$ dmesg
...
[ 1375.352570] usbcore: deregistering interface driver nwfermi
[ 1375.352740] BUG: unable to handle kernel NULL pointer dereference at 00000054
[ 1375.352750] IP: [] mutex_lock+0xd/0x24
[ 1375.352765] *pde = 00000000
[ 1375.352770] Oops: 0002 [#1] SMP
[ 1375.352775] last sysfs file: /sys/devices/virtual/vtconsole/vtcon0/uevent
[ 1375.352782] Modules linked in: fuse loop snd_hda_codec_realtek snd_hda_codec_atihdmi snd_hda_intel snd_hda_codec snd_hwdep snd_pcm snd_seq snd_timer snd_seq_device snd usbhid joydev psmouse i2c_piix4 evdev hid nw_fermi(-) serio_raw pcfglrx(P) snd_page_alloc button ext3 jbd mbcache sd_mod crc_t10dif ata_generic ohci_hcd ahci pata_atiixp thermal thermal_sys r8169 mii ehci_hcd libata usbcore nls_base scsi_mod [last unloaded: scsi_wait_scan]
[ 1375.352834]
[ 1375.352842] Pid: 1959, comm: rmmod Tainted: P (2.6.32-5-686 #1) To be filled by O.E.M.
[ 1375.352847] EIP: 0060:[] EFLAGS: 00010246 CPU: 1
[ 1375.352851] EIP is at mutex_lock+0xd/0x24
[ 1375.352855] EAX: 00000054 EBX: 00000054 ECX: f7cd3ce0 EDX: f6604000
[ 1375.352859] ESI: 00000054 EDI: f6f7bc00 EBP: f6f7bc1c ESP: f6605ed8
[ 1375.352864] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 1375.352869] Process rmmod (pid: 1959, ti=f6604000 task=f5d2a640 task.ti=f6604000)
[ 1375.352872] Stack:
[ 1375.352875] 00000000 00000000 f857e57d ffffffff f6f7bc00 f6f7bc1c f655c800 f857ed64
[ 1375.352884] f7cc7c30 00000000 f6f7bc1c f857ed98 f857ed98 00000880 c11b326c f6f7bc1c
[ 1375.352893] f6f7bc50 c11b3308 f857ed98 00000000 f7cd3420 c11b28b2 f857ed64 f857ed90
[ 1375.352904] Call Trace:
[ 1375.352916] [] ? fermi_disconnect+0x3a/0x88 [nw_fermi]
[ 1375.352933] [] ? usb_unbind_interface+0x3f/0xb4 [usbcore]
[ 1375.352943] [] ? __device_release_driver+0x74/0xb7
[ 1375.352948] [] ? driver_detach+0x59/0x77
[ 1375.352956] [] ? bus_remove_driver+0x66/0x8e
[ 1375.352969] [] ? usb_deregister+0x76/0x7e [usbcore]
[ 1375.352977] [] ? sys_delete_module+0x19f/0x20f
[ 1375.352986] [] ? remove_vma+0x43/0x48
[ 1375.352993] [] ? do_page_fault+0x2f1/0x307
[ 1375.353001] [] ? syscall_call+0x7/0xb
[ 1375.353005] Code: c1 03 48 79 0b 89 d8 e8 ab ff ff ff 85 c0 75 0c 89 e0 25 00 e0 ff ff 89 43 10 31 c0 5b c3 53 89 c3 83 ec 04 e8 fc f8 ff ff 89 d8 ff 08 79 05 e8 60 ff ff ff 89 e0 25 00 e0 ff ff 89 43 10 5b
[ 1375.353054] EIP: [] mutex_lock+0xd/0x24 SS:ESP 0068:f6605ed8
[ 1375.353061] CR2: 0000000000000054

I have reported the bug on launchpad. But since today I didn't get any response from the developers. So I tried to fix the problem on my own. I have modified some lines and I think I have fixed the problem. The modifications were tested using Debian Squeeze(i386) and there were no errors.

The following code is a patch to apply the changes I have made.

March 6th, 2012: In some cases the old patch didn't work. So I have prepared a new one and it seems to work very well.

--- nw-fermi.c.orig        2011-07-22 00:00:00.000000000 +0200
+++ nw-fermi.c        2012-03-02 08:18:17.000000000 +0100
@@ -523,8 +523,25 @@
    int retval = 0;

    if (urb->status) {
-       err("Error on read completion routine.");
-       retval = -EFAULT;
+       dbg("URB Status: %d\n", urb->status);
+       switch(urb->status) {
+       /* device gone, unplugged or unlinked */
+       case -ECONNRESET:
+       case -ENODEV:
+       case -ENOENT:
+       case -ESHUTDOWN:
+           retval = -ENODEV;
+           break;
+       /* errors that might occur during unplugging */
+       case -EILSEQ:
+       case -EPROTO:
+       case -ETIME:
+           retval = -EIO;
+           break;
+       default:
+           err("Error on read completion routine. Code: %d", urb->status);
+           retval = -EFAULT;
+       }
    }
    else {
        if (!dev->interface) {      /* disconnect() was called */
@@ -734,6 +751,11 @@
    struct usb_fermi *dev;
    int minor = interface->minor;

+   /* the minor number should be equal to or greater than 0 */
+   if(minor < 0) {
+       return;
+   }
+
    dev = usb_get_intfdata(interface);
    usb_set_intfdata(interface, NULL);

It's very easy to apply the changes. Just download the patch, apply it and rebuild the module. This might look like the following actions.

. code-block:: console

$ cd /usr/src/nwfermi-0.6.1.0/ $ patch -p0 -i /path/to/your/patch/file.patch $ dpkg-reconfigure nwfermi

If the rebuild of the module doesn't show any errors the computer can be rebooted. After the reboot everything should work fine.

Verwandte Artikel