diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/sta.c')
| -rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/sta.c | 40 | 
1 files changed, 32 insertions, 8 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 69603c3b2b3..a1eb692d7fa 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -81,8 +81,9 @@ static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm)  	return IWL_MVM_STATION_COUNT;  } -/* add a NEW station to fw */ -int iwl_mvm_sta_add_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta) +/* send station add/update command to firmware */ +int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, +			   bool update)  {  	struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;  	struct iwl_mvm_add_sta_cmd add_sta_cmd; @@ -94,8 +95,11 @@ int iwl_mvm_sta_add_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta)  	add_sta_cmd.sta_id = mvm_sta->sta_id;  	add_sta_cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color); -	add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk); -	memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN); +	if (!update) { +		add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk); +		memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN); +	} +	add_sta_cmd.add_modify = update ? 1 : 0;  	/* STA_FLG_FAT_EN_MSK ? */  	/* STA_FLG_MIMO_EN_MSK ? */ @@ -181,7 +185,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,  	/* for HW restart - need to reset the seq_number etc... */  	memset(mvm_sta->tid_data, 0, sizeof(mvm_sta->tid_data)); -	ret = iwl_mvm_sta_add_to_fw(mvm, sta); +	ret = iwl_mvm_sta_send_to_fw(mvm, sta, false);  	if (ret)  		return ret; @@ -195,6 +199,13 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,  	return 0;  } +int iwl_mvm_update_sta(struct iwl_mvm *mvm, +		       struct ieee80211_vif *vif, +		       struct ieee80211_sta *sta) +{ +	return iwl_mvm_sta_send_to_fw(mvm, sta, true); +} +  int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,  		      bool drain)  { @@ -1116,7 +1127,8 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,  	if (WARN_ON_ONCE(mvm_sta->vif != vif))  		return -EINVAL; -	key_flags = cpu_to_le16(keyconf->keyidx & STA_KEY_FLG_KEYID_MSK); +	key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & +				 STA_KEY_FLG_KEYID_MSK);  	key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);  	key_flags |= cpu_to_le16(STA_KEY_NOT_VALID); @@ -1154,14 +1166,26 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,  			     struct ieee80211_sta *sta, u32 iv32,  			     u16 *phase1key)  { -	struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; +	struct iwl_mvm_sta *mvm_sta;  	u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta); -	if (sta_id == IWL_INVALID_STATION) +	if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION))  		return; +	rcu_read_lock(); + +	if (!sta) { +		sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); +		if (WARN_ON(IS_ERR_OR_NULL(sta))) { +			rcu_read_unlock(); +			return; +		} +	} + +	mvm_sta = (void *)sta->drv_priv;  	iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,  			     iv32, phase1key, CMD_ASYNC); +	rcu_read_unlock();  }  void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, int sta_id)  |