Skip to content

Commit

Permalink
[media] dvb_usb_v2: do not free resources until delayed init is done
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Antti Palosaari authored and Mauro Carvalho Chehab committed Aug 4, 2012
1 parent 36a5c2b commit 3238aaf
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 13 deletions.
1 change: 1 addition & 0 deletions drivers/media/dvb/dvb-usb/dvb_usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 8 additions & 13 deletions drivers/media/dvb/dvb-usb/dvb_usb_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 3238aaf

Please sign in to comment.