All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/4] mac80211: jump labels for hw flags
@ 2015-11-09 22:02 Johannes Berg
  2015-11-09 22:02 ` [RFC 1/4] mac80211: add ieee80211_hw_clear() Johannes Berg
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Johannes Berg @ 2015-11-09 22:02 UTC (permalink / raw)
  To: linux-wireless; +Cc: Jason Baron, Peter Zijlstra

This was an experiment I thought of yesterday ...

As also explained in the log for patch 3, we have a lot of behaviour
differences in mac80211 based on which driver we're working against.
In many cases (say OpenWRT router, or a phone/tablet, ChromeBook, etc.)
we only have a single driver built into the system though. In that
case we could - theoretically - elide all the code that isn't required
by that driver, but that seems too dangerous.

Instead, use static keys to set a default for each of the flags. If
the flag is selected as _OFF in Kconfig, then any code that needs it
to be on will be placed out of line and the jump NOPed out; if then
a driver registers that actually needs the code the jump will be put
back and the first thing in the out-of-line section will be to check
the real hw flags.

This pretty much results in the same thing as removing the code/if,
but with more safety.

I haven't done any measurements whatsoever, but I think it might be
something to test on a little MIPS router box.


As far as the code is concerned, there are two really ugly things:
 1) I still use struct static_key - couldn't quite figure it out
    with static_key_false. I think I can replace it easily though.
 2) There are a lot of boilerplate ifdefs/macros.

I can't see a way to avoid more of (2), although I think that we
can probably remove it for a lot of flags and just not have this
ability for those that aren't used in RX/TX/status paths. That'd
probably reduce the code quite a bit.

If anyone has an easy setup to test it on a low-power platform that
would be great.

johannes


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC 1/4] mac80211: add ieee80211_hw_clear()
  2015-11-09 22:02 [RFC 0/4] mac80211: jump labels for hw flags Johannes Berg
@ 2015-11-09 22:02 ` Johannes Berg
  2015-11-09 22:02 ` [RFC 2/4] mac80211: introduce ieee80211_local_check() Johannes Berg
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2015-11-09 22:02 UTC (permalink / raw)
  To: linux-wireless; +Cc: Jason Baron, Peter Zijlstra, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

There are a few hardware flags that *are* valid to change, at least
under certain circumstances. Since drivers are doing that, add an
inline to make it easier to do correctly. They still need to take
care of locking themselves.

While at it, remove the pointless return in ieee80211_hw_set().

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/adm8211.c              | 2 +-
 drivers/net/wireless/iwlwifi/dvm/mac80211.c | 2 +-
 drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 2 +-
 include/net/mac80211.h                      | 9 ++++++++-
 4 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 15f057ed41ad..bdfd60f39078 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -1375,7 +1375,7 @@ static void adm8211_configure_filter(struct ieee80211_hw *dev,
 	if (priv->nar & ADM8211_NAR_PR)
 		ieee80211_hw_set(dev, RX_INCLUDES_FCS);
 	else
-		__clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, dev->flags);
+		ieee80211_hw_clear(dev, RX_INCLUDES_FCS);
 
 	if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
 		adm8211_set_bssid(dev, bcast);
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index b3ad34e8bf5a..d4918a5f7bd7 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -1356,7 +1356,7 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
 	if (vif->type == NL80211_IFTYPE_MONITOR)
 		ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS);
 	else
-		__clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, priv->hw->flags);
+		ieee80211_hw_clear(priv->hw, RX_INCLUDES_FCS);
 
 	err = iwl_setup_interface(priv, ctx);
 	if (!err || reset)
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index ad7ad720d2e7..ca944d3f7401 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -1289,7 +1289,7 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 	mvmvif->uploaded = false;
 
 	if (vif->type == NL80211_IFTYPE_MONITOR)
-		__clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mvm->hw->flags);
+		ieee80211_hw_clear(mvm->hw, RX_INCLUDES_FCS);
 
 	return 0;
 }
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 82045fca388b..47274d829115 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2081,10 +2081,17 @@ static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw,
 static inline void _ieee80211_hw_set(struct ieee80211_hw *hw,
 				     enum ieee80211_hw_flags flg)
 {
-	return __set_bit(flg, hw->flags);
+	__set_bit(flg, hw->flags);
 }
 #define ieee80211_hw_set(hw, flg)	_ieee80211_hw_set(hw, IEEE80211_HW_##flg)
 
+static inline void _ieee80211_hw_clear(struct ieee80211_hw *hw,
+				       enum ieee80211_hw_flags flg)
+{
+	__clear_bit(flg, hw->flags);
+}
+#define ieee80211_hw_clear(hw, flg)	_ieee80211_hw_clear(hw, IEEE80211_HW_##flg)
+
 /**
  * struct ieee80211_scan_request - hw scan request
  *
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC 2/4] mac80211: introduce ieee80211_local_check()
  2015-11-09 22:02 [RFC 0/4] mac80211: jump labels for hw flags Johannes Berg
  2015-11-09 22:02 ` [RFC 1/4] mac80211: add ieee80211_hw_clear() Johannes Berg
@ 2015-11-09 22:02 ` Johannes Berg
  2015-11-09 22:02 ` [RFC 3/4] mac80211: use static keys for hw flags Johannes Berg
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2015-11-09 22:02 UTC (permalink / raw)
  To: linux-wireless; +Cc: Jason Baron, Peter Zijlstra, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

This will later allow introducing different behaviour between
driver and hw checks. Make mac80211 use the new check function
almost everywhere - one place cannot (rate control) and two of
them shouldn't get the behaviour I want to introduce (in hw
registration.)

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/agg-rx.c         |  2 +-
 net/mac80211/agg-tx.c         |  4 +--
 net/mac80211/cfg.c            | 12 ++++-----
 net/mac80211/debugfs_netdev.c |  2 +-
 net/mac80211/driver-ops.c     |  2 +-
 net/mac80211/ieee80211_i.h    |  9 +++++++
 net/mac80211/iface.c          | 10 ++++----
 net/mac80211/key.c            |  4 +--
 net/mac80211/main.c           | 10 ++++----
 net/mac80211/mlme.c           | 58 +++++++++++++++++++++----------------------
 net/mac80211/offchannel.c     |  2 +-
 net/mac80211/pm.c             |  4 +--
 net/mac80211/rate.c           |  6 ++---
 net/mac80211/rx.c             | 26 +++++++++----------
 net/mac80211/scan.c           | 10 ++++----
 net/mac80211/sta_info.c       | 14 +++++------
 net/mac80211/status.c         | 12 ++++-----
 net/mac80211/tdls.c           |  4 +--
 net/mac80211/tx.c             | 36 +++++++++++++--------------
 net/mac80211/util.c           |  6 ++---
 20 files changed, 121 insertions(+), 112 deletions(-)

diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 10ad4ac1fa0b..d9bf3701e4f9 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -189,7 +189,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
 	struct ieee80211_local *local = sdata->local;
 	struct sk_buff *skb;
 	struct ieee80211_mgmt *mgmt;
-	bool amsdu = ieee80211_hw_check(&local->hw, SUPPORTS_AMSDU_IN_AMPDU);
+	bool amsdu = ieee80211_local_check(local, SUPPORTS_AMSDU_IN_AMPDU);
 	u16 capab;
 
 	skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index a758eb84e8f0..18b8809521ff 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -565,8 +565,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
 		return -EINVAL;
 
 	if ((tid >= IEEE80211_NUM_TIDS) ||
-	    !ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION) ||
-	    ieee80211_hw_check(&local->hw, TX_AMPDU_SETUP_IN_HW))
+	    !ieee80211_local_check(local, AMPDU_AGGREGATION) ||
+	    ieee80211_local_check(local, TX_AMPDU_SETUP_IN_HW))
 		return -EINVAL;
 
 	ht_dbg(sdata, "Open BA session requested for %pM tid %u\n",
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index c2bd1b6a6922..cf285033741c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1121,7 +1121,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 
 	if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
 	    !sdata->u.mgd.tdls_wider_bw_prohibited &&
-	    ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) &&
+	    ieee80211_local_check(local, TDLS_WIDER_BW) &&
 	    params->ext_capab_len >= 8 &&
 	    params->ext_capab[7] & WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED)
 		set_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW);
@@ -1746,7 +1746,7 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
 		/* our RSSI threshold implementation is supported only for
 		 * devices that report signal in dBm.
 		 */
-		if (!ieee80211_hw_check(&sdata->local->hw, SIGNAL_DBM))
+		if (!ieee80211_local_check(sdata->local, SIGNAL_DBM))
 			return -ENOTSUPP;
 		conf->rssi_threshold = nconf->rssi_threshold;
 	}
@@ -2405,7 +2405,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 	if (sdata->vif.type != NL80211_IFTYPE_STATION)
 		return -EOPNOTSUPP;
 
-	if (!ieee80211_hw_check(&local->hw, SUPPORTS_PS))
+	if (!ieee80211_local_check(local, SUPPORTS_PS))
 		return -EOPNOTSUPP;
 
 	if (enabled == sdata->u.mgd.powersave &&
@@ -2420,7 +2420,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 	__ieee80211_request_smps_mgd(sdata, sdata->u.mgd.req_smps);
 	sdata_unlock(sdata);
 
-	if (ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS))
+	if (ieee80211_local_check(local, SUPPORTS_DYNAMIC_PS))
 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 
 	ieee80211_recalc_ps(local);
@@ -2469,7 +2469,7 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
 	if (!ieee80211_sdata_running(sdata))
 		return -ENETDOWN;
 
-	if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
+	if (ieee80211_local_check(local, HAS_RATE_CONTROL)) {
 		ret = drv_set_bitrate_mask(local, sdata, mask);
 		if (ret)
 			return ret;
@@ -3466,7 +3466,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 
 	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN |
 					IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
-	if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL))
+	if (ieee80211_local_check(local, QUEUE_CONTROL))
 		IEEE80211_SKB_CB(skb)->hw_queue =
 			local->hw.offchannel_tx_hw_queue;
 
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 37ea30e0754c..e18e49b2faec 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -451,7 +451,7 @@ static ssize_t ieee80211_if_fmt_tdls_wider_bw(
 	const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	bool tdls_wider_bw;
 
-	tdls_wider_bw = ieee80211_hw_check(&sdata->local->hw, TDLS_WIDER_BW) &&
+	tdls_wider_bw = ieee80211_local_check(sdata->local, TDLS_WIDER_BW) &&
 			!ifmgd->tdls_wider_bw_prohibited;
 
 	return snprintf(buf, buflen, "%d\n", tdls_wider_bw);
diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index ca1fe5576103..d84029d892a5 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -61,7 +61,7 @@ int drv_add_interface(struct ieee80211_local *local,
 
 	if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
 		    (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
-		     !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) &&
+		     !ieee80211_local_check(local, WANT_MONITOR_VIF) &&
 		     !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))))
 		return -EINVAL;
 
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d832bd59236b..46bd8965d164 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1357,6 +1357,15 @@ struct ieee80211_local {
 	struct sk_buff_head skb_queue_tdls_chsw;
 };
 
+static inline bool _ieee80211_local_check(struct ieee80211_local *local,
+					  enum ieee80211_hw_flags flg)
+{
+	return test_bit(flg, local->hw.flags);
+}
+
+#define ieee80211_local_check(local, flg)	\
+	_ieee80211_local_check(local, IEEE80211_HW_##flg)
+
 static inline struct ieee80211_sub_if_data *
 IEEE80211_DEV_TO_SUB_IF(struct net_device *dev)
 {
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index d0dc1bfaeec2..43c675ec3c14 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -338,7 +338,7 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
 	if ((iftype != NL80211_IFTYPE_AP &&
 	     iftype != NL80211_IFTYPE_P2P_GO &&
 	     iftype != NL80211_IFTYPE_MESH_POINT) ||
-	    !ieee80211_hw_check(&sdata->local->hw, QUEUE_CONTROL)) {
+	    !ieee80211_local_check(sdata->local, QUEUE_CONTROL)) {
 		sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
 		return 0;
 	}
@@ -378,7 +378,7 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
 	int i;
 
 	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
-		if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL))
+		if (ieee80211_local_check(local, QUEUE_CONTROL))
 			sdata->vif.hw_queue[i] = IEEE80211_INVAL_HW_QUEUE;
 		else if (local->hw.queues >= IEEE80211_NUM_ACS)
 			sdata->vif.hw_queue[i] = i;
@@ -393,7 +393,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 	struct ieee80211_sub_if_data *sdata;
 	int ret;
 
-	if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
+	if (!ieee80211_local_check(local, WANT_MONITOR_VIF))
 		return 0;
 
 	ASSERT_RTNL();
@@ -454,7 +454,7 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
 {
 	struct ieee80211_sub_if_data *sdata;
 
-	if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
+	if (!ieee80211_local_check(local, WANT_MONITOR_VIF))
 		return;
 
 	ASSERT_RTNL();
@@ -1586,7 +1586,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
 		break;
 	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_P2P_GO:
-		if (ieee80211_hw_check(&local->hw, P2P_DEV_ADDR_FOR_INTF)) {
+		if (ieee80211_local_check(local, P2P_DEV_ADDR_FOR_INTF)) {
 			list_for_each_entry(sdata, &local->interfaces, list) {
 				if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE)
 					continue;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 44388d6a1d8e..d9f0f0fbc70b 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -154,7 +154,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
 	 * is supported; if not, return.
 	 */
 	if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) &&
-	    !ieee80211_hw_check(&key->local->hw, SUPPORTS_PER_STA_GTK))
+	    !ieee80211_local_check(key->local, SUPPORTS_PER_STA_GTK))
 		goto out_unsupported;
 
 	if (sta && !sta->uploaded)
@@ -208,7 +208,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
 		/* all of these we can do in software - if driver can */
 		if (ret == 1)
 			return 0;
