diff options
Diffstat (limited to 'drivers/net/wireless/mac80211_hwsim.c')
| -rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 125 | 
1 files changed, 96 insertions, 29 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index cffdf4fbf16..b878a32e7a9 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -25,6 +25,7 @@  #include <linux/if_arp.h>  #include <linux/rtnetlink.h>  #include <linux/etherdevice.h> +#include <linux/platform_device.h>  #include <linux/debugfs.h>  #include <linux/module.h>  #include <linux/ktime.h> @@ -52,6 +53,10 @@ static bool paged_rx = false;  module_param(paged_rx, bool, 0644);  MODULE_PARM_DESC(paged_rx, "Use paged SKBs for RX instead of linear ones"); +static bool rctbl = false; +module_param(rctbl, bool, 0444); +MODULE_PARM_DESC(rctbl, "Handle rate control table"); +  /**   * enum hwsim_regtest - the type of regulatory tests we offer   * @@ -717,9 +722,17 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,  	rx_status.flag |= RX_FLAG_MACTIME_START;  	rx_status.freq = chan->center_freq;  	rx_status.band = chan->band; -	rx_status.rate_idx = info->control.rates[0].idx; -	if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) -		rx_status.flag |= RX_FLAG_HT; +	if (info->control.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) { +		rx_status.rate_idx = +			ieee80211_rate_get_vht_mcs(&info->control.rates[0]); +		rx_status.vht_nss = +			ieee80211_rate_get_vht_nss(&info->control.rates[0]); +		rx_status.flag |= RX_FLAG_VHT; +	} else { +		rx_status.rate_idx = info->control.rates[0].idx; +		if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) +			rx_status.flag |= RX_FLAG_HT; +	}  	if (info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)  		rx_status.flag |= RX_FLAG_40MHZ;  	if (info->control.rates[0].flags & IEEE80211_TX_RC_SHORT_GI) @@ -886,8 +899,12 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,  	if (control->sta)  		hwsim_check_sta_magic(control->sta); -	txi->rate_driver_data[0] = channel; +	if (rctbl) +		ieee80211_get_tx_rates(txi->control.vif, control->sta, skb, +				       txi->control.rates, +				       ARRAY_SIZE(txi->control.rates)); +	txi->rate_driver_data[0] = channel;  	mac80211_hwsim_monitor_rx(hw, skb, channel);  	/* wmediumd mode check */ @@ -964,6 +981,12 @@ static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw,  		    newtype, vif->addr);  	hwsim_check_magic(vif); +	/* +	 * interface may change from non-AP to AP in +	 * which case this needs to be set up again +	 */ +	vif->cab_queue = 0; +  	return 0;  } @@ -983,6 +1006,13 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,  {  	u32 _pid = ACCESS_ONCE(wmediumd_portid); +	if (rctbl) { +		struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb); +		ieee80211_get_tx_rates(txi->control.vif, NULL, skb, +				       txi->control.rates, +				       ARRAY_SIZE(txi->control.rates)); +	} +  	mac80211_hwsim_monitor_rx(hw, skb, chan);  	if (_pid) @@ -1013,6 +1043,11 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,  	if (skb == NULL)  		return;  	info = IEEE80211_SKB_CB(skb); +	if (rctbl) +		ieee80211_get_tx_rates(vif, NULL, skb, +				       info->control.rates, +				       ARRAY_SIZE(info->control.rates)); +  	txrate = ieee80211_get_tx_rate(hw, info);  	mgmt = (struct ieee80211_mgmt *) skb->data; @@ -1056,11 +1091,13 @@ out:  	return HRTIMER_NORESTART;  } -static const char *hwsim_chantypes[] = { -	[NL80211_CHAN_NO_HT] = "noht", -	[NL80211_CHAN_HT20] = "ht20", -	[NL80211_CHAN_HT40MINUS] = "ht40-", -	[NL80211_CHAN_HT40PLUS] = "ht40+", +static const char * const hwsim_chanwidths[] = { +	[NL80211_CHAN_WIDTH_20_NOHT] = "noht", +	[NL80211_CHAN_WIDTH_20] = "ht20", +	[NL80211_CHAN_WIDTH_40] = "ht40", +	[NL80211_CHAN_WIDTH_80] = "vht80", +	[NL80211_CHAN_WIDTH_80P80] = "vht80p80", +	[NL80211_CHAN_WIDTH_160] = "vht160",  };  static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) @@ -1074,18 +1111,28 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)  		[IEEE80211_SMPS_DYNAMIC] = "dynamic",  	}; -	wiphy_debug(hw->wiphy, -		    "%s (freq=%d/%s idle=%d ps=%d smps=%s)\n", -		    __func__, -		    conf->channel ? conf->channel->center_freq : 0, -		    hwsim_chantypes[conf->channel_type], -		    !!(conf->flags & IEEE80211_CONF_IDLE), -		    !!(conf->flags & IEEE80211_CONF_PS), -		    smps_modes[conf->smps_mode]); +	if (conf->chandef.chan) +		wiphy_debug(hw->wiphy, +			    "%s (freq=%d(%d - %d)/%s idle=%d ps=%d smps=%s)\n", +			    __func__, +			    conf->chandef.chan->center_freq, +			    conf->chandef.center_freq1, +			    conf->chandef.center_freq2, +			    hwsim_chanwidths[conf->chandef.width], +			    !!(conf->flags & IEEE80211_CONF_IDLE), +			    !!(conf->flags & IEEE80211_CONF_PS), +			    smps_modes[conf->smps_mode]); +	else +		wiphy_debug(hw->wiphy, +			    "%s (freq=0 idle=%d ps=%d smps=%s)\n", +			    __func__, +			    !!(conf->flags & IEEE80211_CONF_IDLE), +			    !!(conf->flags & IEEE80211_CONF_PS), +			    smps_modes[conf->smps_mode]);  	data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); -	data->channel = conf->channel; +	data->channel = conf->chandef.chan;  	WARN_ON(data->channel && channels > 1); @@ -1271,7 +1318,7 @@ static int mac80211_hwsim_get_survey(  		return -ENOENT;  	/* Current channel */ -	survey->channel = conf->channel; +	survey->channel = conf->chandef.chan;  	/*  	 * Magically conjured noise level --- this is only ok for simulated hardware. @@ -1389,7 +1436,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,  	return 0;  } -static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop) +static void mac80211_hwsim_flush(struct ieee80211_hw *hw, u32 queues, bool drop)  {  	/* Not implemented, queues only on kernel side */  } @@ -1535,7 +1582,8 @@ static void hw_roc_done(struct work_struct *work)  static int mac80211_hwsim_roc(struct ieee80211_hw *hw,  			      struct ieee80211_vif *vif,  			      struct ieee80211_channel *chan, -			      int duration) +			      int duration, +			      enum ieee80211_roc_type type)  {  	struct mac80211_hwsim_data *hwsim = hw->priv; @@ -1668,6 +1716,7 @@ static void mac80211_hwsim_free(void)  		debugfs_remove(data->debugfs_ps);  		debugfs_remove(data->debugfs);  		ieee80211_unregister_hw(data->hw); +		device_release_driver(data->dev);  		device_unregister(data->dev);  		ieee80211_free_hw(data->hw);  	} @@ -1676,7 +1725,9 @@ static void mac80211_hwsim_free(void)  static struct device_driver mac80211_hwsim_driver = { -	.name = "mac80211_hwsim" +	.name = "mac80211_hwsim", +	.bus = &platform_bus_type, +	.owner = THIS_MODULE,  };  static const struct net_device_ops hwsim_netdev_ops = { @@ -2168,9 +2219,15 @@ static int __init init_mac80211_hwsim(void)  	spin_lock_init(&hwsim_radio_lock);  	INIT_LIST_HEAD(&hwsim_radios); +	err = driver_register(&mac80211_hwsim_driver); +	if (err) +		return err; +  	hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); -	if (IS_ERR(hwsim_class)) -		return PTR_ERR(hwsim_class); +	if (IS_ERR(hwsim_class)) { +		err = PTR_ERR(hwsim_class); +		goto failed_unregister_driver; +	}  	memset(addr, 0, ETH_ALEN);  	addr[0] = 0x02; @@ -2192,12 +2249,20 @@ static int __init init_mac80211_hwsim(void)  					  "hwsim%d", i);  		if (IS_ERR(data->dev)) {  			printk(KERN_DEBUG -			       "mac80211_hwsim: device_create " -			       "failed (%ld)\n", PTR_ERR(data->dev)); +			       "mac80211_hwsim: device_create failed (%ld)\n", +			       PTR_ERR(data->dev));  			err = -ENOMEM;  			goto failed_drvdata;  		}  		data->dev->driver = &mac80211_hwsim_driver; +		err = device_bind_driver(data->dev); +		if (err != 0) { +			printk(KERN_DEBUG +			       "mac80211_hwsim: device_bind_driver failed (%d)\n", +			       err); +			goto failed_hw; +		} +  		skb_queue_head_init(&data->pending);  		SET_IEEE80211_DEV(hw, data->dev); @@ -2240,6 +2305,8 @@ static int __init init_mac80211_hwsim(void)  			    IEEE80211_HW_AMPDU_AGGREGATION |  			    IEEE80211_HW_WANT_MONITOR_VIF |  			    IEEE80211_HW_QUEUE_CONTROL; +		if (rctbl) +			hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE;  		hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |  				    WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; @@ -2291,9 +2358,6 @@ static int __init init_mac80211_hwsim(void)  			hw->wiphy->bands[band] = sband; -			if (channels == 1) -				continue; -  			sband->vht_cap.vht_supported = true;  			sband->vht_cap.cap =  				IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | @@ -2499,6 +2563,8 @@ failed_drvdata:  	ieee80211_free_hw(hw);  failed:  	mac80211_hwsim_free(); +failed_unregister_driver: +	driver_unregister(&mac80211_hwsim_driver);  	return err;  }  module_init(init_mac80211_hwsim); @@ -2511,5 +2577,6 @@ static void __exit exit_mac80211_hwsim(void)  	mac80211_hwsim_free();  	unregister_netdev(hwsim_mon); +	driver_unregister(&mac80211_hwsim_driver);  }  module_exit(exit_mac80211_hwsim);  |