diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/link.c')
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/link.c | 59 | 
1 files changed, 45 insertions, 14 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c index f13f13e6b71a..9f69e04594e4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c @@ -46,6 +46,27 @@ static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm,  	return ret;  } +int iwl_mvm_set_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif, +			     struct ieee80211_bss_conf *link_conf) +{ +	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); +	struct iwl_mvm_vif_link_info *link_info = +		mvmvif->link[link_conf->link_id]; + +	if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) { +		link_info->fw_link_id = iwl_mvm_get_free_fw_link_id(mvm, +								    mvmvif); +		if (link_info->fw_link_id >= +		    ARRAY_SIZE(mvm->link_id_to_link_conf)) +			return -EINVAL; + +		rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id], +				   link_conf); +	} + +	return 0; +} +  int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  		     struct ieee80211_bss_conf *link_conf)  { @@ -55,19 +76,14 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  	struct iwl_link_config_cmd cmd = {};  	unsigned int cmd_id = WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD);  	u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1); +	int ret;  	if (WARN_ON_ONCE(!link_info))  		return -EINVAL; -	if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) { -		link_info->fw_link_id = iwl_mvm_get_free_fw_link_id(mvm, -								    mvmvif); -		if (link_info->fw_link_id >= ARRAY_SIZE(mvm->link_id_to_link_conf)) -			return -EINVAL; - -		rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id], -				   link_conf); -	} +	ret = iwl_mvm_set_link_mapping(mvm, vif, link_conf); +	if (ret) +		return ret;  	/* Update SF - Disable if needed. if this fails, SF might still be on  	 * while many macs are bound, which is forbidden - so fail the binding. @@ -248,6 +264,24 @@ send_cmd:  	return ret;  } +int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif, +			       struct ieee80211_bss_conf *link_conf) +{ +	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); +	struct iwl_mvm_vif_link_info *link_info = +		mvmvif->link[link_conf->link_id]; + +	/* mac80211 thought we have the link, but it was never configured */ +	if (WARN_ON(!link_info || +		    link_info->fw_link_id >= +		    ARRAY_SIZE(mvm->link_id_to_link_conf))) +		return -EINVAL; + +	RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id], +			 NULL); +	return 0; +} +  int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  			struct ieee80211_bss_conf *link_conf)  { @@ -257,13 +291,10 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  	struct iwl_link_config_cmd cmd = {};  	int ret; -	/* mac80211 thought we have the link, but it was never configured */ -	if (WARN_ON(!link_info || -		    link_info->fw_link_id >= ARRAY_SIZE(mvm->link_id_to_link_conf))) +	ret = iwl_mvm_unset_link_mapping(mvm, vif, link_conf); +	if (ret)  		return 0; -	RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id], -			 NULL);  	cmd.link_id = cpu_to_le32(link_info->fw_link_id);  	iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id);  	link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;  |