[PATCH 5/7] firedtv: replace semaphore by mutex

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

 



firesat->avc_sem and ->demux_sem have been used exactly like a mutex.
The only exception is the schedule_remotecontrol tasklet which did a
down_trylock in atomic context.  This is not possible with
mutex_trylock; however the whole remote control related code is
non-functional anyway at the moment.  This should be fixed eventually,
probably by turning the tasklet into a worqueue job.

Convert everything else from semaphore to mutex.

Also rewrite a few of the affected functions to unlock the mutex at a
single exit point, instead of in several branches.

Signed-off-by: Stefan Richter <stefanr at s5r6.in-berlin.de>
---
 drivers/media/dvb/firesat/avc_api.c      |   11 +++-
 drivers/media/dvb/firesat/cmp.c          |   27 +++++++----
 drivers/media/dvb/firesat/firesat.h      |   11 +---
 drivers/media/dvb/firesat/firesat_1394.c |    5 +-
 drivers/media/dvb/firesat/firesat_dvb.c  |   54 +++++++++--------------
 5 files changed, 55 insertions(+), 53 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
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/moduleparam.h>
+#include <linux/mutex.h>
 #include <linux/wait.h>
 #include <asm/atomic.h>
 
@@ -237,17 +238,20 @@ static int __AVCWrite(struct firesat *fi
 	return 0;
 }
 
-int AVCWrite(struct firesat*firesat, const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm) {
+int AVCWrite(struct firesat*firesat, const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm)
+{
 	int ret;
-	if(down_interruptible(&firesat->avc_sem))
+
+	if (mutex_lock_interruptible(&firesat->avc_mutex))
 		return -EINTR;
 
 	ret = __AVCWrite(firesat, CmdFrm, RspFrm);
 
-	up(&firesat->avc_sem);
+	mutex_unlock(&firesat->avc_mutex);
 	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);
 
@@ -272,6 +276,7 @@ static void do_schedule_remotecontrol(un
 	}
 	spin_unlock_irqrestore(&firesat_list_lock, flags);
 }
