diff options
Diffstat (limited to 'drivers/media/dvb-core/dvb_frontend.c')
-rw-r--r-- | drivers/media/dvb-core/dvb_frontend.c | 107 |
1 files changed, 53 insertions, 54 deletions
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 01511e5a5566..db74cb74d271 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -28,6 +28,8 @@ /* Enables DVBv3 compatibility bits at the headers */ #define __DVB_CORE__ +#define pr_fmt(fmt) "dvb_frontend: " fmt + #include <linux/string.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -67,6 +69,9 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volt module_param(dvb_mfe_wait_time, int, 0644); MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)"); +#define dprintk(fmt, arg...) \ + printk(KERN_DEBUG pr_fmt("%s: " fmt), __func__, ##arg) + #define FESTATE_IDLE 1 #define FESTATE_RETUNE 2 #define FESTATE_TUNING_FAST 4 @@ -99,8 +104,6 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open( static DEFINE_MUTEX(frontend_mutex); struct dvb_frontend_private { - struct kref refcount; - /* thread/frontend values */ struct dvb_device *dvbdev; struct dvb_frontend_parameters parameters_out; @@ -138,21 +141,30 @@ struct dvb_frontend_private { #endif }; -static void dvb_frontend_private_free(struct kref *ref) +static void dvb_frontend_invoke_release(struct dvb_frontend *fe, + void (*release)(struct dvb_frontend *fe)); + +static void dvb_frontend_free(struct kref *ref) { - struct dvb_frontend_private *fepriv = - container_of(ref, struct dvb_frontend_private, refcount); + struct dvb_frontend *fe = + container_of(ref, struct dvb_frontend, refcount); + struct dvb_frontend_private *fepriv = fe->frontend_priv; + + dvb_free_device(fepriv->dvbdev); + + dvb_frontend_invoke_release(fe, fe->ops.release); + kfree(fepriv); } -static void dvb_frontend_private_put(struct dvb_frontend_private *fepriv) +static void dvb_frontend_put(struct dvb_frontend *fe) { - kref_put(&fepriv->refcount, dvb_frontend_private_free); + kref_put(&fe->refcount, dvb_frontend_free); } -static void dvb_frontend_private_get(struct dvb_frontend_private *fepriv) +static void dvb_frontend_get(struct dvb_frontend *fe) { - kref_get(&fepriv->refcount); + kref_get(&fe->refcount); } static void dvb_frontend_wakeup(struct dvb_frontend *fe); @@ -1515,12 +1527,8 @@ static int dtv_set_frontend(struct dvb_frontend *fe); static bool is_dvbv3_delsys(u32 delsys) { - bool status; - - status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) || - (delsys == SYS_DVBS) || (delsys == SYS_ATSC); - - return status; + return (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) || + (delsys == SYS_DVBS) || (delsys == SYS_ATSC); } /** @@ -2356,7 +2364,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file, int i; u8 last = 1; if (dvb_frontend_debug) - printk("%s switch command: 0x%04lx\n", __func__, swcmd); + dprintk("%s switch command: 0x%04lx\n", + __func__, swcmd); nexttime = ktime_get_boottime(); if (dvb_frontend_debug) tv[0] = nexttime; @@ -2379,10 +2388,10 @@ static int dvb_frontend_ioctl_legacy(struct file *file, dvb_frontend_sleep_until(&nexttime, 8000); } if (dvb_frontend_debug) { - printk("%s(%d): switch delay (should be 32k followed by all 8k\n", + dprintk("%s(%d): switch delay (should be 32k followed by all 8k)\n", __func__, fe->dvb->num); for (i = 1; i < 10; i++) - printk("%d: %d\n", i, + pr_info("%d: %d\n", i, (int) ktime_us_delta(tv[i], tv[i-1])); } err = 0; @@ -2545,7 +2554,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) fepriv->events.eventr = fepriv->events.eventw = 0; } - dvb_frontend_private_get(fepriv); + dvb_frontend_get(fe); if (adapter->mfe_shared) mutex_unlock (&adapter->mfe_lock); @@ -2595,7 +2604,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file) fe->ops.ts_bus_ctrl(fe, 0); } - dvb_frontend_private_put(fepriv); + dvb_frontend_put(fe); return ret; } @@ -2685,7 +2694,14 @@ int dvb_register_frontend(struct dvb_adapter* dvb, } fepriv = fe->frontend_priv; - kref_init(&fepriv->refcount); + kref_init(&fe->refcount); + + /* + * After initialization, there need to be two references: one + * for dvb_unregister_frontend(), and another one for + * dvb_frontend_detach(). + */ + dvb_frontend_get(fe); sema_init(&fepriv->sem, 1); init_waitqueue_head (&fepriv->wait_queue); @@ -2720,50 +2736,33 @@ int dvb_unregister_frontend(struct dvb_frontend* fe) dev_dbg(fe->dvb->device, "%s:\n", __func__); mutex_lock(&frontend_mutex); - dvb_frontend_stop (fe); - dvb_unregister_device (fepriv->dvbdev); + dvb_frontend_stop(fe); + dvb_remove_device(fepriv->dvbdev); /* fe is invalid now */ mutex_unlock(&frontend_mutex); - dvb_frontend_private_put(fepriv); + dvb_frontend_put(fe); return 0; } EXPORT_SYMBOL(dvb_unregister_frontend); -#ifdef CONFIG_MEDIA_ATTACH -void dvb_frontend_detach(struct dvb_frontend* fe) +static void dvb_frontend_invoke_release(struct dvb_frontend *fe, + void (*release)(struct dvb_frontend *fe)) { - void *ptr; - - if (fe->ops.release_sec) { - fe->ops.release_sec(fe); - dvb_detach(fe->ops.release_sec); - } - if (fe->ops.tuner_ops.release) { - fe->ops.tuner_ops.release(fe); - dvb_detach(fe->ops.tuner_ops.release); - } - if (fe->ops.analog_ops.release) { - fe->ops.analog_ops.release(fe); - dvb_detach(fe->ops.analog_ops.release); - } - ptr = (void*)fe->ops.release; - if (ptr) { - fe->ops.release(fe); - dvb_detach(ptr); + if (release) { + release(fe); +#ifdef CONFIG_MEDIA_ATTACH + dvb_detach(release); +#endif } } -#else + void dvb_frontend_detach(struct dvb_frontend* fe) { - if (fe->ops.release_sec) - fe->ops.release_sec(fe); - if (fe->ops.tuner_ops.release) - fe->ops.tuner_ops.release(fe); - if (fe->ops.analog_ops.release) - fe->ops.analog_ops.release(fe); - if (fe->ops.release) - fe->ops.release(fe); + dvb_frontend_invoke_release(fe, fe->ops.release_sec); + dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release); + dvb_frontend_invoke_release(fe, fe->ops.analog_ops.release); + dvb_frontend_invoke_release(fe, fe->ops.detach); + dvb_frontend_put(fe); } -#endif EXPORT_SYMBOL(dvb_frontend_detach); |