[zaptel-commits] jsloan: branch 1.2 r2621 - /branches/1.2/wctc4xxp/base.c

zaptel-commits at lists.digium.com zaptel-commits at lists.digium.com
Mon Jun 11 08:47:37 MST 2007


Author: jsloan
Date: Mon Jun 11 10:47:37 2007
New Revision: 2621

URL: http://svn.digium.com/view/zaptel?view=rev&rev=2621
Log:
Fixed SMP bugs on quad processor machines.  Reduced memory usage

Modified:
    branches/1.2/wctc4xxp/base.c

Modified: branches/1.2/wctc4xxp/base.c
URL: http://svn.digium.com/view/zaptel/branches/1.2/wctc4xxp/base.c?view=diff&rev=2621&r1=2620&r2=2621
==============================================================================
--- branches/1.2/wctc4xxp/base.c (original)
+++ branches/1.2/wctc4xxp/base.c Mon Jun 11 10:47:37 2007
@@ -62,6 +62,7 @@
 
 /* #define USE_TEST_HW */
 #define USE_TDM_CONFIG
+#define QUIET_DSP
 
 #define WC_MAX_IFACES 128
 
@@ -238,6 +239,17 @@
 #define CMD_MSG_VOIP_INDCTRL(s,c) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
 	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x84,0x80, 0x00,0x00, \
 	0x07,0x00, 0x00,0x00 }
+#define CMD_MSG_VOIP_DTMFOPT_LEN 32
+#define CMD_MSG_VOIP_DTMFOPT(s,c) { \
+	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
+	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x02,0x80, 0x00,0x00, \
+	0x08,0x00, 0x00,0x00 }
+
+#define CMD_MSG_VOIP_TONECTL_LEN 32
+#define CMD_MSG_VOIP_TONECTL(s,c) { \
+	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
+	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x5B,0x80, 0x00,0x00, \
+	0x00,0x00, 0x00,0x00 }
 
 /* CPU ACK command */ 
 #define CMD_MSG_ACK_LEN 20
@@ -274,6 +286,7 @@
 				wc->cmdq[wc->cmdq_wndx].cmdlen = length; \
 				for (i = 0; i < length; i++) \
 					wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i]; \
+				wc->last_seqno = fifo[16]; \
 				wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; \
 			} \
 			__transmit_demand(wc); \
@@ -287,7 +300,7 @@
 
 struct cmdq {
 	unsigned int cmdlen;
-	unsigned int cmd[MAX_COMMAND_LEN];
+	unsigned char cmd[MAX_COMMAND_LEN];
 };
 
 struct wcdte {
@@ -312,6 +325,8 @@
 	unsigned int cmdq_wndx;
 	unsigned int cmdq_rndx;
 
+	unsigned int last_seqno;
+	unsigned int last_rseqno;
 	unsigned int last_command_sent;
 	unsigned int last_rcommand;
 	unsigned int last_rparm2;
@@ -366,6 +381,8 @@
 
 	unsigned int timestamp;
 	unsigned int seqno;
+
+	unsigned int cmd_seqno;
 
 	unsigned int timeslot_in_num;		/* DTE chennel on which results we be received from */
 	unsigned int timeslot_out_num;		/* DTE channel to send data to */
@@ -419,6 +436,8 @@
 	state_ptr->wc = wc;
 	state_ptr->timestamp = 0;
 	state_ptr->seqno = 0;
+
+	state_ptr->cmd_seqno = 0;
 
 	state_ptr->packets_sent = 0;
 	state_ptr->packets_received = 0;
@@ -648,6 +667,8 @@
 		up(&wc->chansem);
 		break;
 	case ZT_TCOP_TRANSCODE:
+		if (ztc->chan_built == 0)
+			printk("wcdte error: Sending data to a channel that isn't built yet\n");
 		if ( (((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) && ((zth->dstfmt == ZT_FORMAT_G729A  && zth->srclen >= G729_SAMPLES) ||(zth->dstfmt == ZT_FORMAT_G723_1  && zth->srclen >= G723_SAMPLES)) )
 			|| ((zth->srcfmt == ZT_FORMAT_G729A) && (zth->srclen >= G729_BYTES))
 			|| ((zth->srcfmt == ZT_FORMAT_G723_1) && (zth->srclen >= G723_BYTES)) )
@@ -806,13 +827,19 @@
 
 		
 			wc->rcvflags = RCV_CSMENCAPS;
-			wc->last_rcommand = rcommand;
-			wc->last_rparm2 = readchunk[30] | (readchunk[31] << 8);
-			wake_up_interruptible(&wc->regq);
+			if (rcommand == wc->last_command_sent) {
+				wc->last_rcommand = rcommand;
+				wc->last_rparm2 = readchunk[30] | (readchunk[31] << 8);
+				wake_up_interruptible(&wc->regq);
+			} else {
+				if (debug)
+				printk("wcdte error: unexpected command response received (sent: %04X, received: %04X)\n", wc->last_command_sent, rcommand);
+			}
 			up(&wc->cmdqsem);
 		}
 		else
 		{
+			wc->last_rseqno = readchunk[16];
 			wc->rcvflags = RCV_CSMENCAPS_ACK;
 			wake_up_interruptible(&wc->regq);
 		}
@@ -1024,20 +1051,11 @@
 #endif
 	int res;
 
-	if (wc->wqueints & 0x00000040) {
-		/* Loop descriptors is available */
-		do {
-			res = wcdte_check_descriptor(wc);
-		} while(res);
-	}
-	
-	/* Handle TX interrupts */
-	if (wc->wqueints & 0x00000001)
-	{
-		wc->txints++;
-		transmit_demand(wc);
-		wc->intcount++;
-	}
+	do {
+		res = wcdte_check_descriptor(wc);
+	} while(res);
+	
+	transmit_demand(wc);
 }
 
 ZAP_IRQ_HANDLER(wcdte_interrupt)
