Skip to content

Commit

Permalink
wlcore: Prevent interaction with HW after recovery is queued
Browse files Browse the repository at this point in the history
When a function requests to recover, it would normally abort and will
not send any additional commands to the HW. However, other threads may
not be aware of the failure and could try to communicate with the HW
after a recovery was queued, but before the recovery work began.

Fix this by introducing an intermediate state which is set when recovery
is queued, and modify all state checks accordingly.

Signed-off-by: Ido Yariv <ido@wizery.com>
Signed-off-by: Luciano Coelho <luca@coelho.fi>
  • Loading branch information
Ido Yariv authored and Luciano Coelho committed Sep 27, 2012
1 parent 9b1a0a7 commit 4cc5338
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 55 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/ti/wl18xx/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ static ssize_t clear_fw_stats_write(struct file *file,

mutex_lock(&wl->mutex);

if (wl->state == WL1271_STATE_OFF)
if (unlikely(wl->state != WLCORE_STATE_ON))
goto out;

ret = wl18xx_acx_clear_statistics(wl);
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/wireless/ti/wlcore/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
u16 status;
u16 poll_count = 0;

if (WARN_ON(unlikely(wl->state == WLCORE_STATE_RESTARTING)))
return -EIO;

cmd = buf;
cmd->id = cpu_to_le16(id);
cmd->status = 0;
Expand Down
15 changes: 9 additions & 6 deletions drivers/net/wireless/ti/wlcore/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,14 @@ void wl1271_debugfs_update_stats(struct wl1271 *wl)

mutex_lock(&wl->mutex);

if (unlikely(wl->state != WLCORE_STATE_ON))
goto out;

ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto out;

if (wl->state == WL1271_STATE_ON && !wl->plt &&
if (!wl->plt &&
time_after(jiffies, wl->stats.fw_stats_update +
msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) {
wl1271_acx_statistics(wl, wl->stats.fw_stats);
Expand Down Expand Up @@ -286,7 +289,7 @@ static ssize_t dynamic_ps_timeout_write(struct file *file,

wl->conf.conn.dynamic_ps_timeout = value;

if (wl->state == WL1271_STATE_OFF)
if (unlikely(wl->state != WLCORE_STATE_ON))
goto out;

ret = wl1271_ps_elp_wakeup(wl);
Expand Down Expand Up @@ -353,7 +356,7 @@ static ssize_t forced_ps_write(struct file *file,

wl->conf.conn.forced_ps = value;

if (wl->state == WL1271_STATE_OFF)
if (unlikely(wl->state != WLCORE_STATE_ON))
goto out;

ret = wl1271_ps_elp_wakeup(wl);
Expand Down Expand Up @@ -999,7 +1002,7 @@ static ssize_t sleep_auth_write(struct file *file,

wl->conf.conn.sta_sleep_auth = value;

if (wl->state == WL1271_STATE_OFF) {
if (unlikely(wl->state != WLCORE_STATE_ON)) {
/* this will show up on "read" in case we are off */
wl->sleep_auth = value;
goto out;
Expand Down Expand Up @@ -1060,7 +1063,7 @@ static ssize_t dev_mem_read(struct file *file,

mutex_lock(&wl->mutex);

if (wl->state == WL1271_STATE_OFF) {
if (unlikely(wl->state != WLCORE_STATE_ON)) {
ret = -EFAULT;
goto skip_read;
}
Expand Down Expand Up @@ -1145,7 +1148,7 @@ static ssize_t dev_mem_write(struct file *file, const char __user *user_buf,

mutex_lock(&wl->mutex);

if (wl->state == WL1271_STATE_OFF) {
if (unlikely(wl->state != WLCORE_STATE_ON)) {
ret = -EFAULT;
goto skip_write;
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/ti/wlcore/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr,
return -EIO;

ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed);
if (ret && wl->state != WL1271_STATE_OFF)
if (ret && wl->state != WLCORE_STATE_OFF)
set_bit(WL1271_FLAG_IO_FAILED, &wl->flags);

return ret;
Expand All @@ -80,7 +80,7 @@ static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr,
return -EIO;

ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed);
if (ret && wl->state != WL1271_STATE_OFF)
if (ret && wl->state != WLCORE_STATE_OFF)
set_bit(WL1271_FLAG_IO_FAILED, &wl->flags);

return ret;
Expand Down
Loading

0 comments on commit 4cc5338

Please sign in to comment.