-		if (ieee80211_hw_check(&key->local->hw, SW_CRYPTO_CONTROL))
+		if (ieee80211_local_check(key->local, SW_CRYPTO_CONTROL))
 			return -EINVAL;
 		return 0;
 	default:
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 858f6b1cb149..84d7480fe7c8 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -663,7 +663,7 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
 {
 	bool have_wep = !(IS_ERR(local->wep_tx_tfm) ||
 			  IS_ERR(local->wep_rx_tfm));
-	bool have_mfp = ieee80211_hw_check(&local->hw, MFP_CAPABLE);
+	bool have_mfp = ieee80211_local_check(local, MFP_CAPABLE);
 	int n_suites = 0, r = 0, w = 0;
 	u32 *suites;
 	static const u32 cipher_suites[] = {
@@ -683,7 +683,7 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
 		WLAN_CIPHER_SUITE_BIP_GMAC_256,
 	};
 
-	if (ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL) ||
+	if (ieee80211_local_check(local, SW_CRYPTO_CONTROL) ||
 	    local->hw.wiphy->cipher_suites) {
 		/* If the driver advertises, or doesn't support SW crypto,
 		 * we only need to remove WEP if necessary.
@@ -947,9 +947,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 	/* mac80211 supports control port protocol changing */
 	local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
 
-	if (ieee80211_hw_check(&local->hw, SIGNAL_DBM)) {
+	if (ieee80211_local_check(local, SIGNAL_DBM)) {
 		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
-	} else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC)) {
+	} else if (ieee80211_local_check(local, SIGNAL_UNSPEC)) {
 		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
 		if (hw->max_signal <= 0) {
 			result = -EINVAL;
@@ -1003,7 +1003,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 		local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
 
 	/* mac80211 supports eCSA, if the driver supports STA CSA at all */
-	if (ieee80211_hw_check(&local->hw, CHANCTX_STA_CSA))
+	if (ieee80211_local_check(local, CHANCTX_STA_CSA))
 		local->ext_capa[0] |= WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING;
 
 	local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b140cc6651f4..53b5b524702b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -111,7 +111,7 @@ void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
 	if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
 		return;
 
-	if (ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
+	if (ieee80211_local_check(sdata->local, CONNECTION_MONITOR))
 		return;
 
 	mod_timer(&sdata->u.mgd.bcn_mon_timer,
@@ -127,7 +127,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata)
 
 	ifmgd->probe_send_count = 0;
 
-	if (ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
+	if (ieee80211_local_check(sdata->local, CONNECTION_MONITOR))
 		return;
 
 	mod_timer(&sdata->u.mgd.conn_mon_timer,
@@ -702,7 +702,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 		capab |= WLAN_CAPABILITY_PRIVACY;
 
 	if ((assoc_data->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
-	    ieee80211_hw_check(&local->hw, SPECTRUM_MGMT))
+	    ieee80211_local_check(local, SPECTRUM_MGMT))
 		capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
 
 	if (ifmgd->flags & IEEE80211_STA_ENABLE_RRM)
@@ -910,7 +910,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 	drv_mgd_prepare_tx(local, sdata);
 
 	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
-	if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
+	if (ieee80211_local_check(local, REPORTS_TX_ACK_STATUS))
 		IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
 						IEEE80211_TX_INTFL_MLME_CONN_TX;
 	ieee80211_tx_skb(sdata, skb);
@@ -952,7 +952,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
 	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
 					IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
 
-	if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
+	if (ieee80211_local_check(local, REPORTS_TX_ACK_STATUS))
 		IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
 
 	if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL)
@@ -1205,7 +1205,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 	chanctx = container_of(conf, struct ieee80211_chanctx, conf);
 
 	if (local->use_chanctx &&
-	    !ieee80211_hw_check(&local->hw, CHANCTX_STA_CSA)) {
+	    !ieee80211_local_check(local, CHANCTX_STA_CSA)) {
 		sdata_info(sdata,
 			   "driver doesn't support chan-switch with channel contexts\n");
 		goto drop_connection;
@@ -1414,15 +1414,15 @@ static void ieee80211_enable_ps(struct ieee80211_local *local,
 		return;
 
 	if (conf->dynamic_ps_timeout > 0 &&
-	    !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS)) {
+	    !ieee80211_local_check(local, SUPPORTS_DYNAMIC_PS)) {
 		mod_timer(&local->dynamic_ps_timer, jiffies +
 			  msecs_to_jiffies(conf->dynamic_ps_timeout));
 	} else {
-		if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK))
+		if (ieee80211_local_check(local, PS_NULLFUNC_STACK))
 			ieee80211_send_nullfunc(local, sdata, true);
 
-		if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
-		    ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
+		if (ieee80211_local_check(local, PS_NULLFUNC_STACK) &&
+		    ieee80211_local_check(local, REPORTS_TX_ACK_STATUS))
 			return;
 
 		conf->flags |= IEEE80211_CONF_PS;
@@ -1481,7 +1481,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local)
 	int count = 0;
 	int timeout;
 
-	if (!ieee80211_hw_check(&local->hw, SUPPORTS_PS)) {
+	if (!ieee80211_local_check(local, SUPPORTS_PS)) {
 		local->ps_sdata = NULL;
 		return;
 	}
@@ -1602,7 +1602,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 	}
 
-	if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
+	if (ieee80211_local_check(local, PS_NULLFUNC_STACK) &&
 	    !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
 		if (drv_tx_frames_pending(local)) {
 			mod_timer(&local->dynamic_ps_timer, jiffies +
@@ -1615,8 +1615,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 		}
 	}
 
-	if (!(ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS) &&
-	      ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK)) ||
+	if (!(ieee80211_local_check(local, REPORTS_TX_ACK_STATUS) &&
+	      ieee80211_local_check(local, PS_NULLFUNC_STACK)) ||
 	    (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
 		ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
 		local->hw.conf.flags |= IEEE80211_CONF_PS;
@@ -2157,7 +2157,7 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
 	ieee80211_recalc_ps(local);
 	mutex_unlock(&local->iflist_mtx);
 
-	if (ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
+	if (ieee80211_local_check(sdata->local, CONNECTION_MONITOR))
 		goto out;
 
 	/*
@@ -2255,7 +2255,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
 	 */
 	ifmgd->probe_send_count++;
 
-	if (ieee80211_hw_check(&sdata->local->hw, REPORTS_TX_ACK_STATUS)) {
+	if (ieee80211_local_check(sdata->local, REPORTS_TX_ACK_STATUS)) {
 		ifmgd->nullfunc_failed = false;
 		ieee80211_send_nullfunc(sdata->local, sdata, false);
 	} else {
@@ -2555,7 +2555,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
 		return;
 	auth_data->expected_transaction = 4;
 	drv_mgd_prepare_tx(sdata->local, sdata);
-	if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
+	if (ieee80211_local_check(local, REPORTS_TX_ACK_STATUS))
 		tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
 			   IEEE80211_TX_INTFL_MLME_CONN_TX;
 	ieee80211_send_auth(sdata, 3, auth_data->algorithm, 0,
@@ -3330,7 +3330,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 		}
 		ifmgd->have_beacon = true;
 		ifmgd->assoc_data->need_beacon = false;
-		if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
+		if (ieee80211_local_check(local, TIMING_BEACON_ONLY)) {
 			sdata->vif.bss_conf.sync_tsf =
 				le64_to_cpu(mgmt->u.beacon.timestamp);
 			sdata->vif.bss_conf.sync_device_ts =
@@ -3434,7 +3434,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 					  len - baselen, false, &elems,
 					  care_about_ies, ncrc);
 
-	if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
+	if (ieee80211_local_check(local, PS_NULLFUNC_STACK) &&
 	    ieee80211_check_tim(elems.tim, elems.tim_len, ifmgd->aid)) {
 		if (local->hw.conf.dynamic_ps_timeout > 0) {
 			if (local->hw.conf.flags & IEEE80211_CONF_PS) {
@@ -3498,7 +3498,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 	 * the driver will use them. The synchronized view is currently
 	 * guaranteed only in certain callbacks.
 	 */
-	if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
+	if (ieee80211_local_check(local, TIMING_BEACON_ONLY)) {
 		sdata->vif.bss_conf.sync_tsf =
 			le64_to_cpu(mgmt->u.beacon.timestamp);
 		sdata->vif.bss_conf.sync_device_ts =
@@ -3734,7 +3734,7 @@ static int ieee80211_auth(struct ieee80211_sub_if_data *sdata)
 		auth_data->expected_transaction = trans;
 	}
 
-	if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
+	if (ieee80211_local_check(local, REPORTS_TX_ACK_STATUS))
 		tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
 			   IEEE80211_TX_INTFL_MLME_CONN_TX;
 
@@ -3784,7 +3784,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
 		   IEEE80211_ASSOC_MAX_TRIES);
 	ieee80211_send_assoc(sdata);
 
-	if (!ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
+	if (!ieee80211_local_check(local, REPORTS_TX_ACK_STATUS)) {
 		assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
 		assoc_data->timeout_started = true;
 		run_again(sdata, assoc_data->timeout);
@@ -3897,7 +3897,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 
 		memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
 
-		if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
+		if (ieee80211_local_check(local, REPORTS_TX_ACK_STATUS))
 			max_tries = max_nullfunc_tries;
 		else
 			max_tries = max_probe_tries;
@@ -3922,7 +3922,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 			}
 		} else if (time_is_after_jiffies(ifmgd->probe_timeout))
 			run_again(sdata, ifmgd->probe_timeout);
-		else if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
+		else if (ieee80211_local_check(local, REPORTS_TX_ACK_STATUS)) {
 			mlme_dbg(sdata,
 				 "Failed to send nullfunc to AP %pM after %dms, disconnecting\n",
 				 bssid, probe_wait_ms);
@@ -3995,7 +3995,7 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
 		__ieee80211_stop_poll(sdata);
 
 		/* let's probe the connection once */
-		if (!ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
+		if (!ieee80211_local_check(sdata->local, CONNECTION_MONITOR))
 			ieee80211_queue_work(&sdata->local->hw,
 					     &sdata->u.mgd.monitor_work);
 		/* and do all the other regular work too */
@@ -4409,7 +4409,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
 				sdata->vif.bss_conf.sync_dtim_count = tim_ie[2];
 			else
 				sdata->vif.bss_conf.sync_dtim_count = 0;
-		} else if (!ieee80211_hw_check(&sdata->local->hw,
+		} else if (!ieee80211_local_check(sdata->local,
 					       TIMING_BEACON_ONLY)) {
 			ies = rcu_dereference(cbss->proberesp_ies);
 			/* must be non-NULL since beacon IEs were NULL */
@@ -4717,7 +4717,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 	rcu_read_unlock();
 
 	if (WARN((sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_UAPSD) &&
-		 ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK),
+		 ieee80211_local_check(local, PS_NULLFUNC_STACK),
 	     "U-APSD not supported with HW_PS_NULLFUNC_STACK\n"))
 		sdata->vif.driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD;
 
@@ -4798,7 +4798,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 	rcu_read_lock();
 	beacon_ies = rcu_dereference(req->bss->beacon_ies);
 
-	if (ieee80211_hw_check(&sdata->local->hw, NEED_DTIM_BEFORE_ASSOC) &&
+	if (ieee80211_local_check(sdata->local, NEED_DTIM_BEFORE_ASSOC) &&
 	    !beacon_ies) {
 		/*
 		 * Wait up to one beacon interval ...
@@ -4825,7 +4825,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 		assoc_data->timeout = jiffies;
 		assoc_data->timeout_started = true;
 
-		if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
+		if (ieee80211_local_check(local, TIMING_BEACON_ONLY)) {
 			sdata->vif.bss_conf.sync_tsf = beacon_ies->tsf;
 			sdata->vif.bss_conf.sync_device_ts =
 				bss->device_ts_beacon;
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 04401037140e..bf0ecc8e0954 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -46,7 +46,7 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
 	}
 
 	if (!local->offchannel_ps_enabled ||
-	    !ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK))
+	    !ieee80211_local_check(local, PS_NULLFUNC_STACK))
 		/*
 		 * If power save was enabled, no need to send a nullfunc
 		 * frame because AP knows that we are sleeping. But if the
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 00a43a70e1fc..877ecf747cd2 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -30,7 +30,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 
 	ieee80211_del_virtual_monitor(local);
 
-	if (ieee80211_hw_check(hw, AMPDU_AGGREGATION) &&
+	if (ieee80211_local_check(local, AMPDU_AGGREGATION) &&
 	    !(wowlan && wowlan->any)) {
 		mutex_lock(&local->sta_mtx);
 		list_for_each_entry(sta, &local->sta_list, list) {
@@ -110,7 +110,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 		if (err < 0) {
 			local->quiescing = false;
 			local->wowlan = false;
-			if (ieee80211_hw_check(hw, AMPDU_AGGREGATION)) {
+			if (ieee80211_local_check(local, AMPDU_AGGREGATION)) {
 				mutex_lock(&local->sta_mtx);
 				list_for_each_entry(sta,
 						    &local->sta_list, list) {
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index a4e2f4e67f94..106360ebea97 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -848,7 +848,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
 		info->control.rates[i].count = 0;
 	}
 
-	if (ieee80211_hw_check(&sdata->local->hw, HAS_RATE_CONTROL))
+	if (ieee80211_local_check(sdata->local, HAS_RATE_CONTROL))
 		return;
 
 	if (ista) {
@@ -859,7 +859,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
 		ref->ops->get_rate(ref->priv, NULL, NULL, txrc);
 	}
 
-	if (ieee80211_hw_check(&sdata->local->hw, SUPPORTS_RC_TABLE))
+	if (ieee80211_local_check(sdata->local, SUPPORTS_RC_TABLE))
 		return;
 
 	ieee80211_get_tx_rates(&sdata->vif, ista, txrc->skb,
@@ -904,7 +904,7 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
 	if (local->open_count)
 		return -EBUSY;
 
-	if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
+	if (ieee80211_local_check(local, HAS_RATE_CONTROL)) {
 		if (WARN_ON(!local->ops->set_rts_threshold))
 			return -EINVAL;
 		return 0;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 8bae5de0dc44..311d87a22303 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -97,7 +97,7 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
 					   struct sk_buff *skb,
 					   unsigned int rtap_vendor_space)
 {
-	if (ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS)) {
+	if (ieee80211_local_check(local, RX_INCLUDES_FCS)) {
 		if (likely(skb->len > FCS_LEN))
 			__pskb_trim(skb, skb->len - FCS_LEN);
 		else {
@@ -154,7 +154,7 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
 		len = ALIGN(len, 8);
 		len += 8;
 	}
-	if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
+	if (ieee80211_local_check(local, SIGNAL_DBM))
 		len += 1;
 
 	/* antenna field, if we don't have per-chain info */
@@ -229,7 +229,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 	}
 
 	mpdulen = skb->len;
-	if (!(has_fcs && ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS)))
+	if (!(has_fcs && ieee80211_local_check(local, RX_INCLUDES_FCS)))
 		mpdulen += FCS_LEN;
 
 	rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
@@ -283,7 +283,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 	}
 
 	/* IEEE80211_RADIOTAP_FLAGS */
-	if (has_fcs && ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS))
+	if (has_fcs && ieee80211_local_check(local, RX_INCLUDES_FCS))
 		*pos |= IEEE80211_RADIOTAP_F_FCS;
 	if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
 		*pos |= IEEE80211_RADIOTAP_F_BADFCS;
@@ -333,7 +333,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 	pos += 2;
 
 	/* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
-	if (ieee80211_hw_check(&local->hw, SIGNAL_DBM) &&
+	if (ieee80211_local_check(local, SIGNAL_DBM) &&
 	    !(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
 		*pos = status->signal;
 		rthdr->it_present |=
@@ -498,7 +498,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
 	 * the SKB because it has a bad FCS/PLCP checksum.
 	 */
 
-	if (ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS))
+	if (ieee80211_local_check(local, RX_INCLUDES_FCS))
 		present_fcs_len = FCS_LEN;
 
 	/* ensure hdr->frame_control and vendor radiotap data are in skb head */
@@ -1232,7 +1232,7 @@ static void sta_ps_start(struct sta_info *sta)
 
 	atomic_inc(&ps->num_sta_ps);
 	set_sta_flag(sta, WLAN_STA_PS_STA);
-	if (!ieee80211_hw_check(&local->hw, AP_LINK_PS))
+	if (!ieee80211_local_check(local, AP_LINK_PS))
 		drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
 	ps_dbg(sdata, "STA %pM aid %d enters power save mode\n",
 	       sta->sta.addr, sta->sta.aid);
@@ -1280,7 +1280,7 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *pubsta, bool start)
 	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
 	bool in_ps;
 
-	WARN_ON(!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS));
+	WARN_ON(!ieee80211_local_check(sta->local, AP_LINK_PS));
 
 	/* Don't let the same PS state be set twice */
 	in_ps = test_sta_flag(sta, WLAN_STA_PS_STA);
@@ -1316,7 +1316,7 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
 	 * uAPSD and PS-Poll frames (the latter shouldn't even come up from
 	 * it to mac80211 since they're handled.)
 	 */
-	if (ieee80211_hw_check(&sdata->local->hw, AP_LINK_PS))
+	if (ieee80211_local_check(sdata->local, AP_LINK_PS))
 		return RX_CONTINUE;
 
 	/*
@@ -1453,7 +1453,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 	 * Change STA power saving mode only at the end of a frame
 	 * exchange sequence.
 	 */
-	if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) &&
+	if (!ieee80211_local_check(sta->local, AP_LINK_PS) &&
 	    !ieee80211_has_morefrags(hdr->frame_control) &&
 	    !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
 	    (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
@@ -2579,7 +2579,7 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
 	    !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
 		int sig = 0;
 
-		if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM))
+		if (ieee80211_local_check(rx->local, SIGNAL_DBM))
 			sig = status->signal;
 
 		cfg80211_report_obss_beacon(rx->local->hw.wiphy,
@@ -2910,7 +2910,7 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
 	 * it transmitted were processed or returned.
 	 */
 
-	if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM))
+	if (ieee80211_local_check(rx->local, SIGNAL_DBM))
 		sig = status->signal;
 
 	if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig,
@@ -2975,7 +2975,7 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
 			info->flags = IEEE80211_TX_CTL_TX_OFFCHAN |
 				      IEEE80211_TX_INTFL_OFFCHAN_TX_OK |
 				      IEEE80211_TX_CTL_NO_CCK_RATE;
-			if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL))
+			if (ieee80211_local_check(local, QUEUE_CONTROL))
 				info->hw_queue =
 					local->hw.offchannel_tx_hw_queue;
 		}
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 4aeca4b0c3cb..bea544d8e106 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -69,9 +69,9 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
 	struct cfg80211_inform_bss bss_meta = {};
 	bool signal_valid;
 
-	if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
+	if (ieee80211_local_check(local, SIGNAL_DBM))
 		bss_meta.signal = rx_status->signal * 100;
-	else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
+	else if (ieee80211_local_check(local, SIGNAL_UNSPEC))
 		bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;
 
 	bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_20;
@@ -261,7 +261,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
 	if (test_bit(SCAN_HW_CANCELLED, &local->scanning))
 		return false;
 
-	if (ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS)) {
+	if (ieee80211_local_check(local, SINGLE_SCAN_ON_ALL_BANDS)) {
 		for (i = 0; i < req->n_channels; i++) {
 			local->hw_scan_req->req.channels[i] = req->channels[i];
 			bands_used |= BIT(req->channels[i]->band);
@@ -330,7 +330,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
 		return;
 
 	if (hw_scan && !aborted &&
-	    !ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS) &&
+	    !ieee80211_local_check(local, SINGLE_SCAN_ON_ALL_BANDS) &&
 	    ieee80211_prep_hw_scan(local)) {
 		int rc;
 
@@ -524,7 +524,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
 
 		local->hw_scan_ies_bufsize = local->scan_ies_len + req->ie_len;
 
-		if (ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS)) {
+		if (ieee80211_local_check(local, SINGLE_SCAN_ON_ALL_BANDS)) {
 			int i, n_bands = 0;
 			u8 bands_counted = 0;
 
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index f91d1873218c..49cebf0a748c 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -285,7 +285,7 @@ static void sta_deliver_ps_frames(struct work_struct *wk)
 static int sta_prepare_rate_control(struct ieee80211_local *local,
 				    struct sta_info *sta, gfp_t gfp)
 {
-	if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL))
+	if (ieee80211_local_check(local, HAS_RATE_CONTROL))
 		return 0;
 
 	sta->rate_ctrl = local->rate_ctrl;
@@ -650,7 +650,7 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending)
 	}
 
 	/* No need to do anything if the driver does all */
-	if (ieee80211_hw_check(&local->hw, AP_LINK_PS))
+	if (ieee80211_local_check(local, AP_LINK_PS))
 		return;
 
 	if (sta->dead)
@@ -1155,7 +1155,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
 	sta->driver_buffered_tids = 0;
 	sta->txq_buffered_tids = 0;
 
-	if (!ieee80211_hw_check(&local->hw, AP_LINK_PS))
+	if (!ieee80211_local_check(local, AP_LINK_PS))
 		drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
 
 	if (sta->sta.txq[0]) {
@@ -1927,8 +1927,8 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 		sinfo->rx_beacon_signal_avg = ieee80211_ave_rssi(&sdata->vif);
 	}
 
-	if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) ||
-	    ieee80211_hw_check(&sta->local->hw, SIGNAL_UNSPEC)) {
+	if (ieee80211_local_check(sta->local, SIGNAL_DBM) ||
+	    ieee80211_local_check(sta->local, SIGNAL_UNSPEC)) {
 		if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL))) {
 			sinfo->signal = (s8)sta->rx_stats.last_signal;
 			sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
@@ -1983,7 +1983,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 
 		if (!(tidstats->filled &
 				BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) &&
-		    ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
+		    ieee80211_local_check(local, REPORTS_TX_ACK_STATUS)) {
 			tidstats->filled |=
 				BIT(NL80211_TID_STATS_TX_MSDU_RETRIES);
 			tidstats->tx_msdu_retries =
@@ -1992,7 +1992,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 
 		if (!(tidstats->filled &
 				BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) &&
-		    ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
+		    ieee80211_local_check(local, REPORTS_TX_ACK_STATUS)) {
 			tidstats->filled |=
 				BIT(NL80211_TID_STATS_TX_MSDU_FAILED);
 			tidstats->tx_msdu_failed =
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 5bad05e9af90..f07104ec5c99 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -182,7 +182,7 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
 	struct ieee80211_local *local = sta->local;
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 
-	if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
+	if (ieee80211_local_check(local, REPORTS_TX_ACK_STATUS))
 		sta->rx_stats.last_rx = jiffies;
 
 	if (ieee80211_is_data_qos(mgmt->frame_control)) {
@@ -415,7 +415,7 @@ static void ieee80211_tdls_td_tx_handle(struct ieee80211_local *local,
 
 	if (is_teardown) {
 		/* This mechanism relies on being able to get ACKs */
-		WARN_ON(!ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS));
+		WARN_ON(!ieee80211_local_check(local, REPORTS_TX_ACK_STATUS));
 
 		/* Check if peer has ACKed */
 		if (flags & IEEE80211_TX_STAT_ACK) {
@@ -783,7 +783,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 					ieee80211_get_qos_ctl(hdr),
 					sta, true, acked);
 
-		if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL) &&
+		if (ieee80211_local_check(local, HAS_RATE_CONTROL) &&
 		    (ieee80211_is_data(hdr->frame_control)) &&
 		    (rates_idx != -1))
 			sta->tx_stats.last_rate =
@@ -853,11 +853,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 			ieee80211_frame_acked(sta, skb);
 
 		if ((sta->sdata->vif.type == NL80211_IFTYPE_STATION) &&
-		    ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
+		    ieee80211_local_check(local, REPORTS_TX_ACK_STATUS))
 			ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data,
 						acked, info->status.tx_time);
 
-		if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
+		if (ieee80211_local_check(local, REPORTS_TX_ACK_STATUS)) {
 			if (info->flags & IEEE80211_TX_STAT_ACK) {
 				if (sta->status_stats.lost_packets)
 					sta->status_stats.lost_packets = 0;
@@ -906,7 +906,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 	}
 
 	if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc) &&
-	    ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS) &&
+	    ieee80211_local_check(local, REPORTS_TX_ACK_STATUS) &&
 	    !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
 	    local->ps_sdata && !(local->scanning)) {
 		if (info->flags & IEEE80211_TX_STAT_ACK) {
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index c9eeb3f12808..6aca8572b8de 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -44,7 +44,7 @@ static void ieee80211_tdls_add_ext_capab(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	bool chan_switch = local->hw.wiphy->features &
 			   NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
-	bool wider_band = ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) &&
+	bool wider_band = ieee80211_local_check(local, TDLS_WIDER_BW) &&
 			  !ifmgd->tdls_wider_bw_prohibited;
 	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
 	struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
@@ -1022,7 +1022,7 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
 	 * packet through the AP.
 	 */
 	if ((action_code == WLAN_TDLS_TEARDOWN) &&
-	    ieee80211_hw_check(&sdata->local->hw, REPORTS_TX_ACK_STATUS)) {
+	    ieee80211_local_check(sdata->local, REPORTS_TX_ACK_STATUS)) {
 		bool try_resend; /* Should we keep skb for possible resend */
 
 		/* If not sending directly to peer - no point in keeping skb */
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index bdc224d5053a..6356a95788cc 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -211,11 +211,11 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
 	struct ieee80211_if_managed *ifmgd;
 
 	/* driver doesn't support power save */
-	if (!ieee80211_hw_check(&local->hw, SUPPORTS_PS))
+	if (!ieee80211_local_check(local, SUPPORTS_PS))
 		return TX_CONTINUE;
 
 	/* hardware does dynamic power save */
-	if (ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS))
+	if (ieee80211_local_check(local, SUPPORTS_DYNAMIC_PS))
 		return TX_CONTINUE;
 
 	/* dynamic power save disabled */
@@ -428,7 +428,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
 	if (ieee80211_is_probe_req(hdr->frame_control))
 		return TX_CONTINUE;
 
-	if (ieee80211_hw_check(&tx->local->hw, QUEUE_CONTROL))
+	if (ieee80211_local_check(tx->local, QUEUE_CONTROL))
 		info->hw_queue = tx->sdata->vif.cab_queue;
 
 	/* no stations in PS mode */
@@ -438,7 +438,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
 	info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
 
 	/* device releases frame after DTIM beacon */
-	if (!ieee80211_hw_check(&tx->local->hw, HOST_BROADCAST_PS_BUFFERING))
+	if (!ieee80211_local_check(tx->local, HOST_BROADCAST_PS_BUFFERING))
 		return TX_CONTINUE;
 
 	/* buffered in mac80211 */
@@ -1184,8 +1184,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
 
 	if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
 	    !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
-	    ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION) &&
-	    !ieee80211_hw_check(&local->hw, TX_AMPDU_SETUP_IN_HW)) {
+	    ieee80211_local_check(local, AMPDU_AGGREGATION) &&
+	    !ieee80211_local_check(local, TX_AMPDU_SETUP_IN_HW)) {
 		struct tid_ampdu_tx *tid_tx;
 
 		qc = ieee80211_get_qos_ctl(hdr);
@@ -1430,7 +1430,7 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
 			vif = &sdata->vif;
 			info->hw_queue =
 				vif->hw_queue[skb_get_queue_mapping(skb)];
-		} else if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) {
+		} else if (ieee80211_local_check(local, QUEUE_CONTROL)) {
 			dev_kfree_skb(skb);
 			return true;
 		} else
@@ -1476,7 +1476,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
 	CALL_TXH(ieee80211_tx_h_ps_buf);
 	CALL_TXH(ieee80211_tx_h_check_control_port_protocol);
 	CALL_TXH(ieee80211_tx_h_select_key);
-	if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
+	if (!ieee80211_local_check(tx->local, HAS_RATE_CONTROL))
 		CALL_TXH(ieee80211_tx_h_rate_ctrl);
 
 	if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) {
@@ -1491,7 +1491,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
 	/* handlers after fragment must be aware of tx info fragmentation! */
 	CALL_TXH(ieee80211_tx_h_stats);
 	CALL_TXH(ieee80211_tx_h_encrypt);
-	if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
+	if (!ieee80211_local_check(tx->local, HAS_RATE_CONTROL))
 		CALL_TXH(ieee80211_tx_h_calculate_duration);
 #undef CALL_TXH
 
@@ -1581,7 +1581,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
 
 	/* set up hw_queue value early */
 	if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
-	    !ieee80211_hw_check(&local->hw, QUEUE_CONTROL))
+	    !ieee80211_local_check(local, QUEUE_CONTROL))
 		info->hw_queue =
 			sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
 
