Skip to contentSkip to conversation

Workqueue and kernel panic on device disconnect

DISCUSSION Frank Schäfer 1 participant 2 messages Oct 25, 2011 – Oct 26, 2011

lore
Share & tools
lore
#0 lore raw

Hi,

I'm trying to use a workqueue in a usb driver for polling the states of the device buttons.
That works fine, but when I disconnect the device, the kernel sometimes explodes.
The machine turns off immediately, without saving a backtrace (I will try to make a photo tomorrow)

The code:

static struct delayed_work poll_work;

static const struct usb_device_id device_table[] = {
     {USB_DEVICE(0x1234, 0x5678)},
     {}
};

static void poll(struct work_struct *work)

{
     schedule_delayed_work(&poll_work,
                   msecs_to_jiffies(100));
}

MODULE_DEVICE_TABLE(usb, device_table);

static int test_probe(struct usb_interface *intf,
const struct usb_device_id *id)

{
     INIT_DELAYED_WORK(&poll_work, poll);
     schedule_delayed_work(&poll_work,
                   msecs_to_jiffies(100));
     return 0;
}

static void test_disconnect(struct usb_interface *intf)

{
     cancel_delayed_work_sync(&poll_work);
}

static struct usb_driver test_driver = {

     .name       = MODULE_NAME,
     .id_table   = device_table,
     .probe      = test_probe,

.disconnect = test_disconnect,
};

static int __init test_mod_init(void)

{
     return usb_register(&test_driver);
}

static void __exit test_mod_exit(void)

{
     usb_deregister(&test_driver);
}

module_init(test_mod_init);
module_exit(test_mod_exit);

What am I doing wrong ?
Is there anything else I have to do in addition to calling cancel_delayed_work_sync() in the disconnect fcn ?

Thanks,
Frank Schaefer

#1 lore raw

Am 25.10.2011 23:29, schrieb Frank Sch?fer:

Quoted 63 lines

Hi,

I'm trying to use a workqueue in a usb driver for polling the states of the device buttons.
That works fine, but when I disconnect the device, the kernel sometimes explodes.
The machine turns off immediately, without saving a backtrace (I will try to make a photo tomorrow)

The code:

static struct delayed_work poll_work;

static const struct usb_device_id device_table[] = {
    {USB_DEVICE(0x1234, 0x5678)},
    {}
};

static void poll(struct work_struct *work)

{
    schedule_delayed_work(&poll_work,
                  msecs_to_jiffies(100));
}

MODULE_DEVICE_TABLE(usb, device_table);

static int test_probe(struct usb_interface *intf,
const struct usb_device_id *id)

{
    INIT_DELAYED_WORK(&poll_work, poll);
    schedule_delayed_work(&poll_work,
                  msecs_to_jiffies(100));
    return 0;
}

static void test_disconnect(struct usb_interface *intf)

{
    cancel_delayed_work_sync(&poll_work);
}

static struct usb_driver test_driver = {

    .name       = MODULE_NAME,
    .id_table   = device_table,
    .probe      = test_probe,

.disconnect = test_disconnect,
};

static int __init test_mod_init(void)

{
    return usb_register(&test_driver);
}

static void __exit test_mod_exit(void)

{
    usb_deregister(&test_driver);
}

module_init(test_mod_init);
module_exit(test_mod_exit);

Quoted 7 lines

What am I doing wrong ?
Is there anything else I have to do in addition to calling cancel_delayed_work_sync() in the disconnect fcn ?

Thanks,
Frank Schaefer

I've managed to make a photo of the backtrace:

http://imageshack.us/photo/my-images/823/img075gv.jpg

Could this be a kernel bug ?

Regards,
Frank