[zaptel-commits] mattf: trunk r2453 - /trunk/wct1xxp.c

zaptel-commits at lists.digium.com zaptel-commits at lists.digium.com
Wed Apr 25 09:49:50 MST 2007


Author: mattf
Date: Wed Apr 25 11:49:50 2007
New Revision: 2453

URL: http://svn.digium.com/view/zaptel?view=rev&rev=2453
Log:
Fix potential deadlock in driver-zaptel interaction

Modified:
    trunk/wct1xxp.c

Modified: trunk/wct1xxp.c
URL: http://svn.digium.com/view/zaptel/trunk/wct1xxp.c?view=diff&rev=2453&r1=2452&r2=2453
==============================================================================
--- trunk/wct1xxp.c (original)
+++ trunk/wct1xxp.c Wed Apr 25 11:49:50 2007
@@ -959,10 +959,12 @@
 	zt_receive(&wc->span);
 }
 
-static void __t1xxp_check_sigbits(struct t1xxp *wc, int x)
+static void t1xxp_check_sigbits(struct t1xxp *wc, int x)
 {
 	int a,b,i,y,rxs;
-
+	unsigned long flags;
+
+	spin_lock_irqsave(&wc->lock, flags);
 	if (wc->ise1) {
 		/* Read 5 registers at a time, loading 10 channels at a time */
 		for (i = (x * 5); i < (x * 5) + 5; i++) {
@@ -970,13 +972,19 @@
 			/* Get high channel in low bits */
 			rxs = (a & 0xf);
 			if (!(wc->chans[i+16].sig & ZT_SIG_CLEAR)) {
-				if (wc->chans[i+16].rxsig != rxs)
+				if (wc->chans[i+16].rxsig != rxs) {
+					spin_unlock_irqrestore(&wc->lock, flags);
 					zt_rbsbits(&wc->chans[i+16], rxs);
+					spin_lock_irqsave(&wc->lock, flags);
+				}
 			}
 			rxs = (a >> 4) & 0xf;
 			if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) {
-				if (wc->chans[i].rxsig != rxs)
+				if (wc->chans[i].rxsig != rxs) {
+					spin_unlock_irqrestore(&wc->lock, flags);
 					zt_rbsbits(&wc->chans[i], rxs);
+					spin_lock_irqsave(&wc->lock, flags);
+				}
 			}
 		}
 	} else {
@@ -990,18 +998,25 @@
 			if (b & (1 << y))
 				rxs |= ZT_BBIT;
 			if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) {
-				if (wc->chans[i].rxsig != rxs)
+				if (wc->chans[i].rxsig != rxs) {
+					spin_unlock_irqrestore(&wc->lock, flags);
 					zt_rbsbits(&wc->chans[i], rxs);
+					spin_lock_irqsave(&wc->lock, flags);
+				}
 			}
 		}
 	}
-}
-
-static void __t1xxp_check_alarms(struct t1xxp *wc)
+	spin_unlock_irqrestore(&wc->lock, flags);
+}
+
+static void t1xxp_check_alarms(struct t1xxp *wc)
 {
 	unsigned char c,d;
 	int alarms;
 	int x,j;
+	unsigned long flags;
+
+	spin_lock_irqsave(&wc->lock, flags);
 
 	if (wc->ise1) {
 		__t1_set_reg(wc, 0x06, 0xff); 
@@ -1105,11 +1120,16 @@
 
 	wc->span.alarms = alarms;
 
+	spin_unlock_irqrestore(&wc->lock, flags);
+
 	zt_alarm_notify(&wc->span);
 }
 
-static void __t1xxp_do_counters(struct t1xxp *wc)
-{
+static void t1xxp_do_counters(struct t1xxp *wc)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&wc->lock, flags);
 	if (wc->alarmtimer) {
 		if (!--wc->alarmtimer) {
 			wc->span.alarms &= ~(ZT_ALARM_RECOVER);
@@ -1121,9 +1141,12 @@
 				__t1_set_reg(wc, 0x21, 0x5f);
 			else
 				__t1_set_reg(wc, 0x35, 0x10);
+			spin_unlock_irqrestore(&wc->lock, flags);
 			zt_alarm_notify(&wc->span);
+			spin_lock_irqsave(&wc->lock, flags);
 		}
 	}
+	spin_unlock_irqrestore(&wc->lock, flags);
 }
 
 ZAP_IRQ_HANDLER(t1xxp_interrupt)
@@ -1161,8 +1184,10 @@
 	__handle_leds(wc);
 #endif
 
+	spin_unlock_irqrestore(&wc->lock, flags);
+
 	/* Count down timers */
-	__t1xxp_do_counters(wc);
+	t1xxp_do_counters(wc);
 
 	/* Do some things that we don't have to do very often */
 	x = wc->intcount & 15 /* 63 */;
@@ -1170,17 +1195,15 @@
 	case 0:
 	case 1:
 	case 2:
-		__t1xxp_check_sigbits(wc, x);
+		t1xxp_check_sigbits(wc, x);
 		break;
 	case 4:
 		/* Check alarms 1/4 as frequently */
 		if (!(wc->intcount & 0x30))
-			__t1xxp_check_alarms(wc);
+			t1xxp_check_alarms(wc);
 		break;
 	}
 	
-	spin_unlock_irqrestore(&wc->lock, flags);
-
 	if (ints & 0x10) 
 		printk("PCI Master abort\n");
 



More information about the zaptel-commits mailing list