diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c')
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 69 | 
1 files changed, 66 insertions, 3 deletions
| diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 15f2d826bb4b..a9ac872226fd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1077,6 +1077,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)  	mvm->vif_count = 0;  	mvm->rx_ba_sessions = 0;  	mvm->fwrt.dump.conf = FW_DBG_INVALID; +	mvm->monitor_on = false;  	/* keep statistics ticking */  	iwl_mvm_accu_radio_stats(mvm); @@ -1437,6 +1438,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,  		mvm->p2p_device_vif = vif;  	} +	if (vif->type == NL80211_IFTYPE_MONITOR) +		mvm->monitor_on = true; +  	iwl_mvm_vif_dbgfs_register(mvm, vif);  	goto out_unlock; @@ -1526,6 +1530,9 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,  	iwl_mvm_power_update_mac(mvm);  	iwl_mvm_mac_ctxt_remove(mvm, vif); +	if (vif->type == NL80211_IFTYPE_MONITOR) +		mvm->monitor_on = false; +  out_release:  	mutex_unlock(&mvm->mutex);  } @@ -1546,6 +1553,11 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac,  	struct iwl_mvm_mc_iter_data *data = _data;  	struct iwl_mvm *mvm = data->mvm;  	struct iwl_mcast_filter_cmd *cmd = mvm->mcast_filter_cmd; +	struct iwl_host_cmd hcmd = { +		.id = MCAST_FILTER_CMD, +		.flags = CMD_ASYNC, +		.dataflags[0] = IWL_HCMD_DFL_NOCOPY, +	};  	int ret, len;  	/* if we don't have free ports, mcast frames will be dropped */ @@ -1560,7 +1572,10 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac,  	memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN);  	len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4); -	ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd); +	hcmd.len[0] = len; +	hcmd.data[0] = cmd; + +	ret = iwl_mvm_send_cmd(mvm, &hcmd);  	if (ret)  		IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret);  } @@ -1635,6 +1650,12 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw,  	if (!cmd)  		goto out; +	if (changed_flags & FIF_ALLMULTI) +		cmd->pass_all = !!(*total_flags & FIF_ALLMULTI); + +	if (cmd->pass_all) +		cmd->count = 0; +  	iwl_mvm_recalc_multicast(mvm);  out:  	mutex_unlock(&mvm->mutex); @@ -2563,7 +2584,7 @@ static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm,  			 * queues, so we should never get a second deferred  			 * frame for the RA/TID.  			 */ -			iwl_mvm_start_mac_queues(mvm, info->hw_queue); +			iwl_mvm_start_mac_queues(mvm, BIT(info->hw_queue));  			ieee80211_free_txskb(mvm->hw, skb);  		}  	} @@ -3975,6 +3996,43 @@ out_unlock:  	return ret;  } +static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop) +{ +	if (drop) { +		if (iwl_mvm_has_new_tx_api(mvm)) +			/* TODO new tx api */ +			WARN_ONCE(1, +				  "Need to implement flush TX queue\n"); +		else +			iwl_mvm_flush_tx_path(mvm, +				iwl_mvm_flushable_queues(mvm) & queues, +				0); +	} else { +		if (iwl_mvm_has_new_tx_api(mvm)) { +			struct ieee80211_sta *sta; +			int i; + +			mutex_lock(&mvm->mutex); + +			for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) { +				sta = rcu_dereference_protected( +						mvm->fw_id_to_mac_id[i], +						lockdep_is_held(&mvm->mutex)); +				if (IS_ERR_OR_NULL(sta)) +					continue; + +				iwl_mvm_wait_sta_queues_empty(mvm, +						iwl_mvm_sta_from_mac80211(sta)); +			} + +			mutex_unlock(&mvm->mutex); +		} else { +			iwl_trans_wait_tx_queues_empty(mvm->trans, +						       queues); +		} +	} +} +  static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,  			      struct ieee80211_vif *vif, u32 queues, bool drop)  { @@ -3985,7 +4043,12 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,  	int i;  	u32 msk = 0; -	if (!vif || vif->type != NL80211_IFTYPE_STATION) +	if (!vif) { +		iwl_mvm_flush_no_vif(mvm, queues, drop); +		return; +	} + +	if (vif->type != NL80211_IFTYPE_STATION)  		return;  	/* Make sure we're done with the deferred traffic before flushing */ |