wctc4xxp: spin_lock() -> spin_lock_irqsave() in wctc4xxp_watchdog()
Since commit (e10f740 "wctc4xxp: Service tx ring in interrupt handler."), it
was possible to deadlock the system if the interrupt fires while the
watchdog function is running in the context of the system timer.
This was reported by lockdep.
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
This commit is contained in:
committed by
Russ Meyerriecks
parent
e9ec13dfa0
commit
cb50ae1500
@@ -3693,10 +3693,11 @@ wctc4xxp_watchdog(unsigned long data)
|
||||
LIST_HEAD(cmds_to_retry);
|
||||
const int MAX_RETRIES = 5;
|
||||
int reschedule_timer = 0;
|
||||
unsigned long flags;
|
||||
|
||||
service_tx_ring(wc);
|
||||
|
||||
spin_lock(&wc->cmd_list_lock);
|
||||
spin_lock_irqsave(&wc->cmd_list_lock, flags);
|
||||
/* Go through the list of messages that are waiting for responses from
|
||||
* the DTE, and complete or retry any that have timed out. */
|
||||
list_for_each_entry_safe(cmd, temp,
|
||||
@@ -3715,12 +3716,13 @@ wctc4xxp_watchdog(unsigned long data)
|
||||
|
||||
wctc4xxp_reset_processor(wc);
|
||||
set_bit(DTE_SHUTDOWN, &wc->flags);
|
||||
spin_unlock(&wc->cmd_list_lock);
|
||||
spin_unlock_irqrestore(&wc->cmd_list_lock,
|
||||
flags);
|
||||
_wctc4xxp_stop_dma(wc);
|
||||
dev_err(&wc->pdev->dev,
|
||||
"Board malfunctioning. Halting operation.\n");
|
||||
reschedule_timer = 0;
|
||||
spin_lock(&wc->cmd_list_lock);
|
||||
spin_lock_irqsave(&wc->cmd_list_lock, flags);
|
||||
break;
|
||||
}
|
||||
/* ERROR: We've retried the command and
|
||||
@@ -3749,7 +3751,7 @@ wctc4xxp_watchdog(unsigned long data)
|
||||
reschedule_timer = 1;
|
||||
}
|
||||
}
|
||||
spin_unlock(&wc->cmd_list_lock);
|
||||
spin_unlock_irqrestore(&wc->cmd_list_lock, flags);
|
||||
|
||||
if (list_empty(&cmds_to_retry) && reschedule_timer)
|
||||
mod_timer(&wc->watchdog, jiffies + HZ/2);
|
||||
|
||||
Reference in New Issue
Block a user