@@ -1608,7 +1608,7 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
 	}
 
 	if (skb_cloned(skb) &&
-	    (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) ||
+	    (!ieee80211_local_check(local, SUPPORTS_CLONED_SKBS) ||
 	     !skb_clone_writable(skb, ETH_HLEN) ||
 	     (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt)))
 		I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
@@ -2427,7 +2427,7 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
 	struct ieee80211_chanctx_conf *chanctx_conf;
 	__le16 fc;
 
-	if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT))
+	if (!ieee80211_local_check(local, SUPPORT_FAST_XMIT))
 		return;
 
 	/* Locking here protects both the pointer itself, and against concurrent
@@ -2443,8 +2443,8 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
 	 * cleared/changed already.
 	 */
 	spin_lock_bh(&sta->lock);
-	if (ieee80211_hw_check(&local->hw, SUPPORTS_PS) &&
-	    !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS) &&
+	if (ieee80211_local_check(local, SUPPORTS_PS) &&
+	    !ieee80211_local_check(local, SUPPORTS_DYNAMIC_PS) &&
 	    sdata->vif.type == NL80211_IFTYPE_STATION)
 		goto out;
 
@@ -2797,7 +2797,7 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
 	if (fast_tx->key)
 		info->control.hw_key = &fast_tx->key->conf;
 
