Commit 6c15c1aa authored by Eyal Shapira's avatar Eyal Shapira Committed by Luciano Coelho

wlcore: queue recovery in case of bus errors during cmd_remove_peer

Following the addition of propagating errors from the bus ops
there's a need to distinguish between bus errors (including timeout)
and a legitimate timeout occuring in cmd_wait_for_event_or_timeout.
In case of real bus errors we need to queue recovery even in cases
where a timeout on a response from the FW to a command is acceptable.
Reported-by: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarEyal Shapira <eyal@wizery.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent 7a50bdfb
...@@ -133,24 +133,27 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, ...@@ -133,24 +133,27 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
* Poll the mailbox event field until any of the bits in the mask is set or a * Poll the mailbox event field until any of the bits in the mask is set or a
* timeout occurs (WL1271_EVENT_TIMEOUT in msecs) * timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
*/ */
static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl,
u32 mask, bool *timeout)
{ {
u32 *events_vector; u32 *events_vector;
u32 event; u32 event;
unsigned long timeout; unsigned long timeout_time;
int ret = 0; int ret = 0;
*timeout = false;
events_vector = kmalloc(sizeof(*events_vector), GFP_KERNEL | GFP_DMA); events_vector = kmalloc(sizeof(*events_vector), GFP_KERNEL | GFP_DMA);
if (!events_vector) if (!events_vector)
return -ENOMEM; return -ENOMEM;
timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); timeout_time = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
do { do {
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout_time)) {
wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", wl1271_debug(DEBUG_CMD, "timeout waiting for event %d",
(int)mask); (int)mask);
ret = -ETIMEDOUT; *timeout = true;
goto out; goto out;
} }
...@@ -180,9 +183,10 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) ...@@ -180,9 +183,10 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask)
static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
{ {
int ret; int ret;
bool timeout = false;
ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask); ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask, &timeout);
if (ret != 0) { if (ret != 0 || timeout) {
wl12xx_queue_recovery_work(wl); wl12xx_queue_recovery_work(wl);
return ret; return ret;
} }
...@@ -1435,6 +1439,7 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) ...@@ -1435,6 +1439,7 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
{ {
struct wl12xx_cmd_remove_peer *cmd; struct wl12xx_cmd_remove_peer *cmd;
int ret; int ret;
bool timeout = false;
wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid); wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid);
...@@ -1455,12 +1460,16 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) ...@@ -1455,12 +1460,16 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
goto out_free; goto out_free;
} }
ret = wl1271_cmd_wait_for_event_or_timeout(wl,
PEER_REMOVE_COMPLETE_EVENT_ID,
&timeout);
/* /*
* We are ok with a timeout here. The event is sometimes not sent * We are ok with a timeout here. The event is sometimes not sent
* due to a firmware bug. * due to a firmware bug. In case of another error (like SDIO timeout)
* queue a recovery.
*/ */
wl1271_cmd_wait_for_event_or_timeout(wl, if (ret)
PEER_REMOVE_COMPLETE_EVENT_ID); wl12xx_queue_recovery_work(wl);
out_free: out_free:
kfree(cmd); kfree(cmd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment