summaryrefslogtreecommitdiff
path: root/wctc4xxp
diff options
context:
space:
mode:
authorjsloan <jsloan@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-06-11 15:47:37 +0000
committerjsloan <jsloan@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-06-11 15:47:37 +0000
commit4db210945e3a3d4c92f7d791e207b743d77ec05b (patch)
treee4fc2a8e52a094c5f715084b9475055d6ba50a6e /wctc4xxp
parent71bc975ac67843fe66a4a98711d7546568f3c987 (diff)
Fixed SMP bugs on quad processor machines. Reduced memory usage
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@2621 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wctc4xxp')
-rw-r--r--wctc4xxp/base.c121
1 files changed, 86 insertions, 35 deletions
diff --git a/wctc4xxp/base.c b/wctc4xxp/base.c
index b7138e3..6ff049f 100644
--- a/wctc4xxp/base.c
+++ b/wctc4xxp/base.c
@@ -62,6 +62,7 @@ extern void _binary_tc400m_firmware_bin_size;
/* #define USE_TEST_HW */
#define USE_TDM_CONFIG
+#define QUIET_DSP
#define WC_MAX_IFACES 128
@@ -238,6 +239,17 @@ extern void _binary_tc400m_firmware_bin_size;
#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 @@ extern void _binary_tc400m_firmware_bin_size;
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 @@ extern void _binary_tc400m_firmware_bin_size;
struct cmdq {
unsigned int cmdlen;
- unsigned int cmd[MAX_COMMAND_LEN];
+ unsigned char cmd[MAX_COMMAND_LEN];
};
struct wcdte {
@@ -312,6 +325,8 @@ struct wcdte {
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;
@@ -367,6 +382,8 @@ struct dte_state {
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 */
@@ -420,6 +437,8 @@ static void dte_init_state(struct dte_state *state_ptr, int encoder, unsigned in
state_ptr->timestamp = 0;
state_ptr->seqno = 0;
+ state_ptr->cmd_seqno = 0;
+
state_ptr->packets_sent = 0;
state_ptr->packets_received = 0;
state_ptr->last_dte_seqno = 0;
@@ -648,6 +667,8 @@ static int dte_operation(struct zt_transcoder_channel *ztc, int op)
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 @@ static inline void wcdte_receiveprep(struct wcdte *wc, int dbl)
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 @@ static void dte_wque_run(void *work_data)
#endif
int res;
- if (wc->wqueints & 0x00000040) {
- /* Loop descriptors is available */
- do {
- res = wcdte_check_descriptor(wc);
- } while(res);
- }
+ do {
+ res = wcdte_check_descriptor(wc);
+ } while(res);
- /* Handle TX interrupts */
- if (wc->wqueints & 0x00000001)
- {
- wc->txints++;
- transmit_demand(wc);
- wc->intcount++;
- }
+ transmit_demand(wc);
}
ZAP_IRQ_HANDLER(wcdte_interrupt)
@@ -1105,6 +1123,7 @@ static int wcdte_hardware_init(struct wcdte *wc)
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 @@ static void wcdte_disable_interrupts(struct wcdte *wc)
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 @@ static int wcdte_waitfor_csmencaps(struct wcdte *wc, unsigned int mask, int use_
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 @@ static int wcdte_boot_processor(struct wcdte *wc, const struct firmware *firmwar
} 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 @@ static int wcdte_create_channel(struct wcdte *wc, int simple, int complicated, i
{
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 @@ static int wcdte_create_channel(struct wcdte *wc, int simple, int complicated, i
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_create_channel(struct wcdte *wc, int simple, int complicated, i
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_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned
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 @@ static int wcdte_setup_channels(struct wcdte *wc)
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 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic
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 @@ static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_devic
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