wlcore: Disable interrupts while recovering
In case a recovery is initiated, the FW can no longer be trusted, and the driver should not handle any new FW events. Disable the interrupt handler when a recovery is scheduled and balance it back in the op_stop callback. Signed-off-by: Ido Yariv <ido@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
This commit is contained in:
committed by
Luciano Coelho
parent
645865fc37
commit
b666bb7f2f
@@ -48,6 +48,12 @@ void wlcore_disable_interrupts(struct wl1271 *wl)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(wlcore_disable_interrupts);
|
EXPORT_SYMBOL_GPL(wlcore_disable_interrupts);
|
||||||
|
|
||||||
|
void wlcore_disable_interrupts_nosync(struct wl1271 *wl)
|
||||||
|
{
|
||||||
|
disable_irq_nosync(wl->irq);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(wlcore_disable_interrupts_nosync);
|
||||||
|
|
||||||
void wlcore_enable_interrupts(struct wl1271 *wl)
|
void wlcore_enable_interrupts(struct wl1271 *wl)
|
||||||
{
|
{
|
||||||
enable_irq(wl->irq);
|
enable_irq(wl->irq);
|
||||||
|
@@ -45,6 +45,7 @@
|
|||||||
struct wl1271;
|
struct wl1271;
|
||||||
|
|
||||||
void wlcore_disable_interrupts(struct wl1271 *wl);
|
void wlcore_disable_interrupts(struct wl1271 *wl);
|
||||||
|
void wlcore_disable_interrupts_nosync(struct wl1271 *wl);
|
||||||
void wlcore_enable_interrupts(struct wl1271 *wl);
|
void wlcore_enable_interrupts(struct wl1271 *wl);
|
||||||
|
|
||||||
void wl1271_io_reset(struct wl1271 *wl);
|
void wl1271_io_reset(struct wl1271 *wl);
|
||||||
|
@@ -743,8 +743,11 @@ out:
|
|||||||
|
|
||||||
void wl12xx_queue_recovery_work(struct wl1271 *wl)
|
void wl12xx_queue_recovery_work(struct wl1271 *wl)
|
||||||
{
|
{
|
||||||
if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
|
/* Avoid a recursive recovery */
|
||||||
|
if (!test_and_set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) {
|
||||||
|
wlcore_disable_interrupts_nosync(wl);
|
||||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen)
|
size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen)
|
||||||
@@ -848,9 +851,6 @@ static void wl1271_recovery_work(struct work_struct *work)
|
|||||||
if (wl->state != WL1271_STATE_ON || wl->plt)
|
if (wl->state != WL1271_STATE_ON || wl->plt)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
/* Avoid a recursive recovery */
|
|
||||||
set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
|
|
||||||
|
|
||||||
wl12xx_read_fwlog_panic(wl);
|
wl12xx_read_fwlog_panic(wl);
|
||||||
|
|
||||||
/* change partitions momentarily so we can read the FW pc */
|
/* change partitions momentarily so we can read the FW pc */
|
||||||
@@ -902,8 +902,6 @@ static void wl1271_recovery_work(struct work_struct *work)
|
|||||||
mutex_unlock(&wl->mutex);
|
mutex_unlock(&wl->mutex);
|
||||||
wl1271_op_stop(wl->hw);
|
wl1271_op_stop(wl->hw);
|
||||||
|
|
||||||
clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
|
|
||||||
|
|
||||||
ieee80211_restart_hw(wl->hw);
|
ieee80211_restart_hw(wl->hw);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1706,6 +1704,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
|||||||
wlcore_disable_interrupts(wl);
|
wlcore_disable_interrupts(wl);
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
if (wl->state == WL1271_STATE_OFF) {
|
if (wl->state == WL1271_STATE_OFF) {
|
||||||
|
if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS,
|
||||||
|
&wl->flags))
|
||||||
|
wlcore_enable_interrupts(wl);
|
||||||
|
|
||||||
mutex_unlock(&wl->mutex);
|
mutex_unlock(&wl->mutex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1737,6 +1739,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
|||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
|
|
||||||
wl1271_power_off(wl);
|
wl1271_power_off(wl);
|
||||||
|
/*
|
||||||
|
* In case a recovery was scheduled, interrupts were disabled to avoid
|
||||||
|
* an interrupt storm. Now that the power is down, it is safe to
|
||||||
|
* re-enable interrupts to balance the disable depth
|
||||||
|
*/
|
||||||
|
if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
|
||||||
|
wlcore_enable_interrupts(wl);
|
||||||
|
|
||||||
wl->band = IEEE80211_BAND_2GHZ;
|
wl->band = IEEE80211_BAND_2GHZ;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user