aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2012-09-03 11:27:58 -0400
committerLuciano Coelho <luca@coelho.fi>2012-09-27 05:13:54 -0400
commitaf390f4dd35373b3ca32bafc12d7f2ad12840529 (patch)
tree692652e15a9aed463e43f40aa351b4d640789faa /drivers
parentab2c4f37dcef5bd517a95a32da50d5ed0cc24cb5 (diff)
wlcore: protect wlcore_op_set_key with mutex
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c8
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c68
2 files changed, 43 insertions, 33 deletions
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 9e3e10a13498..a39682a7c25f 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1252,13 +1252,6 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
1252 if (!change_spare) 1252 if (!change_spare)
1253 return wlcore_set_key(wl, cmd, vif, sta, key_conf); 1253 return wlcore_set_key(wl, cmd, vif, sta, key_conf);
1254 1254
1255 /*
1256 * stop the queues and flush to ensure the next packets are
1257 * in sync with FW spare block accounting
1258 */
1259 wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
1260 wl1271_tx_flush(wl);
1261
1262 ret = wlcore_set_key(wl, cmd, vif, sta, key_conf); 1255 ret = wlcore_set_key(wl, cmd, vif, sta, key_conf);
1263 if (ret < 0) 1256 if (ret < 0)
1264 goto out; 1257 goto out;
@@ -1281,7 +1274,6 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
1281 } 1274 }
1282 1275
1283out: 1276out:
1284 wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
1285 return ret; 1277 return ret;
1286} 1278}
1287 1279
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 6ada018fe4a4..25530c8760cb 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -3063,8 +3063,45 @@ static int wlcore_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3063 struct ieee80211_key_conf *key_conf) 3063 struct ieee80211_key_conf *key_conf)
3064{ 3064{
3065 struct wl1271 *wl = hw->priv; 3065 struct wl1271 *wl = hw->priv;
3066 int ret;
3067 bool might_change_spare =
3068 key_conf->cipher == WL1271_CIPHER_SUITE_GEM ||
3069 key_conf->cipher == WLAN_CIPHER_SUITE_TKIP;
3070
3071 if (might_change_spare) {
3072 /*
3073 * stop the queues and flush to ensure the next packets are
3074 * in sync with FW spare block accounting
3075 */
3076 mutex_lock(&wl->mutex);
3077 wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
3078 mutex_unlock(&wl->mutex);
3079
3080 wl1271_tx_flush(wl);
3081 }
3082
3083 mutex_lock(&wl->mutex);
3084
3085 if (unlikely(wl->state != WLCORE_STATE_ON)) {
3086 ret = -EAGAIN;
3087 goto out_wake_queues;
3088 }
3066 3089
3067 return wlcore_hw_set_key(wl, cmd, vif, sta, key_conf); 3090 ret = wl1271_ps_elp_wakeup(wl);
3091 if (ret < 0)
3092 goto out_wake_queues;
3093
3094 ret = wlcore_hw_set_key(wl, cmd, vif, sta, key_conf);
3095
3096 wl1271_ps_elp_sleep(wl);
3097
3098out_wake_queues:
3099 if (might_change_spare)
3100 wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK);
3101
3102 mutex_unlock(&wl->mutex);
3103
3104 return ret;
3068} 3105}
3069 3106
3070int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, 3107int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
@@ -3086,17 +3123,6 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
3086 key_conf->keylen, key_conf->flags); 3123 key_conf->keylen, key_conf->flags);
3087 wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); 3124 wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
3088 3125
3089 mutex_lock(&wl->mutex);
3090
3091 if (unlikely(wl->state != WLCORE_STATE_ON)) {
3092 ret = -EAGAIN;
3093 goto out_unlock;
3094 }
3095
3096 ret = wl1271_ps_elp_wakeup(wl);
3097 if (ret < 0)
3098 goto out_unlock;
3099
3100 switch (key_conf->cipher) { 3126 switch (key_conf->cipher) {
3101 case WLAN_CIPHER_SUITE_WEP40: 3127 case WLAN_CIPHER_SUITE_WEP40:
3102 case WLAN_CIPHER_SUITE_WEP104: 3128 case WLAN_CIPHER_SUITE_WEP104:
@@ -3126,8 +3152,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
3126 default: 3152 default:
3127 wl1271_error("Unknown key algo 0x%x", key_conf->cipher); 3153 wl1271_error("Unknown key algo 0x%x", key_conf->cipher);
3128 3154
3129 ret = -EOPNOTSUPP; 3155 return -EOPNOTSUPP;
3130 goto out_sleep;
3131 } 3156 }
3132 3157
3133 switch (cmd) { 3158 switch (cmd) {
@@ -3138,7 +3163,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
3138 tx_seq_32, tx_seq_16, sta); 3163 tx_seq_32, tx_seq_16, sta);
3139 if (ret < 0) { 3164 if (ret < 0) {
3140 wl1271_error("Could not add or replace key"); 3165 wl1271_error("Could not add or replace key");
3141 goto out_sleep; 3166 return ret;
3142 } 3167 }
3143 3168
3144 /* 3169 /*
@@ -3152,7 +3177,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
3152 ret = wl1271_cmd_build_arp_rsp(wl, wlvif); 3177 ret = wl1271_cmd_build_arp_rsp(wl, wlvif);
3153 if (ret < 0) { 3178 if (ret < 0) {
3154 wl1271_warning("build arp rsp failed: %d", ret); 3179 wl1271_warning("build arp rsp failed: %d", ret);
3155 goto out_sleep; 3180 return ret;
3156 } 3181 }
3157 } 3182 }
3158 break; 3183 break;
@@ -3164,22 +3189,15 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
3164 0, 0, sta); 3189 0, 0, sta);
3165 if (ret < 0) { 3190 if (ret < 0) {
3166 wl1271_error("Could not remove key"); 3191 wl1271_error("Could not remove key");
3167 goto out_sleep; 3192 return ret;
3168 } 3193 }
3169 break; 3194 break;
3170 3195
3171 default: 3196 default:
3172 wl1271_error("Unsupported key cmd 0x%x", cmd); 3197 wl1271_error("Unsupported key cmd 0x%x", cmd);
3173 ret = -EOPNOTSUPP; 3198 return -EOPNOTSUPP;
3174 break;
3175 } 3199 }
3176 3200
3177out_sleep:
3178 wl1271_ps_elp_sleep(wl);
3179
3180out_unlock:
3181 mutex_unlock(&wl->mutex);
3182
3183 return ret; 3201 return ret;
3184} 3202}
3185EXPORT_SYMBOL_GPL(wlcore_set_key); 3203EXPORT_SYMBOL_GPL(wlcore_set_key);