mirror of https://gitee.com/openkylin/linux.git
wl1271: Add hardware recovery mechanism
There is some probability of hardware failures, which currently go largely undetected. Attempt to recover from these failures by shutting down the hardware, and requesting mac80211 to reconfigure it. Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Reviewed-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com> Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
This commit is contained in:
parent
52a2a37550
commit
52b0e7a61f
|
@ -408,6 +408,9 @@ struct wl1271 {
|
|||
/* The target interrupt mask */
|
||||
struct work_struct irq_work;
|
||||
|
||||
/* Hardware recovery work */
|
||||
struct work_struct recovery_work;
|
||||
|
||||
/* The mbox event mask */
|
||||
u32 event_mask;
|
||||
|
||||
|
|
|
@ -94,6 +94,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
|
|||
status = le16_to_cpu(cmd->status);
|
||||
if (status != CMD_STATUS_SUCCESS) {
|
||||
wl1271_error("command execute failure %d", status);
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
|
@ -182,8 +183,10 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
|
|||
timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
|
||||
|
||||
do {
|
||||
if (time_after(jiffies, timeout))
|
||||
if (time_after(jiffies, timeout)) {
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
msleep(1);
|
||||
|
||||
|
|
|
@ -235,6 +235,9 @@ static struct conf_drv_settings default_conf = {
|
|||
}
|
||||
};
|
||||
|
||||
static void __wl1271_op_remove_interface(struct wl1271 *wl);
|
||||
|
||||
|
||||
static void wl1271_device_release(struct device *dev)
|
||||
{
|
||||
|
||||
|
@ -612,6 +615,26 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void wl1271_recovery_work(struct work_struct *work)
|
||||
{
|
||||
struct wl1271 *wl =
|
||||
container_of(work, struct wl1271, recovery_work);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->state != WL1271_STATE_ON)
|
||||
goto out;
|
||||
|
||||
wl1271_info("Hardware recovery in progress.");
|
||||
|
||||
/* reboot the chipset */
|
||||
__wl1271_op_remove_interface(wl);
|
||||
ieee80211_restart_hw(wl->hw);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
static void wl1271_fw_wakeup(struct wl1271 *wl)
|
||||
{
|
||||
u32 elp_reg;
|
||||
|
@ -635,6 +658,7 @@ static int wl1271_setup(struct wl1271 *wl)
|
|||
INIT_WORK(&wl->irq_work, wl1271_irq_work);
|
||||
INIT_WORK(&wl->tx_work, wl1271_tx_work);
|
||||
INIT_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
|
||||
INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -793,11 +817,11 @@ int wl1271_plt_stop(struct wl1271 *wl)
|
|||
mutex_unlock(&wl->mutex);
|
||||
|
||||
cancel_work_sync(&wl->irq_work);
|
||||
cancel_work_sync(&wl->recovery_work);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
|
@ -1046,6 +1070,8 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
|
|||
WARN_ON(wl->vif != vif);
|
||||
__wl1271_op_remove_interface(wl);
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
cancel_work_sync(&wl->recovery_work);
|
||||
}
|
||||
|
||||
static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)
|
||||
|
|
|
@ -64,7 +64,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
|
|||
test_bit(WL1271_FLAG_IDLE, &wl->flags)) {
|
||||
cancel_delayed_work(&wl->elp_work);
|
||||
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
|
||||
msecs_to_jiffies(ELP_ENTRY_DELAY));
|
||||
msecs_to_jiffies(ELP_ENTRY_DELAY));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,6 +99,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
|
|||
&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
|
||||
if (ret == 0) {
|
||||
wl1271_error("ELP wakeup timeout!");
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
ret = -ETIMEDOUT;
|
||||
goto err;
|
||||
} else if (ret < 0) {
|
||||
|
|
Loading…
Reference in New Issue