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

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 = &notifier_list;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&notifier_lock, flags);
 	if (q->tail) {
 		q->tail->next = np;
 		q->tail = np;
 	} else {
 		q->head = q->tail = np;
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&notifier_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(&notifier_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(&notifier_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)