diff options
Diffstat (limited to 'net/mac80211/key.c')
| -rw-r--r-- | net/mac80211/key.c | 51 | 
1 files changed, 37 insertions, 14 deletions
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index af3c56482c8..31afd712930 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -101,6 +101,11 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)  	if (!ret) {  		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; + +		if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || +		      (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))) +			key->local->crypto_tx_tailroom_needed_cnt--; +  		return 0;  	} @@ -156,6 +161,10 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)  			  key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);  	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; + +	if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || +	      (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))) +		key->local->crypto_tx_tailroom_needed_cnt++;  }  void ieee80211_key_removed(struct ieee80211_key_conf *key_conf) @@ -186,7 +195,7 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,  	assert_key_lock(sdata->local);  	if (idx >= 0 && idx < NUM_DEFAULT_KEYS) -		key = sdata->keys[idx]; +		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);  	if (uni)  		rcu_assign_pointer(sdata->default_unicast_key, key); @@ -213,7 +222,7 @@ __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)  	if (idx >= NUM_DEFAULT_KEYS &&  	    idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) -		key = sdata->keys[idx]; +		key = key_mtx_dereference(sdata->local, sdata->keys[idx]);  	rcu_assign_pointer(sdata->default_mgmt_key, key); @@ -257,9 +266,15 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,  		else  			idx = new->conf.keyidx; -		defunikey = old && sdata->default_unicast_key == old; -		defmultikey = old && sdata->default_multicast_key == old; -		defmgmtkey = old && sdata->default_mgmt_key == old; +		defunikey = old && +			old == key_mtx_dereference(sdata->local, +						sdata->default_unicast_key); +		defmultikey = old && +			old == key_mtx_dereference(sdata->local, +						sdata->default_multicast_key); +		defmgmtkey = old && +			old == key_mtx_dereference(sdata->local, +						sdata->default_mgmt_key);  		if (defunikey && !new)  			__ieee80211_set_default_key(sdata, -1, true, false); @@ -388,8 +403,10 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)  		ieee80211_aes_key_free(key->u.ccmp.tfm);  	if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)  		ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); -	if (key->local) +	if (key->local) {  		ieee80211_debugfs_key_remove(key); +		key->local->crypto_tx_tailroom_needed_cnt--; +	}  	kfree(key);  } @@ -440,17 +457,19 @@ int ieee80211_key_link(struct ieee80211_key *key,  	mutex_lock(&sdata->local->key_mtx);  	if (sta && pairwise) -		old_key = sta->ptk; +		old_key = key_mtx_dereference(sdata->local, sta->ptk);  	else if (sta) -		old_key = sta->gtk[idx]; +		old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);  	else -		old_key = sdata->keys[idx]; +		old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);  	__ieee80211_key_replace(sdata, sta, pairwise, old_key, key);  	__ieee80211_key_destroy(old_key);  	ieee80211_debugfs_key_add(key); +	key->local->crypto_tx_tailroom_needed_cnt++; +  	ret = ieee80211_key_enable_hw_accel(key);  	mutex_unlock(&sdata->local->key_mtx); @@ -458,8 +477,11 @@ int ieee80211_key_link(struct ieee80211_key *key,  	return ret;  } -static void __ieee80211_key_free(struct ieee80211_key *key) +void __ieee80211_key_free(struct ieee80211_key *key)  { +	if (!key) +		return; +  	/*  	 * Replace key with nothingness if it was ever used.  	 */ @@ -473,9 +495,6 @@ static void __ieee80211_key_free(struct ieee80211_key *key)  void ieee80211_key_free(struct ieee80211_local *local,  			struct ieee80211_key *key)  { -	if (!key) -		return; -  	mutex_lock(&local->key_mtx);  	__ieee80211_key_free(key);  	mutex_unlock(&local->key_mtx); @@ -492,8 +511,12 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)  	mutex_lock(&sdata->local->key_mtx); -	list_for_each_entry(key, &sdata->key_list, list) +	sdata->local->crypto_tx_tailroom_needed_cnt = 0; + +	list_for_each_entry(key, &sdata->key_list, list) { +		sdata->local->crypto_tx_tailroom_needed_cnt++;  		ieee80211_key_enable_hw_accel(key); +	}  	mutex_unlock(&sdata->local->key_mtx);  }  |