V4L/DVB (4391): Refactor dvb_detach calls into a single dvb_frontend_detach function.

Remove buggy dvb_detach() macro and replace with unified
dvb_frontend_detach() call.

Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net>
Acked-by: Trent Piepho <xyzzy@speakeasy.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index e2d2e65..0c3bab3 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -571,9 +571,7 @@
 	} else {
 		if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
 			err("frontend registration failed!");
-			dvb_detach(fc->fe->ops.release_sec, fc->fe);
-			dvb_detach(fc->fe->ops.tuner_ops.release, fc->fe);
-			dvb_detach(fc->fe->ops.release, fc->fe);
+			dvb_frontend_detach(fc->fe);
 			fc->fe = NULL;
 			return -EINVAL;
 		}
@@ -586,9 +584,7 @@
 {
 	if (fc->init_state & FC_STATE_FE_INIT) {
 		dvb_unregister_frontend(fc->fe);
-		dvb_detach(fc->fe->ops.release_sec, fc->fe);
-		dvb_detach(fc->fe->ops.tuner_ops.release, fc->fe);
-		dvb_detach(fc->fe->ops.release, fc->fe);
+		dvb_frontend_detach(fc->fe);
 	}
 
 	fc->init_state &= ~FC_STATE_FE_INIT;
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 6f0bb73..db1eba9 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -706,9 +706,7 @@
 	else
 		if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
 			printk("dvb-bt8xx: Frontend registration failed!\n");
-			dvb_detach(card->fe->ops.release_sec, card->fe);
-			dvb_detach(card->fe->ops.tuner_ops.release, card->fe);
-			dvb_detach(card->fe->ops.release, card->fe);
+			dvb_frontend_detach(card->fe);
 			card->fe = NULL;
 		}
 }
@@ -927,9 +925,7 @@
 	dvb_dmx_release(&card->demux);
 	if (card->fe) {
 		dvb_unregister_frontend(card->fe);
-		dvb_detach(card->fe->ops.release_sec, card->fe);
-		dvb_detach(card->fe->ops.tuner_ops.release, card->fe);
-		dvb_detach(card->fe->ops.release, card->fe);
+		dvb_frontend_detach(card->fe);
 	}
 	dvb_unregister_adapter(&card->dvb_adapter);
 
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index d544731..86dadc7 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -1112,3 +1112,35 @@
 	return 0;
 }
 EXPORT_SYMBOL(dvb_unregister_frontend);
+
+#ifdef CONFIG_DVB_DETACH
+void dvb_frontend_detach(struct dvb_frontend* fe)
+{
+	void *ptr;
+
+	if (fe->ops.release_sec) {
+		fe->ops.release_sec(fe);
+		symbol_put_addr(fe->ops.release_sec);
+	}
+	if (fe->ops.tuner_ops.release) {
+		fe->ops.tuner_ops.release(fe);
+		symbol_put_addr(fe->ops.tuner_ops.release);
+	}
+	ptr = (void*)fe->ops.release;
+	if (ptr) {
+		fe->ops.release(fe);
+		symbol_put_addr(ptr);
+	}
+}
+#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.release)
+		fe->ops.release(fe);
+}
+#endif
+EXPORT_SYMBOL(dvb_frontend_detach);
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 6bea01af..e5d5028 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -158,6 +158,8 @@
 
 extern int dvb_unregister_frontend(struct dvb_frontend* fe);
 
+extern void dvb_frontend_detach(struct dvb_frontend* fe);
+
 extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
 
 extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index 66d91e5..620e788 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -102,7 +102,6 @@
 			    int (*func)(struct inode *inode, struct file *file,
 			    unsigned int cmd, void *arg));
 
-
 /** generic DVB attach function. */
 #ifdef CONFIG_DVB_CORE_ATTACH
 #define dvb_attach(FUNCTION, ARGS...) ({ \
@@ -118,28 +117,11 @@
 	__r; \
 })
 
-#define dvb_detach(FUNCPTR, ARGS...) ({ \
-	typeof((FUNCPTR)) __funcptrtmp = FUNCPTR; \
-	if (__funcptrtmp) { \
-		__funcptrtmp(ARGS); \
-		symbol_put_addr(__funcptrtmp); \
-	} \
-	FUNCPTR = NULL; \
-})
-
 #else
 #define dvb_attach(FUNCTION, ARGS...) ({ \
 	FUNCTION(ARGS); \
 })
 
