[media] cx231xx: fix race condition in DVB initialization

Fix case where analog calls come in while the DVB side of the board is still
initializing.  This patch is actually just an exact port of the same patch
made by Mauro to em28xx in hg rev 14762.

Signed-off-by: Devin Heitmueller <dheitmueller@hauppauge.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Devin Heitmueller 2010-07-06 19:24:19 -03:00 committed by Mauro Carvalho Chehab
parent d78148fba4
commit 761f6cf642
2 changed files with 12 additions and 13 deletions

View File

@ -97,20 +97,17 @@ void cx231xx_add_into_devlist(struct cx231xx *dev)
}; };
static LIST_HEAD(cx231xx_extension_devlist); static LIST_HEAD(cx231xx_extension_devlist);
static DEFINE_MUTEX(cx231xx_extension_devlist_lock);
int cx231xx_register_extension(struct cx231xx_ops *ops) int cx231xx_register_extension(struct cx231xx_ops *ops)
{ {
struct cx231xx *dev = NULL; struct cx231xx *dev = NULL;
mutex_lock(&cx231xx_devlist_mutex); mutex_lock(&cx231xx_devlist_mutex);
mutex_lock(&cx231xx_extension_devlist_lock);
list_add_tail(&ops->next, &cx231xx_extension_devlist); list_add_tail(&ops->next, &cx231xx_extension_devlist);
list_for_each_entry(dev, &cx231xx_devlist, devlist) list_for_each_entry(dev, &cx231xx_devlist, devlist)
ops->init(dev); ops->init(dev);
printk(KERN_INFO DRIVER_NAME ": %s initialized\n", ops->name); printk(KERN_INFO DRIVER_NAME ": %s initialized\n", ops->name);
mutex_unlock(&cx231xx_extension_devlist_lock);
mutex_unlock(&cx231xx_devlist_mutex); mutex_unlock(&cx231xx_devlist_mutex);
return 0; return 0;
} }
@ -125,10 +122,8 @@ void cx231xx_unregister_extension(struct cx231xx_ops *ops)
ops->fini(dev); ops->fini(dev);
mutex_lock(&cx231xx_extension_devlist_lock);
printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name); printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name);
list_del(&ops->next); list_del(&ops->next);
mutex_unlock(&cx231xx_extension_devlist_lock);
mutex_unlock(&cx231xx_devlist_mutex); mutex_unlock(&cx231xx_devlist_mutex);
} }
EXPORT_SYMBOL(cx231xx_unregister_extension); EXPORT_SYMBOL(cx231xx_unregister_extension);
@ -137,28 +132,28 @@ void cx231xx_init_extension(struct cx231xx *dev)
{ {
struct cx231xx_ops *ops = NULL; struct cx231xx_ops *ops = NULL;
mutex_lock(&cx231xx_extension_devlist_lock); mutex_lock(&cx231xx_devlist_mutex);
if (!list_empty(&cx231xx_extension_devlist)) { if (!list_empty(&cx231xx_extension_devlist)) {
list_for_each_entry(ops, &cx231xx_extension_devlist, next) { list_for_each_entry(ops, &cx231xx_extension_devlist, next) {
if (ops->init) if (ops->init)
ops->init(dev); ops->init(dev);
} }
} }
mutex_unlock(&cx231xx_extension_devlist_lock); mutex_unlock(&cx231xx_devlist_mutex);
} }
void cx231xx_close_extension(struct cx231xx *dev) void cx231xx_close_extension(struct cx231xx *dev)
{ {
struct cx231xx_ops *ops = NULL; struct cx231xx_ops *ops = NULL;
mutex_lock(&cx231xx_extension_devlist_lock); mutex_lock(&cx231xx_devlist_mutex);
if (!list_empty(&cx231xx_extension_devlist)) { if (!list_empty(&cx231xx_extension_devlist)) {
list_for_each_entry(ops, &cx231xx_extension_devlist, next) { list_for_each_entry(ops, &cx231xx_extension_devlist, next) {
if (ops->fini) if (ops->fini)
ops->fini(dev); ops->fini(dev);
} }
} }
mutex_unlock(&cx231xx_extension_devlist_lock); mutex_unlock(&cx231xx_devlist_mutex);
} }
/**************************************************************** /****************************************************************

View File

@ -565,6 +565,7 @@ static int dvb_init(struct cx231xx *dev)
dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq; dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;
dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner; dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;
mutex_lock(&dev->lock);
cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
cx231xx_demod_reset(dev); cx231xx_demod_reset(dev);
/* init frontend */ /* init frontend */
@ -707,15 +708,18 @@ static int dvb_init(struct cx231xx *dev)
if (result < 0) if (result < 0)
goto out_free; goto out_free;
cx231xx_set_mode(dev, CX231XX_SUSPEND);
printk(KERN_INFO "Successfully loaded cx231xx-dvb\n"); printk(KERN_INFO "Successfully loaded cx231xx-dvb\n");
return 0;
ret:
cx231xx_set_mode(dev, CX231XX_SUSPEND);
mutex_unlock(&dev->lock);
return result;
out_free: out_free:
cx231xx_set_mode(dev, CX231XX_SUSPEND);
kfree(dvb); kfree(dvb);
dev->dvb = NULL; dev->dvb = NULL;
return result; goto ret;
} }
static int dvb_fini(struct cx231xx *dev) static int dvb_fini(struct cx231xx *dev)