[PATCH 1/2] firedtv: replace tasklet by workqueue job

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

 



Non-atomic context is a lot nicer to work with.

Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
---

This completes the sem2mutex conversion which I sent last weekend, and
it prepares for fixing up the remote control handling.

 drivers/media/dvb/firesat/avc_api.c      |   57 ++++-------------------
 drivers/media/dvb/firesat/avc_api.h      |    1 
 drivers/media/dvb/firesat/firesat.h      |    4 -
 drivers/media/dvb/firesat/firesat_1394.c |    4 +
 4 files changed, 18 insertions(+), 48 deletions(-)

Index: linux/drivers/media/dvb/firesat/avc_api.c
===================================================================
--- linux.orig/drivers/media/dvb/firesat/avc_api.c
+++ linux/drivers/media/dvb/firesat/avc_api.c
@@ -17,6 +17,7 @@
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <linux/wait.h>
+#include <linux/workqueue.h>
 #include <asm/atomic.h>
 
 #include <ieee1394_transactions.h>
@@ -34,8 +35,6 @@ static unsigned int avc_comm_debug = 0;
 module_param(avc_comm_debug, int, 0644);
 MODULE_PARM_DESC(avc_comm_debug, "debug logging level [0..2] of AV/C communication, default is 0 (no)");
 
