diff options
author | Shaun Ruffell <sruffell@digium.com> | 2009-03-23 23:48:54 +0000 |
---|---|---|
committer | Shaun Ruffell <sruffell@digium.com> | 2009-03-23 23:48:54 +0000 |
commit | 9b45990849f0389d8e96c53eb933242cdbc52753 (patch) | |
tree | 89962f01e208ab27c9944d640b00355504c029ea /drivers/dahdi/wctc4xxp | |
parent | 5cb582b4f1278b3d43e17dff5152f04731f75d15 (diff) |
Do not handle duplicate reponses.
It is possible for system activity to prevent the wctc4xxp driver from
responding the the firmware on the TC400M for a period of time. If this occurs,
the TC400M will resend a response to a command that we sent. This duplicate
reponse will then sometimes confuse the driver. Normally this would manifest
as an attempt to connect the same channel together in a transcoding session.
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@6224 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/wctc4xxp')
-rw-r--r-- | drivers/dahdi/wctc4xxp/base.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/dahdi/wctc4xxp/base.c b/drivers/dahdi/wctc4xxp/base.c index 8b775cf..f46682e 100644 --- a/drivers/dahdi/wctc4xxp/base.c +++ b/drivers/dahdi/wctc4xxp/base.c @@ -410,6 +410,7 @@ struct wcdte { struct list_head rx_list; unsigned int seq_num; + int last_rx_seq_num; unsigned char numchannels; unsigned char complexname[40]; @@ -2111,8 +2112,17 @@ do_rx_response_packet(struct wcdte *wc, struct tcb *cmd) const struct csm_encaps_hdr *listhdr, *rxhdr; struct tcb *pos, *temp; unsigned long flags; - + u32 handled = 0; rxhdr = cmd->data; + if (0xffff == rxhdr->channel) { + /* We received a duplicate response. */ + if (rxhdr->seq_num == wc->last_rx_seq_num) { + free_cmd(cmd); + return; + } + wc->last_rx_seq_num = rxhdr->seq_num; + } + spin_lock_bh(&wc->cmd_list_lock); list_for_each_entry_safe(pos, temp, &wc->waiting_for_response_list, node) { @@ -2130,11 +2140,17 @@ do_rx_response_packet(struct wcdte *wc, struct tcb *cmd) complete(&pos->complete); } spin_unlock_irqrestore(&pos->lock, flags); + handled = 1; break; } } spin_unlock_bh(&wc->cmd_list_lock); + + if (!handled) { + printk(KERN_INFO "Freeing unhandled response\n"); + free_cmd(cmd); + } } static void @@ -3277,10 +3293,9 @@ wctc4xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) * Setup the pure software constructs internal to this driver. * --------------------------------------------------------------- */ - wc = kmalloc(sizeof(*wc), GFP_KERNEL); + wc = kzalloc(sizeof(*wc), GFP_KERNEL); if (!wc) return -ENOMEM; - memset(wc, 0, sizeof(*wc)); position_on_list = wctc4xxp_add_to_device_list(wc); snprintf(wc->board_name, sizeof(wc->board_name)-1, "%s%d", @@ -3289,6 +3304,7 @@ wctc4xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) wc->pdev = pdev; wc->pos = position_on_list; wc->variety = d->long_name; + wc->last_rx_seq_num = -1; init_MUTEX(&wc->chansem); spin_lock_init(&wc->reglock); |