[PATCH 5/7] firedtv: replace semaphore by mutex
Stefan Richter
stefanr at s5r6.in-berlin.de
Sun Aug 24 14:29:30 PDT 2008
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/
More information about the devel
mailing list