-#define dvb_detach(FUNCPTR, ARGS...) \
-do { \
-	if (FUNCPTR) \
-		FUNCPTR(ARGS); \
-	FUNCPTR = NULL; \
-} while(0)
-
 #endif
 
-
 #endif /* #ifndef _DVBDEV_H_ */
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index f0da15e..9f8d3f0 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -188,9 +188,7 @@
 
 		if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
 			err("Frontend registration failed.");
-			dvb_detach(d->fe->ops.release_sec, d->fe);
-			dvb_detach(d->fe->ops.tuner_ops.release, d->fe);
-			dvb_detach(d->fe->ops.release, d->fe);
+			dvb_frontend_detach(d->fe);
 			d->fe = NULL;
 			return -ENODEV;
 		}
@@ -207,9 +205,7 @@
 {
 	if (d->fe != NULL) {
 		dvb_unregister_frontend(d->fe);
-		dvb_detach(d->fe->ops.release_sec, d->fe);
-		dvb_detach(d->fe->ops.tuner_ops.release, d->fe);
-		dvb_detach(d->fe->ops.release, d->fe);
+		dvb_frontend_detach(d->fe);
 	}
 	return 0;
 }
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index d195cf5..5742154 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -1385,9 +1385,7 @@
 
 	if (av7110->fe != NULL) {
 		dvb_unregister_frontend(av7110->fe);
-		dvb_detach(av7110->fe->ops.release_sec, av7110->fe);
-		dvb_detach(av7110->fe->ops.tuner_ops.release, av7110->fe);
-		dvb_detach(av7110->fe->ops.release, av7110->fe);
+		dvb_frontend_detach(av7110->fe);
 	}
 	dvb_unregister_device(av7110->osd_dev);
 	av7110_av_unregister(av7110);
@@ -2259,9 +2257,7 @@
 		ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
 		if (ret < 0) {
 			printk("av7110: Frontend registration failed!\n");
-			dvb_detach(av7110->fe->ops.release_sec, av7110->fe);
-			dvb_detach(av7110->fe->ops.tuner_ops.release, av7110->fe);
-			dvb_detach(av7110->fe->ops.release, av7110->fe);
+			dvb_frontend_detach(av7110->fe);
 			av7110->fe = NULL;
 		}
 	}
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index c648c01..6f1c41fb 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -1192,9 +1192,7 @@
 	if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
 				  budget_av->budget.dvb_frontend)) {
 		printk(KERN_ERR "budget-av: Frontend registration failed!\n");
-		dvb_detach(budget_av->budget.dvb_frontend->ops.release_sec, budget_av->budget.dvb_frontend);
-		dvb_detach(budget_av->budget.dvb_frontend->ops.tuner_ops.release, budget_av->budget.dvb_frontend);
-		dvb_detach(budget_av->budget.dvb_frontend->ops.release, budget_av->budget.dvb_frontend);
+		dvb_frontend_detach(budget_av->budget.dvb_frontend);
 		budget_av->budget.dvb_frontend = NULL;
 	}
 }
@@ -1230,9 +1228,7 @@
 
 	if (budget_av->budget.dvb_frontend != NULL) {
 		dvb_unregister_frontend(budget_av->budget.dvb_frontend);
-		dvb_detach(budget_av->budget.dvb_frontend->ops.release_sec, budget_av->budget.dvb_frontend);
-		dvb_detach(budget_av->budget.dvb_frontend->ops.tuner_ops.release, budget_av->budget.dvb_frontend);
-		dvb_detach(budget_av->budget.dvb_frontend->ops.release, budget_av->budget.dvb_frontend);
+		dvb_frontend_detach(budget_av->budget.dvb_frontend);
 	}
 	err = ttpci_budget_deinit(&budget_av->budget);
 
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 20b5e8d..e440fa1 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -1065,9 +1065,7 @@
 		if (dvb_register_frontend
 		    (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
 			printk("budget-ci: Frontend registration failed!\n");
-			dvb_detach(budget_ci->budget.dvb_frontend->ops.release_sec, budget_ci->budget.dvb_frontend);
-			dvb_detach(budget_ci->budget.dvb_frontend->ops.tuner_ops.release, budget_ci->budget.dvb_frontend);
-			dvb_detach(budget_ci->budget.dvb_frontend->ops.release, budget_ci->budget.dvb_frontend);
+			dvb_frontend_detach(budget_ci->budget.dvb_frontend);
 			budget_ci->budget.dvb_frontend = NULL;
 		}
 	}
