summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteffen A. Mork <linux-dev@morknet.de>2004-11-16 16:14:52 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-11-16 16:14:52 -0800
commit555983d64332ce0f98f68dbbd8706eabd045b992 (patch)
tree52348b67d9c58cb32e514c38b1c06b9900bb3f83
parentf46e994c95d0fc29eb517d2c1fe9adcc0f129dd7 (diff)
[PATCH] Make dss1_divert ISDN module work on SMP again
When I switched my installation from kernel 2.4 to 2.6 I recognized that the ISDN module dss1_divert was marked incompilable (config option CONFIG_CLEAN_COMPILE must be turned off). The compile problem was the obsolete using of kernel 2.4 critical sections. I replaced the cli() stuff with spinlocks as explained in the Documentation/spinlocks.txt file. After that the module compiles and runs as expected. Signed-off-by: Steffen A. Mork <linux-dev@morknet.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/isdn/divert/divert_init.c14
-rw-r--r--drivers/isdn/divert/divert_procfs.c7
-rw-r--r--drivers/isdn/divert/isdn_divert.c108
-rw-r--r--drivers/isdn/i4l/Kconfig2
4 files changed, 66 insertions, 65 deletions
diff --git a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c
index ede2b7eb75ea..d29f9efc0feb 100644
--- a/drivers/isdn/divert/divert_init.c
+++ b/drivers/isdn/divert/divert_init.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
+
#include "isdn_divert.h"
MODULE_DESCRIPTION("ISDN4Linux: Call diversion support");
@@ -59,23 +60,24 @@ static int __init divert_init(void)
/* Module deinit code */
/**********************/
static void __exit divert_exit(void)
-{ unsigned long flags;
+{
+ unsigned long flags;
+ spinlock_t divert_lock = SPIN_LOCK_UNLOCKED;
int i;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
divert_if.cmd = DIVERT_CMD_REL; /* release */
if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR)
{ printk(KERN_WARNING "dss1_divert: error %d releasing module\n",i);
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
return;
}
if (divert_dev_deinit())
{ printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n");
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
return;
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
deleterule(-1); /* delete all rules and free mem */
deleteprocs();
printk(KERN_INFO "dss1_divert module successfully removed \n");
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index d3506ee8543d..06f679321463 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -22,6 +22,7 @@
#include <linux/isdnif.h>
#include "isdn_divert.h"
+
/*********************************/
/* Variables for interface queue */
/*********************************/
@@ -181,6 +182,7 @@ isdn_divert_ioctl(struct inode *inode, struct file *file,
divert_ioctl dioctl;
int i;
unsigned long flags;
+ spinlock_t divert_lock = SPIN_LOCK_UNLOCKED;
divert_rule *rulep;
char *cp;
@@ -215,10 +217,9 @@ isdn_divert_ioctl(struct inode *inode, struct file *file,
case IIOCMODRULE:
if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
return (-EINVAL);
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
*rulep = dioctl.getsetrule.rule; /* copy data */
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
return (0); /* no copy required */
break;
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c
index 568530d54987..72f2b2c921b4 100644
--- a/drivers/isdn/divert/isdn_divert.c
+++ b/drivers/isdn/divert/isdn_divert.c
@@ -11,6 +11,7 @@
#include <linux/version.h>
#include <linux/proc_fs.h>
+
#include "isdn_divert.h"
/**********************************/
@@ -51,50 +52,48 @@ static unsigned char extern_wait_max = 4; /* maximum wait in s for external proc
/* timer callback function */
/***************************/
static void deflect_timer_expire(ulong arg)
-{ unsigned long flags;
+{
+ unsigned long flags;
+ spinlock_t divert_lock = SPIN_LOCK_UNLOCKED;
struct call_struc *cs = (struct call_struc *) arg;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
del_timer(&cs->timer); /* delete active timer */
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
switch(cs->akt_state)
{ case DEFLECT_PROCEED:
cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */
divert_if.ll_cmd(&cs->ics);
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
add_timer(&cs->timer);
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
break;
case DEFLECT_ALERT:
cs->ics.command = ISDN_CMD_REDIR; /* protocol */
strcpy(cs->ics.parm.setup.phone,cs->deflect_dest);
strcpy(cs->ics.parm.setup.eazmsn,"Testtext delayed");
- divert_if.ll_cmd(&cs->ics);
- save_flags(flags);
- cli();
+ divert_if.ll_cmd(&cs->ics);
+ spin_lock_irqsave(&divert_lock, flags);
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
add_timer(&cs->timer);
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
break;
case DEFLECT_AUTODEL:
default:
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
if (cs->prev)
cs->prev->next = cs->next; /* forward link */
else
divert_head = cs->next;
if (cs->next)
cs->next->prev = cs->prev; /* back link */
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
kfree(cs);
return;
@@ -110,6 +109,7 @@ int cf_command(int drvid, int mode,
u_char proc, char *msn,
u_char service, char *fwd_nr, ulong *procid)
{ unsigned long flags;
+ spinlock_t divert_lock = SPIN_LOCK_UNLOCKED;
int retval,msnlen;
int fwd_len;
char *p,*ielenp,tmp[60];
@@ -166,10 +166,9 @@ int cf_command(int drvid, int mode,
cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */
cs->ics.parm.dss1_io.data = tmp; /* start of buffer */
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
*procid = cs->ics.parm.dss1_io.ll_id;
sprintf(cs->info,"%d 0x%lx %s%s 0 %s %02x %d%s%s\n",
@@ -187,11 +186,10 @@ int cf_command(int drvid, int mode,
if (!retval)
{ cs->prev = NULL;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
cs->next = divert_head;
divert_head = cs;
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
}
else
kfree(cs);
@@ -206,6 +204,7 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
{ struct call_struc *cs;
isdn_ctrl ic;
unsigned long flags;
+ spinlock_t divert_lock = SPIN_LOCK_UNLOCKED;
int i;
if ((cmd & 0x7F) > 2) return(-EINVAL); /* invalid command */
@@ -224,13 +223,12 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
{ case 0: /* hangup */
del_timer(&cs->timer);
ic.command = ISDN_CMD_HANGUP;
- i = divert_if.ll_cmd(&ic);
- save_flags(flags);
- cli();
+ i = divert_if.ll_cmd(&ic);
+ spin_lock_irqsave(&divert_lock, flags);
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
add_timer(&cs->timer);
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
break;
case 1: /* alert */
@@ -239,12 +237,12 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
del_timer(&cs->timer);
ic.command = ISDN_CMD_ALERT;
if ((i = divert_if.ll_cmd(&ic)))
- { save_flags(flags);
- cli();
+ {
+ spin_lock_irqsave(&divert_lock, flags);
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
add_timer(&cs->timer);
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
}
else
cs->akt_state = DEFLECT_ALERT;
@@ -256,12 +254,12 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual");
ic.command = ISDN_CMD_REDIR;
if ((i = divert_if.ll_cmd(&ic)))
- { save_flags(flags);
- cli();
+ {
+ spin_lock_irqsave(&divert_lock, flags);
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
add_timer(&cs->timer);
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
}
else
cs->akt_state = DEFLECT_ALERT;
@@ -277,6 +275,7 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
int insertrule(int idx, divert_rule *newrule)
{ struct deflect_struc *ds,*ds1=NULL;
unsigned long flags;
+ spinlock_t divert_lock = SPIN_LOCK_UNLOCKED;
if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc),
GFP_KERNEL)))
@@ -284,8 +283,7 @@ int insertrule(int idx, divert_rule *newrule)
ds->rule = *newrule; /* set rule */
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
if (idx >= 0)
{ ds1 = table_head;
@@ -313,7 +311,7 @@ int insertrule(int idx, divert_rule *newrule)
table_head = ds; /* first element */
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
return(0);
} /* insertrule */
@@ -323,14 +321,14 @@ int insertrule(int idx, divert_rule *newrule)
int deleterule(int idx)
{ struct deflect_struc *ds,*ds1;
unsigned long flags;
+ spinlock_t divert_lock = SPIN_LOCK_UNLOCKED;
if (idx < 0)
- { save_flags(flags);
- cli();
+ { spin_lock_irqsave(&divert_lock, flags);
ds = table_head;
table_head = NULL;
table_tail = NULL;
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
while (ds)
{ ds1 = ds;
ds = ds->next;
@@ -339,8 +337,7 @@ int deleterule(int idx)
return(0);
}
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
ds = table_head;
while ((ds) && (idx > 0))
@@ -349,7 +346,8 @@ int deleterule(int idx)
}
if (!ds)
- { restore_flags(flags);
+ {
+ spin_unlock_irqrestore(&divert_lock, flags);
return(-EINVAL);
}
@@ -363,7 +361,7 @@ int deleterule(int idx)
else
table_head = ds->next; /* start of chain */
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
kfree(ds);
return(0);
} /* deleterule */
@@ -391,6 +389,7 @@ divert_rule *getruleptr(int idx)
int isdn_divert_icall(isdn_ctrl *ic)
{ int retval = 0;
unsigned long flags;
+ spinlock_t divert_lock = SPIN_LOCK_UNLOCKED;
struct call_struc *cs = NULL;
struct deflect_struc *dv;
char *p,*p1;
@@ -474,10 +473,9 @@ int isdn_divert_icall(isdn_ctrl *ic)
else
cs->timer.expires = 0;
cs->akt_state = dv->rule.action;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
cs->divert_id = next_id++; /* new sequence number */
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
cs->prev = NULL;
if (cs->akt_state == DEFLECT_ALERT)
{ strcpy(cs->deflect_dest,dv->rule.to_nr);
@@ -525,12 +523,11 @@ int isdn_divert_icall(isdn_ctrl *ic)
if (cs)
{ cs->prev = NULL;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
cs->next = divert_head;
divert_head = cs;
if (cs->timer.expires) add_timer(&cs->timer);
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
put_info_buffer(cs->info);
return(retval);
@@ -543,9 +540,9 @@ int isdn_divert_icall(isdn_ctrl *ic)
void deleteprocs(void)
{ struct call_struc *cs, *cs1;
unsigned long flags;
+ spinlock_t divert_lock = SPIN_LOCK_UNLOCKED;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
cs = divert_head;
divert_head = NULL;
while (cs)
@@ -554,7 +551,7 @@ void deleteprocs(void)
cs = cs->next;
kfree(cs1);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
} /* deleteprocs */
/****************************************************/
@@ -701,6 +698,7 @@ int prot_stat_callback(isdn_ctrl *ic)
{ struct call_struc *cs, *cs1;
int i;
unsigned long flags;
+ spinlock_t divert_lock = SPIN_LOCK_UNLOCKED;
cs = divert_head; /* start of list */
cs1 = NULL;
@@ -769,8 +767,8 @@ int prot_stat_callback(isdn_ctrl *ic)
}
if (cs1->ics.driver == -1)
- { save_flags(flags);
- cli();
+ {
+ spin_lock_irqsave(&divert_lock, flags);
del_timer(&cs1->timer);
if (cs1->prev)
cs1->prev->next = cs1->next; /* forward link */
@@ -778,7 +776,7 @@ int prot_stat_callback(isdn_ctrl *ic)
divert_head = cs1->next;
if (cs1->next)
cs1->next->prev = cs1->prev; /* back link */
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
kfree(cs1);
}
@@ -792,6 +790,7 @@ int prot_stat_callback(isdn_ctrl *ic)
int isdn_divert_stat_callback(isdn_ctrl *ic)
{ struct call_struc *cs, *cs1;
unsigned long flags;
+ spinlock_t divert_lock = SPIN_LOCK_UNLOCKED;
int retval;
retval = -1;
@@ -826,15 +825,14 @@ int isdn_divert_stat_callback(isdn_ctrl *ic)
cs = cs->next;
if (cs1->ics.driver == -1)
{
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&divert_lock, flags);
if (cs1->prev)
cs1->prev->next = cs1->next; /* forward link */
else
divert_head = cs1->next;
if (cs1->next)
cs1->next->prev = cs1->prev; /* back link */
- restore_flags(flags);
+ spin_unlock_irqrestore(&divert_lock, flags);
kfree(cs1);
}
}
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
index 4071c437769f..3ac15d97f9d6 100644
--- a/drivers/isdn/i4l/Kconfig
+++ b/drivers/isdn/i4l/Kconfig
@@ -99,7 +99,7 @@ config ISDN_DRV_LOOP
config ISDN_DIVERSION
tristate "Support isdn diversion services"
- depends on BROKEN && BROKEN_ON_SMP
+ depends on ISDN && ISDN_I4L
help
This option allows you to use some supplementary diversion
services in conjunction with the HiSax driver on an EURO/DSS1