ath9k: assign a keycache slot per station for unencrypted links to fix powersave frame filtering
SVN-Revision: 26712
This commit is contained in:
		| @@ -0,0 +1,119 @@ | ||||
| --- a/drivers/net/wireless/ath/ath9k/ath9k.h | ||||
| +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | ||||
| @@ -256,6 +256,8 @@ struct ath_node { | ||||
|  #endif | ||||
|  	struct ath_atx_tid tid[WME_NUM_TID]; | ||||
|  	struct ath_atx_ac ac[WME_NUM_AC]; | ||||
| +	int ps_key; | ||||
| + | ||||
|  	u16 maxampdu; | ||||
|  	u8 mpdudensity; | ||||
|   | ||||
| --- a/drivers/net/wireless/ath/ath9k/main.c | ||||
| +++ b/drivers/net/wireless/ath/ath9k/main.c | ||||
| @@ -1775,18 +1775,37 @@ static int ath9k_sta_add(struct ieee8021 | ||||
|  			 struct ieee80211_sta *sta) | ||||
|  { | ||||
|  	struct ath_softc *sc = hw->priv; | ||||
| +	struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||||
| +	struct ath_node *an = (struct ath_node *) sta->drv_priv; | ||||
| +	struct ieee80211_key_conf ps_key = { }; | ||||
|   | ||||
|  	ath_node_attach(sc, sta); | ||||
| +	an->ps_key = ath_key_config(common, vif, sta, &ps_key); | ||||
|   | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| +static void ath9k_del_ps_key(struct ath_softc *sc, | ||||
| +			     struct ieee80211_vif *vif, | ||||
| +			     struct ieee80211_sta *sta) | ||||
| +{ | ||||
| +	struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||||
| +	struct ath_node *an = (struct ath_node *) sta->drv_priv; | ||||
| +	struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key }; | ||||
| + | ||||
| +	if (!an->ps_key) | ||||
| +	    return; | ||||
| + | ||||
| +	ath_key_delete(common, &ps_key); | ||||
| +} | ||||
| + | ||||
|  static int ath9k_sta_remove(struct ieee80211_hw *hw, | ||||
|  			    struct ieee80211_vif *vif, | ||||
|  			    struct ieee80211_sta *sta) | ||||
|  { | ||||
|  	struct ath_softc *sc = hw->priv; | ||||
|   | ||||
| +	ath9k_del_ps_key(sc, vif, sta); | ||||
|  	ath_node_detach(sc, sta); | ||||
|   | ||||
|  	return 0; | ||||
| @@ -1889,6 +1908,9 @@ static int ath9k_set_key(struct ieee8021 | ||||
|   | ||||
|  	switch (cmd) { | ||||
|  	case SET_KEY: | ||||
| +		if (sta) | ||||
| +			ath9k_del_ps_key(sc, vif, sta); | ||||
| + | ||||
|  		ret = ath_key_config(common, vif, sta, key); | ||||
|  		if (ret >= 0) { | ||||
|  			key->hw_key_idx = ret; | ||||
| --- a/drivers/net/wireless/ath/key.c | ||||
| +++ b/drivers/net/wireless/ath/key.c | ||||
| @@ -483,6 +483,9 @@ int ath_key_config(struct ath_common *co | ||||
|  	memset(&hk, 0, sizeof(hk)); | ||||
|   | ||||
|  	switch (key->cipher) { | ||||
| +	case 0: | ||||
| +		hk.kv_type = ATH_CIPHER_CLR; | ||||
| +		break; | ||||
|  	case WLAN_CIPHER_SUITE_WEP40: | ||||
|  	case WLAN_CIPHER_SUITE_WEP104: | ||||
|  		hk.kv_type = ATH_CIPHER_WEP; | ||||
| @@ -498,7 +501,8 @@ int ath_key_config(struct ath_common *co | ||||
|  	} | ||||
|   | ||||
|  	hk.kv_len = key->keylen; | ||||
| -	memcpy(hk.kv_val, key->key, key->keylen); | ||||
| +	if (key->keylen) | ||||
| +		memcpy(hk.kv_val, key->key, key->keylen); | ||||
|   | ||||
|  	if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||||
|  		switch (vif->type) { | ||||
| --- a/drivers/net/wireless/ath/ath9k/xmit.c | ||||
| +++ b/drivers/net/wireless/ath/ath9k/xmit.c | ||||
| @@ -1526,7 +1526,7 @@ static void setup_frame_info(struct ieee | ||||
|  	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; | ||||
|  	struct ieee80211_hdr *hdr; | ||||
|  	struct ath_frame_info *fi = get_frame_info(skb); | ||||
| -	struct ath_node *an; | ||||
| +	struct ath_node *an = NULL; | ||||
|  	struct ath_atx_tid *tid; | ||||
|  	enum ath9k_key_type keytype; | ||||
|  	u16 seqno = 0; | ||||
| @@ -1534,11 +1534,13 @@ static void setup_frame_info(struct ieee | ||||
|   | ||||
|  	keytype = ath9k_cmn_get_hw_crypto_keytype(skb); | ||||
|   | ||||
| +	if (sta) | ||||
| +		an = (struct ath_node *) sta->drv_priv; | ||||
| + | ||||
|  	hdr = (struct ieee80211_hdr *)skb->data; | ||||
| -	if (sta && ieee80211_is_data_qos(hdr->frame_control) && | ||||
| +	if (an && ieee80211_is_data_qos(hdr->frame_control) && | ||||
|  		conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { | ||||
|   | ||||
| -		an = (struct ath_node *) sta->drv_priv; | ||||
|  		tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; | ||||
|   | ||||
|  		/* | ||||
| @@ -1554,6 +1556,8 @@ static void setup_frame_info(struct ieee | ||||
|  	memset(fi, 0, sizeof(*fi)); | ||||
|  	if (hw_key) | ||||
|  		fi->keyix = hw_key->hw_key_idx; | ||||
| +	else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) | ||||
| +		fi->keyix = an->ps_key; | ||||
|  	else | ||||
|  		fi->keyix = ATH9K_TXKEYIX_INVALID; | ||||
|  	fi->keytype = keytype; | ||||
		Reference in New Issue
	
	Block a user
	 Felix Fietkau
					Felix Fietkau