[media] dvb_usb_v2: do not free resources until delayed init is done
authorAntti Palosaari <crope@iki.fi>
Sun, 10 Jun 2012 00:11:28 +0000 (21:11 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 4 Aug 2012 10:56:28 +0000 (07:56 -0300)
It was possible to free resources by unloading module while
initialization was still ongoing on delayed work.

Use PID to make decision on .disconnect() if caller is our
work or some other as work also calls .disconnect() in error
case. There could be better solution still...

Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/dvb/dvb-usb/dvb_usb.h
drivers/media/dvb/dvb-usb/dvb_usb_init.c

index 4394a5d6f161e48b2133cfded48d32bbf504e082..79f8571b9b209b7692ebb3a5e2442a0aa9a770f6 100644 (file)
@@ -322,6 +322,7 @@ struct dvb_usb_device {
        struct dvb_usb_rc rc;
        struct usb_device *udev;
        struct work_struct probe_work;
+       pid_t work_pid;
        struct usb_interface *intf;
 
 #define DVB_USB_STATE_INIT        0x000
index 0a452fc4edc8a895182d5d6954b9303ba6650e3b..9f75bb18ed17eb1591ae0f61ba592b19eb15a21d 100644 (file)
@@ -266,10 +266,6 @@ int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
        return 0;
 }
 
-/*
- * USB
- */
-
 /*
  * udev, which is used for the firmware downloading, requires we cannot
  * block during module_init(). module_init() calls USB probe() which
@@ -284,7 +280,9 @@ static void dvb_usbv2_init_work(struct work_struct *work)
                        container_of(work, struct dvb_usb_device, probe_work);
        bool cold = false;
 
-       pr_debug("%s:\n", __func__);
+       d->work_pid = current->pid;
+
+       pr_debug("%s: work_pid=%d\n", __func__, d->work_pid);
 
        if (d->props.size_of_priv) {
                d->priv = kzalloc(d->props.size_of_priv, GFP_KERNEL);
@@ -405,15 +403,12 @@ void dvb_usbv2_disconnect(struct usb_interface *intf)
        struct dvb_usb_device *d = usb_get_intfdata(intf);
        const char *name = "generic DVB-USB module";
 
-       pr_debug("%s:\n", __func__);
+       pr_debug("%s: pid=%d work_pid=%d\n", __func__, current->pid,
+                       d->work_pid);
 
-       /*
-        * FIXME: We should ensure initialization work is finished
-        * until exit from this routine (cancel_work_sync / flush_work).
-        * Unfortunately usb_driver_release_interface() call finally goes
-        * here too and in that case we endup deadlock. How to perform
-        * operation conditionally only on disconned / unload?
-        */
+       /* ensure initialization work is finished until release resources */
+       if (d->work_pid != current->pid)
+               cancel_work_sync(&d->probe_work);
 
        usb_set_intfdata(intf, NULL);
        if (d) {