-static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal);
-
 /* Frees an allocated packet */
 static void avc_free_packet(struct hpsb_packet *packet)
 {
@@ -251,34 +250,8 @@ int AVCWrite(struct firesat*firesat, con
 	return ret;
 }
 
-#if 0 /* FIXME:  This should probably be a workqueue job. */
-static void do_schedule_remotecontrol(unsigned long ignored);
-DECLARE_TASKLET(schedule_remotecontrol, do_schedule_remotecontrol, 0);
-
-static void do_schedule_remotecontrol(unsigned long ignored) {
-	struct firesat *firesat;
-	unsigned long flags;
-
-	spin_lock_irqsave(&firesat_list_lock, flags);
-	list_for_each_entry(firesat,&firesat_list,list) {
-		if(atomic_read(&firesat->reschedule_remotecontrol) == 1) {
-			if(down_trylock(&firesat->avc_sem))
-				tasklet_schedule(&schedule_remotecontrol);
-			else {
-				if(__AVCRegisterRemoteControl(firesat, 1) == 0)
-					atomic_set(&firesat->reschedule_remotecontrol, 0);
-				else
-					tasklet_schedule(&schedule_remotecontrol);
-
-				up(&firesat->avc_sem);
-			}
-		}
-	}
-	spin_unlock_irqrestore(&firesat_list_lock, flags);
-}
-#endif
-
-int AVCRecv(struct firesat *firesat, u8 *data, size_t length) {
+int AVCRecv(struct firesat *firesat, u8 *data, size_t length)
+{
 //	printk(KERN_INFO "%s\n",__func__);
 
 	// remote control handling
@@ -294,10 +267,7 @@ int AVCRecv(struct firesat *firesat, u8 
 		if(RspFrm->resp == CHANGED) {
 //			printk(KERN_INFO "%s: code = %02x %02x\n",__func__,RspFrm->operand[4],RspFrm->operand[5]);
 			firesat_got_remotecontrolcode((((u16)RspFrm->operand[4]) << 8) | ((u16)RspFrm->operand[5]));
-
-			// schedule
-			atomic_set(&firesat->reschedule_remotecontrol, 1);
-			tasklet_schedule(&schedule_remotecontrol);
+			schedule_work(&firesat->remote_ctrl_work);
 		} else if(RspFrm->resp != INTERIM)
 			printk(KERN_INFO "%s: remote control result = %d\n",__func__, RspFrm->resp);
 		return 0;
@@ -910,7 +880,7 @@ int AVCSubUnitInfo(struct firesat *fires
 	return 0;
 }
 
-static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal)
+int AVCRegisterRemoteControl(struct firesat *firesat)
 {
 	AVCCmdFrm CmdFrm;
 
@@ -931,19 +901,16 @@ static int __AVCRegisterRemoteControl(st
 
 	CmdFrm.length = 8;
 
-	if(internal) {
-		if(__AVCWrite(firesat,&CmdFrm,NULL) < 0)
-			return -EIO;
-	} else
-		if(AVCWrite(firesat,&CmdFrm,NULL) < 0)
-			return -EIO;
-
-	return 0;
+	return AVCWrite(firesat, &CmdFrm, NULL);
 }
 
-int AVCRegisterRemoteControl(struct firesat*firesat)
+void avc_remote_ctrl_work(struct work_struct *work)
 {
-	return __AVCRegisterRemoteControl(firesat, 0);
+	struct firesat *firesat =
+			container_of(work, struct firesat, remote_ctrl_work);
+
+	/* Should it be rescheduled in failure cases? */
+	AVCRegisterRemoteControl(firesat);
 }
 
 int AVCTuner_Host2Ca(struct firesat *firesat)
Index: linux/drivers/media/dvb/firesat/avc_api.h
===================================================================
--- linux.orig/drivers/media/dvb/firesat/avc_api.h
+++ linux/drivers/media/dvb/firesat/avc_api.h
@@ -432,6 +432,7 @@ int AVCLNBControl(struct firesat *firesa
 		char conttone, char nrdiseq,
 		struct dvb_diseqc_master_cmd *diseqcmd);
 int AVCSubUnitInfo(struct firesat *firesat, char *subunitcount);
+void avc_remote_ctrl_work(struct work_struct *work);
 int AVCRegisterRemoteControl(struct firesat *firesat);
 int AVCTuner_Host2Ca(struct firesat *firesat);
 int avc_ca_app_info(struct firesat *firesat, char *app_info, int *length);
Index: linux/drivers/media/dvb/firesat/firesat.h
===================================================================
--- linux.orig/drivers/media/dvb/firesat/firesat.h
+++ linux/drivers/media/dvb/firesat/firesat.h
@@ -20,6 +20,7 @@
 #include <linux/spinlock_types.h>
 #include <linux/types.h>
 #include <linux/wait.h>
+#include <linux/workqueue.h>
 #include <asm/atomic.h>
 
 #include <demux.h>
@@ -149,8 +150,7 @@ struct firesat {
 	struct mutex			avc_mutex;
 	wait_queue_head_t		avc_wait;
 	atomic_t			avc_reply_received;
-
-	atomic_t			reschedule_remotecontrol;
+	struct work_struct		remote_ctrl_work;
 
 	struct firesat_channel {
 		struct firesat *firesat;
Index: linux/drivers/media/dvb/firesat/firesat_1394.c
===================================================================
--- linux.orig/drivers/media/dvb/firesat/firesat_1394.c
+++ linux/drivers/media/dvb/firesat/firesat_1394.c
@@ -182,7 +182,7 @@ static int firesat_probe(struct device *
 		init_waitqueue_head(&firesat->avc_wait);
 		atomic_set(&firesat->avc_reply_received, 1);
 		mutex_init(&firesat->demux_mutex);
-		atomic_set(&firesat->reschedule_remotecontrol, 0);
+		INIT_WORK(&firesat->remote_ctrl_work, avc_remote_ctrl_work);
 
 		spin_lock_irqsave(&firesat_list_lock, flags);
 		INIT_LIST_HEAD(&firesat->list);
@@ -268,6 +268,8 @@ static int firesat_remove(struct device 
 				list_del(&firesats[k]->list);
 				spin_unlock_irqrestore(&firesat_list_lock, flags);
 
+				cancel_work_sync(&firesats[k]->remote_ctrl_work);
+
 				kfree(firesats[k]->fe);
 				kfree(firesats[k]->adapter);
 				kfree(firesats[k]->respfrm);


-- 
Stefan Richter
-=====-==--- =--- ==-=-
http://arcgraph.de/sr/



[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux