patch-2.3.99-pre6 linux/drivers/isdn/avmb1/kcapi.c
Next file: linux/drivers/isdn/avmb1/t1isa.c
Previous file: linux/drivers/isdn/avmb1/capifs.c
Back to the patch index
Back to the overall index
- Lines: 131
- Date:
Fri Apr 21 15:17:57 2000
- Orig file:
v2.3.99-pre5/linux/drivers/isdn/avmb1/kcapi.c
- Orig date:
Mon Mar 27 08:08:25 2000
diff -u --recursive --new-file v2.3.99-pre5/linux/drivers/isdn/avmb1/kcapi.c linux/drivers/isdn/avmb1/kcapi.c
@@ -1,11 +1,22 @@
/*
- * $Id: kcapi.c,v 1.13 2000/03/03 15:50:42 calle Exp $
+ * $Id: kcapi.c,v 1.15 2000/04/06 15:01:25 calle Exp $
*
* Kernel CAPI 2.0 Module
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: kcapi.c,v $
+ * Revision 1.15 2000/04/06 15:01:25 calle
+ * Bugfix: crash in capidrv.c when reseting a capi controller.
+ * - changed code order on remove of controller.
+ * - using tq_schedule for notifier in kcapi.c.
+ * - now using spin_lock_irqsave() and spin_unlock_irqrestore().
+ * strange: sometimes even MP hang on unload of isdn.o ...
+ *
+ * Revision 1.14 2000/04/03 13:29:25 calle
+ * make Tim Waugh happy (module unload races in 2.3.99-pre3).
+ * no real problem there, but now it is much cleaner ...
+ *
* Revision 1.13 2000/03/03 15:50:42 calle
* - kernel CAPI:
* - Changed parameter "param" in capi_signal from __u32 to void *.
@@ -98,7 +109,7 @@
#include <linux/b1lli.h>
#endif
-static char *revision = "$Revision: 1.13 $";
+static char *revision = "$Revision: 1.15 $";
/* ------------------------------------------------------------- */
@@ -270,7 +281,7 @@
*eof = 1;
if (off >= len+begin)
return 0;
- *start = page + (begin-off);
+ *start = page + (off-begin);
return ((count < begin+len-off) ? count : begin+len-off);
}
@@ -541,20 +552,21 @@
struct capi_notifier *tail;
} notifier_list;
+static spinlock_t notifier_lock = SPIN_LOCK_UNLOCKED;
+
static inline void notify_enqueue(struct capi_notifier *np)
{
struct capi_notifier_list *q = ¬ifier_list;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(¬ifier_lock, flags);
if (q->tail) {
q->tail->next = np;
q->tail = np;
} else {
q->head = q->tail = np;
}
- restore_flags(flags);
+ spin_unlock_irqrestore(¬ifier_lock, flags);
}
static inline struct capi_notifier *notify_dequeue(void)
@@ -563,15 +575,14 @@
struct capi_notifier *np = 0;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(¬ifier_lock, flags);
if (q->head) {
np = q->head;
if ((q->head = np->next) == 0)
q->tail = 0;
np->next = 0;
}
- restore_flags(flags);
+ spin_unlock_irqrestore(¬ifier_lock, flags);
return np;
}
@@ -580,18 +591,24 @@
{
struct capi_notifier *np;
+ MOD_INC_USE_COUNT;
np = (struct capi_notifier *)kmalloc(sizeof(struct capi_notifier), GFP_ATOMIC);
- if (!np)
+ if (!np) {
+ MOD_DEC_USE_COUNT;
return -1;
+ }
memset(np, 0, sizeof(struct capi_notifier));
np->cmd = cmd;
np->controller = controller;
np->applid = applid;
np->ncci = ncci;
notify_enqueue(np);
- MOD_INC_USE_COUNT;
- queue_task(&tq_state_notify, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ /*
+ * The notifier will result in adding/deleteing
+ * of devices. Devices can only removed in
+ * user process, not in bh.
+ */
+ queue_task(&tq_state_notify, &tq_scheduler);
return 0;
}
@@ -1732,6 +1749,8 @@
char *p;
char rev[10];
+ MOD_INC_USE_COUNT;
+
skb_queue_head_init(&recv_queue);
/* init_bh(CAPI_BH, do_capi_bh); */
@@ -1773,6 +1792,7 @@
(void)c4_init();
#endif
#endif
+ MOD_DEC_USE_COUNT;
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)