+#endif
 
 int AVCRecv(struct firesat *firesat, u8 *data, size_t length) {
 //	printk(KERN_INFO "%s\n",__func__);
Index: linux/drivers/media/dvb/firesat/cmp.c
===================================================================
--- linux.orig/drivers/media/dvb/firesat/cmp.c
+++ linux/drivers/media/dvb/firesat/cmp.c
@@ -13,6 +13,7 @@
 #include <linux/bug.h>
 #include <linux/hardirq.h>
 #include <linux/kernel.h>
+#include <linux/mutex.h>
 #include <linux/types.h>
 
 #include <hosts.h>
@@ -79,27 +80,33 @@ int firesat_hpsb_lock(struct hpsb_host *
 }
 
 
-static int cmp_read(struct firesat *firesat, void *buffer, u64 addr, size_t length) {
+static int cmp_read(struct firesat *firesat, void *buf, u64 addr, size_t len)
+{
 	int ret;
-	if(down_interruptible(&firesat->avc_sem))
+
+	if (mutex_lock_interruptible(&firesat->avc_mutex))
 		return -EINTR;
 
-	ret = hpsb_read(firesat->host, firesat->nodeentry->nodeid, firesat->nodeentry->generation,
-		addr, buffer, length);
+	ret = hpsb_read(firesat->host, firesat->nodeentry->nodeid,
+			firesat->nodeentry->generation, addr, buf, len);
 
-	up(&firesat->avc_sem);
+	mutex_unlock(&firesat->avc_mutex);
 	return ret;
 }
 
-static int cmp_lock(struct firesat *firesat, quadlet_t *data, u64 addr, quadlet_t arg, int ext_tcode) {
+static int cmp_lock(struct firesat *firesat, quadlet_t *data, u64 addr,
+		quadlet_t arg, int ext_tcode)
+{
 	int ret;
-	if(down_interruptible(&firesat->avc_sem))
+
+	if (mutex_lock_interruptible(&firesat->avc_mutex))
 		return -EINTR;
 
-	ret = firesat_hpsb_lock(firesat->host, firesat->nodeentry->nodeid, firesat->nodeentry->generation,
-		addr, ext_tcode, data, arg);
+	ret = firesat_hpsb_lock(firesat->host, firesat->nodeentry->nodeid,
+				firesat->nodeentry->generation,
+				addr, ext_tcode, data, arg);
 
-	up(&firesat->avc_sem);
+	mutex_unlock(&firesat->avc_mutex);
 	return ret;
 }
 
Index: linux/drivers/media/dvb/firesat/firesat.h
===================================================================
--- linux.orig/drivers/media/dvb/firesat/firesat.h
+++ linux/drivers/media/dvb/firesat/firesat.h
@@ -13,14 +13,10 @@
 #ifndef _FIREDTV_H
 #define _FIREDTV_H
 
-#include <linux/version.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
-#include <linux/semaphore.h>
-#endif
-
 #include <linux/dvb/dmx.h>
 #include <linux/dvb/frontend.h>
 #include <linux/list.h>
+#include <linux/mutex.h>
 #include <linux/spinlock_types.h>
 #include <linux/types.h>
 #include <linux/wait.h>
@@ -32,6 +28,7 @@
 #include <dvb_net.h>
 #include <dvbdev.h>
 
+#include <linux/version.h>
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
 #define DVB_REGISTER_ADAPTER(x, y, z, w, v) dvb_register_adapter(x, y, z, w, v)
 #else
@@ -149,7 +146,7 @@ struct firesat {
 	int				ca_last_command;
 	int				ca_time_interval;
 
-	struct semaphore		avc_sem;
+	struct mutex			avc_mutex;
 	wait_queue_head_t		avc_wait;
 	atomic_t			avc_reply_received;
 
@@ -164,7 +161,7 @@ struct firesat {
 		int pid;
 		int type;	/* 1 - TS, 2 - Filter */
 	} channel[16];
-	struct semaphore		demux_sem;
+	struct mutex			demux_mutex;
 
 	/* needed by avc_api */
 	void *respfrm;
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
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
@@ -177,10 +178,10 @@ static int firesat_probe(struct device *
 			return -ENOMEM;
 		}
 
-		sema_init(&firesat->avc_sem, 1);
+		mutex_init(&firesat->avc_mutex);
 		init_waitqueue_head(&firesat->avc_wait);
 		atomic_set(&firesat->avc_reply_received, 1);
-		sema_init(&firesat->demux_sem, 1);
+		mutex_init(&firesat->demux_mutex);
 		atomic_set(&firesat->reschedule_remotecontrol, 0);
 
 		spin_lock_irqsave(&firesat_list_lock, flags);
Index: linux/drivers/media/dvb/firesat/firesat_dvb.c
===================================================================
--- linux.orig/drivers/media/dvb/firesat/firesat_dvb.c
+++ linux/drivers/media/dvb/firesat/firesat_dvb.c
@@ -12,6 +12,7 @@
 
 #include <linux/errno.h>
 #include <linux/kernel.h>
+#include <linux/mutex.h>
 #include <linux/types.h>
 
 #include <dvb_demux.h>
@@ -26,39 +27,35 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr
 
 static struct firesat_channel *firesat_channel_allocate(struct firesat *firesat)
 {
+	struct firesat_channel *c = NULL;
 	int k;
 
-	//printk(KERN_INFO "%s\n", __func__);
-
-	if (down_interruptible(&firesat->demux_sem))
+	if (mutex_lock_interruptible(&firesat->demux_mutex))
 		return NULL;
 
-	for (k = 0; k < 16; k++) {
-		//printk(KERN_INFO "%s: channel %d: active = %d, pid = 0x%x\n",__func__,k,firesat->channel[k].active,firesat->channel[k].pid);
-
+	for (k = 0; k < 16; k++)
 		if (firesat->channel[k].active == 0) {
 			firesat->channel[k].active = 1;
-			up(&firesat->demux_sem);
-			return &firesat->channel[k];
+			c = &firesat->channel[k];
+			break;
 		}
-	}
 
-	up(&firesat->demux_sem);
-	return NULL; // no more channels available
+	mutex_unlock(&firesat->demux_mutex);
+	return c;
 }
 
 static int firesat_channel_collect(struct firesat *firesat, int *pidc, u16 pid[])
 {
 	int k, l = 0;
 
-	if (down_interruptible(&firesat->demux_sem))
+	if (mutex_lock_interruptible(&firesat->demux_mutex))
 		return -EINTR;
 
 	for (k = 0; k < 16; k++)
 		if (firesat->channel[k].active == 1)
 			pid[l++] = firesat->channel[k].pid;
 
-	up(&firesat->demux_sem);
+	mutex_unlock(&firesat->demux_mutex);
 
 	*pidc = l;
 
@@ -68,12 +65,12 @@ static int firesat_channel_collect(struc
 static int firesat_channel_release(struct firesat *firesat,
 				   struct firesat_channel *channel)
 {
-	if (down_interruptible(&firesat->demux_sem))
+	if (mutex_lock_interruptible(&firesat->demux_mutex))
 		return -EINTR;
 
 	channel->active = 0;
 
-	up(&firesat->demux_sem);
+	mutex_unlock(&firesat->demux_mutex);
 	return 0;
 }
 
@@ -163,7 +160,8 @@ int firesat_stop_feed(struct dvb_demux_f
 {
 	struct dvb_demux *demux = dvbdmxfeed->demux;
 	struct firesat *firesat = (struct firesat*)demux->priv;
-	int k, l = 0;
+	struct firesat_channel *c = dvbdmxfeed->priv;
+	int k, l;
 	u16 pids[16];
 
 	//printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid);
@@ -188,30 +186,24 @@ int firesat_stop_feed(struct dvb_demux_f
 			return 0;
 	}
 
-	if (down_interruptible(&firesat->demux_sem))
+	if (mutex_lock_interruptible(&firesat->demux_mutex))
 		return -EINTR;
 
-
-	// list except channel to be removed
-	for (k = 0; k < 16; k++)
+	/* list except channel to be removed */
+	for (k = 0, l = 0; k < 16; k++)
 		if (firesat->channel[k].active == 1) {
-			if (&firesat->channel[k] !=
-				(struct firesat_channel *)dvbdmxfeed->priv)
+			if (&firesat->channel[k] != c)
 				pids[l++] = firesat->channel[k].pid;
 			else
 				firesat->channel[k].active = 0;
 		}
 
-	if ((k = AVCTuner_SetPIDs(firesat, l, pids))) {
-		up(&firesat->demux_sem);
-		return k;
-	}
-
-	((struct firesat_channel *)dvbdmxfeed->priv)->active = 0;
-
-	up(&firesat->demux_sem);
+	k = AVCTuner_SetPIDs(firesat, l, pids);
+	if (!k)
+		c->active = 0;
 
-	return 0;
+	mutex_unlock(&firesat->demux_mutex);
+	return k;
 }
 
 int firesat_dvbdev_init(struct firesat *firesat,

-- 
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