@@ -1105,6 +1123,7 @@
 	newjiffies = jiffies + HZ/10;
 	while(((reg = wcdte_getctl(wc,0x0000)) & 0x00000001) && (newjiffies > jiffies));
 
+	wcdte_setctl(wc, 0x0000, 0xFFFA0000);
 	
 	/* Configure watchdogs, access, etc */
 	wcdte_setctl(wc, 0x0030, 0x00280048);
@@ -1169,18 +1188,20 @@
 	wcdte_setctl(wc, 0x0084, 0x00000000);
 }
 
-static int wcdte_waitfor_csmencaps(struct wcdte *wc, unsigned int mask, int use_mask)
+static int wcdte_waitfor_csmencaps(struct wcdte *wc, unsigned int mask, int wait_mode)
 {
 	int ret;
 
 
-	if (use_mask)
+	if (wait_mode == 1)
 		ret = wait_event_interruptible_timeout(wc->regq, (wc->rcvflags == mask), wc->timeout);
+	else if (wait_mode == 2)
+		ret = wait_event_interruptible_timeout(wc->regq, ((wc->last_seqno == wc->last_rseqno) && (wc->rcvflags == mask)), wc->timeout);
 	else
-		ret = wait_event_interruptible_timeout(wc->regq, (wc->last_rcommand == wc->last_command_sent), wc->timeout);
+		ret = wait_event_interruptible_timeout(wc->regq, ((wc->last_rcommand == wc->last_command_sent) && (wc->last_seqno == wc->last_rseqno) && (wc->rcvflags == mask)), wc->timeout);
 	wc->rcvflags = 0;
 	wc->last_rcommand = 0;
-	wc->last_command_sent = 0;
+	wc->last_seqno = 0;
 
 	if (ret < 0)
 	{
@@ -1191,9 +1212,12 @@
 	if (ret == 0)
 	{
 		if (debug)
-			printk("wcdte error: Waitfor CSMENCAPS response timed out (ret = %d)\n", ret);
+			printk("wcdte error: Waitfor CSMENCAPS response timed out (ret = %d) (cmd_snt = %04X)\n", ret, wc->last_command_sent);
 		return(2);
 	}
+	if (wait_mode == 0)
+		wc->last_command_sent = 999;
+	wc->last_rseqno = 999;
 	return(0);
 }
 
@@ -1345,6 +1369,7 @@
 
 	} while (byteloc < firmware->size-20);
 	wc->timeout = 10 * HZ;
+	wc->last_command_sent = 0;
 	if (wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 1))
 		return(1);
 	
@@ -1360,6 +1385,8 @@
 {
 	int length = 0;
 	unsigned char chan1, chan2;
+	struct zt_transcoder_channel *ztc1, *ztc2;
+	struct dte_state *st1, *st2;
 	if(complicated == DTE_FORMAT_G729A)
 		length = G729_LENGTH;
 	else if (complicated == DTE_FORMAT_G723_1)
@@ -1373,19 +1400,31 @@
 	zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part2_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010);
 	chan2 = wc->last_rparm2;
 
+	ztc1 = &(wc->uencode->channels[part1_id/2]);
+	ztc2 = &(wc->udecode->channels[part2_id/2]);
+	st1 = ztc1->pvt;
+	st2 = ztc2->pvt;
+
 	/* Configure complex channel */
-	zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(wc->seq_num++, chan1, part2_id, part1_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000);
-	zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(wc->seq_num++, chan1, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001);
+	zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(st1->cmd_seqno++, chan1, part2_id, part1_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000);
+	zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(st1->cmd_seqno++, chan1, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001);
 
 	/* Configure simple channel */