@@ -1117,9 +1115,7 @@
 		ciintf_deinit(budget_ci);
 	if (budget_ci->budget.dvb_frontend) {
 		dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
-		dvb_detach(budget_ci->budget.dvb_frontend->ops.release_sec, budget_ci->budget.dvb_frontend);
-		dvb_detach(budget_ci->budget.dvb_frontend->ops.tuner_ops.release, budget_ci->budget.dvb_frontend);
-		dvb_detach(budget_ci->budget.dvb_frontend->ops.release, budget_ci->budget.dvb_frontend);
+		dvb_frontend_detach(budget_ci->budget.dvb_frontend);
 	}
 	err = ttpci_budget_deinit(&budget_ci->budget);
 
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 82dbef8..d043e1f 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -367,9 +367,7 @@
 	} else {
 		if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) {
 			printk("budget-av: Frontend registration failed!\n");
-			dvb_detach(budget->dvb_frontend->ops.release_sec, budget->dvb_frontend);
-			dvb_detach(budget->dvb_frontend->ops.tuner_ops.release, budget->dvb_frontend);
-			dvb_detach(budget->dvb_frontend->ops.release, budget->dvb_frontend);
+			dvb_frontend_detach(budget->dvb_frontend);
 			budget->dvb_frontend = NULL;
 		}
 	}
@@ -630,9 +628,7 @@
 
 	if (budget->dvb_frontend) {
 		dvb_unregister_frontend(budget->dvb_frontend);
-		dvb_detach(budget->dvb_frontend->ops.release_sec, budget->dvb_frontend);
-		dvb_detach(budget->dvb_frontend->ops.tuner_ops.release, budget->dvb_frontend);
-		dvb_detach(budget->dvb_frontend->ops.release, budget->dvb_frontend);
+		dvb_frontend_detach(budget->dvb_frontend);
 	}
 	err = ttpci_budget_deinit (budget);
 
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 19beb11..e846b96 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -442,9 +442,7 @@
 
 error_out:
 	printk("budget: Frontend registration failed!\n");
-	dvb_detach(budget->dvb_frontend->ops.release_sec, budget->dvb_frontend);
-	dvb_detach(budget->dvb_frontend->ops.tuner_ops.release, budget->dvb_frontend);
-	dvb_detach(budget->dvb_frontend->ops.release, budget->dvb_frontend);
+	dvb_frontend_detach(budget->dvb_frontend);
 	budget->dvb_frontend = NULL;
 	return;
 }
@@ -484,9 +482,7 @@
 
 	if (budget->dvb_frontend) {
 		dvb_unregister_frontend(budget->dvb_frontend);
-		dvb_detach(budget->dvb_frontend->ops.release_sec, budget->dvb_frontend);
-		dvb_detach(budget->dvb_frontend->ops.tuner_ops.release, budget->dvb_frontend);
-		dvb_detach(budget->dvb_frontend->ops.release, budget->dvb_frontend);
+		dvb_frontend_detach(budget->dvb_frontend);
 	}
 
 	err = ttpci_budget_deinit (budget);
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 6f58c66..2341998 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -1625,9 +1625,7 @@
 	} else {
 		if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) {
 			printk("dvb-ttusb-budget: Frontend registration failed!\n");
-			dvb_detach(ttusb->fe->ops.release_sec, ttusb->fe);
-			dvb_detach(ttusb->fe->ops.tuner_ops.release, ttusb->fe);
-			dvb_detach(ttusb->fe->ops.release, ttusb->fe);
+			dvb_frontend_detach(ttusb->fe);
 			ttusb->fe = NULL;
 		}
 	}
@@ -1766,9 +1764,7 @@
 	dvb_dmx_release(&ttusb->dvb_demux);
 	if (ttusb->fe != NULL) {
 		dvb_unregister_frontend(ttusb->fe);
-		dvb_detach(ttusb->fe->ops.release_sec, ttusb->fe);
-		dvb_detach(ttusb->fe->ops.tuner_ops.release, ttusb->fe);
-		dvb_detach(ttusb->fe->ops.release, ttusb->fe);
+		dvb_frontend_detach(ttusb->fe);
 	}
 	i2c_del_adapter(&ttusb->i2c_adap);
 	dvb_unregister_adapter(&ttusb->adapter);