summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2009-03-23 23:48:54 +0000
committerShaun Ruffell <sruffell@digium.com>2009-03-23 23:48:54 +0000
commit9b45990849f0389d8e96c53eb933242cdbc52753 (patch)
tree89962f01e208ab27c9944d640b00355504c029ea
parent5cb582b4f1278b3d43e17dff5152f04731f75d15 (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
-rw-r--r--drivers/dahdi/wctc4xxp/base.c22
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);