-	zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(wc->seq_num++, chan2, part1_id, part2_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000);
-	zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(wc->seq_num++, chan2, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001);
+	zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(st2->cmd_seqno++, chan2, part1_id, part2_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000);
+	zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(st2->cmd_seqno++, chan2, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001);
+
+#ifdef QUIET_DSP
+	zt_send_cmd(wc, CMD_MSG_VOIP_TONECTL(st1->cmd_seqno++, chan1), CMD_MSG_VOIP_TONECTL_LEN, 0x805B);
+	zt_send_cmd(wc, CMD_MSG_VOIP_DTMFOPT(st1->cmd_seqno++, chan1), CMD_MSG_VOIP_DTMFOPT_LEN, 0x8002);
+	zt_send_cmd(wc, CMD_MSG_VOIP_TONECTL(st2->cmd_seqno++, chan2), CMD_MSG_VOIP_TONECTL_LEN, 0x805B);
+	zt_send_cmd(wc, CMD_MSG_VOIP_DTMFOPT(st2->cmd_seqno++, chan2), CMD_MSG_VOIP_DTMFOPT_LEN, 0x8002);
+	zt_send_cmd(wc, CMD_MSG_VOIP_INDCTRL(st1->cmd_seqno++, chan1), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084);
+	zt_send_cmd(wc, CMD_MSG_VOIP_INDCTRL(st2->cmd_seqno++, chan2), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084);
+#endif
 
 	zt_send_cmd(wc, CMD_MSG_TRANS_CONNECT(wc->seq_num++, 1, chan1, chan2, complicated, simple), CMD_MSG_TRANS_CONNECT_LEN, 0x9322);
-	zt_send_cmd(wc, CMD_MSG_VOIP_INDCTRL(wc->seq_num++, chan1), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084);
-	zt_send_cmd(wc, CMD_MSG_VOIP_INDCTRL(wc->seq_num++, chan2), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084);
-	zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(wc->seq_num++, chan1, complicated), CMD_MSG_VOIP_VOPENA_LEN, 0x8000);
-	zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(wc->seq_num++, chan2, simple), CMD_MSG_VOIP_VOPENA_LEN, 0x8000);
+	zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(st1->cmd_seqno++, chan1, complicated), CMD_MSG_VOIP_VOPENA_LEN, 0x8000);
+	zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(st2->cmd_seqno++, chan2, simple), CMD_MSG_VOIP_VOPENA_LEN, 0x8000);
 
 	*dte_chan1 = chan1;
 	*dte_chan2 = chan2;
@@ -1395,16 +1434,23 @@
 
 static int wcdte_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2)
 {
+	struct zt_transcoder_channel *ztc1, *ztc2;
+	struct dte_state *st1, *st2;
+
+	ztc1 = &(wc->uencode->channels[chan1/2]);
+	ztc2 = &(wc->udecode->channels[chan2/2]);
+	st1 = ztc1->pvt;
+	st2 = ztc2->pvt;
 
 	/* Turn off both channels */
-	zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(wc->seq_num++, chan1), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000);
-	zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(wc->seq_num++, chan2), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000);
+	zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(st1->cmd_seqno++, chan1), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000);
+	zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(st2->cmd_seqno++, chan2), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000);
 	
 	/* Disconnect the channels */
 	zt_send_cmd(wc, CMD_MSG_TRANS_CONNECT(wc->seq_num++, 0, chan1, chan2, 0, 0), CMD_MSG_TRANS_CONNECT_LEN, 0x9322);
 
 	/* Remove the channels */
-	zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan1), CMD_MSG_DESTROY_CHANNEL_LEN,  0x0011);
+	zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan1), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011);
 	zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan2), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011);
 
 	return 1;
@@ -1412,6 +1458,8 @@
 
 static int wcdte_setup_channels(struct wcdte *wc)	
 {
+	down(&wc->chansem);
+
 #ifndef USE_TEST_HW
 	zt_send_cmd(wc, CMD_MSG_SET_ARM_CLK(wc->seq_num++), CMD_MSG_SET_ARM_CLK_LEN, 0x0411);
 	zt_send_cmd(wc, CMD_MSG_SET_SPU_CLK(wc->seq_num++), CMD_MSG_SET_SPU_CLK_LEN, 0x0412);
@@ -1443,7 +1491,9 @@
 	zt_send_cmd(wc, CMD_MSG_TDM_OPT(wc->seq_num++), CMD_MSG_TDM_OPT_LEN, 0x0435);
 #endif
 
-	wc->timeout = HZ/100 + 1; 	/* 10msec */
+	wc->timeout = HZ/10 + 1; 	/* 100msec */
+
+	up(&wc->chansem);
 
 	return(0);
 }
@@ -1502,6 +1552,7 @@
 			wc->tdbl = 0;
 			wc->rdbl = 0;
 			wc->rcvflags = 0;
+			wc->last_seqno = 999;
 			wc->last_command_sent = 0;
 			wc->last_rcommand = 0;
 			wc->last_rparm2 = 0;
@@ -1538,7 +1589,7 @@
 			init_waitqueue_head(&wc->regq);
 		
 			/* Initialize the work queue */
-			wc->dte_wq = create_workqueue("tc400b");
+			wc->dte_wq = create_singlethread_workqueue("tc400b");
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
 			INIT_WORK(&wc->dte_work, dte_wque_run);
 #else



More information about the zaptel-commits mailing list