mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	wifi: mac80211: add flag to opt out of virtual monitor support
This is useful for multi-radio devices that are capable of monitoring on multiple channels simultanenously. When this flag is set, each monitor interface is passed to the driver individually and can have a configured channel. The vif mac address for non-active monitor interfaces is cleared, in order to allow the driver to tell them apart from active ones. Signed-off-by: Felix Fietkau <nbd@nbd.name> Link: https://patch.msgid.link/3c55505ee0cf0a5f141fbcb30d1e8be8d9f40373.1728462320.git-series.nbd@nbd.name Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
		
							parent
							
								
									9c4f830927
								
							
						
					
					
						commit
						9d40f7e327
					
				
					 9 changed files with 83 additions and 28 deletions
				
			
		| 
						 | 
					@ -2694,6 +2694,11 @@ struct ieee80211_txq {
 | 
				
			||||||
 *	a virtual monitor interface when monitor interfaces are the only
 | 
					 *	a virtual monitor interface when monitor interfaces are the only
 | 
				
			||||||
 *	active interfaces.
 | 
					 *	active interfaces.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @IEEE80211_HW_NO_VIRTUAL_MONITOR: The driver would like to be informed
 | 
				
			||||||
 | 
					 *	of any monitor interface, as well as their configured channel.
 | 
				
			||||||
 | 
					 *	This is useful for supporting multiple monitor interfaces on different
 | 
				
			||||||
 | 
					 *	channels.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * @IEEE80211_HW_NO_AUTO_VIF: The driver would like for no wlanX to
 | 
					 * @IEEE80211_HW_NO_AUTO_VIF: The driver would like for no wlanX to
 | 
				
			||||||
 *	be created.  It is expected user-space will create vifs as
 | 
					 *	be created.  It is expected user-space will create vifs as
 | 
				
			||||||
 *	desired (and thus have them named as desired).
 | 
					 *	desired (and thus have them named as desired).
 | 
				
			||||||
| 
						 | 
					@ -2853,6 +2858,7 @@ enum ieee80211_hw_flags {
 | 
				
			||||||
	IEEE80211_HW_SUPPORTS_DYNAMIC_PS,
 | 
						IEEE80211_HW_SUPPORTS_DYNAMIC_PS,
 | 
				
			||||||
	IEEE80211_HW_MFP_CAPABLE,
 | 
						IEEE80211_HW_MFP_CAPABLE,
 | 
				
			||||||
	IEEE80211_HW_WANT_MONITOR_VIF,
 | 
						IEEE80211_HW_WANT_MONITOR_VIF,
 | 
				
			||||||
 | 
						IEEE80211_HW_NO_VIRTUAL_MONITOR,
 | 
				
			||||||
	IEEE80211_HW_NO_AUTO_VIF,
 | 
						IEEE80211_HW_NO_AUTO_VIF,
 | 
				
			||||||
	IEEE80211_HW_SW_CRYPTO_CONTROL,
 | 
						IEEE80211_HW_SW_CRYPTO_CONTROL,
 | 
				
			||||||
	IEEE80211_HW_SUPPORT_FAST_XMIT,
 | 
						IEEE80211_HW_SUPPORT_FAST_XMIT,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,8 +105,11 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* also validate MU-MIMO change */
 | 
						/* also validate MU-MIMO change */
 | 
				
			||||||
	monitor_sdata = wiphy_dereference(local->hw.wiphy,
 | 
						if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
 | 
				
			||||||
					  local->monitor_sdata);
 | 
							monitor_sdata = sdata;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							monitor_sdata = wiphy_dereference(local->hw.wiphy,
 | 
				
			||||||
 | 
											  local->monitor_sdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!monitor_sdata &&
 | 
						if (!monitor_sdata &&
 | 
				
			||||||
	    (params->vht_mumimo_groups || params->vht_mumimo_follow_addr))
 | 
						    (params->vht_mumimo_groups || params->vht_mumimo_follow_addr))
 | 
				
			||||||
| 
						 | 
					@ -114,7 +117,9 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* apply all changes now - no failures allowed */
 | 
						/* apply all changes now - no failures allowed */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (monitor_sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
 | 
						if (monitor_sdata &&
 | 
				
			||||||
 | 
							(ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) ||
 | 
				
			||||||
 | 
							 ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)))
 | 
				
			||||||
		ieee80211_set_mu_mimo_follow(monitor_sdata, params);
 | 
							ieee80211_set_mu_mimo_follow(monitor_sdata, params);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (params->flags) {
 | 
						if (params->flags) {
 | 
				
			||||||
| 
						 | 
					@ -907,22 +912,25 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lockdep_assert_wiphy(local->hw.wiphy);
 | 
						lockdep_assert_wiphy(local->hw.wiphy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cfg80211_chandef_identical(&local->monitor_chanreq.oper,
 | 
						sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 | 
				
			||||||
				       &chanreq.oper))
 | 
						if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
 | 
				
			||||||
		return 0;
 | 
							if (cfg80211_chandef_identical(&local->monitor_chanreq.oper,
 | 
				
			||||||
 | 
											   &chanreq.oper))
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdata = wiphy_dereference(local->hw.wiphy,
 | 
							sdata = wiphy_dereference(wiphy, local->monitor_sdata);
 | 
				
			||||||
				  local->monitor_sdata);
 | 
							if (!sdata)
 | 
				
			||||||
	if (!sdata)
 | 
								goto done;
 | 
				
			||||||
		goto done;
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cfg80211_chandef_identical(&sdata->vif.bss_conf.chanreq.oper,
 | 
						if (rcu_access_pointer(sdata->deflink.conf->chanctx_conf) &&
 | 
				
			||||||
 | 
							cfg80211_chandef_identical(&sdata->vif.bss_conf.chanreq.oper,
 | 
				
			||||||
				       &chanreq.oper))
 | 
									       &chanreq.oper))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ieee80211_link_release_channel(&sdata->deflink);
 | 
						ieee80211_link_release_channel(&sdata->deflink);
 | 
				
			||||||
	ret = ieee80211_link_use_channel(&sdata->deflink, &chanreq,
 | 
						ret = ieee80211_link_use_channel(&sdata->deflink, &chanreq,
 | 
				
			||||||
					 IEEE80211_CHANCTX_EXCLUSIVE);
 | 
										 IEEE80211_CHANCTX_SHARED);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
done:
 | 
					done:
 | 
				
			||||||
| 
						 | 
					@ -3084,7 +3092,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
 | 
				
			||||||
	if (wdev) {
 | 
						if (wdev) {
 | 
				
			||||||
		sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 | 
							sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
 | 
							if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
 | 
				
			||||||
 | 
							    !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
 | 
				
			||||||
			if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
 | 
								if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
 | 
				
			||||||
				return -EOPNOTSUPP;
 | 
									return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3118,7 +3127,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
 | 
				
			||||||
	local->user_power_level = user_power_level;
 | 
						local->user_power_level = user_power_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry(sdata, &local->interfaces, list) {
 | 
						list_for_each_entry(sdata, &local->interfaces, list) {
 | 
				
			||||||
		if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
 | 
							if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
 | 
				
			||||||
 | 
							    !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
 | 
				
			||||||
			has_monitor = true;
 | 
								has_monitor = true;
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -3139,7 +3149,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	list_for_each_entry(sdata, &local->interfaces, list) {
 | 
						list_for_each_entry(sdata, &local->interfaces, list) {
 | 
				
			||||||
		if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
 | 
							if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
 | 
				
			||||||
 | 
							    !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (int link_id = 0;
 | 
							for (int link_id = 0;
 | 
				
			||||||
| 
						 | 
					@ -4342,7 +4353,8 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
 | 
				
			||||||
	if (chanctx_conf) {
 | 
						if (chanctx_conf) {
 | 
				
			||||||
		*chandef = link->conf->chanreq.oper;
 | 
							*chandef = link->conf->chanreq.oper;
 | 
				
			||||||
		ret = 0;
 | 
							ret = 0;
 | 
				
			||||||
	} else if (local->open_count > 0 &&
 | 
						} else if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) &&
 | 
				
			||||||
 | 
							   local->open_count > 0 &&
 | 
				
			||||||
		   local->open_count == local->monitors &&
 | 
							   local->open_count == local->monitors &&
 | 
				
			||||||
		   sdata->vif.type == NL80211_IFTYPE_MONITOR) {
 | 
							   sdata->vif.type == NL80211_IFTYPE_MONITOR) {
 | 
				
			||||||
		*chandef = local->monitor_chanreq.oper;
 | 
							*chandef = local->monitor_chanreq.oper;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -347,6 +347,10 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
 | 
				
			||||||
		case NL80211_IFTYPE_P2P_DEVICE:
 | 
							case NL80211_IFTYPE_P2P_DEVICE:
 | 
				
			||||||
		case NL80211_IFTYPE_NAN:
 | 
							case NL80211_IFTYPE_NAN:
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
							case NL80211_IFTYPE_MONITOR:
 | 
				
			||||||
 | 
								WARN_ON_ONCE(!ieee80211_hw_check(&local->hw,
 | 
				
			||||||
 | 
												 NO_VIRTUAL_MONITOR));
 | 
				
			||||||
 | 
								fallthrough;
 | 
				
			||||||
		case NL80211_IFTYPE_ADHOC:
 | 
							case NL80211_IFTYPE_ADHOC:
 | 
				
			||||||
		case NL80211_IFTYPE_MESH_POINT:
 | 
							case NL80211_IFTYPE_MESH_POINT:
 | 
				
			||||||
		case NL80211_IFTYPE_OCB:
 | 
							case NL80211_IFTYPE_OCB:
 | 
				
			||||||
| 
						 | 
					@ -355,7 +359,6 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
 | 
				
			||||||
		case NL80211_IFTYPE_WDS:
 | 
							case NL80211_IFTYPE_WDS:
 | 
				
			||||||
		case NL80211_IFTYPE_UNSPECIFIED:
 | 
							case NL80211_IFTYPE_UNSPECIFIED:
 | 
				
			||||||
		case NUM_NL80211_IFTYPES:
 | 
							case NUM_NL80211_IFTYPES:
 | 
				
			||||||
		case NL80211_IFTYPE_MONITOR:
 | 
					 | 
				
			||||||
		case NL80211_IFTYPE_P2P_CLIENT:
 | 
							case NL80211_IFTYPE_P2P_CLIENT:
 | 
				
			||||||
		case NL80211_IFTYPE_P2P_GO:
 | 
							case NL80211_IFTYPE_P2P_GO:
 | 
				
			||||||
			WARN_ON_ONCE(1);
 | 
								WARN_ON_ONCE(1);
 | 
				
			||||||
| 
						 | 
					@ -964,6 +967,10 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
 | 
				
			||||||
			if (!link->sdata->u.mgd.associated)
 | 
								if (!link->sdata->u.mgd.associated)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case NL80211_IFTYPE_MONITOR:
 | 
				
			||||||
 | 
								if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case NL80211_IFTYPE_AP:
 | 
							case NL80211_IFTYPE_AP:
 | 
				
			||||||
		case NL80211_IFTYPE_ADHOC:
 | 
							case NL80211_IFTYPE_ADHOC:
 | 
				
			||||||
		case NL80211_IFTYPE_MESH_POINT:
 | 
							case NL80211_IFTYPE_MESH_POINT:
 | 
				
			||||||
| 
						 | 
					@ -976,6 +983,11 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
 | 
				
			||||||
		if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf)
 | 
							if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (link->sdata->vif.type == NL80211_IFTYPE_MONITOR) {
 | 
				
			||||||
 | 
								rx_chains_dynamic = rx_chains_static = local->rx_chains;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch (link->smps_mode) {
 | 
							switch (link->smps_mode) {
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			WARN_ONCE(1, "Invalid SMPS mode %d\n",
 | 
								WARN_ONCE(1, "Invalid SMPS mode %d\n",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -456,6 +456,7 @@ static const char *hw_flag_names[] = {
 | 
				
			||||||
	FLAG(SUPPORTS_DYNAMIC_PS),
 | 
						FLAG(SUPPORTS_DYNAMIC_PS),
 | 
				
			||||||
	FLAG(MFP_CAPABLE),
 | 
						FLAG(MFP_CAPABLE),
 | 
				
			||||||
	FLAG(WANT_MONITOR_VIF),
 | 
						FLAG(WANT_MONITOR_VIF),
 | 
				
			||||||
 | 
						FLAG(NO_VIRTUAL_MONITOR),
 | 
				
			||||||
	FLAG(NO_AUTO_VIF),
 | 
						FLAG(NO_AUTO_VIF),
 | 
				
			||||||
	FLAG(SW_CRYPTO_CONTROL),
 | 
						FLAG(SW_CRYPTO_CONTROL),
 | 
				
			||||||
	FLAG(SUPPORT_FAST_XMIT),
 | 
						FLAG(SUPPORT_FAST_XMIT),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,6 +65,7 @@ int drv_add_interface(struct ieee80211_local *local,
 | 
				
			||||||
	if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
 | 
						if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
 | 
				
			||||||
		    (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
 | 
							    (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
 | 
				
			||||||
		     !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) &&
 | 
							     !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) &&
 | 
				
			||||||
 | 
							     !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) &&
 | 
				
			||||||
		     !(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))))
 | 
							     !(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))))
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -279,8 +279,13 @@ static int _ieee80211_change_mac(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
	ret = eth_mac_addr(sdata->dev, sa);
 | 
						ret = eth_mac_addr(sdata->dev, sa);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ret == 0) {
 | 
						if (ret == 0) {
 | 
				
			||||||
		memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
 | 
							if (check_dup) {
 | 
				
			||||||
		ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
 | 
								memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
 | 
				
			||||||
 | 
								ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								memset(sdata->vif.addr, 0, ETH_ALEN);
 | 
				
			||||||
 | 
								memset(sdata->vif.bss_conf.addr, 0, ETH_ALEN);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Regardless of eth_mac_addr() return we still want to add the
 | 
						/* Regardless of eth_mac_addr() return we still want to add the
 | 
				
			||||||
| 
						 | 
					@ -699,9 +704,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
 | 
				
			||||||
		ieee80211_recalc_idle(local);
 | 
							ieee80211_recalc_idle(local);
 | 
				
			||||||
		ieee80211_recalc_offload(local);
 | 
							ieee80211_recalc_offload(local);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
 | 
							if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
 | 
				
			||||||
 | 
							    !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ieee80211_link_release_channel(&sdata->deflink);
 | 
				
			||||||
		fallthrough;
 | 
							fallthrough;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		if (!going_down)
 | 
							if (!going_down)
 | 
				
			||||||
| 
						 | 
					@ -1131,7 +1138,8 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 | 
				
			||||||
	ASSERT_RTNL();
 | 
						ASSERT_RTNL();
 | 
				
			||||||
	lockdep_assert_wiphy(local->hw.wiphy);
 | 
						lockdep_assert_wiphy(local->hw.wiphy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (local->monitor_sdata)
 | 
						if (local->monitor_sdata ||
 | 
				
			||||||
 | 
						    ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
 | 
						sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
 | 
				
			||||||
| 
						 | 
					@ -1193,6 +1201,9 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ieee80211_sub_if_data *sdata;
 | 
						struct ieee80211_sub_if_data *sdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ASSERT_RTNL();
 | 
						ASSERT_RTNL();
 | 
				
			||||||
	lockdep_assert_wiphy(local->hw.wiphy);
 | 
						lockdep_assert_wiphy(local->hw.wiphy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1328,7 +1339,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
 | 
							if ((sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) ||
 | 
				
			||||||
 | 
							    ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
 | 
				
			||||||
			res = drv_add_interface(local, sdata);
 | 
								res = drv_add_interface(local, sdata);
 | 
				
			||||||
			if (res)
 | 
								if (res)
 | 
				
			||||||
				goto err_stop;
 | 
									goto err_stop;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -840,6 +840,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
 | 
				
			||||||
		bool last_monitor = list_is_last(&sdata->u.mntr.list,
 | 
							bool last_monitor = list_is_last(&sdata->u.mntr.list,
 | 
				
			||||||
						 &local->mon_list);
 | 
											 &local->mon_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
 | 
				
			||||||
 | 
								ieee80211_handle_mu_mimo_mon(sdata, origskb, rtap_space);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!monskb)
 | 
							if (!monskb)
 | 
				
			||||||
			monskb = ieee80211_make_monitor_skb(local, &origskb,
 | 
								monskb = ieee80211_make_monitor_skb(local, &origskb,
 | 
				
			||||||
							    rate, rtap_space,
 | 
												    rate, rtap_space,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1763,7 +1763,8 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (sdata->vif.type) {
 | 
						switch (sdata->vif.type) {
 | 
				
			||||||
	case NL80211_IFTYPE_MONITOR:
 | 
						case NL80211_IFTYPE_MONITOR:
 | 
				
			||||||
		if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
 | 
							if ((sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) ||
 | 
				
			||||||
 | 
							    ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
 | 
				
			||||||
			vif = &sdata->vif;
 | 
								vif = &sdata->vif;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -3952,7 +3953,8 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (tx.sdata->vif.type) {
 | 
						switch (tx.sdata->vif.type) {
 | 
				
			||||||
	case NL80211_IFTYPE_MONITOR:
 | 
						case NL80211_IFTYPE_MONITOR:
 | 
				
			||||||
		if (tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
 | 
							if ((tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) ||
 | 
				
			||||||
 | 
							    ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
 | 
				
			||||||
			vif = &tx.sdata->vif;
 | 
								vif = &tx.sdata->vif;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -756,7 +756,8 @@ static void __iterate_interfaces(struct ieee80211_local *local,
 | 
				
			||||||
				lockdep_is_held(&local->hw.wiphy->mtx)) {
 | 
									lockdep_is_held(&local->hw.wiphy->mtx)) {
 | 
				
			||||||
		switch (sdata->vif.type) {
 | 
							switch (sdata->vif.type) {
 | 
				
			||||||
		case NL80211_IFTYPE_MONITOR:
 | 
							case NL80211_IFTYPE_MONITOR:
 | 
				
			||||||
			if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
 | 
								if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
 | 
				
			||||||
 | 
								    !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case NL80211_IFTYPE_AP_VLAN:
 | 
							case NL80211_IFTYPE_AP_VLAN:
 | 
				
			||||||
| 
						 | 
					@ -1873,8 +1874,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry(sdata, &local->interfaces, list) {
 | 
						list_for_each_entry(sdata, &local->interfaces, list) {
 | 
				
			||||||
 | 
							if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
 | 
				
			||||||
 | 
							    !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
		if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 | 
							if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 | 
				
			||||||
		    sdata->vif.type != NL80211_IFTYPE_MONITOR &&
 | 
					 | 
				
			||||||
		    ieee80211_sdata_running(sdata)) {
 | 
							    ieee80211_sdata_running(sdata)) {
 | 
				
			||||||
			res = drv_add_interface(local, sdata);
 | 
								res = drv_add_interface(local, sdata);
 | 
				
			||||||
			if (WARN_ON(res))
 | 
								if (WARN_ON(res))
 | 
				
			||||||
| 
						 | 
					@ -1887,11 +1890,14 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (res) {
 | 
						if (res) {
 | 
				
			||||||
		list_for_each_entry_continue_reverse(sdata, &local->interfaces,
 | 
							list_for_each_entry_continue_reverse(sdata, &local->interfaces,
 | 
				
			||||||
						     list)
 | 
											     list) {
 | 
				
			||||||
 | 
								if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
 | 
				
			||||||
 | 
								    !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
			if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 | 
								if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 | 
				
			||||||
			    sdata->vif.type != NL80211_IFTYPE_MONITOR &&
 | 
					 | 
				
			||||||
			    ieee80211_sdata_running(sdata))
 | 
								    ieee80211_sdata_running(sdata))
 | 
				
			||||||
				drv_remove_interface(local, sdata);
 | 
									drv_remove_interface(local, sdata);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		ieee80211_handle_reconfig_failure(local);
 | 
							ieee80211_handle_reconfig_failure(local);
 | 
				
			||||||
		return res;
 | 
							return res;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue