Skip to content

Commit

Permalink
wlcore: protect wlcore_op_set_key with mutex
Browse files Browse the repository at this point in the history
wlcore_op_set_key() calls wl18xx_set_key(),
which in turn executes some of his function
calls without acquiring wl->mutex and making
sure the fw is awake.

Adding mutex_lock()/ps_elp_wakeup() calls is
not enough, as wl18xx_set_key() calls
wl1271_tx_flush() which can't be called while
the mutex is taken.

Add the required calls to wlcore_op_set_key,
but limit the queues_stop and flushing
to the only encryption types in which
a spare block might be needed (GEM and TKIP).

[Arik - move state != ON check]

Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Luciano Coelho <luca@coelho.fi>
  • Loading branch information
Eliad Peller authored and Luciano Coelho committed Sep 27, 2012
1 parent ab2c4f3 commit af390f4
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 33 deletions.
8 changes: 0 additions & 8 deletions drivers/net/wireless/ti/wl18xx/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1252,13 +1252,6 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
if (!change_spare)
return wlcore_set_key(wl, cmd, vif, sta, key_conf);

/*
* stop the queues and flush to ensure the next packets are
* in sync with FW spare block accounting
*/
wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
wl1271_tx_flush(wl);

ret = wlcore_set_key(wl, cmd, vif, sta, key_conf);
if (ret < 0)
goto out;
Expand All @@ -1281,7 +1274,6 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
}

out:
wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
return ret;
}

Expand Down
68 changes: 43 additions & 25 deletions drivers/net/wireless/ti/wlcore/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3063,8 +3063,45 @@ static int wlcore_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_key_conf *key_conf)
{
struct wl1271 *wl = hw->priv;
int ret;
bool might_change_spare =
key_conf->cipher == WL1271_CIPHER_SUITE_GEM ||
key_conf->cipher == WLAN_CIPHER_SUITE_TKIP;

if (might_change_spare) {
/*
* stop the queues and flush to ensure the next packets are
* in sync with FW spare block accounting
*/
mutex_lock(&wl->mutex);
wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
mutex_unlock(&wl->mutex);

wl1271_tx_flush(wl);
}

mutex_lock(&wl->mutex);

if (unlikely(wl->state != WLCORE_STATE_ON)) {
ret = -EAGAIN;
goto out_wake_queues;
}

return wlcore_hw_set_key(wl, cmd, vif, sta, key_conf);
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto out_wake_queues;

ret = wlcore_hw_set_key(wl, cmd, vif, sta, key_conf);

wl1271_ps_elp_sleep(wl);

out_wake_queues:
if (might_change_spare)
wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);

mutex_unlock(&wl->mutex);

return ret;
}

int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
Expand All @@ -3086,17 +3123,6 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
key_conf->keylen, key_conf->flags);
wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);

mutex_lock(&wl->mutex);

if (unlikely(wl->state != WLCORE_STATE_ON)) {
ret = -EAGAIN;
goto out_unlock;
}

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

switch (key_conf->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
Expand Down Expand Up @@ -3126,8 +3152,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
default:
wl1271_error("Unknown key algo 0x%x", key_conf->cipher);

ret = -EOPNOTSUPP;
goto out_sleep;
return -EOPNOTSUPP;
}

switch (cmd) {
Expand All @@ -3138,7 +3163,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
tx_seq_32, tx_seq_16, sta);
if (ret < 0) {
wl1271_error("Could not add or replace key");
goto out_sleep;
return ret;
}

/*
Expand All @@ -3152,7 +3177,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
ret = wl1271_cmd_build_arp_rsp(wl, wlvif);
if (ret < 0) {
wl1271_warning("build arp rsp failed: %d", ret);
goto out_sleep;
return ret;
}
}
break;
Expand All @@ -3164,22 +3189,15 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
0, 0, sta);
if (ret < 0) {
wl1271_error("Could not remove key");
goto out_sleep;
return ret;
}
break;

default:
wl1271_error("Unsupported key cmd 0x%x", cmd);
ret = -EOPNOTSUPP;
break;
return -EOPNOTSUPP;
}

out_sleep:
wl1271_ps_elp_sleep(wl);

out_unlock:
mutex_unlock(&wl->mutex);

return ret;
}
EXPORT_SYMBOL_GPL(wlcore_set_key);
Expand Down

0 comments on commit af390f4

Please sign in to comment.