summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2011-07-27 16:27:47 +0000
committerShaun Ruffell <sruffell@digium.com>2011-07-27 16:27:47 +0000
commita3279d1155f3016d1880ca5101b36d6a864babac (patch)
treea140f3f8e5f835ebf72a815320be3b70590d04a2
parentde9374fcc9f27b42880bed0c3e257e255de04156 (diff)
wctc4xxp: Cleanup in-flight commands when halting due to hardware error.
On one system I was seeing the board reset in the middle of a transaction. Any commands that were on the response list when this would happen would never be completed and the process would then be stuck in an uninterruptible sleep. This change also prevents the driver from sleeping in timer context, which would result in a kernel panic. This change at least lets an error message propogate back to the user. DAHDI-880 Signed-off-by: Shaun Ruffell <sruffell@digium.com> Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10082 Conflicts: drivers/dahdi/wctc4xxp/base.c git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.4@10084 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/wctc4xxp/base.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/drivers/dahdi/wctc4xxp/base.c b/drivers/dahdi/wctc4xxp/base.c
index 5ff92e9..3ab4ca6 100644
--- a/drivers/dahdi/wctc4xxp/base.c
+++ b/drivers/dahdi/wctc4xxp/base.c
@@ -1615,6 +1615,20 @@ wctc4xxp_transmit_cmd(struct wcdte *wc, struct tcb *cmd)
{
int res;
+ /* If we're shutdown all commands will timeout. Just complete the
+ * command here with the timeout flag */
+ if (unlikely(test_bit(DTE_SHUTDOWN, &wc->flags))) {
+ if (cmd->flags & DO_NOT_AUTO_FREE) {
+ cmd->flags |= DTE_CMD_TIMEOUT;
+ list_del_init(&cmd->node);
+ complete(&cmd->complete);
+ } else {
+ list_del(&cmd->node);
+ free_cmd(cmd);
+ }
+ return;
+ }
+
if (cmd->data_len < MIN_PACKET_LEN) {
memset((u8 *)(cmd->data) + cmd->data_len, 0,
MIN_PACKET_LEN-cmd->data_len);
@@ -2741,11 +2755,10 @@ wctc4xxp_start_dma(struct wcdte *wc)
}
static void
-wctc4xxp_stop_dma(struct wcdte *wc)
+_wctc4xxp_stop_dma(struct wcdte *wc)
{
/* Disable interrupts and reset */
unsigned int reg;
- unsigned long newjiffies;
/* Disable interrupts */
wctc4xxp_setintmask(wc, 0x00000000);
wctc4xxp_setctl(wc, 0x0084, 0x00000000);
@@ -2754,7 +2767,14 @@ wctc4xxp_stop_dma(struct wcdte *wc)
reg = wctc4xxp_getctl(wc, 0x0000);
reg |= 0x00000001;
wctc4xxp_setctl(wc, 0x0000, reg);
+}
+static void
+wctc4xxp_stop_dma(struct wcdte *wc)
+{
+ unsigned long newjiffies;
+
+ _wctc4xxp_stop_dma(wc);
newjiffies = jiffies + HZ; /* One second timeout */
/* We'll wait here for the part to come out of reset */
while (((wctc4xxp_getctl(wc, 0x0000)) & 0x00000001) &&
@@ -2762,7 +2782,6 @@ wctc4xxp_stop_dma(struct wcdte *wc)
msleep(1);
}
-
#define MDIO_SHIFT_CLK 0x10000
#define MDIO_DATA_WRITE1 0x20000
#define MDIO_ENB 0x00000
@@ -3307,13 +3326,19 @@ wctc4xxp_watchdog(unsigned long data)
if (time_after(jiffies, cmd->timeout)) {
if (++cmd->retries > MAX_RETRIES) {
if (!(cmd->flags & TX_COMPLETE)) {
+
+ cmd->flags |= DTE_CMD_TIMEOUT;
+ list_del_init(&cmd->node);
+ complete(&cmd->complete);
+
set_bit(DTE_SHUTDOWN, &wc->flags);
spin_unlock(&wc->cmd_list_lock);
- wctc4xxp_stop_dma(wc);
+ _wctc4xxp_stop_dma(wc);
DTE_PRINTK(ERR,
"Board malfunctioning. " \
"Halting operation.\n");
- return;
+ reschedule_timer = 0;
+ break;
}
/* ERROR: We've retried the command and
* haven't received the ACK or the response.