[media] dvb_usb_v2: get rid of deferred probe

Deferred probe was added in order to avoid udev vs. Kernel firmware
download problems. It is not needed anymore.
https://bugzilla.redhat.com/show_bug.cgi?id=827538

Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
This commit is contained in:
Antti Palosaari 2013-07-30 17:22:25 -03:00 committed by Mauro Carvalho Chehab
parent e42efde4e4
commit dd0f5e0b75
2 changed files with 45 additions and 94 deletions

View File

@ -352,9 +352,7 @@ struct dvb_usb_adapter {
* @rc_map: name of rc codes table * @rc_map: name of rc codes table
* @rc_polling_active: set when RC polling is active * @rc_polling_active: set when RC polling is active
* @udev: pointer to the device's struct usb_device * @udev: pointer to the device's struct usb_device
* @intf: pointer to the device's usb interface
* @rc: remote controller configuration * @rc: remote controller configuration
* @probe_work: work to defer .probe()
* @powered: indicated whether the device is power or not * @powered: indicated whether the device is power or not
* @usb_mutex: mutex for usb control messages * @usb_mutex: mutex for usb control messages
* @i2c_mutex: mutex for i2c-transfers * @i2c_mutex: mutex for i2c-transfers
@ -370,10 +368,7 @@ struct dvb_usb_device {
const char *rc_map; const char *rc_map;
bool rc_polling_active; bool rc_polling_active;
struct usb_device *udev; struct usb_device *udev;
struct usb_interface *intf;
struct dvb_usb_rc rc; struct dvb_usb_rc rc;
struct work_struct probe_work;
pid_t work_pid;
int powered; int powered;
/* locking */ /* locking */

View File

@ -833,20 +833,44 @@ err:
return ret; return ret;
} }
/* int dvb_usbv2_probe(struct usb_interface *intf,
* udev, which is used for the firmware downloading, requires we cannot const struct usb_device_id *id)
* block during module_init(). module_init() calls USB probe() which
* is this routine. Due to that we delay actual operation using workqueue
* and return always success here.
*/
static void dvb_usbv2_init_work(struct work_struct *work)
{ {
int ret; int ret;
struct dvb_usb_device *d = struct dvb_usb_device *d;
container_of(work, struct dvb_usb_device, probe_work); struct usb_device *udev = interface_to_usbdev(intf);
struct dvb_usb_driver_info *driver_info =
(struct dvb_usb_driver_info *) id->driver_info;
d->work_pid = current->pid; dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__,
dev_dbg(&d->udev->dev, "%s: work_pid=%d\n", __func__, d->work_pid); intf->cur_altsetting->desc.bInterfaceNumber);
if (!id->driver_info) {
dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME);
ret = -ENODEV;
goto err;
}
d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
if (!d) {
dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
ret = -ENOMEM;
goto err;
}
d->name = driver_info->name;
d->rc_map = driver_info->rc_map;
d->udev = udev;
d->props = driver_info->props;
if (intf->cur_altsetting->desc.bInterfaceNumber !=
d->props->bInterfaceNumber) {
ret = -ENODEV;
goto err_free_all;
}
mutex_init(&d->usb_mutex);
mutex_init(&d->i2c_mutex);
if (d->props->size_of_priv) { if (d->props->size_of_priv) {
d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL); d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL);
@ -854,7 +878,7 @@ static void dvb_usbv2_init_work(struct work_struct *work)
dev_err(&d->udev->dev, "%s: kzalloc() failed\n", dev_err(&d->udev->dev, "%s: kzalloc() failed\n",
KBUILD_MODNAME); KBUILD_MODNAME);
ret = -ENOMEM; ret = -ENOMEM;
goto err_usb_driver_release_interface; goto err_free_all;
} }
} }
@ -884,20 +908,12 @@ static void dvb_usbv2_init_work(struct work_struct *work)
* device. As 'new' device is warm we should * device. As 'new' device is warm we should
* never go here again. * never go here again.
*/ */
return; goto exit;
} else { } else {
/* goto err_free_all;
* Unexpected error. We must unregister driver
* manually from the device, because device is
* already register by returning from probe()
* with success. usb_driver_release_interface()
* finally calls disconnect() in order to free
* resources.
*/
goto err_usb_driver_release_interface;
} }
} else { } else {
goto err_usb_driver_release_interface; goto err_free_all;
} }
} }
@ -906,73 +922,17 @@ static void dvb_usbv2_init_work(struct work_struct *work)
ret = dvb_usbv2_init(d); ret = dvb_usbv2_init(d);
if (ret < 0) if (ret < 0)
goto err_usb_driver_release_interface; goto err_free_all;
dev_info(&d->udev->dev, dev_info(&d->udev->dev,
"%s: '%s' successfully initialized and connected\n", "%s: '%s' successfully initialized and connected\n",
KBUILD_MODNAME, d->name); KBUILD_MODNAME, d->name);
exit:
return;
err_usb_driver_release_interface:
dev_info(&d->udev->dev, "%s: '%s' error while loading driver (%d)\n",
KBUILD_MODNAME, d->name, ret);
usb_driver_release_interface(to_usb_driver(d->intf->dev.driver),
d->intf);
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
return;
}
int dvb_usbv2_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
int ret;
struct dvb_usb_device *d;
struct usb_device *udev = interface_to_usbdev(intf);
struct dvb_usb_driver_info *driver_info =
(struct dvb_usb_driver_info *) id->driver_info;
dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__,
intf->cur_altsetting->desc.bInterfaceNumber);
if (!id->driver_info) {
dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME);
ret = -ENODEV;
goto err;
}
d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
if (!d) {
dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
ret = -ENOMEM;
goto err;
}
d->name = driver_info->name;
d->rc_map = driver_info->rc_map;
d->udev = udev;
d->intf = intf;
d->props = driver_info->props;
if (d->intf->cur_altsetting->desc.bInterfaceNumber !=
d->props->bInterfaceNumber) {
ret = -ENODEV;
goto err_kfree;
}
mutex_init(&d->usb_mutex);
mutex_init(&d->i2c_mutex);
INIT_WORK(&d->probe_work, dvb_usbv2_init_work);
usb_set_intfdata(intf, d); usb_set_intfdata(intf, d);
ret = schedule_work(&d->probe_work);
if (ret < 0) {
dev_err(&d->udev->dev, "%s: schedule_work() failed\n",
KBUILD_MODNAME);
goto err_kfree;
}
return 0; return 0;
err_kfree: err_free_all:
kfree(d); dvb_usbv2_exit(d);
err: err:
dev_dbg(&udev->dev, "%s: failed=%d\n", __func__, ret); dev_dbg(&udev->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
@ -984,12 +944,8 @@ void dvb_usbv2_disconnect(struct usb_interface *intf)
struct dvb_usb_device *d = usb_get_intfdata(intf); struct dvb_usb_device *d = usb_get_intfdata(intf);
const char *name = d->name; const char *name = d->name;
struct device dev = d->udev->dev; struct device dev = d->udev->dev;
dev_dbg(&d->udev->dev, "%s: pid=%d work_pid=%d\n", __func__, dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__,
current->pid, d->work_pid); intf->cur_altsetting->desc.bInterfaceNumber);
/* ensure initialization work is finished until release resources */
if (d->work_pid != current->pid)
cancel_work_sync(&d->probe_work);
if (d->props->exit) if (d->props->exit)
d->props->exit(d); d->props->exit(d);