[RFC 2/3] dvb_frontend: Add dvb_frontend_init() function

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The function is meant to initialize a newly allocated frontend before it
can be used. This ensures that fields needed to release the frontend
(such as the refcount) are initialized early enough before frontend
registration to be usable in error handling code paths.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@xxxxxxxxxxxxxxxx>
---
 drivers/media/dvb-core/dvb_frontend.c | 44 +++++++++++++++++++++--------------
 drivers/media/dvb-core/dvb_frontend.h | 11 +++++++++
 2 files changed, 38 insertions(+), 17 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index f8caedc83d70..f957511a4037 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -2679,7 +2679,7 @@ EXPORT_SYMBOL(dvb_frontend_resume);
 int dvb_register_frontend(struct dvb_adapter* dvb,
 			  struct dvb_frontend* fe)
 {
-	struct dvb_frontend_private *fepriv;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	const struct dvb_device dvbdev_template = {
 		.users = ~0,
 		.writers = 1,
@@ -2696,28 +2696,15 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
 	if (mutex_lock_interruptible(&frontend_mutex))
 		return -ERESTARTSYS;
 
-	fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL);
-	if (fe->frontend_priv == NULL) {
-		mutex_unlock(&frontend_mutex);
-		return -ENOMEM;
-	}
-	fepriv = fe->frontend_priv;
-
-	kref_init(&fe->refcount);
+	printk(KERN_INFO "%s: frontend %p (id %d)\n", __func__, fe, fe->id);
 
 	/*
-	 * After initialization, there need to be two references: one
-	 * for dvb_unregister_frontend(), and another one for
-	 * dvb_frontend_detach().
+	 * Take a reference to the frontend that will be released at
+	 * unregistration time.
 	 */
 	dvb_frontend_get(fe);
 
-	sema_init(&fepriv->sem, 1);
-	init_waitqueue_head (&fepriv->wait_queue);
-	init_waitqueue_head (&fepriv->events.wait_queue);
-	mutex_init(&fepriv->events.mtx);
 	fe->dvb = dvb;
-	fepriv->inversion = INVERSION_OFF;
 
 	dev_info(fe->dvb->device,
 			"DVB: registering adapter %i frontend %i (%s)...\n",
@@ -2775,3 +2762,26 @@ void dvb_frontend_detach(struct dvb_frontend* fe)
 	dvb_frontend_put(fe);
 }
 EXPORT_SYMBOL(dvb_frontend_detach);
+
+int dvb_frontend_init(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv;
+
+	fepriv = kzalloc(sizeof(*fepriv), GFP_KERNEL);
+	if (fepriv == NULL)
+		return -ENOMEM;
+
+	fe->frontend_priv = fepriv;
+
+	kref_init(&fe->refcount);
+
+	sema_init(&fepriv->sem, 1);
+	init_waitqueue_head(&fepriv->wait_queue);
+	init_waitqueue_head(&fepriv->events.wait_queue);
+	mutex_init(&fepriv->events.mtx);
+
+	fepriv->inversion = INVERSION_OFF;
+
+	return 0;
+}
+EXPORT_SYMBOL(dvb_frontend_init);
diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
index 907a05bde162..02fa16ab8650 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -707,6 +707,17 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
 int dvb_unregister_frontend(struct dvb_frontend *fe);
 
 /**
+ * dvb_frontend_init() - Initialize a frontend after allocation
+ * @fe: the frontend to be initialized
+ *
+ * This function must be called by frontend drivers in their attach handler to
+ * initialize the frontend structure they allocate.
+ *
+ * Return 0 on success and a negative error code on failure.
+ */
+int dvb_frontend_init(struct dvb_frontend *fe);
+
+/**
  * dvb_frontend_detach() - Detaches and frees frontend specific data
  *
  * @fe: pointer to the frontend struct
-- 
Regards,

Laurent Pinchart




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux