aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb-core/dvb_frontend.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb-core/dvb_frontend.c')
-rw-r--r--drivers/media/dvb-core/dvb_frontend.c107
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);