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/