-	if (!ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
+	if (!ieee80211_local_check(local, HAS_RATE_CONTROL)) {
 		tx.skb = skb;
 		r = ieee80211_tx_h_rate_ctrl(&tx);
 		skb = tx.skb;
@@ -3529,7 +3529,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
 	if (tim_length)
 		*tim_length = offs.tim_length;
 
-	if (ieee80211_hw_check(hw, BEACON_TX_STATUS) ||
+	if (ieee80211_local_check(hw_to_local(hw), BEACON_TX_STATUS) ||
 	    !hw_to_local(hw)->monitors)
 		return bcn;
 
@@ -3839,7 +3839,7 @@ int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid)
 	synchronize_net();
 
 	/* Tear down BA sessions so we stop aggregating on this TID */
-	if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION)) {
+	if (ieee80211_local_check(local, AMPDU_AGGREGATION)) {
 		set_sta_flag(sta, WLAN_STA_BLOCK_BA);
 		__ieee80211_stop_tx_ba_session(sta, tid,
 					       AGG_STOP_LOCAL_REQUEST);
@@ -3853,7 +3853,7 @@ int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid)
 	ieee80211_wake_vif_queues(local, sdata,
 				  IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
 
-	if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION))
+	if (ieee80211_local_check(local, AMPDU_AGGREGATION))
 		clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
 
 	ret = 0;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 74058020b7d6..6cffa4a6face 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -516,7 +516,7 @@ ieee80211_get_vif_queues(struct ieee80211_local *local,
 {
 	unsigned int queues;
 
-	if (sdata && ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) {
+	if (sdata && ieee80211_local_check(local, QUEUE_CONTROL)) {
 		int ac;
 
 		queues = 0;
@@ -544,7 +544,7 @@ void __ieee80211_flush_queues(struct ieee80211_local *local,
 	 * If no queue was set, or if the HW doesn't support
 	 * IEEE80211_HW_QUEUE_CONTROL - flush all queues
 	 */
-	if (!queues || !ieee80211_hw_check(&local->hw, QUEUE_CONTROL))
+	if (!queues || !ieee80211_local_check(local, QUEUE_CONTROL))
 		queues = ieee80211_get_vif_queues(local, sdata);
 
 	ieee80211_stop_queues_by_reason(&local->hw, queues,
@@ -2041,7 +2041,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 	 * about the sessions, but we and the AP still think they
 	 * are active. This is really a workaround though.
 	 */
-	if (ieee80211_hw_check(hw, AMPDU_AGGREGATION)) {
+	if (ieee80211_local_check(local, AMPDU_AGGREGATION)) {
 		mutex_lock(&local->sta_mtx);
 
 		list_for_each_entry(sta, &local->sta_list, list) {
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC 3/4] mac80211: use static keys for hw flags
  2015-11-09 22:02 [RFC 0/4] mac80211: jump labels for hw flags Johannes Berg
  2015-11-09 22:02 ` [RFC 1/4] mac80211: add ieee80211_hw_clear() Johannes Berg
  2015-11-09 22:02 ` [RFC 2/4] mac80211: introduce ieee80211_local_check() Johannes Berg
@ 2015-11-09 22:02 ` Johannes Berg
  2015-11-09 22:02 ` [RFC 4/4] mac80211: test the static key code Johannes Berg
  2015-11-09 22:42 ` [RFC 0/4] mac80211: jump labels for hw flags Peter Zijlstra
  4 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2015-11-09 22:02 UTC (permalink / raw)
  To: linux-wireless; +Cc: Jason Baron, Peter Zijlstra, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

There are many drivers with different behaviour, but in a lot of
systems only a single driver will ever be built. In that case we
could practically get rid of the code for the paths that this
driver/device doesn't need. Doing that, however, would be rather
dangerous.

As a decent alternative, use static keys to simply get into the
required code path for the single built driver.

To achieve this associate with each flag an _ON and _OFF Kconfig
symbol. Selecting this symbol in a driver will cause the system
to take this as the default state (if both are selected, there's
no optimisation at all.)

If, for example, the Kconfig selection said that a given flag is
expected to always be turned off, then the code depending on it
would be placed out-of-line and the jump to it NOPed out. If a
different driver that actually requires the code contrary to the
Kconfig selection is loaded, the jump will be patched in and the
first thing in the out-of-line section will be to check the real
hardware flag (since multiple drivers can be loaded.)

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h       |  28 +-
 net/mac80211/Kconfig         |   2 +
 net/mac80211/Kconfig.hwflags | 192 +++++++++++++
 net/mac80211/Makefile        |   1 +
 net/mac80211/hwflags.c       | 128 +++++++++
 net/mac80211/hwflags.h       | 638 +++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/ieee80211_i.h   |  12 +-
 net/mac80211/main.c          |   6 +
 8 files changed, 986 insertions(+), 21 deletions(-)
 create mode 100644 net/mac80211/Kconfig.hwflags
 create mode 100644 net/mac80211/hwflags.c
 create mode 100644 net/mac80211/hwflags.h

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 47274d829115..db98eb5673c2 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2078,19 +2078,23 @@ static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw,
 }
 #define ieee80211_hw_check(hw, flg)	_ieee80211_hw_check(hw, IEEE80211_HW_##flg)
 
-static inline void _ieee80211_hw_set(struct ieee80211_hw *hw,
-				     enum ieee80211_hw_flags flg)
-{
-	__set_bit(flg, hw->flags);
-}
-#define ieee80211_hw_set(hw, flg)	_ieee80211_hw_set(hw, IEEE80211_HW_##flg)
-
-static inline void _ieee80211_hw_clear(struct ieee80211_hw *hw,
-				       enum ieee80211_hw_flags flg)
+#ifdef CONFIG_JUMP_LABEL
+void ieee80211_hw_mod_flag(struct ieee80211_hw *hw,
+			   enum ieee80211_hw_flags flg, bool set);
+#else
+static inline void ieee80211_hw_mod_flag(struct ieee80211_hw *hw,
+					 enum ieee80211_hw_flags flg, bool set)
 {
-	__clear_bit(flg, hw->flags);
-}
-#define ieee80211_hw_clear(hw, flg)	_ieee80211_hw_clear(hw, IEEE80211_HW_##flg)
+	if (set)
+		__set_bit(flg, hw->flags);
+	else
+		__clear_bit(flg, hw->flags);
+#endif /* CONFIG_JUMP_LABEL */
+
+#define ieee80211_hw_set(hw, flg)	\
+	ieee80211_hw_mod_flag(hw, IEEE80211_HW_##flg, true)
+#define ieee80211_hw_clear(hw, flg)	\
+	ieee80211_hw_mod_flag(hw, IEEE80211_HW_##flg, false)
 
 /**
  * struct ieee80211_scan_request - hw scan request
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 3891cbd2adea..206b11598dd1 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -318,3 +318,5 @@ config MAC80211_STA_HASH_MAX_SIZE
 	  connect more stations than the number selected here.)
 
 	  If unsure, leave the default of 0.
+
+source "net/mac80211/Kconfig.hwflags"
diff --git a/net/mac80211/Kconfig.hwflags b/net/mac80211/Kconfig.hwflags
new file mode 100644
index 000000000000..06f6ba12c86e
--- /dev/null
+++ b/net/mac80211/Kconfig.hwflags
@@ -0,0 +1,192 @@
+config MAC80211_HW_HAS_RATE_CONTROL_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_HAS_RATE_CONTROL_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_RX_INCLUDES_FCS_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_RX_INCLUDES_FCS_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_HOST_BROADCAST_PS_BUFFERING_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_HOST_BROADCAST_PS_BUFFERING_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SIGNAL_UNSPEC_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SIGNAL_UNSPEC_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SIGNAL_DBM_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SIGNAL_DBM_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_NEED_DTIM_BEFORE_ASSOC_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_NEED_DTIM_BEFORE_ASSOC_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SPECTRUM_MGMT_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SPECTRUM_MGMT_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_AMPDU_AGGREGATION_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_AMPDU_AGGREGATION_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_PS_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_PS_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_PS_NULLFUNC_STACK_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_PS_NULLFUNC_STACK_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_DYNAMIC_PS_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_DYNAMIC_PS_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_MFP_CAPABLE_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_MFP_CAPABLE_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_WANT_MONITOR_VIF_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_WANT_MONITOR_VIF_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_NO_AUTO_VIF_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_NO_AUTO_VIF_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SW_CRYPTO_CONTROL_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SW_CRYPTO_CONTROL_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORT_FAST_XMIT_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORT_FAST_XMIT_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_REPORTS_TX_ACK_STATUS_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_REPORTS_TX_ACK_STATUS_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_CONNECTION_MONITOR_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_CONNECTION_MONITOR_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_QUEUE_CONTROL_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_QUEUE_CONTROL_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_PER_STA_GTK_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_PER_STA_GTK_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_AP_LINK_PS_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_AP_LINK_PS_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_TX_AMPDU_SETUP_IN_HW_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_TX_AMPDU_SETUP_IN_HW_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_RC_TABLE_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_RC_TABLE_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_P2P_DEV_ADDR_FOR_INTF_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_P2P_DEV_ADDR_FOR_INTF_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_TIMING_BEACON_ONLY_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_TIMING_BEACON_ONLY_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_HT_CCK_RATES_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_HT_CCK_RATES_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_CHANCTX_STA_CSA_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_CHANCTX_STA_CSA_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_CLONED_SKBS_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_CLONED_SKBS_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_TDLS_WIDER_BW_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_TDLS_WIDER_BW_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_AMSDU_IN_AMPDU_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_SUPPORTS_AMSDU_IN_AMPDU_OFF
+	bool
+	depends on MAC80211
+config MAC80211_HW_BEACON_TX_STATUS_ON
+	bool
+	depends on MAC80211
+config MAC80211_HW_BEACON_TX_STATUS_OFF
+	bool
+	depends on MAC80211
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index f9137a8341f4..ba1e407ccfc5 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -48,6 +48,7 @@ mac80211-$(CONFIG_MAC80211_MESH) += \
 	mesh_ps.o
 
 mac80211-$(CONFIG_PM) += pm.o
+mac80211-$(CONFIG_JUMP_LABEL) += hwflags.o
 
 CFLAGS_trace.o := -I$(src)
 
diff --git a/net/mac80211/hwflags.c b/net/mac80211/hwflags.c
new file mode 100644
index 000000000000..00386ca27eaf
--- /dev/null
+++ b/net/mac80211/hwflags.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2015	Intel Deutschland GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/jump_label.h>
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+
+/* assume FALSE initialisation (atomic_t 0) */
+struct static_key hwflags_keys[NUM_IEEE80211_HW_FLAGS];
+
+static s8 hwflags_defstate[] = {
+	[IEEE80211_HW_HAS_RATE_CONTROL] =
+		HWFLAGS_DEFSTATE_HAS_RATE_CONTROL,
+	[IEEE80211_HW_RX_INCLUDES_FCS] =
+		HWFLAGS_DEFSTATE_RX_INCLUDES_FCS,
+	[IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING] =
+		HWFLAGS_DEFSTATE_HOST_BROADCAST_PS_BUFFERING,
+	[IEEE80211_HW_SIGNAL_UNSPEC] =
+		HWFLAGS_DEFSTATE_SIGNAL_UNSPEC,
+	[IEEE80211_HW_SIGNAL_DBM] =
+		HWFLAGS_DEFSTATE_SIGNAL_DBM,
+	[IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC] =
+		HWFLAGS_DEFSTATE_NEED_DTIM_BEFORE_ASSOC,
+	[IEEE80211_HW_SPECTRUM_MGMT] =
+		HWFLAGS_DEFSTATE_SPECTRUM_MGMT,
+	[IEEE80211_HW_AMPDU_AGGREGATION] =
+		HWFLAGS_DEFSTATE_AMPDU_AGGREGATION,
+	[IEEE80211_HW_SUPPORTS_PS] =
+		HWFLAGS_DEFSTATE_SUPPORTS_PS,
+	[IEEE80211_HW_PS_NULLFUNC_STACK] =
+		HWFLAGS_DEFSTATE_PS_NULLFUNC_STACK,
+	[IEEE80211_HW_SUPPORTS_DYNAMIC_PS] =
+		HWFLAGS_DEFSTATE_SUPPORTS_DYNAMIC_PS,
+	[IEEE80211_HW_MFP_CAPABLE] =
+		HWFLAGS_DEFSTATE_MFP_CAPABLE,
+	[IEEE80211_HW_WANT_MONITOR_VIF] =
+		HWFLAGS_DEFSTATE_WANT_MONITOR_VIF,
+	[IEEE80211_HW_NO_AUTO_VIF] =
+		HWFLAGS_DEFSTATE_NO_AUTO_VIF,
+	[IEEE80211_HW_SW_CRYPTO_CONTROL] =
+		HWFLAGS_DEFSTATE_SW_CRYPTO_CONTROL,
+	[IEEE80211_HW_SUPPORT_FAST_XMIT] =
+		HWFLAGS_DEFSTATE_SUPPORT_FAST_XMIT,
+	[IEEE80211_HW_REPORTS_TX_ACK_STATUS] =
+		HWFLAGS_DEFSTATE_REPORTS_TX_ACK_STATUS,
+	[IEEE80211_HW_CONNECTION_MONITOR] =
+		HWFLAGS_DEFSTATE_CONNECTION_MONITOR,
+	[IEEE80211_HW_QUEUE_CONTROL] =
+		HWFLAGS_DEFSTATE_QUEUE_CONTROL,
+	[IEEE80211_HW_SUPPORTS_PER_STA_GTK] =
+		HWFLAGS_DEFSTATE_SUPPORTS_PER_STA_GTK,
+	[IEEE80211_HW_AP_LINK_PS] =
+		HWFLAGS_DEFSTATE_AP_LINK_PS,
+	[IEEE80211_HW_TX_AMPDU_SETUP_IN_HW] =
+		HWFLAGS_DEFSTATE_TX_AMPDU_SETUP_IN_HW,
+	[IEEE80211_HW_SUPPORTS_RC_TABLE] =
+		HWFLAGS_DEFSTATE_SUPPORTS_RC_TABLE,
+	[IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF] =
+		HWFLAGS_DEFSTATE_P2P_DEV_ADDR_FOR_INTF,
+	[IEEE80211_HW_TIMING_BEACON_ONLY] =
+		HWFLAGS_DEFSTATE_TIMING_BEACON_ONLY,
+	[IEEE80211_HW_SUPPORTS_HT_CCK_RATES] =
+		HWFLAGS_DEFSTATE_SUPPORTS_HT_CCK_RATES,
+	[IEEE80211_HW_CHANCTX_STA_CSA] =
+		HWFLAGS_DEFSTATE_CHANCTX_STA_CSA,
+	[IEEE80211_HW_SUPPORTS_CLONED_SKBS] =
+		HWFLAGS_DEFSTATE_SUPPORTS_CLONED_SKBS,
+	[IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS] =
+		HWFLAGS_DEFSTATE_SINGLE_SCAN_ON_ALL_BANDS,
+	[IEEE80211_HW_TDLS_WIDER_BW] =
+		HWFLAGS_DEFSTATE_TDLS_WIDER_BW,
+	[IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU] =
+		HWFLAGS_DEFSTATE_SUPPORTS_AMSDU_IN_AMPDU,
+	[IEEE80211_HW_BEACON_TX_STATUS] =
+		HWFLAGS_DEFSTATE_BEACON_TX_STATUS,
+};
+
+void ieee80211_hw_mod_flag(struct ieee80211_hw *hw,
+			   enum ieee80211_hw_flags flg, bool set)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	if (set) {
+		if (test_bit(flg, hw->flags))
+			return;
+		__set_bit(flg, hw->flags);
+	} else {
+		if (!test_bit(flg, hw->flags))
+			return;
+		__clear_bit(flg, hw->flags);
+	}
+
+	if (!local->registered)
+		return;
+
+	if (hwflags_defstate[flg] < 0)
+		return;
+
+	if (hwflags_defstate[flg] == !!test_bit(flg, hw->flags))
+		static_key_slow_dec(&hwflags_keys[flg]);
+	else
+		static_key_slow_inc(&hwflags_keys[flg]);
+}
+EXPORT_SYMBOL_GPL(ieee80211_hw_mod_flag);
+
+void ieee80211_hwflags_sync_add(unsigned long *flags)
+{
+	unsigned int flg;
+
+	for (flg = 0; flg < NUM_IEEE80211_HW_FLAGS; flg++) {
+		if (hwflags_defstate[flg] != !!test_bit(flg, flags))
+			static_key_slow_inc(&hwflags_keys[flg]);
+	}
+}
+
+void ieee80211_hwflags_sync_del(unsigned long *flags)
+{
+	unsigned int flg;
+
+	for (flg = 0; flg < NUM_IEEE80211_HW_FLAGS; flg++) {
+		if (hwflags_defstate[flg] != !!test_bit(flg, flags))
+			static_key_slow_dec(&hwflags_keys[flg]);
+	}
+}
diff --git a/net/mac80211/hwflags.h b/net/mac80211/hwflags.h
new file mode 100644
index 000000000000..1a690f72a43f
--- /dev/null
+++ b/net/mac80211/hwflags.h
@@ -0,0 +1,638 @@
+/*
+ * Copyright 2015	Intel Deutschland GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __mac80211_hwflags_h
+#define __mac80211_hwflags_h
+#include <linux/jump_label.h>
+#include <net/mac80211.h>
+
+extern struct static_key hwflags_keys[NUM_IEEE80211_HW_FLAGS];
+
+#ifdef CONFIG_JUMP_LABEL
+#if (defined(CONFIG_MAC80211_HW_HAS_RATE_CONTROL_ON) &&	\
+     defined(CONFIG_MAC80211_HW_HAS_RATE_CONTROL_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_HAS_RATE_CONTROL_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_HAS_RATE_CONTROL_OFF))
+#define HWFLAGS_CHECK_HAS_RATE_CONTROL(flags) \
+	test_bit(IEEE80211_HW_HAS_RATE_CONTROL, flags)
+#define HWFLAGS_DEFSTATE_HAS_RATE_CONTROL -1
+#elif defined(CONFIG_MAC80211_HW_HAS_RATE_CONTROL_ON)
+#define HWFLAGS_CHECK_HAS_RATE_CONTROL(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_HAS_RATE_CONTROL]) || \
+	 test_bit(IEEE80211_HW_HAS_RATE_CONTROL, flags))
+#define HWFLAGS_DEFSTATE_HAS_RATE_CONTROL 1
+#else /* CONFIG_MAC80211_HW_HAS_RATE_CONTROL_OFF */
+#define HWFLAGS_CHECK_HAS_RATE_CONTROL(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_HAS_RATE_CONTROL]) && \
+	 test_bit(IEEE80211_HW_HAS_RATE_CONTROL, flags))
+#define HWFLAGS_DEFSTATE_HAS_RATE_CONTROL 0
+#endif /* CONFIG_MAC80211_HW_HAS_RATE_CONTROL_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_RX_INCLUDES_FCS_ON) &&	\
+     defined(CONFIG_MAC80211_HW_RX_INCLUDES_FCS_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_RX_INCLUDES_FCS_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_RX_INCLUDES_FCS_OFF))
+#define HWFLAGS_CHECK_RX_INCLUDES_FCS(flags) \
+	test_bit(IEEE80211_HW_RX_INCLUDES_FCS, flags)
+#define HWFLAGS_DEFSTATE_RX_INCLUDES_FCS -1
+#elif defined(CONFIG_MAC80211_HW_RX_INCLUDES_FCS_ON)
+#define HWFLAGS_CHECK_RX_INCLUDES_FCS(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_RX_INCLUDES_FCS]) || \
+	 test_bit(IEEE80211_HW_RX_INCLUDES_FCS, flags))
+#define HWFLAGS_DEFSTATE_RX_INCLUDES_FCS 1
+#else /* CONFIG_MAC80211_HW_RX_INCLUDES_FCS_OFF */
+#define HWFLAGS_CHECK_RX_INCLUDES_FCS(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_RX_INCLUDES_FCS]) && \
+	 test_bit(IEEE80211_HW_RX_INCLUDES_FCS, flags))
+#define HWFLAGS_DEFSTATE_RX_INCLUDES_FCS 0
+#endif /* CONFIG_MAC80211_HW_RX_INCLUDES_FCS_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_HOST_BROADCAST_PS_BUFFERING_ON) &&	\
+     defined(CONFIG_MAC80211_HW_HOST_BROADCAST_PS_BUFFERING_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_HOST_BROADCAST_PS_BUFFERING_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_HOST_BROADCAST_PS_BUFFERING_OFF))
+#define HWFLAGS_CHECK_HOST_BROADCAST_PS_BUFFERING(flags) \
+	test_bit(IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING, flags)
+#define HWFLAGS_DEFSTATE_HOST_BROADCAST_PS_BUFFERING -1
+#elif defined(CONFIG_MAC80211_HW_HOST_BROADCAST_PS_BUFFERING_ON)
+#define HWFLAGS_CHECK_HOST_BROADCAST_PS_BUFFERING(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING]) || \
+	 test_bit(IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING, flags))
+#define HWFLAGS_DEFSTATE_HOST_BROADCAST_PS_BUFFERING 1
+#else /* CONFIG_MAC80211_HW_HOST_BROADCAST_PS_BUFFERING_OFF */
+#define HWFLAGS_CHECK_HOST_BROADCAST_PS_BUFFERING(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING]) && \
+	 test_bit(IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING, flags))
+#define HWFLAGS_DEFSTATE_HOST_BROADCAST_PS_BUFFERING 0
+#endif /* CONFIG_MAC80211_HW_HOST_BROADCAST_PS_BUFFERING_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SIGNAL_UNSPEC_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SIGNAL_UNSPEC_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SIGNAL_UNSPEC_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SIGNAL_UNSPEC_OFF))
+#define HWFLAGS_CHECK_SIGNAL_UNSPEC(flags) \
+	test_bit(IEEE80211_HW_SIGNAL_UNSPEC, flags)
+#define HWFLAGS_DEFSTATE_SIGNAL_UNSPEC -1
+#elif defined(CONFIG_MAC80211_HW_SIGNAL_UNSPEC_ON)
+#define HWFLAGS_CHECK_SIGNAL_UNSPEC(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SIGNAL_UNSPEC]) || \
+	 test_bit(IEEE80211_HW_SIGNAL_UNSPEC, flags))
+#define HWFLAGS_DEFSTATE_SIGNAL_UNSPEC 1
+#else /* CONFIG_MAC80211_HW_SIGNAL_UNSPEC_OFF */
+#define HWFLAGS_CHECK_SIGNAL_UNSPEC(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SIGNAL_UNSPEC]) && \
+	 test_bit(IEEE80211_HW_SIGNAL_UNSPEC, flags))
+#define HWFLAGS_DEFSTATE_SIGNAL_UNSPEC 0
+#endif /* CONFIG_MAC80211_HW_SIGNAL_UNSPEC_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SIGNAL_DBM_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SIGNAL_DBM_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SIGNAL_DBM_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SIGNAL_DBM_OFF))
+#define HWFLAGS_CHECK_SIGNAL_DBM(flags) \
+	test_bit(IEEE80211_HW_SIGNAL_DBM, flags)
+#define HWFLAGS_DEFSTATE_SIGNAL_DBM -1
+#elif defined(CONFIG_MAC80211_HW_SIGNAL_DBM_ON)
+#define HWFLAGS_CHECK_SIGNAL_DBM(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SIGNAL_DBM]) || \
+	 test_bit(IEEE80211_HW_SIGNAL_DBM, flags))
+#define HWFLAGS_DEFSTATE_SIGNAL_DBM 1
+#else /* CONFIG_MAC80211_HW_SIGNAL_DBM_OFF */
+#define HWFLAGS_CHECK_SIGNAL_DBM(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SIGNAL_DBM]) && \
+	 test_bit(IEEE80211_HW_SIGNAL_DBM, flags))
+#define HWFLAGS_DEFSTATE_SIGNAL_DBM 0
+#endif /* CONFIG_MAC80211_HW_SIGNAL_DBM_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_NEED_DTIM_BEFORE_ASSOC_ON) &&	\
+     defined(CONFIG_MAC80211_HW_NEED_DTIM_BEFORE_ASSOC_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_NEED_DTIM_BEFORE_ASSOC_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_NEED_DTIM_BEFORE_ASSOC_OFF))
+#define HWFLAGS_CHECK_NEED_DTIM_BEFORE_ASSOC(flags) \
+	test_bit(IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC, flags)
+#define HWFLAGS_DEFSTATE_NEED_DTIM_BEFORE_ASSOC -1
+#elif defined(CONFIG_MAC80211_HW_NEED_DTIM_BEFORE_ASSOC_ON)
+#define HWFLAGS_CHECK_NEED_DTIM_BEFORE_ASSOC(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC]) || \
+	 test_bit(IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC, flags))
+#define HWFLAGS_DEFSTATE_NEED_DTIM_BEFORE_ASSOC 1
+#else /* CONFIG_MAC80211_HW_NEED_DTIM_BEFORE_ASSOC_OFF */
+#define HWFLAGS_CHECK_NEED_DTIM_BEFORE_ASSOC(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC]) && \
+	 test_bit(IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC, flags))
+#define HWFLAGS_DEFSTATE_NEED_DTIM_BEFORE_ASSOC 0
+#endif /* CONFIG_MAC80211_HW_NEED_DTIM_BEFORE_ASSOC_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SPECTRUM_MGMT_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SPECTRUM_MGMT_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SPECTRUM_MGMT_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SPECTRUM_MGMT_OFF))
+#define HWFLAGS_CHECK_SPECTRUM_MGMT(flags) \
+	test_bit(IEEE80211_HW_SPECTRUM_MGMT, flags)
+#define HWFLAGS_DEFSTATE_SPECTRUM_MGMT -1
+#elif defined(CONFIG_MAC80211_HW_SPECTRUM_MGMT_ON)
+#define HWFLAGS_CHECK_SPECTRUM_MGMT(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SPECTRUM_MGMT]) || \
+	 test_bit(IEEE80211_HW_SPECTRUM_MGMT, flags))
+#define HWFLAGS_DEFSTATE_SPECTRUM_MGMT 1
+#else /* CONFIG_MAC80211_HW_SPECTRUM_MGMT_OFF */
+#define HWFLAGS_CHECK_SPECTRUM_MGMT(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SPECTRUM_MGMT]) && \
+	 test_bit(IEEE80211_HW_SPECTRUM_MGMT, flags))
+#define HWFLAGS_DEFSTATE_SPECTRUM_MGMT 0
+#endif /* CONFIG_MAC80211_HW_SPECTRUM_MGMT_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_AMPDU_AGGREGATION_ON) &&	\
+     defined(CONFIG_MAC80211_HW_AMPDU_AGGREGATION_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_AMPDU_AGGREGATION_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_AMPDU_AGGREGATION_OFF))
+#define HWFLAGS_CHECK_AMPDU_AGGREGATION(flags) \
+	test_bit(IEEE80211_HW_AMPDU_AGGREGATION, flags)
+#define HWFLAGS_DEFSTATE_AMPDU_AGGREGATION -1
+#elif defined(CONFIG_MAC80211_HW_AMPDU_AGGREGATION_ON)
+#define HWFLAGS_CHECK_AMPDU_AGGREGATION(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_AMPDU_AGGREGATION]) || \
+	 test_bit(IEEE80211_HW_AMPDU_AGGREGATION, flags))
+#define HWFLAGS_DEFSTATE_AMPDU_AGGREGATION 1
+#else /* CONFIG_MAC80211_HW_AMPDU_AGGREGATION_OFF */
+#define HWFLAGS_CHECK_AMPDU_AGGREGATION(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_AMPDU_AGGREGATION]) && \
+	 test_bit(IEEE80211_HW_AMPDU_AGGREGATION, flags))
+#define HWFLAGS_DEFSTATE_AMPDU_AGGREGATION 0
+#endif /* CONFIG_MAC80211_HW_AMPDU_AGGREGATION_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SUPPORTS_PS_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SUPPORTS_PS_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SUPPORTS_PS_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SUPPORTS_PS_OFF))
+#define HWFLAGS_CHECK_SUPPORTS_PS(flags) \
+	test_bit(IEEE80211_HW_SUPPORTS_PS, flags)
+#define HWFLAGS_DEFSTATE_SUPPORTS_PS -1
+#elif defined(CONFIG_MAC80211_HW_SUPPORTS_PS_ON)
+#define HWFLAGS_CHECK_SUPPORTS_PS(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_PS]) || \
+	 test_bit(IEEE80211_HW_SUPPORTS_PS, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_PS 1
+#else /* CONFIG_MAC80211_HW_SUPPORTS_PS_OFF */
+#define HWFLAGS_CHECK_SUPPORTS_PS(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_PS]) && \
+	 test_bit(IEEE80211_HW_SUPPORTS_PS, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_PS 0
+#endif /* CONFIG_MAC80211_HW_SUPPORTS_PS_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_PS_NULLFUNC_STACK_ON) &&	\
+     defined(CONFIG_MAC80211_HW_PS_NULLFUNC_STACK_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_PS_NULLFUNC_STACK_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_PS_NULLFUNC_STACK_OFF))
+#define HWFLAGS_CHECK_PS_NULLFUNC_STACK(flags) \
+	test_bit(IEEE80211_HW_PS_NULLFUNC_STACK, flags)
+#define HWFLAGS_DEFSTATE_PS_NULLFUNC_STACK -1
+#elif defined(CONFIG_MAC80211_HW_PS_NULLFUNC_STACK_ON)
+#define HWFLAGS_CHECK_PS_NULLFUNC_STACK(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_PS_NULLFUNC_STACK]) || \
+	 test_bit(IEEE80211_HW_PS_NULLFUNC_STACK, flags))
+#define HWFLAGS_DEFSTATE_PS_NULLFUNC_STACK 1
+#else /* CONFIG_MAC80211_HW_PS_NULLFUNC_STACK_OFF */
+#define HWFLAGS_CHECK_PS_NULLFUNC_STACK(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_PS_NULLFUNC_STACK]) && \
+	 test_bit(IEEE80211_HW_PS_NULLFUNC_STACK, flags))
+#define HWFLAGS_DEFSTATE_PS_NULLFUNC_STACK 0
+#endif /* CONFIG_MAC80211_HW_PS_NULLFUNC_STACK_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SUPPORTS_DYNAMIC_PS_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SUPPORTS_DYNAMIC_PS_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SUPPORTS_DYNAMIC_PS_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SUPPORTS_DYNAMIC_PS_OFF))
+#define HWFLAGS_CHECK_SUPPORTS_DYNAMIC_PS(flags) \
+	test_bit(IEEE80211_HW_SUPPORTS_DYNAMIC_PS, flags)
+#define HWFLAGS_DEFSTATE_SUPPORTS_DYNAMIC_PS -1
+#elif defined(CONFIG_MAC80211_HW_SUPPORTS_DYNAMIC_PS_ON)
+#define HWFLAGS_CHECK_SUPPORTS_DYNAMIC_PS(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_DYNAMIC_PS]) || \
+	 test_bit(IEEE80211_HW_SUPPORTS_DYNAMIC_PS, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_DYNAMIC_PS 1
+#else /* CONFIG_MAC80211_HW_SUPPORTS_DYNAMIC_PS_OFF */
+#define HWFLAGS_CHECK_SUPPORTS_DYNAMIC_PS(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_DYNAMIC_PS]) && \
+	 test_bit(IEEE80211_HW_SUPPORTS_DYNAMIC_PS, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_DYNAMIC_PS 0
+#endif /* CONFIG_MAC80211_HW_SUPPORTS_DYNAMIC_PS_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_MFP_CAPABLE_ON) &&	\
+     defined(CONFIG_MAC80211_HW_MFP_CAPABLE_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_MFP_CAPABLE_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_MFP_CAPABLE_OFF))
+#define HWFLAGS_CHECK_MFP_CAPABLE(flags) \
+	test_bit(IEEE80211_HW_MFP_CAPABLE, flags)
+#define HWFLAGS_DEFSTATE_MFP_CAPABLE -1
+#elif defined(CONFIG_MAC80211_HW_MFP_CAPABLE_ON)
+#define HWFLAGS_CHECK_MFP_CAPABLE(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_MFP_CAPABLE]) || \
+	 test_bit(IEEE80211_HW_MFP_CAPABLE, flags))
+#define HWFLAGS_DEFSTATE_MFP_CAPABLE 1
+#else /* CONFIG_MAC80211_HW_MFP_CAPABLE_OFF */
+#define HWFLAGS_CHECK_MFP_CAPABLE(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_MFP_CAPABLE]) && \
+	 test_bit(IEEE80211_HW_MFP_CAPABLE, flags))
+#define HWFLAGS_DEFSTATE_MFP_CAPABLE 0
+#endif /* CONFIG_MAC80211_HW_MFP_CAPABLE_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_WANT_MONITOR_VIF_ON) &&	\
+     defined(CONFIG_MAC80211_HW_WANT_MONITOR_VIF_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_WANT_MONITOR_VIF_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_WANT_MONITOR_VIF_OFF))
+#define HWFLAGS_CHECK_WANT_MONITOR_VIF(flags) \
+	test_bit(IEEE80211_HW_WANT_MONITOR_VIF, flags)
+#define HWFLAGS_DEFSTATE_WANT_MONITOR_VIF -1
+#elif defined(CONFIG_MAC80211_HW_WANT_MONITOR_VIF_ON)
+#define HWFLAGS_CHECK_WANT_MONITOR_VIF(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_WANT_MONITOR_VIF]) || \
+	 test_bit(IEEE80211_HW_WANT_MONITOR_VIF, flags))
+#define HWFLAGS_DEFSTATE_WANT_MONITOR_VIF 1
+#else /* CONFIG_MAC80211_HW_WANT_MONITOR_VIF_OFF */
+#define HWFLAGS_CHECK_WANT_MONITOR_VIF(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_WANT_MONITOR_VIF]) && \
+	 test_bit(IEEE80211_HW_WANT_MONITOR_VIF, flags))
+#define HWFLAGS_DEFSTATE_WANT_MONITOR_VIF 0
+#endif /* CONFIG_MAC80211_HW_WANT_MONITOR_VIF_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_NO_AUTO_VIF_ON) &&	\
+     defined(CONFIG_MAC80211_HW_NO_AUTO_VIF_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_NO_AUTO_VIF_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_NO_AUTO_VIF_OFF))
+#define HWFLAGS_CHECK_NO_AUTO_VIF(flags) \
+	test_bit(IEEE80211_HW_NO_AUTO_VIF, flags)
+#define HWFLAGS_DEFSTATE_NO_AUTO_VIF -1
+#elif defined(CONFIG_MAC80211_HW_NO_AUTO_VIF_ON)
+#define HWFLAGS_CHECK_NO_AUTO_VIF(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_NO_AUTO_VIF]) || \
+	 test_bit(IEEE80211_HW_NO_AUTO_VIF, flags))
+#define HWFLAGS_DEFSTATE_NO_AUTO_VIF 1
+#else /* CONFIG_MAC80211_HW_NO_AUTO_VIF_OFF */
+#define HWFLAGS_CHECK_NO_AUTO_VIF(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_NO_AUTO_VIF]) && \
+	 test_bit(IEEE80211_HW_NO_AUTO_VIF, flags))
+#define HWFLAGS_DEFSTATE_NO_AUTO_VIF 0
+#endif /* CONFIG_MAC80211_HW_NO_AUTO_VIF_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SW_CRYPTO_CONTROL_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SW_CRYPTO_CONTROL_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SW_CRYPTO_CONTROL_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SW_CRYPTO_CONTROL_OFF))
+#define HWFLAGS_CHECK_SW_CRYPTO_CONTROL(flags) \
+	test_bit(IEEE80211_HW_SW_CRYPTO_CONTROL, flags)
+#define HWFLAGS_DEFSTATE_SW_CRYPTO_CONTROL -1
+#elif defined(CONFIG_MAC80211_HW_SW_CRYPTO_CONTROL_ON)
+#define HWFLAGS_CHECK_SW_CRYPTO_CONTROL(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SW_CRYPTO_CONTROL]) || \
+	 test_bit(IEEE80211_HW_SW_CRYPTO_CONTROL, flags))
+#define HWFLAGS_DEFSTATE_SW_CRYPTO_CONTROL 1
+#else /* CONFIG_MAC80211_HW_SW_CRYPTO_CONTROL_OFF */
+#define HWFLAGS_CHECK_SW_CRYPTO_CONTROL(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SW_CRYPTO_CONTROL]) && \
+	 test_bit(IEEE80211_HW_SW_CRYPTO_CONTROL, flags))
+#define HWFLAGS_DEFSTATE_SW_CRYPTO_CONTROL 0
+#endif /* CONFIG_MAC80211_HW_SW_CRYPTO_CONTROL_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SUPPORT_FAST_XMIT_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SUPPORT_FAST_XMIT_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SUPPORT_FAST_XMIT_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SUPPORT_FAST_XMIT_OFF))
+#define HWFLAGS_CHECK_SUPPORT_FAST_XMIT(flags) \
+	test_bit(IEEE80211_HW_SUPPORT_FAST_XMIT, flags)
+#define HWFLAGS_DEFSTATE_SUPPORT_FAST_XMIT -1
+#elif defined(CONFIG_MAC80211_HW_SUPPORT_FAST_XMIT_ON)
+#define HWFLAGS_CHECK_SUPPORT_FAST_XMIT(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORT_FAST_XMIT]) || \
+	 test_bit(IEEE80211_HW_SUPPORT_FAST_XMIT, flags))
+#define HWFLAGS_DEFSTATE_SUPPORT_FAST_XMIT 1
+#else /* CONFIG_MAC80211_HW_SUPPORT_FAST_XMIT_OFF */
+#define HWFLAGS_CHECK_SUPPORT_FAST_XMIT(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORT_FAST_XMIT]) && \
+	 test_bit(IEEE80211_HW_SUPPORT_FAST_XMIT, flags))
+#define HWFLAGS_DEFSTATE_SUPPORT_FAST_XMIT 0
+#endif /* CONFIG_MAC80211_HW_SUPPORT_FAST_XMIT_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_REPORTS_TX_ACK_STATUS_ON) &&	\
+     defined(CONFIG_MAC80211_HW_REPORTS_TX_ACK_STATUS_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_REPORTS_TX_ACK_STATUS_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_REPORTS_TX_ACK_STATUS_OFF))
+#define HWFLAGS_CHECK_REPORTS_TX_ACK_STATUS(flags) \
+	test_bit(IEEE80211_HW_REPORTS_TX_ACK_STATUS, flags)
+#define HWFLAGS_DEFSTATE_REPORTS_TX_ACK_STATUS -1
+#elif defined(CONFIG_MAC80211_HW_REPORTS_TX_ACK_STATUS_ON)
+#define HWFLAGS_CHECK_REPORTS_TX_ACK_STATUS(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_REPORTS_TX_ACK_STATUS]) || \
+	 test_bit(IEEE80211_HW_REPORTS_TX_ACK_STATUS, flags))
+#define HWFLAGS_DEFSTATE_REPORTS_TX_ACK_STATUS 1
+#else /* CONFIG_MAC80211_HW_REPORTS_TX_ACK_STATUS_OFF */
+#define HWFLAGS_CHECK_REPORTS_TX_ACK_STATUS(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_REPORTS_TX_ACK_STATUS]) && \
+	 test_bit(IEEE80211_HW_REPORTS_TX_ACK_STATUS, flags))
+#define HWFLAGS_DEFSTATE_REPORTS_TX_ACK_STATUS 0
+#endif /* CONFIG_MAC80211_HW_REPORTS_TX_ACK_STATUS_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_CONNECTION_MONITOR_ON) &&	\
+     defined(CONFIG_MAC80211_HW_CONNECTION_MONITOR_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_CONNECTION_MONITOR_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_CONNECTION_MONITOR_OFF))
+#define HWFLAGS_CHECK_CONNECTION_MONITOR(flags) \
+	test_bit(IEEE80211_HW_CONNECTION_MONITOR, flags)
+#define HWFLAGS_DEFSTATE_CONNECTION_MONITOR -1
+#elif defined(CONFIG_MAC80211_HW_CONNECTION_MONITOR_ON)
+#define HWFLAGS_CHECK_CONNECTION_MONITOR(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_CONNECTION_MONITOR]) || \
+	 test_bit(IEEE80211_HW_CONNECTION_MONITOR, flags))
+#define HWFLAGS_DEFSTATE_CONNECTION_MONITOR 1
+#else /* CONFIG_MAC80211_HW_CONNECTION_MONITOR_OFF */
+#define HWFLAGS_CHECK_CONNECTION_MONITOR(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_CONNECTION_MONITOR]) && \
+	 test_bit(IEEE80211_HW_CONNECTION_MONITOR, flags))
+#define HWFLAGS_DEFSTATE_CONNECTION_MONITOR 0
+#endif /* CONFIG_MAC80211_HW_CONNECTION_MONITOR_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_QUEUE_CONTROL_ON) &&	\
+     defined(CONFIG_MAC80211_HW_QUEUE_CONTROL_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_QUEUE_CONTROL_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_QUEUE_CONTROL_OFF))
+#define HWFLAGS_CHECK_QUEUE_CONTROL(flags) \
+	test_bit(IEEE80211_HW_QUEUE_CONTROL, flags)
+#define HWFLAGS_DEFSTATE_QUEUE_CONTROL -1
+#elif defined(CONFIG_MAC80211_HW_QUEUE_CONTROL_ON)
+#define HWFLAGS_CHECK_QUEUE_CONTROL(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_QUEUE_CONTROL]) || \
+	 test_bit(IEEE80211_HW_QUEUE_CONTROL, flags))
+#define HWFLAGS_DEFSTATE_QUEUE_CONTROL 1
+#else /* CONFIG_MAC80211_HW_QUEUE_CONTROL_OFF */
+#define HWFLAGS_CHECK_QUEUE_CONTROL(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_QUEUE_CONTROL]) && \
+	 test_bit(IEEE80211_HW_QUEUE_CONTROL, flags))
+#define HWFLAGS_DEFSTATE_QUEUE_CONTROL 0
+#endif /* CONFIG_MAC80211_HW_QUEUE_CONTROL_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SUPPORTS_PER_STA_GTK_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SUPPORTS_PER_STA_GTK_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SUPPORTS_PER_STA_GTK_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SUPPORTS_PER_STA_GTK_OFF))
+#define HWFLAGS_CHECK_SUPPORTS_PER_STA_GTK(flags) \
+	test_bit(IEEE80211_HW_SUPPORTS_PER_STA_GTK, flags)
+#define HWFLAGS_DEFSTATE_SUPPORTS_PER_STA_GTK -1
+#elif defined(CONFIG_MAC80211_HW_SUPPORTS_PER_STA_GTK_ON)
+#define HWFLAGS_CHECK_SUPPORTS_PER_STA_GTK(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_PER_STA_GTK]) || \
+	 test_bit(IEEE80211_HW_SUPPORTS_PER_STA_GTK, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_PER_STA_GTK 1
+#else /* CONFIG_MAC80211_HW_SUPPORTS_PER_STA_GTK_OFF */
+#define HWFLAGS_CHECK_SUPPORTS_PER_STA_GTK(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_PER_STA_GTK]) && \
+	 test_bit(IEEE80211_HW_SUPPORTS_PER_STA_GTK, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_PER_STA_GTK 0
+#endif /* CONFIG_MAC80211_HW_SUPPORTS_PER_STA_GTK_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_AP_LINK_PS_ON) &&	\
+     defined(CONFIG_MAC80211_HW_AP_LINK_PS_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_AP_LINK_PS_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_AP_LINK_PS_OFF))
+#define HWFLAGS_CHECK_AP_LINK_PS(flags) \
+	test_bit(IEEE80211_HW_AP_LINK_PS, flags)
+#define HWFLAGS_DEFSTATE_AP_LINK_PS -1
+#elif defined(CONFIG_MAC80211_HW_AP_LINK_PS_ON)
+#define HWFLAGS_CHECK_AP_LINK_PS(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_AP_LINK_PS]) || \
+	 test_bit(IEEE80211_HW_AP_LINK_PS, flags))
+#define HWFLAGS_DEFSTATE_AP_LINK_PS 1
+#else /* CONFIG_MAC80211_HW_AP_LINK_PS_OFF */
+#define HWFLAGS_CHECK_AP_LINK_PS(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_AP_LINK_PS]) && \
+	 test_bit(IEEE80211_HW_AP_LINK_PS, flags))
+#define HWFLAGS_DEFSTATE_AP_LINK_PS 0
+#endif /* CONFIG_MAC80211_HW_AP_LINK_PS_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_TX_AMPDU_SETUP_IN_HW_ON) &&	\
+     defined(CONFIG_MAC80211_HW_TX_AMPDU_SETUP_IN_HW_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_TX_AMPDU_SETUP_IN_HW_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_TX_AMPDU_SETUP_IN_HW_OFF))
+#define HWFLAGS_CHECK_TX_AMPDU_SETUP_IN_HW(flags) \
+	test_bit(IEEE80211_HW_TX_AMPDU_SETUP_IN_HW, flags)
+#define HWFLAGS_DEFSTATE_TX_AMPDU_SETUP_IN_HW -1
+#elif defined(CONFIG_MAC80211_HW_TX_AMPDU_SETUP_IN_HW_ON)
+#define HWFLAGS_CHECK_TX_AMPDU_SETUP_IN_HW(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_TX_AMPDU_SETUP_IN_HW]) || \
+	 test_bit(IEEE80211_HW_TX_AMPDU_SETUP_IN_HW, flags))
+#define HWFLAGS_DEFSTATE_TX_AMPDU_SETUP_IN_HW 1
+#else /* CONFIG_MAC80211_HW_TX_AMPDU_SETUP_IN_HW_OFF */
+#define HWFLAGS_CHECK_TX_AMPDU_SETUP_IN_HW(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_TX_AMPDU_SETUP_IN_HW]) && \
+	 test_bit(IEEE80211_HW_TX_AMPDU_SETUP_IN_HW, flags))
+#define HWFLAGS_DEFSTATE_TX_AMPDU_SETUP_IN_HW 0
+#endif /* CONFIG_MAC80211_HW_TX_AMPDU_SETUP_IN_HW_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SUPPORTS_RC_TABLE_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SUPPORTS_RC_TABLE_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SUPPORTS_RC_TABLE_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SUPPORTS_RC_TABLE_OFF))
+#define HWFLAGS_CHECK_SUPPORTS_RC_TABLE(flags) \
+	test_bit(IEEE80211_HW_SUPPORTS_RC_TABLE, flags)
+#define HWFLAGS_DEFSTATE_SUPPORTS_RC_TABLE -1
+#elif defined(CONFIG_MAC80211_HW_SUPPORTS_RC_TABLE_ON)
+#define HWFLAGS_CHECK_SUPPORTS_RC_TABLE(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_RC_TABLE]) || \
+	 test_bit(IEEE80211_HW_SUPPORTS_RC_TABLE, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_RC_TABLE 1
+#else /* CONFIG_MAC80211_HW_SUPPORTS_RC_TABLE_OFF */
+#define HWFLAGS_CHECK_SUPPORTS_RC_TABLE(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_RC_TABLE]) && \
+	 test_bit(IEEE80211_HW_SUPPORTS_RC_TABLE, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_RC_TABLE 0
+#endif /* CONFIG_MAC80211_HW_SUPPORTS_RC_TABLE_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_P2P_DEV_ADDR_FOR_INTF_ON) &&	\
+     defined(CONFIG_MAC80211_HW_P2P_DEV_ADDR_FOR_INTF_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_P2P_DEV_ADDR_FOR_INTF_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_P2P_DEV_ADDR_FOR_INTF_OFF))
+#define HWFLAGS_CHECK_P2P_DEV_ADDR_FOR_INTF(flags) \
+	test_bit(IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF, flags)
+#define HWFLAGS_DEFSTATE_P2P_DEV_ADDR_FOR_INTF -1
+#elif defined(CONFIG_MAC80211_HW_P2P_DEV_ADDR_FOR_INTF_ON)
+#define HWFLAGS_CHECK_P2P_DEV_ADDR_FOR_INTF(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF]) || \
+	 test_bit(IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF, flags))
+#define HWFLAGS_DEFSTATE_P2P_DEV_ADDR_FOR_INTF 1
+#else /* CONFIG_MAC80211_HW_P2P_DEV_ADDR_FOR_INTF_OFF */
+#define HWFLAGS_CHECK_P2P_DEV_ADDR_FOR_INTF(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF]) && \
+	 test_bit(IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF, flags))
+#define HWFLAGS_DEFSTATE_P2P_DEV_ADDR_FOR_INTF 0
+#endif /* CONFIG_MAC80211_HW_P2P_DEV_ADDR_FOR_INTF_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_TIMING_BEACON_ONLY_ON) &&	\
+     defined(CONFIG_MAC80211_HW_TIMING_BEACON_ONLY_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_TIMING_BEACON_ONLY_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_TIMING_BEACON_ONLY_OFF))
+#define HWFLAGS_CHECK_TIMING_BEACON_ONLY(flags) \
+	test_bit(IEEE80211_HW_TIMING_BEACON_ONLY, flags)
+#define HWFLAGS_DEFSTATE_TIMING_BEACON_ONLY -1
+#elif defined(CONFIG_MAC80211_HW_TIMING_BEACON_ONLY_ON)
+#define HWFLAGS_CHECK_TIMING_BEACON_ONLY(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_TIMING_BEACON_ONLY]) || \
+	 test_bit(IEEE80211_HW_TIMING_BEACON_ONLY, flags))
+#define HWFLAGS_DEFSTATE_TIMING_BEACON_ONLY 1
+#else /* CONFIG_MAC80211_HW_TIMING_BEACON_ONLY_OFF */
+#define HWFLAGS_CHECK_TIMING_BEACON_ONLY(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_TIMING_BEACON_ONLY]) && \
+	 test_bit(IEEE80211_HW_TIMING_BEACON_ONLY, flags))
+#define HWFLAGS_DEFSTATE_TIMING_BEACON_ONLY 0
+#endif /* CONFIG_MAC80211_HW_TIMING_BEACON_ONLY_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SUPPORTS_HT_CCK_RATES_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SUPPORTS_HT_CCK_RATES_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SUPPORTS_HT_CCK_RATES_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SUPPORTS_HT_CCK_RATES_OFF))
+#define HWFLAGS_CHECK_SUPPORTS_HT_CCK_RATES(flags) \
+	test_bit(IEEE80211_HW_SUPPORTS_HT_CCK_RATES, flags)
+#define HWFLAGS_DEFSTATE_SUPPORTS_HT_CCK_RATES -1
+#elif defined(CONFIG_MAC80211_HW_SUPPORTS_HT_CCK_RATES_ON)
+#define HWFLAGS_CHECK_SUPPORTS_HT_CCK_RATES(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_HT_CCK_RATES]) || \
+	 test_bit(IEEE80211_HW_SUPPORTS_HT_CCK_RATES, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_HT_CCK_RATES 1
+#else /* CONFIG_MAC80211_HW_SUPPORTS_HT_CCK_RATES_OFF */
+#define HWFLAGS_CHECK_SUPPORTS_HT_CCK_RATES(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_HT_CCK_RATES]) && \
+	 test_bit(IEEE80211_HW_SUPPORTS_HT_CCK_RATES, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_HT_CCK_RATES 0
+#endif /* CONFIG_MAC80211_HW_SUPPORTS_HT_CCK_RATES_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_CHANCTX_STA_CSA_ON) &&	\
+     defined(CONFIG_MAC80211_HW_CHANCTX_STA_CSA_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_CHANCTX_STA_CSA_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_CHANCTX_STA_CSA_OFF))
+#define HWFLAGS_CHECK_CHANCTX_STA_CSA(flags) \
+	test_bit(IEEE80211_HW_CHANCTX_STA_CSA, flags)
+#define HWFLAGS_DEFSTATE_CHANCTX_STA_CSA -1
+#elif defined(CONFIG_MAC80211_HW_CHANCTX_STA_CSA_ON)
+#define HWFLAGS_CHECK_CHANCTX_STA_CSA(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_CHANCTX_STA_CSA]) || \
+	 test_bit(IEEE80211_HW_CHANCTX_STA_CSA, flags))
+#define HWFLAGS_DEFSTATE_CHANCTX_STA_CSA 1
+#else /* CONFIG_MAC80211_HW_CHANCTX_STA_CSA_OFF */
+#define HWFLAGS_CHECK_CHANCTX_STA_CSA(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_CHANCTX_STA_CSA]) && \
+	 test_bit(IEEE80211_HW_CHANCTX_STA_CSA, flags))
+#define HWFLAGS_DEFSTATE_CHANCTX_STA_CSA 0
+#endif /* CONFIG_MAC80211_HW_CHANCTX_STA_CSA_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SUPPORTS_CLONED_SKBS_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SUPPORTS_CLONED_SKBS_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SUPPORTS_CLONED_SKBS_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SUPPORTS_CLONED_SKBS_OFF))
+#define HWFLAGS_CHECK_SUPPORTS_CLONED_SKBS(flags) \
+	test_bit(IEEE80211_HW_SUPPORTS_CLONED_SKBS, flags)
+#define HWFLAGS_DEFSTATE_SUPPORTS_CLONED_SKBS -1
+#elif defined(CONFIG_MAC80211_HW_SUPPORTS_CLONED_SKBS_ON)
+#define HWFLAGS_CHECK_SUPPORTS_CLONED_SKBS(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_CLONED_SKBS]) || \
+	 test_bit(IEEE80211_HW_SUPPORTS_CLONED_SKBS, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_CLONED_SKBS 1
+#else /* CONFIG_MAC80211_HW_SUPPORTS_CLONED_SKBS_OFF */
+#define HWFLAGS_CHECK_SUPPORTS_CLONED_SKBS(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_CLONED_SKBS]) && \
+	 test_bit(IEEE80211_HW_SUPPORTS_CLONED_SKBS, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_CLONED_SKBS 0
+#endif /* CONFIG_MAC80211_HW_SUPPORTS_CLONED_SKBS_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS_OFF))
+#define HWFLAGS_CHECK_SINGLE_SCAN_ON_ALL_BANDS(flags) \
+	test_bit(IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS, flags)
+#define HWFLAGS_DEFSTATE_SINGLE_SCAN_ON_ALL_BANDS -1
+#elif defined(CONFIG_MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS_ON)
+#define HWFLAGS_CHECK_SINGLE_SCAN_ON_ALL_BANDS(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS]) || \
+	 test_bit(IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS, flags))
+#define HWFLAGS_DEFSTATE_SINGLE_SCAN_ON_ALL_BANDS 1
+#else /* CONFIG_MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS_OFF */
+#define HWFLAGS_CHECK_SINGLE_SCAN_ON_ALL_BANDS(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS]) && \
+	 test_bit(IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS, flags))
+#define HWFLAGS_DEFSTATE_SINGLE_SCAN_ON_ALL_BANDS 0
+#endif /* CONFIG_MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_TDLS_WIDER_BW_ON) &&	\
+     defined(CONFIG_MAC80211_HW_TDLS_WIDER_BW_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_TDLS_WIDER_BW_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_TDLS_WIDER_BW_OFF))
+#define HWFLAGS_CHECK_TDLS_WIDER_BW(flags) \
+	test_bit(IEEE80211_HW_TDLS_WIDER_BW, flags)
+#define HWFLAGS_DEFSTATE_TDLS_WIDER_BW -1
+#elif defined(CONFIG_MAC80211_HW_TDLS_WIDER_BW_ON)
+#define HWFLAGS_CHECK_TDLS_WIDER_BW(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_TDLS_WIDER_BW]) || \
+	 test_bit(IEEE80211_HW_TDLS_WIDER_BW, flags))
+#define HWFLAGS_DEFSTATE_TDLS_WIDER_BW 1
+#else /* CONFIG_MAC80211_HW_TDLS_WIDER_BW_OFF */
+#define HWFLAGS_CHECK_TDLS_WIDER_BW(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_TDLS_WIDER_BW]) && \
+	 test_bit(IEEE80211_HW_TDLS_WIDER_BW, flags))
+#define HWFLAGS_DEFSTATE_TDLS_WIDER_BW 0
+#endif /* CONFIG_MAC80211_HW_TDLS_WIDER_BW_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_SUPPORTS_AMSDU_IN_AMPDU_ON) &&	\
+     defined(CONFIG_MAC80211_HW_SUPPORTS_AMSDU_IN_AMPDU_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_SUPPORTS_AMSDU_IN_AMPDU_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_SUPPORTS_AMSDU_IN_AMPDU_OFF))
+#define HWFLAGS_CHECK_SUPPORTS_AMSDU_IN_AMPDU(flags) \
+	test_bit(IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU, flags)
+#define HWFLAGS_DEFSTATE_SUPPORTS_AMSDU_IN_AMPDU -1
+#elif defined(CONFIG_MAC80211_HW_SUPPORTS_AMSDU_IN_AMPDU_ON)
+#define HWFLAGS_CHECK_SUPPORTS_AMSDU_IN_AMPDU(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU]) || \
+	 test_bit(IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_AMSDU_IN_AMPDU 1
+#else /* CONFIG_MAC80211_HW_SUPPORTS_AMSDU_IN_AMPDU_OFF */
+#define HWFLAGS_CHECK_SUPPORTS_AMSDU_IN_AMPDU(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU]) && \
+	 test_bit(IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU, flags))
+#define HWFLAGS_DEFSTATE_SUPPORTS_AMSDU_IN_AMPDU 0
+#endif /* CONFIG_MAC80211_HW_SUPPORTS_AMSDU_IN_AMPDU_ON/OFF */
+
+#if (defined(CONFIG_MAC80211_HW_BEACON_TX_STATUS_ON) &&	\
+     defined(CONFIG_MAC80211_HW_BEACON_TX_STATUS_OFF)) ||	\
+    (!defined(CONFIG_MAC80211_HW_BEACON_TX_STATUS_ON) &&	\
+     !defined(CONFIG_MAC80211_HW_BEACON_TX_STATUS_OFF))
+#define HWFLAGS_CHECK_BEACON_TX_STATUS(flags) \
+	test_bit(IEEE80211_HW_BEACON_TX_STATUS, flags)
+#define HWFLAGS_DEFSTATE_BEACON_TX_STATUS -1
+#elif defined(CONFIG_MAC80211_HW_BEACON_TX_STATUS_ON)
+#define HWFLAGS_CHECK_BEACON_TX_STATUS(flags) \
+	(!static_key_false(&hwflags_keys[IEEE80211_HW_BEACON_TX_STATUS]) || \
+	 test_bit(IEEE80211_HW_BEACON_TX_STATUS, flags))
+#define HWFLAGS_DEFSTATE_BEACON_TX_STATUS 1
+#else /* CONFIG_MAC80211_HW_BEACON_TX_STATUS_OFF */
+#define HWFLAGS_CHECK_BEACON_TX_STATUS(flags) \
+	(static_key_false(&hwflags_keys[IEEE80211_HW_BEACON_TX_STATUS]) && \
+	 test_bit(IEEE80211_HW_BEACON_TX_STATUS, flags))
+#define HWFLAGS_DEFSTATE_BEACON_TX_STATUS 0
+#endif /* CONFIG_MAC80211_HW_BEACON_TX_STATUS_ON/OFF */
+
+
+#define ieee80211_local_check(local, flg)		\
+	HWFLAGS_CHECK_##flg((local)->hw.flags)
+
+void ieee80211_hwflags_sync_add(unsigned long *flags);
+void ieee80211_hwflags_sync_del(unsigned long *flags);
+#else /* CONFIG_JUMP_LABEL */
+#define ieee80211_local_check(local, flg)	\
+	test_bit(IEEE80211_HW_##flg, local->hw.flags)
+
+static inline void ieee80211_hwflags_sync_add(unsigned long *flags) {}
+static inline void ieee80211_hwflags_sync_del(unsigned long *flags) {}
+#endif /* CONFIG_JUMP_LABEL */
+
+#endif /* __mac80211_hwflags_h */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 46bd8965d164..0663eda5b478 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -33,6 +33,7 @@
 #include "key.h"
 #include "sta_info.h"
 #include "debug.h"
+#include "hwflags.h"
 
 extern const struct cfg80211_ops mac80211_config_ops;
 
@@ -1121,6 +1122,8 @@ struct ieee80211_local {
 
 	bool wiphy_ciphers_allocated;
 
+	bool registered;
+
 	bool use_chanctx;
 
 	/* protects the aggregated multicast list and filter calls */
@@ -1357,15 +1360,6 @@ struct ieee80211_local {
 	struct sk_buff_head skb_queue_tdls_chsw;
 };
 
-static inline bool _ieee80211_local_check(struct ieee80211_local *local,
-					  enum ieee80211_hw_flags flg)
-{
-	return test_bit(flg, local->hw.flags);
-}
-
-#define ieee80211_local_check(local, flg)	\
-	_ieee80211_local_check(local, IEEE80211_HW_##flg)
-
 static inline struct ieee80211_sub_if_data *
 IEEE80211_DEV_TO_SUB_IF(struct net_device *dev)
 {
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 84d7480fe7c8..03ad36ba4945 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1095,6 +1095,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 		goto fail_ifa6;
 #endif
 
+	ieee80211_hwflags_sync_add(local->hw.flags);
+	local->registered = true;
+
 	return 0;
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -1169,6 +1172,9 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 	ieee80211_wep_free(local);
 	ieee80211_led_exit(local);
 	kfree(local->int_scan_req);
+
+	local->registered = false;
+	ieee80211_hwflags_sync_del(local->hw.flags);
 }
 EXPORT_SYMBOL(ieee80211_unregister_hw);
 
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC 4/4] mac80211: test the static key code
  2015-11-09 22:02 [RFC 0/4] mac80211: jump labels for hw flags Johannes Berg
                   ` (2 preceding siblings ...)
  2015-11-09 22:02 ` [RFC 3/4] mac80211: use static keys for hw flags Johannes Berg
@ 2015-11-09 22:02 ` Johannes Berg
  2015-11-09 22:42 ` [RFC 0/4] mac80211: jump labels for hw flags Peter Zijlstra
  4 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2015-11-09 22:02 UTC (permalink / raw)
  To: linux-wireless; +Cc: Jason Baron, Peter Zijlstra, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Make hwsim select a few on/off symbols and check that the
result is as expected:
 * before 'registering' a device the branches are according
   to the Kconfig default only
 * 'registering' a device fixes that up to actually check
   the hardware flags
 * 'unregistering' again goes back to the default

Test this with a fake flags field that contains the *inverse*
of the Kconfig selections.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/Kconfig | 11 +++++++++++
 net/mac80211/hwflags.c       | 36 ++++++++++++++++++++++++++++++++++++
 net/mac80211/hwflags.h       |  2 ++
 net/mac80211/main.c          |  2 ++
 4 files changed, 51 insertions(+)

diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index f9f94229bf1b..f2a8fdca5ede 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -246,6 +246,17 @@ source "drivers/net/wireless/realtek/rtl818x/Kconfig"
 config MAC80211_HWSIM
 	tristate "Simulated radio testing tool for mac80211"
 	depends on MAC80211
+	select MAC80211_HW_SUPPORT_FAST_XMIT_ON
+	select MAC80211_HW_CHANCTX_STA_CSA_ON
+	select MAC80211_HW_SUPPORTS_HT_CCK_RATES_ON
+	select MAC80211_HW_QUEUE_CONTROL_ON
+	select MAC80211_HW_WANT_MONITOR_VIF_ON
+	select MAC80211_HW_AMPDU_AGGREGATION_ON
+	select MAC80211_HW_MFP_CAPABLE_ON
+	select MAC80211_HW_SIGNAL_DBM_ON
+	select MAC80211_HW_TDLS_WIDER_BW_ON
+	select MAC80211_HW_HAS_RATE_CONTROL_OFF
+	select MAC80211_HW_RX_INCLUDES_FCS_OFF
 	---help---
 	  This driver is a developer testing tool that can be used to test
 	  IEEE 802.11 networking stack (mac80211) functionality. This is not
diff --git a/net/mac80211/hwflags.c b/net/mac80211/hwflags.c
index 00386ca27eaf..69032d863a51 100644
--- a/net/mac80211/hwflags.c
+++ b/net/mac80211/hwflags.c
@@ -126,3 +126,39 @@ void ieee80211_hwflags_sync_del(unsigned long *flags)
 			static_key_slow_dec(&hwflags_keys[flg]);
 	}
 }
+
+void ieee80211_test_hwflags(void)
+{
+	struct {
+		struct {
+			unsigned long flags[2];
+		} hw;
+	} _local;
+
+	__set_bit(IEEE80211_HW_HAS_RATE_CONTROL, _local.hw.flags);
+	__clear_bit(IEEE80211_HW_SUPPORT_FAST_XMIT, _local.hw.flags);
+
+	/* before the sync_add(), we expect only as per Kconfig */
+	if (ieee80211_local_check(&_local, HAS_RATE_CONTROL))
+		printk(KERN_DEBUG "BAD: HW rate control\n");
+	if (!ieee80211_local_check(&_local, SUPPORT_FAST_XMIT))
+		printk(KERN_DEBUG "BAD: !SUPPORT_FAST_XMIT\n");
+
+	ieee80211_hwflags_sync_add(_local.hw.flags);
+	printk(KERN_DEBUG "added\n");
+
+	/* now it should be like as per flags */
+	if (!ieee80211_local_check(&_local, HAS_RATE_CONTROL))
+		printk(KERN_DEBUG "BAD: !HW rate control\n");
+	if (ieee80211_local_check(&_local, SUPPORT_FAST_XMIT))
+		printk(KERN_DEBUG "BAD: SUPPORT_FAST_XMIT\n");
+
+	ieee80211_hwflags_sync_del(_local.hw.flags);
+	printk(KERN_DEBUG "removed\n");
+
+	/* after remove it should be as before */
+	if (ieee80211_local_check(&_local, HAS_RATE_CONTROL))
+		printk(KERN_DEBUG "BAD: HW rate control\n");
+	if (!ieee80211_local_check(&_local, SUPPORT_FAST_XMIT))
+		printk(KERN_DEBUG "BAD: !SUPPORT_FAST_XMIT\n");
+}
diff --git a/net/mac80211/hwflags.h b/net/mac80211/hwflags.h
index 1a690f72a43f..7714b4bd6a57 100644
--- a/net/mac80211/hwflags.h
+++ b/net/mac80211/hwflags.h
@@ -635,4 +635,6 @@ static inline void ieee80211_hwflags_sync_add(unsigned long *flags) {}
 static inline void ieee80211_hwflags_sync_del(unsigned long *flags) {}
 #endif /* CONFIG_JUMP_LABEL */
 
+void ieee80211_test_hwflags(void);
+
 #endif /* __mac80211_hwflags_h */
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 03ad36ba4945..d64aae164d7a 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1228,6 +1228,8 @@ static int __init ieee80211_init(void)
 	if (ret)
 		goto err_netdev;
 
+	ieee80211_test_hwflags();
+
 	return 0;
  err_netdev:
 	rc80211_minstrel_ht_exit();
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFC 0/4] mac80211: jump labels for hw flags
  2015-11-09 22:02 [RFC 0/4] mac80211: jump labels for hw flags Johannes Berg
                   ` (3 preceding siblings ...)
  2015-11-09 22:02 ` [RFC 4/4] mac80211: test the static key code Johannes Berg
@ 2015-11-09 22:42 ` Peter Zijlstra
  2015-11-10  7:43   ` Johannes Berg
  4 siblings, 1 reply; 7+ messages in thread
From: Peter Zijlstra @ 2015-11-09 22:42 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Jason Baron, Steven Rostedt

On Mon, Nov 09, 2015 at 11:02:33PM +0100, Johannes Berg wrote:
> As far as the code is concerned, there are two really ugly things:
>  1) I still use struct static_key - couldn't quite figure it out
>     with static_key_false. I think I can replace it easily though.

Yeah, didn't see anything that would avoid using struct
static_key_false. Was there anything specific that was difficult?

>  2) There are a lot of boilerplate ifdefs/macros.

I'm sure we can reduce that a lot with some CPP trickery, lots of that
looked like endless repetition of the same pattern.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC 0/4] mac80211: jump labels for hw flags
  2015-11-09 22:42 ` [RFC 0/4] mac80211: jump labels for hw flags Peter Zijlstra
@ 2015-11-10  7:43   ` Johannes Berg
  0 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2015-11-10  7:43 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-wireless, Jason Baron, Steven Rostedt

On Mon, 2015-11-09 at 23:42 +0100, Peter Zijlstra wrote:
> On Mon, Nov 09, 2015 at 11:02:33PM +0100, Johannes Berg wrote:
> > As far as the code is concerned, there are two really ugly things:
> >  1) I still use struct static_key - couldn't quite figure it out
> >     with static_key_false. I think I can replace it easily though.
> 
> Yeah, didn't see anything that would avoid using struct
> static_key_false. Was there anything specific that was difficult?

No, I think I just needed to wrap my head around the _ON and _OFF
semantics. I had originally thought I needed both _true and _false
static keys.

> >  2) There are a lot of boilerplate ifdefs/macros.
> 
> I'm sure we can reduce that a lot with some CPP trickery, lots of
> that looked like endless repetition of the same pattern.

Oh, it is, and I even generated it that way. I just haven't quite
figured out how to do that since you can't put an #if into a macro
expansion. Perhaps some tricks with the optimiser "if (0 && ..." or so.
I'll play with it.

For now though I think we need to figure out if we want this at all :)

johannes

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-11-10  7:43 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-09 22:02 [RFC 0/4] mac80211: jump labels for hw flags Johannes Berg
2015-11-09 22:02 ` [RFC 1/4] mac80211: add ieee80211_hw_clear() Johannes Berg
2015-11-09 22:02 ` [RFC 2/4] mac80211: introduce ieee80211_local_check() Johannes Berg
2015-11-09 22:02 ` [RFC 3/4] mac80211: use static keys for hw flags Johannes Berg
2015-11-09 22:02 ` [RFC 4/4] mac80211: test the static key code Johannes Berg
2015-11-09 22:42 ` [RFC 0/4] mac80211: jump labels for hw flags Peter Zijlstra
2015-11-10  7:43   ` Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.