All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v4 0/8] mac80211: jump labels for HW flags
@ 2015-11-12  8:47 Johannes Berg
  2015-11-12  8:47 ` [RFC v4 1/8] mac80211: add ieee80211_hw_clear() Johannes Berg
                   ` (7 more replies)
  0 siblings, 8 replies; 18+ messages in thread
From: Johannes Berg @ 2015-11-12  8:47 UTC (permalink / raw)
  To: linux-wireless; +Cc: Jason Baron, Peter Zijlstra, Steven Rostedt, Michal Marek

Changes since v3:
 * fix Kconfig count to count only enabled (!= n) symbols
 * fix code when CONFIG_JUMP_LABEL is not enabled

Changes since v2:
 * introduce Kconfig count and use it instead of _ON/_OFF in
   the first few patches and described below
   (I'll squash that later if I don't abandon the whole thing)

Changes since v1:
 * use struct static_key_false
 * get rid of all those generated macros and use the optimiser

-----

This was an experiment I thought of on Sunday ...

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] 18+ messages in thread

* [RFC v4 1/8] mac80211: add ieee80211_hw_clear()
  2015-11-12  8:47 [RFC v4 0/8] mac80211: jump labels for HW flags Johannes Berg
@ 2015-11-12  8:47 ` Johannes Berg
  2015-11-12  8:47 ` [RFC v4 2/8] mac80211: introduce ieee80211_local_check() Johannes Berg
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Johannes Berg @ 2015-11-12  8:47 UTC (permalink / raw)
  To: linux-wireless
  Cc: Jason Baron, Peter Zijlstra, Steven Rostedt, Michal Marek, 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] 18+ messages in thread

* [RFC v4 2/8] mac80211: introduce ieee80211_local_check()
  2015-11-12  8:47 [RFC v4 0/8] mac80211: jump labels for HW flags Johannes Berg
  2015-11-12  8:47 ` [RFC v4 1/8] mac80211: add ieee80211_hw_clear() Johannes Berg
@ 2015-11-12  8:47 ` Johannes Berg
  2015-11-12  8:47 ` [RFC v4 3/8] mac80211: use static keys for hw flags Johannes Berg
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Johannes Berg @ 2015-11-12  8:47 UTC (permalink / raw)
  To: linux-wireless
  Cc: Jason Baron, Peter Zijlstra, Steven Rostedt, Michal Marek, 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] 18+ messages in thread

* [RFC v4 3/8] mac80211: use static keys for hw flags
  2015-11-12  8:47 [RFC v4 0/8] mac80211: jump labels for HW flags Johannes Berg
  2015-11-12  8:47 ` [RFC v4 1/8] mac80211: add ieee80211_hw_clear() Johannes Berg
  2015-11-12  8:47 ` [RFC v4 2/8] mac80211: introduce ieee80211_local_check() Johannes Berg
@ 2015-11-12  8:47 ` Johannes Berg
  2015-11-13 16:22   ` Steven Rostedt
  2015-11-12  8:47 ` [RFC v4 4/8] mac80211: test the static key code Johannes Berg
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Johannes Berg @ 2015-11-12  8:47 UTC (permalink / raw)
  To: linux-wireless
  Cc: Jason Baron, Peter Zijlstra, Steven Rostedt, Michal Marek, 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       |  25 +++---
 net/mac80211/Kconfig         |   2 +
 net/mac80211/Kconfig.hwflags | 192 +++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/Makefile        |   1 +
 net/mac80211/hwflags.c       | 129 +++++++++++++++++++++++++++++
 net/mac80211/hwflags.h       |  89 ++++++++++++++++++++
 net/mac80211/ieee80211_i.h   |  12 +--
 net/mac80211/main.c          |   6 ++
 8 files changed, 437 insertions(+), 19 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..586aa89ad8bd 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2078,19 +2078,24 @@ 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)
+#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)
 {
-	__set_bit(flg, hw->flags);
+	if (set)
+		__set_bit(flg, hw->flags);
+	else
+		__clear_bit(flg, hw->flags);
 }
-#define ieee80211_hw_set(hw, flg)	_ieee80211_hw_set(hw, IEEE80211_HW_##flg)
+#endif /* CONFIG_JUMP_LABEL */
 
-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)
+#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..3beeee512f91
--- /dev/null
+++ b/net/mac80211/hwflags.c
@@ -0,0 +1,129 @@
+/*
+ * 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"
+
+struct static_key_false hwflags_keys[NUM_IEEE80211_HW_FLAGS] = {
+	[0 ... NUM_IEEE80211_HW_FLAGS - 1] = STATIC_KEY_FALSE_INIT,
+};
+
+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_branch_dec(&hwflags_keys[flg]);
+	else
+		static_branch_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_branch_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_branch_dec(&hwflags_keys[flg]);
+	}
+}
diff --git a/net/mac80211/hwflags.h b/net/mac80211/hwflags.h
new file mode 100644
index 000000000000..e220c5e04406
--- /dev/null
+++ b/net/mac80211/hwflags.h
@@ -0,0 +1,89 @@
+/*
+ * 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_false hwflags_keys[NUM_IEEE80211_HW_FLAGS];
+
+#ifdef CONFIG_JUMP_LABEL
+#define _HWFLAGS_DEFSTATE(_name, _on, _off)				\
+	HWFLAGS_DEFSTATE_##_name = -1 + ((_on) ^ (_off)) * (1 + _on)
+#define HWFLAGS_DEFSTATE(_name)						\
+	_HWFLAGS_DEFSTATE(_name,					\
+			  IS_ENABLED(CONFIG_MAC80211_HW_##_name##_ON),	\
+			  IS_ENABLED(CONFIG_MAC80211_HW_##_name##_OFF))
+
+enum hwflags_defstates {
+HWFLAGS_DEFSTATE(HAS_RATE_CONTROL),
+HWFLAGS_DEFSTATE(RX_INCLUDES_FCS),
+HWFLAGS_DEFSTATE(HOST_BROADCAST_PS_BUFFERING),
+HWFLAGS_DEFSTATE(SIGNAL_UNSPEC),
+HWFLAGS_DEFSTATE(SIGNAL_DBM),
+HWFLAGS_DEFSTATE(NEED_DTIM_BEFORE_ASSOC),
+HWFLAGS_DEFSTATE(SPECTRUM_MGMT),
+HWFLAGS_DEFSTATE(AMPDU_AGGREGATION),
+HWFLAGS_DEFSTATE(SUPPORTS_PS),
+HWFLAGS_DEFSTATE(PS_NULLFUNC_STACK),
+HWFLAGS_DEFSTATE(SUPPORTS_DYNAMIC_PS),
+HWFLAGS_DEFSTATE(MFP_CAPABLE),
+HWFLAGS_DEFSTATE(WANT_MONITOR_VIF),
+HWFLAGS_DEFSTATE(NO_AUTO_VIF),
+HWFLAGS_DEFSTATE(SW_CRYPTO_CONTROL),
+HWFLAGS_DEFSTATE(SUPPORT_FAST_XMIT),
+HWFLAGS_DEFSTATE(REPORTS_TX_ACK_STATUS),
+HWFLAGS_DEFSTATE(CONNECTION_MONITOR),
+HWFLAGS_DEFSTATE(QUEUE_CONTROL),
+HWFLAGS_DEFSTATE(SUPPORTS_PER_STA_GTK),
+HWFLAGS_DEFSTATE(AP_LINK_PS),
+HWFLAGS_DEFSTATE(TX_AMPDU_SETUP_IN_HW),
+HWFLAGS_DEFSTATE(SUPPORTS_RC_TABLE),
+HWFLAGS_DEFSTATE(P2P_DEV_ADDR_FOR_INTF),
+HWFLAGS_DEFSTATE(TIMING_BEACON_ONLY),
+HWFLAGS_DEFSTATE(SUPPORTS_HT_CCK_RATES),
+HWFLAGS_DEFSTATE(CHANCTX_STA_CSA),
+HWFLAGS_DEFSTATE(SUPPORTS_CLONED_SKBS),
+HWFLAGS_DEFSTATE(SINGLE_SCAN_ON_ALL_BANDS),
+HWFLAGS_DEFSTATE(TDLS_WIDER_BW),
+HWFLAGS_DEFSTATE(SUPPORTS_AMSDU_IN_AMPDU),
+HWFLAGS_DEFSTATE(BEACON_TX_STATUS),
+};
+
+bool _____optimisation_missing(void);
+
+#define ieee80211_local_check(local, flg)				\
+({									\
+	enum ieee80211_hw_flags flag = IEEE80211_HW_##flg;		\
+	bool result;							\
+									\
+	if (HWFLAGS_DEFSTATE_##flg == -1)				\
+		result = test_bit(flag, (local)->hw.flags);		\
+	else if (HWFLAGS_DEFSTATE_##flg == 1)				\
+		result = (!static_branch_unlikely(&hwflags_keys[flag]) ||\
+			  test_bit(flag, (local)->hw.flags));		\
+	else if (HWFLAGS_DEFSTATE_##flg == 0)				\
+		result = (static_branch_unlikely(&hwflags_keys[flag]) &&\
+			  test_bit(flag, (local)->hw.flags));		\
+	else								\
+		result = _____optimisation_missing();			\
+									\
+	result;								\
+})
+
+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] 18+ messages in thread

* [RFC v4 4/8] mac80211: test the static key code
  2015-11-12  8:47 [RFC v4 0/8] mac80211: jump labels for HW flags Johannes Berg
                   ` (2 preceding siblings ...)
  2015-11-12  8:47 ` [RFC v4 3/8] mac80211: use static keys for hw flags Johannes Berg
@ 2015-11-12  8:47 ` Johannes Berg
  2015-11-12  8:47 ` [RFC v4 5/8] mac80211: generate hw flags from include file Johannes Berg
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Johannes Berg @ 2015-11-12  8:47 UTC (permalink / raw)
  To: linux-wireless
  Cc: Jason Baron, Peter Zijlstra, Steven Rostedt, Michal Marek, 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 3beeee512f91..eca0e3ee6818 100644
--- a/net/mac80211/hwflags.c
+++ b/net/mac80211/hwflags.c
@@ -127,3 +127,39 @@ void ieee80211_hwflags_sync_del(unsigned long *flags)
 			static_branch_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 e220c5e04406..06f0a9f64fe6 100644
--- a/net/mac80211/hwflags.h
+++ b/net/mac80211/hwflags.h
@@ -86,4 +86,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] 18+ messages in thread

* [RFC v4 5/8] mac80211: generate hw flags from include file
  2015-11-12  8:47 [RFC v4 0/8] mac80211: jump labels for HW flags Johannes Berg
                   ` (3 preceding siblings ...)
  2015-11-12  8:47 ` [RFC v4 4/8] mac80211: test the static key code Johannes Berg
@ 2015-11-12  8:47 ` Johannes Berg
  2015-11-13 16:25   ` Steven Rostedt
  2015-11-12  8:47 ` [RFC v4 6/8] kconfig: introduce "count" Johannes Berg
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Johannes Berg @ 2015-11-12  8:47 UTC (permalink / raw)
  To: linux-wireless
  Cc: Jason Baron, Peter Zijlstra, Steven Rostedt, Michal Marek, Johannes Berg

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

Instead of having to list all the hw flags in many places, just
list the macro to generate everything in a new include file and
include it in the proper places.

Unfortunately this breaks docbook processing since that doesn't
pre-process the file. It also doesn't generate the necessary
Kconfig items.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211-hwflags.h | 33 ++++++++++++++++++++
 include/net/mac80211.h         | 37 ++---------------------
 net/mac80211/debugfs.c         | 47 +++--------------------------
 net/mac80211/hwflags.c         | 68 +++---------------------------------------
 net/mac80211/hwflags.h         | 47 +++++------------------------
 5 files changed, 52 insertions(+), 180 deletions(-)
 create mode 100644 include/net/mac80211-hwflags.h

diff --git a/include/net/mac80211-hwflags.h b/include/net/mac80211-hwflags.h
new file mode 100644
index 000000000000..c0450391088c
--- /dev/null
+++ b/include/net/mac80211-hwflags.h
@@ -0,0 +1,33 @@
+/* this file intentionally has no include guard */
+DEFINE_HWFLAG(HAS_RATE_CONTROL)
+DEFINE_HWFLAG(RX_INCLUDES_FCS)
+DEFINE_HWFLAG(HOST_BROADCAST_PS_BUFFERING)
+DEFINE_HWFLAG(SIGNAL_UNSPEC)
+DEFINE_HWFLAG(SIGNAL_DBM)
+DEFINE_HWFLAG(NEED_DTIM_BEFORE_ASSOC)
+DEFINE_HWFLAG(SPECTRUM_MGMT)
+DEFINE_HWFLAG(AMPDU_AGGREGATION)
+DEFINE_HWFLAG(SUPPORTS_PS)
+DEFINE_HWFLAG(PS_NULLFUNC_STACK)
+DEFINE_HWFLAG(SUPPORTS_DYNAMIC_PS)
+DEFINE_HWFLAG(MFP_CAPABLE)
+DEFINE_HWFLAG(WANT_MONITOR_VIF)
+DEFINE_HWFLAG(NO_AUTO_VIF)
+DEFINE_HWFLAG(SW_CRYPTO_CONTROL)
+DEFINE_HWFLAG(SUPPORT_FAST_XMIT)
+DEFINE_HWFLAG(REPORTS_TX_ACK_STATUS)
+DEFINE_HWFLAG(CONNECTION_MONITOR)
+DEFINE_HWFLAG(QUEUE_CONTROL)
+DEFINE_HWFLAG(SUPPORTS_PER_STA_GTK)
+DEFINE_HWFLAG(AP_LINK_PS)
+DEFINE_HWFLAG(TX_AMPDU_SETUP_IN_HW)
+DEFINE_HWFLAG(SUPPORTS_RC_TABLE)
+DEFINE_HWFLAG(P2P_DEV_ADDR_FOR_INTF)
+DEFINE_HWFLAG(TIMING_BEACON_ONLY)
+DEFINE_HWFLAG(SUPPORTS_HT_CCK_RATES)
+DEFINE_HWFLAG(CHANCTX_STA_CSA)
+DEFINE_HWFLAG(SUPPORTS_CLONED_SKBS)
+DEFINE_HWFLAG(SINGLE_SCAN_ON_ALL_BANDS)
+DEFINE_HWFLAG(TDLS_WIDER_BW)
+DEFINE_HWFLAG(SUPPORTS_AMSDU_IN_AMPDU)
+DEFINE_HWFLAG(BEACON_TX_STATUS)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 586aa89ad8bd..6d81e0c204e7 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1904,40 +1904,9 @@ struct ieee80211_txq {
  * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
  */
 enum ieee80211_hw_flags {
-	IEEE80211_HW_HAS_RATE_CONTROL,
-	IEEE80211_HW_RX_INCLUDES_FCS,
-	IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING,
-	IEEE80211_HW_SIGNAL_UNSPEC,
-	IEEE80211_HW_SIGNAL_DBM,
-	IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC,
-	IEEE80211_HW_SPECTRUM_MGMT,
-	IEEE80211_HW_AMPDU_AGGREGATION,
-	IEEE80211_HW_SUPPORTS_PS,
-	IEEE80211_HW_PS_NULLFUNC_STACK,
-	IEEE80211_HW_SUPPORTS_DYNAMIC_PS,
-	IEEE80211_HW_MFP_CAPABLE,
-	IEEE80211_HW_WANT_MONITOR_VIF,
-	IEEE80211_HW_NO_AUTO_VIF,
-	IEEE80211_HW_SW_CRYPTO_CONTROL,
-	IEEE80211_HW_SUPPORT_FAST_XMIT,
-	IEEE80211_HW_REPORTS_TX_ACK_STATUS,
-	IEEE80211_HW_CONNECTION_MONITOR,
-	IEEE80211_HW_QUEUE_CONTROL,
-	IEEE80211_HW_SUPPORTS_PER_STA_GTK,
-	IEEE80211_HW_AP_LINK_PS,
-	IEEE80211_HW_TX_AMPDU_SETUP_IN_HW,
-	IEEE80211_HW_SUPPORTS_RC_TABLE,
-	IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF,
-	IEEE80211_HW_TIMING_BEACON_ONLY,
-	IEEE80211_HW_SUPPORTS_HT_CCK_RATES,
-	IEEE80211_HW_CHANCTX_STA_CSA,
-	IEEE80211_HW_SUPPORTS_CLONED_SKBS,
-	IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS,
-	IEEE80211_HW_TDLS_WIDER_BW,
-	IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU,
-	IEEE80211_HW_BEACON_TX_STATUS,
-
-	/* keep last, obviously */
+#define DEFINE_HWFLAG(_flg) IEEE80211_HW_##_flg,
+#include <net/mac80211-hwflags.h>
+#undef DEFINE_HWFLAG
 	NUM_IEEE80211_HW_FLAGS
 };
 
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 4d2aaebd4f97..dc0eca604be1 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -91,44 +91,10 @@ static const struct file_operations reset_ops = {
 };
 #endif
 
-static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS + 1] = {
-#define FLAG(F)	[IEEE80211_HW_##F] = #F
-	FLAG(HAS_RATE_CONTROL),
-	FLAG(RX_INCLUDES_FCS),
-	FLAG(HOST_BROADCAST_PS_BUFFERING),
-	FLAG(SIGNAL_UNSPEC),
-	FLAG(SIGNAL_DBM),
-	FLAG(NEED_DTIM_BEFORE_ASSOC),
-	FLAG(SPECTRUM_MGMT),
-	FLAG(AMPDU_AGGREGATION),
-	FLAG(SUPPORTS_PS),
-	FLAG(PS_NULLFUNC_STACK),
-	FLAG(SUPPORTS_DYNAMIC_PS),
-	FLAG(MFP_CAPABLE),
-	FLAG(WANT_MONITOR_VIF),
-	FLAG(NO_AUTO_VIF),
-	FLAG(SW_CRYPTO_CONTROL),
-	FLAG(SUPPORT_FAST_XMIT),
-	FLAG(REPORTS_TX_ACK_STATUS),
-	FLAG(CONNECTION_MONITOR),
-	FLAG(QUEUE_CONTROL),
-	FLAG(SUPPORTS_PER_STA_GTK),
-	FLAG(AP_LINK_PS),
-	FLAG(TX_AMPDU_SETUP_IN_HW),
-	FLAG(SUPPORTS_RC_TABLE),
-	FLAG(P2P_DEV_ADDR_FOR_INTF),
-	FLAG(TIMING_BEACON_ONLY),
-	FLAG(SUPPORTS_HT_CCK_RATES),
-	FLAG(CHANCTX_STA_CSA),
-	FLAG(SUPPORTS_CLONED_SKBS),
-	FLAG(SINGLE_SCAN_ON_ALL_BANDS),
-	FLAG(TDLS_WIDER_BW),
-	FLAG(SUPPORTS_AMSDU_IN_AMPDU),
-	FLAG(BEACON_TX_STATUS),
-
-	/* keep last for the build bug below */
-	(void *)0x1
-#undef FLAG
+static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS] = {
+#define DEFINE_HWFLAG(_flg)	[IEEE80211_HW_##_flg] = #_flg,
+#include <net/mac80211-hwflags.h>
+#undef DEFINE_HWFLAG
 };
 
 static ssize_t hwflags_read(struct file *file, char __user *user_buf,
@@ -144,11 +110,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
 	if (!buf)
 		return -ENOMEM;
 
-	/* fail compilation if somebody adds or removes
-	 * a flag without updating the name array above
-	 */
-	BUILD_BUG_ON(hw_flag_names[NUM_IEEE80211_HW_FLAGS] != (void *)0x1);
-
 	for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) {
 		if (test_bit(i, local->hw.flags))
 			pos += scnprintf(pos, end - pos, "%s\n",
diff --git a/net/mac80211/hwflags.c b/net/mac80211/hwflags.c
index eca0e3ee6818..ef4fc0d0f517 100644
--- a/net/mac80211/hwflags.c
+++ b/net/mac80211/hwflags.c
@@ -14,70 +14,10 @@ struct static_key_false 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,
+#define DEFINE_HWFLAG(_flg)	\
+	[IEEE80211_HW_##_flg] = HWFLAGS_DEFSTATE_##_flg,
+#include <net/mac80211-hwflags.h>
+#undef DEFINE_HWFLAG
 };
 
 void ieee80211_hw_mod_flag(struct ieee80211_hw *hw,
diff --git a/net/mac80211/hwflags.h b/net/mac80211/hwflags.h
index 06f0a9f64fe6..82bf89658cb7 100644
--- a/net/mac80211/hwflags.h
+++ b/net/mac80211/hwflags.h
@@ -13,46 +13,15 @@
 extern struct static_key_false hwflags_keys[NUM_IEEE80211_HW_FLAGS];
 
 #ifdef CONFIG_JUMP_LABEL
-#define _HWFLAGS_DEFSTATE(_name, _on, _off)				\
-	HWFLAGS_DEFSTATE_##_name = -1 + ((_on) ^ (_off)) * (1 + _on)
-#define HWFLAGS_DEFSTATE(_name)						\
-	_HWFLAGS_DEFSTATE(_name,					\
-			  IS_ENABLED(CONFIG_MAC80211_HW_##_name##_ON),	\
-			  IS_ENABLED(CONFIG_MAC80211_HW_##_name##_OFF))
-
 enum hwflags_defstates {
-HWFLAGS_DEFSTATE(HAS_RATE_CONTROL),
-HWFLAGS_DEFSTATE(RX_INCLUDES_FCS),
-HWFLAGS_DEFSTATE(HOST_BROADCAST_PS_BUFFERING),
-HWFLAGS_DEFSTATE(SIGNAL_UNSPEC),
-HWFLAGS_DEFSTATE(SIGNAL_DBM),
-HWFLAGS_DEFSTATE(NEED_DTIM_BEFORE_ASSOC),
-HWFLAGS_DEFSTATE(SPECTRUM_MGMT),
-HWFLAGS_DEFSTATE(AMPDU_AGGREGATION),
-HWFLAGS_DEFSTATE(SUPPORTS_PS),
-HWFLAGS_DEFSTATE(PS_NULLFUNC_STACK),
-HWFLAGS_DEFSTATE(SUPPORTS_DYNAMIC_PS),
-HWFLAGS_DEFSTATE(MFP_CAPABLE),
-HWFLAGS_DEFSTATE(WANT_MONITOR_VIF),
-HWFLAGS_DEFSTATE(NO_AUTO_VIF),
-HWFLAGS_DEFSTATE(SW_CRYPTO_CONTROL),
-HWFLAGS_DEFSTATE(SUPPORT_FAST_XMIT),
-HWFLAGS_DEFSTATE(REPORTS_TX_ACK_STATUS),
-HWFLAGS_DEFSTATE(CONNECTION_MONITOR),
-HWFLAGS_DEFSTATE(QUEUE_CONTROL),
-HWFLAGS_DEFSTATE(SUPPORTS_PER_STA_GTK),
-HWFLAGS_DEFSTATE(AP_LINK_PS),
-HWFLAGS_DEFSTATE(TX_AMPDU_SETUP_IN_HW),
-HWFLAGS_DEFSTATE(SUPPORTS_RC_TABLE),
-HWFLAGS_DEFSTATE(P2P_DEV_ADDR_FOR_INTF),
-HWFLAGS_DEFSTATE(TIMING_BEACON_ONLY),
-HWFLAGS_DEFSTATE(SUPPORTS_HT_CCK_RATES),
-HWFLAGS_DEFSTATE(CHANCTX_STA_CSA),
-HWFLAGS_DEFSTATE(SUPPORTS_CLONED_SKBS),
-HWFLAGS_DEFSTATE(SINGLE_SCAN_ON_ALL_BANDS),
-HWFLAGS_DEFSTATE(TDLS_WIDER_BW),
-HWFLAGS_DEFSTATE(SUPPORTS_AMSDU_IN_AMPDU),
-HWFLAGS_DEFSTATE(BEACON_TX_STATUS),
+#define __DEFINE_HWFLAG(_flg, _on, _off)				\
+	HWFLAGS_DEFSTATE_##_flg = -1 + ((_on) ^ (_off)) * (1 + _on),
+#define DEFINE_HWFLAG(_flg)						\
+	__DEFINE_HWFLAG(_flg,						\
+			IS_ENABLED(CONFIG_MAC80211_HW_##_flg##_ON),	\
+			IS_ENABLED(CONFIG_MAC80211_HW_##_flg##_OFF))
+#include <net/mac80211-hwflags.h>
+#undef DEFINE_HWFLAG
 };
 
 bool _____optimisation_missing(void);
-- 
2.6.2


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

* [RFC v4 6/8] kconfig: introduce "count"
  2015-11-12  8:47 [RFC v4 0/8] mac80211: jump labels for HW flags Johannes Berg
                   ` (4 preceding siblings ...)
  2015-11-12  8:47 ` [RFC v4 5/8] mac80211: generate hw flags from include file Johannes Berg
@ 2015-11-12  8:47 ` Johannes Berg
  2015-11-13 16:26   ` Steven Rostedt
  2015-11-12  8:47 ` [RFC v4 7/8] kconfig: regenerate the shipped files Johannes Berg
  2015-11-12  8:47 ` [RFC v4 8/8] mac80211: use Kconfig counters to determine feature optimisation Johannes Berg
  7 siblings, 1 reply; 18+ messages in thread
From: Johannes Berg @ 2015-11-12  8:47 UTC (permalink / raw)
  To: linux-wireless
  Cc: Jason Baron, Peter Zijlstra, Steven Rostedt, Michal Marek, Johannes Berg

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

"count" works similar to "select"; take, for example, this snippet:

    config MY_COUNTER
            int

    config MY_DRIVER_1
            bool "my driver 1"
            count MY_COUNTER

    config MY_DRIVER_2
            bool "my driver 2"
            count MY_COUNTER

This will get MY_COUNTER to have a value of 0, 1 or 2, depending
on whether or not MY_DRIVER_1/MY_DRIVER_2 are not at all, one or
both selected respectively.

This can be useful for certain optimization purposes but I'm sure
people will come up with other creative usage.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 Documentation/kbuild/kconfig-language.txt |  7 +++++++
 scripts/kconfig/expr.h                    |  1 +
 scripts/kconfig/menu.c                    | 28 +++++++++++++++++++++++++++-
 scripts/kconfig/symbol.c                  | 30 +++++++++++++++++++++++++++++-
 scripts/kconfig/zconf.gperf               |  1 +
 scripts/kconfig/zconf.y                   | 16 ++++++++++++++--
 6 files changed, 79 insertions(+), 4 deletions(-)

diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
index 350f733bf2c7..cee587254d3b 100644
--- a/Documentation/kbuild/kconfig-language.txt
+++ b/Documentation/kbuild/kconfig-language.txt
@@ -113,6 +113,13 @@ applicable everywhere (see syntax).
 	That will limit the usefulness but on the other hand avoid
 	the illegal configurations all over.
 
+- counting: "count" <symbol> ["if" <expr>]
+  If, for some reason, it is desired to understand the number of times a
+  given symbol is selected, that can be achieved by using "count" instead
+  of select. The <symbol> must be an int, and the default value is added
+  to the count.
+  A lot of the caveats for "select" apply here since it's very similar.
+
 - limiting menu display: "visible if" <expr>
   This attribute is only applicable to menu blocks, if the condition is
   false, the menu block is not displayed to the user (the symbols
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 973b6f733368..c77c8c30dd52 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -139,6 +139,7 @@ enum prop_type {
 	P_RANGE,    /* range 7..100 (for a symbol) */
 	P_ENV,      /* value from environment variable */
 	P_SYMBOL,   /* where a symbol is defined */
+	P_COUNT,    /* count BAR - increments BAR counter */
 };
 
 struct property {
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index b05cc3d4a9be..0f7ef400741a 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -265,6 +265,18 @@ static void sym_check_prop(struct symbol *sym)
 				    "accept arguments of boolean and "
 				    "tristate type", sym2->name);
 			break;
+		case P_COUNT:
+			sym2 = prop_get_symbol(prop);
+			if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
+				prop_warn(prop,
+				    "config symbol '%s' uses select, but is "
+				    "not boolean or tristate", sym->name);
+			else if (sym2->type != S_INT)
+				prop_warn(prop,
+				    "'%s' has wrong type. 'count' only "
+				    "accept arguments of int type",
+				    sym2->name);
+			break;
 		case P_RANGE:
 			if (sym->type != S_INT && sym->type != S_HEX)
 				prop_warn(prop, "range is only allowed "
@@ -333,6 +345,9 @@ void menu_finalize(struct menu *parent)
 					struct symbol *es = prop_get_symbol(prop);
 					es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
 							expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
+				} else if (prop->type == P_COUNT) {
+					struct symbol *es = prop_get_symbol(prop);
+					es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, expr_alloc_symbol(menu->sym));
 				}
 			}
 		}
@@ -657,10 +672,21 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
 			str_printf(r, " && ");
 		expr_gstr_print(prop->expr, r);
 	}
+	for_all_properties(sym, prop, P_COUNT) {
+		if (!hit) {
+			str_append(r, "  Counts: ");
+			hit = true;
+		} else
+			str_printf(r, " && ");
+		expr_gstr_print(prop->expr, r);
+	}
 	if (hit)
 		str_append(r, "\n");
 	if (sym->rev_dep.expr) {
-		str_append(r, _("  Selected by: "));
+		if (sym->type != S_INT)
+			str_append(r, _("  Selected by: "));
+		else
+			str_append(r, _("  Counted by: "));
 		expr_gstr_print(sym->rev_dep.expr, r);
 		str_append(r, "\n");
 	}
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 50878dc025a5..c50835f28243 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -310,6 +310,21 @@ static struct symbol *sym_calc_choice(struct symbol *sym)
 	return def_sym;
 }
 
+static unsigned long long count_or_symbols(struct expr *e)
+{
+	switch (e->type) {
+	case E_SYMBOL:
+		sym_calc_value(e->left.sym);
+		return e->left.sym->curr.tri != no;
+	case E_OR:
+		return count_or_symbols(e->left.expr) +
+		       count_or_symbols(e->right.expr);
+	default:
+		fprintf(stderr, "warning: unexpected expression in count");
+		return 0;
+	}
+}
+
 void sym_calc_value(struct symbol *sym)
 {
 	struct symbol_value newval, oldval;
@@ -421,6 +436,15 @@ void sym_calc_value(struct symbol *sym)
 				newval.val = ds->curr.val;
 			}
 		}
+		if (sym->rev_dep.expr) {
+			long long val = strtoll(newval.val, NULL, 0);
+			char *buf = xmalloc(22);
+
+			val += count_or_symbols(sym->rev_dep.expr);
+			sprintf(buf, "%lld", val);
+			newval.val = buf;
+			sym->flags |= SYMBOL_WRITE;
+		}
 		break;
 	default:
 		;
@@ -1197,7 +1221,9 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
 		goto out;
 
 	for (prop = sym->prop; prop; prop = prop->next) {
-		if (prop->type == P_CHOICE || prop->type == P_SELECT)
+		if (prop->type == P_CHOICE ||
+		    prop->type == P_SELECT ||
+		    prop->type == P_COUNT)
 			continue;
 		stack.prop = prop;
 		sym2 = sym_check_expr_deps(prop->visible.expr);
@@ -1336,6 +1362,8 @@ const char *prop_get_type_name(enum prop_type type)
 		return "choice";
 	case P_SELECT:
 		return "select";
+	case P_COUNT:
+		return "count";
 	case P_RANGE:
 		return "range";
 	case P_SYMBOL:
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf
index ac498f01b449..46ce5833887e 100644
--- a/scripts/kconfig/zconf.gperf
+++ b/scripts/kconfig/zconf.gperf
@@ -46,4 +46,5 @@ modules,	T_OPT_MODULES,	TF_OPTION
 defconfig_list,	T_OPT_DEFCONFIG_LIST,TF_OPTION
 env,		T_OPT_ENV,	TF_OPTION
 allnoconfig_y,	T_OPT_ALLNOCONFIG_Y,TF_OPTION
+count,		T_COUNT,	TF_COMMAND
 %%
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 71bf8bff696a..18c43561860b 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -31,7 +31,7 @@ struct symbol *symbol_hash[SYMBOL_HASHSIZE];
 static struct menu *current_menu, *current_entry;
 
 %}
-%expect 30
+%expect 32
 
 %union
 {
@@ -76,6 +76,7 @@ static struct menu *current_menu, *current_entry;
 %token T_CLOSE_PAREN
 %token T_OPEN_PAREN
 %token T_EOL
+%token <id>T_COUNT
 
 %left T_OR
 %left T_AND
@@ -124,7 +125,7 @@ stmt_list:
 ;
 
 option_name:
-	T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
+	T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_COUNT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
 ;
 
 common_stmt:
@@ -216,6 +217,12 @@ config_option: T_SELECT T_WORD if_expr T_EOL
 	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
 };
 
+config_option: T_COUNT T_WORD if_expr T_EOL
+{
+	menu_add_symbol(P_COUNT, sym_lookup($2, 0), $3);
+	printd(DEBUG_PARSE, "%s:%d:count\n", zconf_curname(), zconf_lineno());
+};
+
 config_option: T_RANGE symbol symbol if_expr T_EOL
 {
 	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
@@ -664,6 +671,11 @@ static void print_symbol(FILE *out, struct menu *menu)
 			expr_fprint(prop->expr, out);
 			fputc('\n', out);
 			break;
+		case P_COUNT:
+			fputs( "  count ", out);
+			expr_fprint(prop->expr, out);
+			fputc('\n', out);
+			break;
 		case P_RANGE:
 			fputs( "  range ", out);
 			expr_fprint(prop->expr, out);
-- 
2.6.2


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

* [RFC v4 7/8] kconfig: regenerate the shipped files
  2015-11-12  8:47 [RFC v4 0/8] mac80211: jump labels for HW flags Johannes Berg
                   ` (5 preceding siblings ...)
  2015-11-12  8:47 ` [RFC v4 6/8] kconfig: introduce "count" Johannes Berg
@ 2015-11-12  8:47 ` Johannes Berg
  2015-11-12  8:47 ` [RFC v4 8/8] mac80211: use Kconfig counters to determine feature optimisation Johannes Berg
  7 siblings, 0 replies; 18+ messages in thread
From: Johannes Berg @ 2015-11-12  8:47 UTC (permalink / raw)
  To: linux-wireless
  Cc: Jason Baron, Peter Zijlstra, Steven Rostedt, Michal Marek, Johannes Berg

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

Unfortunately, I again used a different version of the tools,
so the changes are rather large.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 scripts/kconfig/zconf.hash.c_shipped |   10 +-
 scripts/kconfig/zconf.lex.c_shipped  |   62 +-
 scripts/kconfig/zconf.tab.c_shipped  | 1600 ++++++++++++++++------------------
 3 files changed, 789 insertions(+), 883 deletions(-)

diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped
index 360a62df2b5e..759bfe9400e2 100644
--- a/scripts/kconfig/zconf.hash.c_shipped
+++ b/scripts/kconfig/zconf.hash.c_shipped
@@ -118,6 +118,7 @@ struct kconf_id_strings_t
     char kconf_id_strings_str41[sizeof("source")];
     char kconf_id_strings_str42[sizeof("visible")];
     char kconf_id_strings_str43[sizeof("hex")];
+    char kconf_id_strings_str45[sizeof("count")];
     char kconf_id_strings_str46[sizeof("config")];
     char kconf_id_strings_str47[sizeof("boolean")];
     char kconf_id_strings_str51[sizeof("string")];
@@ -155,6 +156,7 @@ static const struct kconf_id_strings_t kconf_id_strings_contents =
     "source",
     "visible",
     "hex",
+    "count",
     "config",
     "boolean",
     "string",
@@ -174,7 +176,7 @@ kconf_id_lookup (register const char *str, register unsigned int len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 34,
+      TOTAL_KEYWORDS = 35,
       MIN_WORD_LENGTH = 2,
       MAX_WORD_LENGTH = 14,
       MIN_HASH_VALUE = 2,
@@ -251,7 +253,9 @@ kconf_id_lookup (register const char *str, register unsigned int len)
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42,	T_VISIBLE,	TF_COMMAND},
 #line 38 "scripts/kconfig/zconf.gperf"
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43,		T_TYPE,		TF_COMMAND, S_HEX},
-      {-1}, {-1},
+      {-1},
+#line 49 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str45,		T_COUNT,	TF_COMMAND},
 #line 22 "scripts/kconfig/zconf.gperf"
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46,		T_CONFIG,	TF_COMMAND},
 #line 35 "scripts/kconfig/zconf.gperf"
@@ -289,5 +293,5 @@ kconf_id_lookup (register const char *str, register unsigned int len)
     }
   return 0;
 }
-#line 49 "scripts/kconfig/zconf.gperf"
+#line 50 "scripts/kconfig/zconf.gperf"
 
diff --git a/scripts/kconfig/zconf.lex.c_shipped b/scripts/kconfig/zconf.lex.c_shipped
index 37fdf6123505..204d2d265201 100644
--- a/scripts/kconfig/zconf.lex.c_shipped
+++ b/scripts/kconfig/zconf.lex.c_shipped
@@ -27,7 +27,7 @@
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
+#define YY_FLEX_SUBMINOR_VERSION 39
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
@@ -180,7 +180,12 @@ typedef unsigned int flex_uint32_t;
 typedef struct yy_buffer_state *YY_BUFFER_STATE;
 #endif
 
-extern int zconfleng;
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+extern yy_size_t zconfleng;
 
 extern FILE *zconfin, *zconfout;
 
@@ -189,6 +194,7 @@ extern FILE *zconfin, *zconfout;
 #define EOB_ACT_LAST_MATCH 2
 
     #define YY_LESS_LINENO(n)
+    #define YY_LINENO_REWIND_TO(ptr)
     
 /* Return all but the first "n" matched characters back to the input stream. */
 #define yyless(n) \
@@ -206,11 +212,6 @@ extern FILE *zconfin, *zconfout;
 
 #define unput(c) yyunput( c, (yytext_ptr)  )
 
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
 #ifndef YY_STRUCT_YY_BUFFER_STATE
 #define YY_STRUCT_YY_BUFFER_STATE
 struct yy_buffer_state
@@ -228,7 +229,7 @@ struct yy_buffer_state
 	/* Number of characters read into yy_ch_buf, not including EOB
 	 * characters.
 	 */
-	int yy_n_chars;
+	yy_size_t yy_n_chars;
 
 	/* Whether we "own" the buffer - i.e., we know we created it,
 	 * and can realloc() it to grow it, and should free() it to
@@ -298,8 +299,8 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
 
 /* yy_hold_char holds the character lost when zconftext is formed. */
 static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int zconfleng;
+static yy_size_t yy_n_chars;		/* number of characters read into yy_ch_buf */
+yy_size_t zconfleng;
 
 /* Points to current character in buffer. */
 static char *yy_c_buf_p = (char *) 0;
@@ -327,7 +328,7 @@ static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file  );
 
 YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size  );
 YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len  );
+YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,yy_size_t len  );
 
 void *zconfalloc (yy_size_t  );
 void *zconfrealloc (void *,yy_size_t  );
@@ -359,7 +360,7 @@ void zconffree (void *  );
 
 /* Begin user sect3 */
 
-#define zconfwrap(n) 1
+#define zconfwrap() 1
 #define YY_SKIP_YYWRAP
 
 typedef unsigned char YY_CHAR;
@@ -374,6 +375,7 @@ int zconflineno = 1;
 
 extern char *zconftext;
 #define yytext_ptr zconftext
+
 static yyconst flex_int16_t yy_nxt[][18] =
     {
     {
@@ -902,7 +904,7 @@ FILE *zconfget_out (void );
 
 void zconfset_out  (FILE * out_str  );
 
-int zconfget_leng (void );
+yy_size_t zconfget_leng (void );
 
 char *zconfget_text (void );
 
@@ -1034,9 +1036,6 @@ YY_DECL
 	register char *yy_cp, *yy_bp;
 	register int yy_act;
     
-	int str = 0;
-	int ts, i;
-
 	if ( !(yy_init) )
 		{
 		(yy_init) = 1;
@@ -1063,6 +1062,11 @@ YY_DECL
 		zconf_load_buffer_state( );
 		}
 
+	{
+
+	int str = 0;
+	int ts, i;
+
 	while ( 1 )		/* loops until end-of-file is reached */
 		{
 		yy_cp = (yy_c_buf_p);
@@ -1245,6 +1249,7 @@ case YY_STATE_EOF(PARAM):
 case 27:
 /* rule 27 can match eol */
 *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+YY_LINENO_REWIND_TO(yy_cp - 1);
 (yy_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
 YY_RULE_SETUP
@@ -1263,6 +1268,7 @@ YY_RULE_SETUP
 case 29:
 /* rule 29 can match eol */
 *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+YY_LINENO_REWIND_TO(yy_cp - 1);
 (yy_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
 YY_RULE_SETUP
@@ -1333,6 +1339,7 @@ YY_RULE_SETUP
 case 34:
 /* rule 34 can match eol */
 *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+YY_LINENO_REWIND_TO(yy_cp - 1);
 (yy_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
 YY_RULE_SETUP
@@ -1513,6 +1520,7 @@ YY_FATAL_ERROR( "flex scanner jammed" );
 			"fatal flex scanner internal error--no action found" );
 	} /* end of action switch */
 		} /* end of scanning one token */
+	} /* end of user's declarations */
 } /* end of zconflex */
 
 /* yy_get_next_buffer - try to read in a new buffer
@@ -1568,21 +1576,21 @@ static int yy_get_next_buffer (void)
 
 	else
 		{
-			int num_to_read =
+			yy_size_t num_to_read =
 			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
 
 		while ( num_to_read <= 0 )
 			{ /* Not enough room in the buffer - grow it. */
 
 			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
 
 			int yy_c_buf_p_offset =
 				(int) ((yy_c_buf_p) - b->yy_ch_buf);
 
 			if ( b->yy_is_our_buffer )
 				{
-				int new_size = b->yy_buf_size * 2;
+				yy_size_t new_size = b->yy_buf_size * 2;
 
 				if ( new_size <= 0 )
 					b->yy_buf_size += b->yy_buf_size / 8;
@@ -1613,7 +1621,7 @@ static int yy_get_next_buffer (void)
 
 		/* Read in more data. */
 		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), (size_t) num_to_read );
+			(yy_n_chars), num_to_read );
 
 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
 		}
@@ -1683,7 +1691,7 @@ static int yy_get_next_buffer (void)
 	yy_current_state = yy_nxt[yy_current_state][1];
 	yy_is_jam = (yy_current_state <= 0);
 
-	return yy_is_jam ? 0 : yy_current_state;
+		return yy_is_jam ? 0 : yy_current_state;
 }
 
     static void yyunput (int c, register char * yy_bp )
@@ -1698,7 +1706,7 @@ static int yy_get_next_buffer (void)
 	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
 		{ /* need to shift things up to make room */
 		/* +2 for EOB chars. */
-		register int number_to_move = (yy_n_chars) + 2;
+		register yy_size_t number_to_move = (yy_n_chars) + 2;
 		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
 					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
 		register char *source =
@@ -1747,7 +1755,7 @@ static int yy_get_next_buffer (void)
 
 		else
 			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
+			yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
 			++(yy_c_buf_p);
 
 			switch ( yy_get_next_buffer(  ) )
@@ -2019,7 +2027,7 @@ void zconfpop_buffer_state (void)
  */
 static void zconfensure_buffer_stack (void)
 {
-	int num_to_alloc;
+	yy_size_t num_to_alloc;
     
 	if (!(yy_buffer_stack)) {
 
@@ -2116,12 +2124,12 @@ YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr )
  * 
  * @return the newly allocated buffer state object.
  */
-YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len )
 {
 	YY_BUFFER_STATE b;
 	char *buf;
 	yy_size_t n;
-	int i;
+	yy_size_t i;
     
 	/* Get memory for full buffer, including space for trailing EOB's. */
 	n = _yybytes_len + 2;
@@ -2203,7 +2211,7 @@ FILE *zconfget_out  (void)
 /** Get the length of the current token.
  * 
  */
-int zconfget_leng  (void)
+yy_size_t zconfget_leng  (void)
 {
         return zconfleng;
 }
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index 7a4d658c2066..2d34ce63fd0e 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -1,19 +1,19 @@
-/* A Bison parser, made by GNU Bison 2.5.1.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
 /* Bison implementation for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-   
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
@@ -26,7 +26,7 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
@@ -44,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.5.1"
+#define YYBISON_VERSION "3.0.4"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -58,18 +58,16 @@
 /* Pull parsers.  */
 #define YYPULL 1
 
-/* Using locations.  */
-#define YYLSP_NEEDED 0
 
 /* Substitute the variable and function names.  */
 #define yyparse         zconfparse
 #define yylex           zconflex
 #define yyerror         zconferror
-#define yylval          zconflval
-#define yychar          zconfchar
 #define yydebug         zconfdebug
 #define yynerrs         zconfnerrs
 
+#define yylval          zconflval
+#define yychar          zconfchar
 
 /* Copy the first part of user declarations.  */
 
@@ -108,19 +106,14 @@ static struct menu *current_menu, *current_entry;
 
 
 
-# ifndef YY_NULL
+# ifndef YY_NULLPTR
 #  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULL nullptr
+#   define YY_NULLPTR nullptr
 #  else
-#   define YY_NULL 0
+#   define YY_NULLPTR 0
 #  endif
 # endif
 
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 1
-#endif
-
 /* Enabling verbose error messages.  */
 #ifdef YYERROR_VERBOSE
 # undef YYERROR_VERBOSE
@@ -129,62 +122,65 @@ static struct menu *current_menu, *current_entry;
 # define YYERROR_VERBOSE 0
 #endif
 
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
 
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+#if YYDEBUG
+extern int zconfdebug;
+#endif
 
-/* Tokens.  */
+/* Token type.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     T_MAINMENU = 258,
-     T_MENU = 259,
-     T_ENDMENU = 260,
-     T_SOURCE = 261,
-     T_CHOICE = 262,
-     T_ENDCHOICE = 263,
-     T_COMMENT = 264,
-     T_CONFIG = 265,
-     T_MENUCONFIG = 266,
-     T_HELP = 267,
-     T_HELPTEXT = 268,
-     T_IF = 269,
-     T_ENDIF = 270,
-     T_DEPENDS = 271,
-     T_OPTIONAL = 272,
-     T_PROMPT = 273,
-     T_TYPE = 274,
-     T_DEFAULT = 275,
-     T_SELECT = 276,
-     T_RANGE = 277,
-     T_VISIBLE = 278,
-     T_OPTION = 279,
-     T_ON = 280,
-     T_WORD = 281,
-     T_WORD_QUOTE = 282,
-     T_UNEQUAL = 283,
-     T_LESS = 284,
-     T_LESS_EQUAL = 285,
-     T_GREATER = 286,
-     T_GREATER_EQUAL = 287,
-     T_CLOSE_PAREN = 288,
-     T_OPEN_PAREN = 289,
-     T_EOL = 290,
-     T_OR = 291,
-     T_AND = 292,
-     T_EQUAL = 293,
-     T_NOT = 294
-   };
+  enum yytokentype
+  {
+    T_MAINMENU = 258,
+    T_MENU = 259,
+    T_ENDMENU = 260,
+    T_SOURCE = 261,
+    T_CHOICE = 262,
+    T_ENDCHOICE = 263,
+    T_COMMENT = 264,
+    T_CONFIG = 265,
+    T_MENUCONFIG = 266,
+    T_HELP = 267,
+    T_HELPTEXT = 268,
+    T_IF = 269,
+    T_ENDIF = 270,
+    T_DEPENDS = 271,
+    T_OPTIONAL = 272,
+    T_PROMPT = 273,
+    T_TYPE = 274,
+    T_DEFAULT = 275,
+    T_SELECT = 276,
+    T_RANGE = 277,
+    T_VISIBLE = 278,
+    T_OPTION = 279,
+    T_ON = 280,
+    T_WORD = 281,
+    T_WORD_QUOTE = 282,
+    T_UNEQUAL = 283,
+    T_LESS = 284,
+    T_LESS_EQUAL = 285,
+    T_GREATER = 286,
+    T_GREATER_EQUAL = 287,
+    T_CLOSE_PAREN = 288,
+    T_OPEN_PAREN = 289,
+    T_EOL = 290,
+    T_COUNT = 291,
+    T_OR = 292,
+    T_AND = 293,
+    T_EQUAL = 294,
+    T_NOT = 295
+  };
 #endif
 
-
-
+/* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
+
+union YYSTYPE
 {
 
 
@@ -196,14 +192,20 @@ typedef union YYSTYPE
 	const struct kconf_id *id;
 
 
+};
 
-} YYSTYPE;
+typedef union YYSTYPE YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
 
+extern YYSTYPE zconflval;
+
+int zconfparse (void);
+
+
+
 /* Copy the second part of user declarations.  */
 
 
@@ -224,11 +226,8 @@ typedef unsigned char yytype_uint8;
 
 #ifdef YYTYPE_INT8
 typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
 #else
-typedef short int yytype_int8;
+typedef signed char yytype_int8;
 #endif
 
 #ifdef YYTYPE_UINT16
@@ -248,8 +247,7 @@ typedef short int yytype_int16;
 #  define YYSIZE_T __SIZE_TYPE__
 # elif defined size_t
 #  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+# elif ! defined YYSIZE_T
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
@@ -263,38 +261,67 @@ typedef short int yytype_int16;
 # if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
 #  endif
 # endif
 # ifndef YY_
-#  define YY_(msgid) msgid
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
 # endif
 #endif
 
 /* Suppress unused-variable warnings by "using" E.  */
 #if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
+# define YYUSE(E) ((void) (E))
 #else
-# define YYUSE(e) /* empty */
+# define YYUSE(E) /* empty */
 #endif
 
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
 #else
-static int
-YYID (yyi)
-    int yyi;
+# define YY_INITIAL_VALUE(Value) Value
 #endif
-{
-  return yyi;
-}
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
 #endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
 
 #if ! defined yyoverflow || YYERROR_VERBOSE
 
@@ -313,8 +340,7 @@ YYID (yyi)
 #    define alloca _alloca
 #   else
 #    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
       /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
 #     ifndef EXIT_SUCCESS
@@ -326,8 +352,8 @@ YYID (yyi)
 # endif
 
 # ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
     /* The OS might guarantee only one guard page at the bottom of the stack,
        and a page size can be as small as 4096 bytes.  So we cannot safely
@@ -343,7 +369,7 @@ YYID (yyi)
 #  endif
 #  if (defined __cplusplus && ! defined EXIT_SUCCESS \
        && ! ((defined YYMALLOC || defined malloc) \
-	     && (defined YYFREE || defined free)))
+             && (defined YYFREE || defined free)))
 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
 #   ifndef EXIT_SUCCESS
 #    define EXIT_SUCCESS 0
@@ -351,15 +377,13 @@ YYID (yyi)
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined malloc && ! defined EXIT_SUCCESS
 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
 #  ifndef YYFREE
 #   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined free && ! defined EXIT_SUCCESS
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
@@ -369,7 +393,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
 
 #if (! defined yyoverflow \
      && (! defined __cplusplus \
-	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
 
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
@@ -394,16 +418,16 @@ union yyalloc
    elements in the stack, and YYPTR gives the new location of the
    stack.  Advance YYPTR to a properly aligned location for the next
    stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
-	Stack = &yyptr->Stack_alloc;					\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
 
 #endif
 
@@ -422,7 +446,7 @@ union yyalloc
           for (yyi = 0; yyi < (Count); yyi++)   \
             (Dst)[yyi] = (Src)[yyi];            \
         }                                       \
-      while (YYID (0))
+      while (0)
 #  endif
 # endif
 #endif /* !YYCOPY_NEEDED */
@@ -430,25 +454,27 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  11
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   298
+#define YYLAST   313
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  40
+#define YYNTOKENS  41
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  50
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  122
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  199
+#define YYNRULES  124
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  204
 
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   294
+#define YYMAXUTOK   295
 
-#define YYTRANSLATE(YYX)						\
+#define YYTRANSLATE(YYX)                                                \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
 static const yytype_uint8 yytranslate[] =
 {
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -480,90 +506,30 @@ static const yytype_uint8 yytranslate[] =
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39
+      35,    36,    37,    38,    39,    40
 };
 
 #if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     6,     8,    11,    13,    14,    17,    20,
-      23,    26,    31,    36,    40,    42,    44,    46,    48,    50,
-      52,    54,    56,    58,    60,    62,    64,    66,    68,    72,
-      75,    79,    82,    86,    89,    90,    93,    96,    99,   102,
-     105,   108,   112,   117,   122,   127,   133,   137,   138,   142,
-     143,   146,   150,   153,   155,   159,   160,   163,   166,   169,
-     172,   175,   180,   184,   187,   192,   193,   196,   200,   202,
-     206,   207,   210,   213,   216,   220,   224,   228,   230,   234,
-     235,   238,   241,   244,   248,   252,   255,   258,   261,   262,
-     265,   268,   271,   276,   277,   280,   283,   286,   287,   290,
-     292,   294,   297,   300,   303,   305,   308,   309,   312,   314,
-     318,   322,   326,   330,   334,   338,   342,   345,   349,   353,
-     355,   357,   358
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      41,     0,    -1,    85,    42,    -1,    42,    -1,    67,    43,
-      -1,    43,    -1,    -1,    43,    45,    -1,    43,    59,    -1,
-      43,    71,    -1,    43,    84,    -1,    43,    26,     1,    35,
-      -1,    43,    44,     1,    35,    -1,    43,     1,    35,    -1,
-      16,    -1,    18,    -1,    19,    -1,    21,    -1,    17,    -1,
-      22,    -1,    20,    -1,    23,    -1,    35,    -1,    65,    -1,
-      75,    -1,    48,    -1,    50,    -1,    73,    -1,    26,     1,
-      35,    -1,     1,    35,    -1,    10,    26,    35,    -1,    47,
-      51,    -1,    11,    26,    35,    -1,    49,    51,    -1,    -1,
-      51,    52,    -1,    51,    53,    -1,    51,    79,    -1,    51,
-      77,    -1,    51,    46,    -1,    51,    35,    -1,    19,    82,
-      35,    -1,    18,    83,    86,    35,    -1,    20,    87,    86,
-      35,    -1,    21,    26,    86,    35,    -1,    22,    88,    88,
-      86,    35,    -1,    24,    54,    35,    -1,    -1,    54,    26,
-      55,    -1,    -1,    38,    83,    -1,     7,    89,    35,    -1,
-      56,    60,    -1,    84,    -1,    57,    62,    58,    -1,    -1,
-      60,    61,    -1,    60,    79,    -1,    60,    77,    -1,    60,
-      35,    -1,    60,    46,    -1,    18,    83,    86,    35,    -1,
-      19,    82,    35,    -1,    17,    35,    -1,    20,    26,    86,
-      35,    -1,    -1,    62,    45,    -1,    14,    87,    85,    -1,
-      84,    -1,    63,    66,    64,    -1,    -1,    66,    45,    -1,
-      66,    71,    -1,    66,    59,    -1,     3,    83,    85,    -1,
-       4,    83,    35,    -1,    68,    80,    78,    -1,    84,    -1,
-      69,    72,    70,    -1,    -1,    72,    45,    -1,    72,    71,
-      -1,    72,    59,    -1,     6,    83,    35,    -1,     9,    83,
-      35,    -1,    74,    78,    -1,    12,    35,    -1,    76,    13,
-      -1,    -1,    78,    79,    -1,    78,    35,    -1,    78,    46,
-      -1,    16,    25,    87,    35,    -1,    -1,    80,    81,    -1,
-      80,    35,    -1,    23,    86,    -1,    -1,    83,    86,    -1,
-      26,    -1,    27,    -1,     5,    35,    -1,     8,    35,    -1,
-      15,    35,    -1,    35,    -1,    85,    35,    -1,    -1,    14,
-      87,    -1,    88,    -1,    88,    29,    88,    -1,    88,    30,
-      88,    -1,    88,    31,    88,    -1,    88,    32,    88,    -1,
-      88,    38,    88,    -1,    88,    28,    88,    -1,    34,    87,
-      33,    -1,    39,    87,    -1,    87,    36,    87,    -1,    87,
-      37,    87,    -1,    26,    -1,    27,    -1,    -1,    26,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   108,   108,   108,   110,   110,   112,   114,   115,   116,
-     117,   118,   119,   123,   127,   127,   127,   127,   127,   127,
-     127,   127,   131,   132,   133,   134,   135,   136,   140,   141,
-     147,   155,   161,   169,   179,   181,   182,   183,   184,   185,
-     186,   189,   197,   203,   213,   219,   225,   228,   230,   241,
-     242,   247,   256,   261,   269,   272,   274,   275,   276,   277,
-     278,   281,   287,   298,   304,   314,   316,   321,   329,   337,
-     340,   342,   343,   344,   349,   356,   363,   368,   376,   379,
-     381,   382,   383,   386,   394,   401,   408,   414,   421,   423,
-     424,   425,   428,   436,   438,   439,   442,   449,   451,   456,
-     457,   460,   461,   462,   466,   467,   470,   471,   474,   475,
-     476,   477,   478,   479,   480,   481,   482,   483,   484,   487,
-     488,   491,   492
+       0,   109,   109,   109,   111,   111,   113,   115,   116,   117,
+     118,   119,   120,   124,   128,   128,   128,   128,   128,   128,
+     128,   128,   128,   132,   133,   134,   135,   136,   137,   141,
+     142,   148,   156,   162,   170,   180,   182,   183,   184,   185,
+     186,   187,   190,   198,   204,   214,   220,   226,   232,   235,
+     237,   248,   249,   254,   263,   268,   276,   279,   281,   282,
+     283,   284,   285,   288,   294,   305,   311,   321,   323,   328,
+     336,   344,   347,   349,   350,   351,   356,   363,   370,   375,
+     383,   386,   388,   389,   390,   393,   401,   408,   415,   421,
+     428,   430,   431,   432,   435,   443,   445,   446,   449,   456,
+     458,   463,   464,   467,   468,   469,   473,   474,   477,   478,
+     481,   482,   483,   484,   485,   486,   487,   488,   489,   490,
+     491,   494,   495,   498,   499
 };
 #endif
 
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+#if YYDEBUG || YYERROR_VERBOSE || 0
 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
@@ -574,271 +540,268 @@ static const char *const yytname[] =
   "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE",
   "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
   "T_LESS", "T_LESS_EQUAL", "T_GREATER", "T_GREATER_EQUAL",
-  "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
-  "T_NOT", "$accept", "input", "start", "stmt_list", "option_name",
-  "common_stmt", "option_error", "config_entry_start", "config_stmt",
-  "menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
-  "config_option", "symbol_option", "symbol_option_list",
-  "symbol_option_arg", "choice", "choice_entry", "choice_end",
-  "choice_stmt", "choice_option_list", "choice_option", "choice_block",
-  "if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu",
-  "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt",
-  "comment", "comment_stmt", "help_start", "help", "depends_list",
-  "depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt",
-  "end", "nl", "if_expr", "expr", "symbol", "word_opt", YY_NULL
+  "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_COUNT", "T_OR", "T_AND",
+  "T_EQUAL", "T_NOT", "$accept", "input", "start", "stmt_list",
+  "option_name", "common_stmt", "option_error", "config_entry_start",
+  "config_stmt", "menuconfig_entry_start", "menuconfig_stmt",
+  "config_option_list", "config_option", "symbol_option",
+  "symbol_option_list", "symbol_option_arg", "choice", "choice_entry",
+  "choice_end", "choice_stmt", "choice_option_list", "choice_option",
+  "choice_block", "if_entry", "if_end", "if_stmt", "if_block",
+  "mainmenu_stmt", "menu", "menu_entry", "menu_end", "menu_stmt",
+  "menu_block", "source_stmt", "comment", "comment_stmt", "help_start",
+  "help", "depends_list", "depends", "visibility_list", "visible",
+  "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol",
+  "word_opt", YY_NULLPTR
 };
 #endif
 
 # ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
 static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295
 };
 # endif
 
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    40,    41,    41,    42,    42,    43,    43,    43,    43,
-      43,    43,    43,    43,    44,    44,    44,    44,    44,    44,
-      44,    44,    45,    45,    45,    45,    45,    45,    46,    46,
-      47,    48,    49,    50,    51,    51,    51,    51,    51,    51,
-      51,    52,    52,    52,    52,    52,    53,    54,    54,    55,
-      55,    56,    57,    58,    59,    60,    60,    60,    60,    60,
-      60,    61,    61,    61,    61,    62,    62,    63,    64,    65,
-      66,    66,    66,    66,    67,    68,    69,    70,    71,    72,
-      72,    72,    72,    73,    74,    75,    76,    77,    78,    78,
-      78,    78,    79,    80,    80,    80,    81,    82,    82,    83,
-      83,    84,    84,    84,    85,    85,    86,    86,    87,    87,
-      87,    87,    87,    87,    87,    87,    87,    87,    87,    88,
-      88,    89,    89
-};
+#define YYPACT_NINF -92
 
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     2,     1,     2,     1,     0,     2,     2,     2,
-       2,     4,     4,     3,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     3,     2,
-       3,     2,     3,     2,     0,     2,     2,     2,     2,     2,
-       2,     3,     4,     4,     4,     5,     3,     0,     3,     0,
-       2,     3,     2,     1,     3,     0,     2,     2,     2,     2,
-       2,     4,     3,     2,     4,     0,     2,     3,     1,     3,
-       0,     2,     2,     2,     3,     3,     3,     1,     3,     0,
-       2,     2,     2,     3,     3,     2,     2,     2,     0,     2,
-       2,     2,     4,     0,     2,     2,     2,     0,     2,     1,
-       1,     2,     2,     2,     1,     2,     0,     2,     1,     3,
-       3,     3,     3,     3,     3,     3,     2,     3,     3,     1,
-       1,     0,     1
-};
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-92)))
 
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
-   Performed when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
+#define YYTABLE_NINF -88
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int16 yypact[] =
 {
-       6,     0,   104,     0,     3,     0,     6,     6,    99,   100,
-       0,     1,     0,     0,     0,     0,   121,     0,     0,     0,
-       0,     0,     0,    14,    18,    15,    16,    20,    17,    19,
-      21,     0,    22,     0,     7,    34,    25,    34,    26,    55,
-      65,     8,    70,    23,    93,    79,     9,    27,    88,    24,
-      10,     0,   105,     2,    74,    13,     0,   101,     0,   122,
-       0,   102,     0,     0,     0,   119,   120,     0,     0,     0,
-     108,   103,     0,     0,     0,     0,     0,     0,     0,    88,
-       0,     0,    75,    83,    51,    84,    30,    32,     0,   116,
-       0,     0,    67,     0,     0,     0,     0,     0,     0,    11,
-      12,     0,     0,     0,     0,    97,     0,     0,     0,    47,
-       0,    40,    39,    35,    36,     0,    38,    37,     0,     0,
-      97,     0,    59,    60,    56,    58,    57,    66,    54,    53,
-      71,    73,    69,    72,    68,   106,    95,     0,    94,    80,
-      82,    78,    81,    77,    90,    91,    89,   115,   117,   118,
-     114,   109,   110,   111,   112,   113,    29,    86,     0,   106,
-       0,   106,   106,   106,     0,     0,     0,    87,    63,   106,
-       0,   106,     0,    96,     0,     0,    41,    98,     0,     0,
-     106,    49,    46,    28,     0,    62,     0,   107,    92,    42,
-      43,    44,     0,     0,    48,    61,    64,    45,    50
+      19,     3,   -92,    13,   -92,    80,   -92,    20,   -92,   -92,
+     -16,   -92,    -9,     3,    21,     3,    34,    37,     3,    50,
+      79,    31,    57,   -92,   -92,   -92,   -92,   -92,   -92,   -92,
+     -92,   112,   -92,   -92,   118,   -92,   -92,   -92,   -92,   -92,
+     -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,
+     -92,   -92,   150,   -92,   -92,    95,   -92,   107,   -92,   114,
+     -92,   139,   -92,   143,   144,   145,   -92,   -92,    31,    31,
+      29,   274,   -92,   146,   147,    27,   117,   215,   266,   251,
+     -14,   251,   183,   -92,   -92,   -92,   -92,   -92,   -92,    41,
+     -92,    31,    31,    95,    42,    42,    42,    42,    42,    42,
+     -92,   -92,   160,   172,   185,     3,     3,    31,   182,    42,
+     -92,   210,   -92,   186,   -92,   -92,   -92,   200,   -92,   -92,
+     179,     3,     3,   189,   -92,   -92,   -92,   -92,   -92,   -92,
+     -92,   -92,   -92,   -92,   -92,   -92,   -92,   203,   -92,   238,
+     -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,
+     184,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,
+      31,   203,   193,   203,    45,   203,    42,    26,   201,   203,
+     -92,   -92,   203,   202,   203,    31,   -92,    72,   205,   -92,
+     -92,   216,   228,   203,   199,   -92,   -92,   232,   233,   -92,
+     234,   125,   -92,   -92,   -92,   -92,   235,     3,   -92,   -92,
+     -92,   -92,   -92,   -92
 };
 
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int16 yydefgoto[] =
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
 {
-      -1,     3,     4,     5,    33,    34,   112,    35,    36,    37,
-      38,    74,   113,   114,   165,   194,    39,    40,   128,    41,
-      76,   124,    77,    42,   132,    43,    78,     6,    44,    45,
-     141,    46,    80,    47,    48,    49,   115,   116,    81,   117,
-      79,   138,   160,   161,    50,     7,   173,    69,    70,    60
+       6,     0,   106,     0,     3,     0,     6,     6,   101,   102,
+       0,     1,     0,     0,     0,     0,   123,     0,     0,     0,
+       0,     0,     0,    14,    19,    15,    16,    21,    17,    20,
+      22,     0,    23,    18,     0,     7,    35,    26,    35,    27,
+      57,    67,     8,    72,    24,    95,    81,     9,    28,    90,
+      25,    10,     0,   107,     2,    76,    13,     0,   103,     0,
+     124,     0,   104,     0,     0,     0,   121,   122,     0,     0,
+       0,   110,   105,     0,     0,     0,     0,     0,     0,     0,
+      90,     0,     0,    77,    85,    53,    86,    31,    33,     0,
+     118,     0,     0,    69,     0,     0,     0,     0,     0,     0,
+      11,    12,     0,     0,     0,     0,    99,     0,     0,     0,
+      49,     0,    41,     0,    40,    36,    37,     0,    39,    38,
+       0,     0,    99,     0,    61,    62,    58,    60,    59,    68,
+      56,    55,    73,    75,    71,    74,    70,   108,    97,     0,
+      96,    82,    84,    80,    83,    79,    92,    93,    91,   117,
+     119,   120,   116,   111,   112,   113,   114,   115,    30,    88,
+       0,   108,     0,   108,   108,   108,     0,     0,     0,   108,
+      89,    65,   108,     0,   108,     0,    98,     0,     0,    42,
+     100,     0,     0,   108,    51,    48,    29,     0,     0,    64,
+       0,   109,    94,    43,    44,    45,     0,     0,    50,    46,
+      63,    66,    47,    52
 };
 
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -91
-static const yytype_int16 yypact[] =
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
 {
-      19,    37,   -91,    13,   -91,    79,   -91,    20,   -91,   -91,
-     -16,   -91,    21,    37,    25,    37,    41,    36,    37,    78,
-      83,    31,    56,   -91,   -91,   -91,   -91,   -91,   -91,   -91,
-     -91,   116,   -91,   127,   -91,   -91,   -91,   -91,   -91,   -91,
-     -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,
-     -91,   147,   -91,   -91,   105,   -91,   109,   -91,   111,   -91,
-     114,   -91,   136,   137,   142,   -91,   -91,    31,    31,    76,
-     254,   -91,   143,   146,    27,   115,   207,   258,   243,   -14,
-     243,   179,   -91,   -91,   -91,   -91,   -91,   -91,    -7,   -91,
-      31,    31,   105,    51,    51,    51,    51,    51,    51,   -91,
-     -91,   156,   168,   181,    37,    37,    31,   178,    51,   -91,
-     206,   -91,   -91,   -91,   -91,   196,   -91,   -91,   175,    37,
-      37,   185,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,
-     -91,   -91,   -91,   -91,   -91,   214,   -91,   230,   -91,   -91,
-     -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   183,   -91,
-     -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,    31,   214,
-     194,   214,    45,   214,    51,    26,   195,   -91,   -91,   214,
-     197,   214,    31,   -91,   139,   208,   -91,   -91,   220,   224,
-     214,   222,   -91,   -91,   226,   -91,   227,   123,   -91,   -91,
-     -91,   -91,   235,    37,   -91,   -91,   -91,   -91,   -91
+     -92,   -92,   271,   273,   -92,    33,   -66,   -92,   -92,   -92,
+     -92,   244,   -92,   -92,   -92,   -92,   -92,   -92,   -92,    67,
+     -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,
+     -92,    96,   -92,   -92,   -92,   -92,   -92,   206,   204,   -62,
+     -92,   -92,   168,    -1,    66,     0,   124,   -67,   -91,   -92
 };
 
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int16 yypgoto[] =
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
 {
-     -91,   -91,   264,   268,   -91,    30,   -65,   -91,   -91,   -91,
-     -91,   238,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -12,
-     -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,
-     -91,    -5,   -91,   -91,   -91,   -91,   -91,   200,   209,   -61,
-     -91,   -91,   170,    -1,    65,     0,   118,   -66,   -90,   -91
+      -1,     3,     4,     5,    34,    35,   114,    36,    37,    38,
+      39,    75,   115,   116,   167,   198,    40,    41,   130,    42,
+      77,   126,    78,    43,   134,    44,    79,     6,    45,    46,
+     143,    47,    81,    48,    49,    50,   117,   118,    82,   119,
+      80,   140,   162,   163,    51,     7,   176,    70,    71,    61
 };
 
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -86
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_int16 yytable[] =
 {
-      10,    88,    89,   150,   151,   152,   153,   154,   155,   135,
-      54,   123,    56,    11,    58,   126,   145,    62,   164,     2,
-     146,   136,     1,     1,   148,   149,   147,   -31,   101,    90,
-      91,   -31,   -31,   -31,   -31,   -31,   -31,   -31,   -31,   102,
-     162,   -31,   -31,   103,   -31,   104,   105,   106,   107,   108,
-     -31,   109,   181,   110,     2,    52,    55,    65,    66,   172,
-      57,   182,   111,     8,     9,    67,   131,    59,   140,    92,
-      68,    61,   145,   133,   180,   142,   146,    65,    66,    -5,
-      12,    90,    91,    13,    14,    15,    16,    17,    18,    19,
-      20,    71,   174,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,   159,    63,    31,   187,   127,   130,    64,
-     139,     2,    90,    91,    32,   -33,   101,    72,   169,   -33,
-     -33,   -33,   -33,   -33,   -33,   -33,   -33,   102,    73,   -33,
-     -33,   103,   -33,   104,   105,   106,   107,   108,   -33,   109,
-      52,   110,   129,   134,    82,   143,    83,    -4,    12,    84,
-     111,    13,    14,    15,    16,    17,    18,    19,    20,    90,
-      91,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    85,    86,    31,   188,    90,    91,    87,    99,   -85,
-     101,   100,    32,   -85,   -85,   -85,   -85,   -85,   -85,   -85,
-     -85,   156,   198,   -85,   -85,   103,   -85,   -85,   -85,   -85,
-     -85,   -85,   -85,   157,   163,   110,   158,   166,   101,   167,
-     168,   171,   -52,   -52,   144,   -52,   -52,   -52,   -52,   102,
-      91,   -52,   -52,   103,   118,   119,   120,   121,   172,   176,
-     183,   101,   185,   110,   -76,   -76,   -76,   -76,   -76,   -76,
-     -76,   -76,   122,   189,   -76,   -76,   103,    13,    14,    15,
-      16,    17,    18,    19,    20,   190,   110,    21,    22,   191,
-     193,   195,   196,    14,    15,   144,    17,    18,    19,    20,
-     197,    53,    21,    22,    51,    75,   125,   175,    32,   177,
-     178,   179,    93,    94,    95,    96,    97,   184,   137,   186,
-     170,     0,    98,    32,     0,     0,     0,     0,   192
+      10,    89,    90,   152,   153,   154,   155,   156,   157,   137,
+      55,   125,    57,    11,    59,   128,   147,    63,   166,     2,
+     148,   138,     1,     1,   150,   151,    56,   -32,   102,     8,
+       9,   -32,   -32,   -32,   -32,   -32,   -32,   -32,   -32,   103,
+     164,   -32,   -32,   104,   -32,   105,   106,   107,   108,   109,
+     -32,   110,   184,   111,     2,    53,    58,    66,    67,   175,
+      60,   185,   112,   113,     2,    68,    91,    92,    66,    67,
+      93,    69,    62,   147,   149,   183,    64,   148,    91,    92,
+      -5,    12,    91,    92,    13,    14,    15,    16,    17,    18,
+      19,    20,    72,   177,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,   161,    65,    31,   192,   191,    91,
+      92,   129,   132,    73,   141,    32,    33,   -34,   102,    74,
+     172,   -34,   -34,   -34,   -34,   -34,   -34,   -34,   -34,   103,
+      53,   -34,   -34,   104,   -34,   105,   106,   107,   108,   109,
+     -34,   110,    83,   111,   131,   136,   133,   145,   142,    84,
+      -4,    12,   112,   113,    13,    14,    15,    16,    17,    18,
+      19,    20,    91,    92,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    85,   135,    31,   144,    86,    87,
+      88,   100,   101,   -87,   102,    32,    33,   -87,   -87,   -87,
+     -87,   -87,   -87,   -87,   -87,   158,   203,   -87,   -87,   104,
+     -87,   -87,   -87,   -87,   -87,   -87,   -87,   159,   165,   111,
+     160,   168,   169,   170,   171,   174,   102,   175,   146,   -87,
+     -54,   -54,    92,   -54,   -54,   -54,   -54,   103,   179,   -54,
+     -54,   104,   120,   121,   122,   123,   186,   189,   197,   102,
+     193,   111,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,
+     124,   194,   -78,   -78,   104,    13,    14,    15,    16,    17,
+      18,    19,    20,   195,   111,    21,    22,   199,   200,   201,
+     202,    14,    15,   146,    17,    18,    19,    20,    54,    52,
+      21,    22,    76,   127,   139,   178,    32,   180,   181,   182,
+     173,     0,     0,   187,     0,     0,   188,     0,   190,     0,
+       0,    32,    94,    95,    96,    97,    98,   196,     0,     0,
+       0,     0,     0,    99
 };
 
-#define yypact_value_is_default(yystate) \
-  ((yystate) == (-91))
-
-#define yytable_value_is_error(yytable_value) \
-  YYID (0)
-
 static const yytype_int16 yycheck[] =
 {
-       1,    67,    68,    93,    94,    95,    96,    97,    98,    23,
-      10,    76,    13,     0,    15,    76,    81,    18,   108,    35,
-      81,    35,     3,     3,    90,    91,    33,     0,     1,    36,
-      37,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-     106,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+       1,    68,    69,    94,    95,    96,    97,    98,    99,    23,
+      10,    77,    13,     0,    15,    77,    82,    18,   109,    35,
+      82,    35,     3,     3,    91,    92,    35,     0,     1,    26,
+      27,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+     107,    14,    15,    16,    17,    18,    19,    20,    21,    22,
       23,    24,    26,    26,    35,    35,    35,    26,    27,    14,
-      35,    35,    35,    26,    27,    34,    78,    26,    80,    69,
-      39,    35,   137,    78,   164,    80,   137,    26,    27,     0,
-       1,    36,    37,     4,     5,     6,     7,     8,     9,    10,
-      11,    35,   158,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,   104,    26,    26,   172,    77,    78,    26,
-      80,    35,    36,    37,    35,     0,     1,     1,   119,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,     1,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      35,    26,    77,    78,    35,    80,    35,     0,     1,    35,
-      35,     4,     5,     6,     7,     8,     9,    10,    11,    36,
-      37,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,    35,    35,    26,    35,    36,    37,    35,    35,     0,
-       1,    35,    35,     4,     5,     6,     7,     8,     9,    10,
-      11,    35,   193,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    35,    26,    26,    25,     1,     1,    13,
-      35,    26,     5,     6,    35,     8,     9,    10,    11,    12,
-      37,    14,    15,    16,    17,    18,    19,    20,    14,    35,
-      35,     1,    35,    26,     4,     5,     6,     7,     8,     9,
-      10,    11,    35,    35,    14,    15,    16,     4,     5,     6,
-       7,     8,     9,    10,    11,    35,    26,    14,    15,    35,
-      38,    35,    35,     5,     6,    35,     8,     9,    10,    11,
-      35,     7,    14,    15,     6,    37,    76,   159,    35,   161,
-     162,   163,    28,    29,    30,    31,    32,   169,    79,   171,
-     120,    -1,    38,    35,    -1,    -1,    -1,    -1,   180
+      26,    35,    35,    36,    35,    34,    37,    38,    26,    27,
+      70,    40,    35,   139,    33,   166,    26,   139,    37,    38,
+       0,     1,    37,    38,     4,     5,     6,     7,     8,     9,
+      10,    11,    35,   160,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,   105,    26,    26,    35,   175,    37,
+      38,    78,    79,     1,    81,    35,    36,     0,     1,     1,
+     121,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+      35,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,    35,    26,    78,    79,    79,    81,    81,    35,
+       0,     1,    35,    36,     4,     5,     6,     7,     8,     9,
+      10,    11,    37,    38,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    35,    79,    26,    81,    35,    35,
+      35,    35,    35,     0,     1,    35,    36,     4,     5,     6,
+       7,     8,     9,    10,    11,    35,   197,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    35,    26,    26,
+      25,     1,    26,    13,    35,    26,     1,    14,    35,    36,
+       5,     6,    38,     8,     9,    10,    11,    12,    35,    14,
+      15,    16,    17,    18,    19,    20,    35,    35,    39,     1,
+      35,    26,     4,     5,     6,     7,     8,     9,    10,    11,
+      35,    35,    14,    15,    16,     4,     5,     6,     7,     8,
+       9,    10,    11,    35,    26,    14,    15,    35,    35,    35,
+      35,     5,     6,    35,     8,     9,    10,    11,     7,     6,
+      14,    15,    38,    77,    80,   161,    35,   163,   164,   165,
+     122,    -1,    -1,   169,    -1,    -1,   172,    -1,   174,    -1,
+      -1,    35,    28,    29,    30,    31,    32,   183,    -1,    -1,
+      -1,    -1,    -1,    39
 };
 
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,    35,    41,    42,    43,    67,    85,    26,    27,
-      83,     0,     1,     4,     5,     6,     7,     8,     9,    10,
+       0,     3,    35,    42,    43,    44,    68,    86,    26,    27,
+      84,     0,     1,     4,     5,     6,     7,     8,     9,    10,
       11,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,    26,    35,    44,    45,    47,    48,    49,    50,    56,
-      57,    59,    63,    65,    68,    69,    71,    73,    74,    75,
-      84,    43,    35,    42,    85,    35,    83,    35,    83,    26,
-      89,    35,    83,    26,    26,    26,    27,    34,    39,    87,
-      88,    35,     1,     1,    51,    51,    60,    62,    66,    80,
-      72,    78,    35,    35,    35,    35,    35,    35,    87,    87,
-      36,    37,    85,    28,    29,    30,    31,    32,    38,    35,
-      35,     1,    12,    16,    18,    19,    20,    21,    22,    24,
-      26,    35,    46,    52,    53,    76,    77,    79,    17,    18,
-      19,    20,    35,    46,    61,    77,    79,    45,    58,    84,
-      45,    59,    64,    71,    84,    23,    35,    78,    81,    45,
-      59,    70,    71,    84,    35,    46,    79,    33,    87,    87,
-      88,    88,    88,    88,    88,    88,    35,    35,    25,    83,
-      82,    83,    87,    26,    88,    54,     1,    13,    35,    83,
-      82,    26,    14,    86,    87,    86,    35,    86,    86,    86,
-      88,    26,    35,    35,    86,    35,    86,    87,    35,    35,
-      35,    35,    86,    38,    55,    35,    35,    35,    83
+      23,    26,    35,    36,    45,    46,    48,    49,    50,    51,
+      57,    58,    60,    64,    66,    69,    70,    72,    74,    75,
+      76,    85,    44,    35,    43,    86,    35,    84,    35,    84,
+      26,    90,    35,    84,    26,    26,    26,    27,    34,    40,
+      88,    89,    35,     1,     1,    52,    52,    61,    63,    67,
+      81,    73,    79,    35,    35,    35,    35,    35,    35,    88,
+      88,    37,    38,    86,    28,    29,    30,    31,    32,    39,
+      35,    35,     1,    12,    16,    18,    19,    20,    21,    22,
+      24,    26,    35,    36,    47,    53,    54,    77,    78,    80,
+      17,    18,    19,    20,    35,    47,    62,    78,    80,    46,
+      59,    85,    46,    60,    65,    72,    85,    23,    35,    79,
+      82,    46,    60,    71,    72,    85,    35,    47,    80,    33,
+      88,    88,    89,    89,    89,    89,    89,    89,    35,    35,
+      25,    84,    83,    84,    88,    26,    89,    55,     1,    26,
+      13,    35,    84,    83,    26,    14,    87,    88,    87,    35,
+      87,    87,    87,    89,    26,    35,    35,    87,    87,    35,
+      87,    88,    35,    35,    35,    35,    87,    39,    56,    35,
+      35,    35,    35,    84
 };
 
-#define yyerrok		(yyerrstatus = 0)
-#define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		(-2)
-#define YYEOF		0
-
-#define YYACCEPT	goto yyacceptlab
-#define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  However,
-   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
-   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
-   discussed.  */
-
-#define YYFAIL		goto yyerrlab
-#if defined YYFAIL
-  /* This is here to suppress warnings from the GCC cpp's
-     -Wunused-macros.  Normally we don't worry about that warning, but
-     some users do, and we want to make it easy for users to remove
-     YYFAIL uses, which will produce warnings from Bison 2.5.  */
-#endif
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    41,    42,    42,    43,    43,    44,    44,    44,    44,
+      44,    44,    44,    44,    45,    45,    45,    45,    45,    45,
+      45,    45,    45,    46,    46,    46,    46,    46,    46,    47,
+      47,    48,    49,    50,    51,    52,    52,    52,    52,    52,
+      52,    52,    53,    53,    53,    53,    53,    53,    54,    55,
+      55,    56,    56,    57,    58,    59,    60,    61,    61,    61,
+      61,    61,    61,    62,    62,    62,    62,    63,    63,    64,
+      65,    66,    67,    67,    67,    67,    68,    69,    70,    71,
+      72,    73,    73,    73,    73,    74,    75,    76,    77,    78,
+      79,    79,    79,    79,    80,    81,    81,    81,    82,    83,
+      83,    84,    84,    85,    85,    85,    86,    86,    87,    87,
+      88,    88,    88,    88,    88,    88,    88,    88,    88,    88,
+      88,    89,    89,    90,    90
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     2,     1,     2,     1,     0,     2,     2,     2,
+       2,     4,     4,     3,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     3,
+       2,     3,     2,     3,     2,     0,     2,     2,     2,     2,
+       2,     2,     3,     4,     4,     4,     4,     5,     3,     0,
+       3,     0,     2,     3,     2,     1,     3,     0,     2,     2,
+       2,     2,     2,     4,     3,     2,     4,     0,     2,     3,
+       1,     3,     0,     2,     2,     2,     3,     3,     3,     1,
+       3,     0,     2,     2,     2,     3,     3,     2,     2,     2,
+       0,     2,     2,     2,     4,     0,     2,     2,     2,     0,
+       2,     1,     1,     2,     2,     2,     1,     2,     0,     2,
+       1,     3,     3,     3,     3,     3,     3,     3,     2,     3,
+       3,     1,     1,     0,     1
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
@@ -855,55 +818,15 @@ do                                                              \
   else                                                          \
     {                                                           \
       yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;							\
-    }								\
-while (YYID (0))
-
-
-#define YYTERROR	1
-#define YYERRCODE	256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)				\
-    do									\
-      if (YYID (N))                                                    \
-	{								\
-	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
-	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
-	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
-	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
-	}								\
-      else								\
-	{								\
-	  (Current).first_line   = (Current).last_line   =		\
-	    YYRHSLOC (Rhs, 0).last_line;				\
-	  (Current).first_column = (Current).last_column =		\
-	    YYRHSLOC (Rhs, 0).last_column;				\
-	}								\
-    while (YYID (0))
-#endif
-
-
-/* This macro is provided for backward compatibility. */
-
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
 
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
 
-/* YYLEX -- calling `yylex' with the right arguments.  */
 
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
 
 /* Enable debugging if requested.  */
 #if YYDEBUG
@@ -913,40 +836,36 @@ while (YYID (0))
 #  define YYFPRINTF fprintf
 # endif
 
-# define YYDPRINTF(Args)			\
-do {						\
-  if (yydebug)					\
-    YYFPRINTF Args;				\
-} while (YYID (0))
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
 
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
-do {									  \
-  if (yydebug)								  \
-    {									  \
-      YYFPRINTF (stderr, "%s ", Title);					  \
-      yy_symbol_print (stderr,						  \
-		  Type, Value); \
-      YYFPRINTF (stderr, "\n");						  \
-    }									  \
-} while (YYID (0))
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
 
 
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
 
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
 {
   FILE *yyo = yyoutput;
   YYUSE (yyo);
@@ -955,14 +874,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
     YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
 # endif
-  switch (yytype)
-    {
-      default:
-	break;
-    }
+  YYUSE (yytype);
 }
 
 
@@ -970,22 +883,11 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
 | Print this symbol on YYOUTPUT.  |
 `--------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
 {
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
   yy_symbol_value_print (yyoutput, yytype, yyvaluep);
   YYFPRINTF (yyoutput, ")");
@@ -996,16 +898,8 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
 | TOP (included).                                                   |
 `------------------------------------------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
-    yytype_int16 *yybottom;
-    yytype_int16 *yytop;
-#endif
 {
   YYFPRINTF (stderr, "Stack now");
   for (; yybottom <= yytop; yybottom++)
@@ -1016,49 +910,42 @@ yy_stack_print (yybottom, yytop)
   YYFPRINTF (stderr, "\n");
 }
 
-# define YY_STACK_PRINT(Bottom, Top)				\
-do {								\
-  if (yydebug)							\
-    yy_stack_print ((Bottom), (Top));				\
-} while (YYID (0))
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
 
 
 /*------------------------------------------------.
 | Report that the YYRULE is going to be reduced.  |
 `------------------------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
-    YYSTYPE *yyvsp;
-    int yyrule;
-#endif
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule)
 {
+  unsigned long int yylno = yyrline[yyrule];
   int yynrhs = yyr2[yyrule];
   int yyi;
-  unsigned long int yylno = yyrline[yyrule];
   YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-	     yyrule - 1, yylno);
+             yyrule - 1, yylno);
   /* The symbols being reduced.  */
   for (yyi = 0; yyi < yynrhs; yyi++)
     {
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-		       &(yyvsp[(yyi + 1) - (yynrhs)])
-		       		       );
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              );
       YYFPRINTF (stderr, "\n");
     }
 }
 
-# define YY_REDUCE_PRINT(Rule)		\
-do {					\
-  if (yydebug)				\
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule); \
+} while (0)
 
 /* Nonzero means print parse trace.  It is left uninitialized so that
    multiple parsers can coexist.  */
@@ -1072,7 +959,7 @@ int yydebug;
 
 
 /* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef	YYINITDEPTH
+#ifndef YYINITDEPTH
 # define YYINITDEPTH 200
 #endif
 
@@ -1095,15 +982,8 @@ int yydebug;
 #   define yystrlen strlen
 #  else
 /* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static YYSIZE_T
 yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
 {
   YYSIZE_T yylen;
   for (yylen = 0; yystr[yylen]; yylen++)
@@ -1119,16 +999,8 @@ yystrlen (yystr)
 #  else
 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
    YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static char *
 yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
 {
   char *yyd = yydest;
   const char *yys = yysrc;
@@ -1158,27 +1030,27 @@ yytnamerr (char *yyres, const char *yystr)
       char const *yyp = yystr;
 
       for (;;)
-	switch (*++yyp)
-	  {
-	  case '\'':
-	  case ',':
-	    goto do_not_strip_quotes;
-
-	  case '\\':
-	    if (*++yyp != '\\')
-	      goto do_not_strip_quotes;
-	    /* Fall through.  */
-	  default:
-	    if (yyres)
-	      yyres[yyn] = *yyp;
-	    yyn++;
-	    break;
-
-	  case '"':
-	    if (yyres)
-	      yyres[yyn] = '\0';
-	    return yyn;
-	  }
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
     do_not_strip_quotes: ;
     }
 
@@ -1201,12 +1073,11 @@ static int
 yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
                 yytype_int16 *yyssp, int yytoken)
 {
-  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
   YYSIZE_T yysize = yysize0;
-  YYSIZE_T yysize1;
   enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
   /* Internationalized format string. */
-  const char *yyformat = YY_NULL;
+  const char *yyformat = YY_NULLPTR;
   /* Arguments of yyformat. */
   char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
   /* Number of reported tokens (one for the "unexpected", one per
@@ -1214,10 +1085,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
   int yycount = 0;
 
   /* There are many possibilities here to consider:
-     - Assume YYFAIL is not used.  It's too flawed to consider.  See
-       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
-       for details.  YYERROR is fine as it does not invoke this
-       function.
      - If this state is a consistent state with a default action, then
        the only way this function was invoked is if the default action
        is an error action.  In that case, don't check for expected
@@ -1266,11 +1133,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
                     break;
                   }
                 yyarg[yycount++] = yytname[yyx];
-                yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
-                if (! (yysize <= yysize1
-                       && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                  return 2;
-                yysize = yysize1;
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
               }
         }
     }
@@ -1290,10 +1159,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 # undef YYCASE_
     }
 
-  yysize1 = yysize + yystrlen (yyformat);
-  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-    return 2;
-  yysize = yysize1;
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
 
   if (*yymsg_alloc < yysize)
     {
@@ -1330,78 +1201,58 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 | Release the memory associated to this symbol.  |
 `-----------------------------------------------*/
 
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
 {
   YYUSE (yyvaluep);
-
   if (!yymsg)
     yymsg = "Deleting";
   YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   switch (yytype)
     {
-      case 57: /* "choice_entry" */
+          case 58: /* choice_entry  */
 
-	{
+      {
 	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
-		(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
-	if (current_menu == (yyvaluep->menu))
+		((*yyvaluep).menu)->file->name, ((*yyvaluep).menu)->lineno);
+	if (current_menu == ((*yyvaluep).menu))
 		menu_end_menu();
-};
+}
 
-	break;
-      case 63: /* "if_entry" */
+        break;
 
-	{
+    case 64: /* if_entry  */
+
+      {
 	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
-		(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
-	if (current_menu == (yyvaluep->menu))
+		((*yyvaluep).menu)->file->name, ((*yyvaluep).menu)->lineno);
+	if (current_menu == ((*yyvaluep).menu))
 		menu_end_menu();
-};
+}
 
-	break;
-      case 69: /* "menu_entry" */
+        break;
 
-	{
+    case 70: /* menu_entry  */
+
+      {
 	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
-		(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
-	if (current_menu == (yyvaluep->menu))
+		((*yyvaluep).menu)->file->name, ((*yyvaluep).menu)->lineno);
+	if (current_menu == ((*yyvaluep).menu))
 		menu_end_menu();
-};
+}
+
+        break;
 
-	break;
 
       default:
-	break;
+        break;
     }
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 }
 
 
-/* Prevent warnings from -Wmissing-prototypes.  */
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
 
 
 /* The lookahead symbol.  */
@@ -1409,7 +1260,6 @@ int yychar;
 
 /* The semantic value of the lookahead symbol.  */
 YYSTYPE yylval;
-
 /* Number of syntax errors so far.  */
 int yynerrs;
 
@@ -1418,35 +1268,16 @@ int yynerrs;
 | yyparse.  |
 `----------*/
 
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 int
 yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
 {
     int yystate;
     /* Number of tokens to shift before error messages enabled.  */
     int yyerrstatus;
 
     /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.
+       'yyss': related to states.
+       'yyvs': related to semantic values.
 
        Refer to the stacks through separate pointers, to allow yyoverflow
        to reallocate them elsewhere.  */
@@ -1466,7 +1297,7 @@ yyparse ()
   int yyn;
   int yyresult;
   /* Lookahead token as an internal (translated) token number.  */
-  int yytoken;
+  int yytoken = 0;
   /* The variables used to return semantic value and location from the
      action routines.  */
   YYSTYPE yyval;
@@ -1484,9 +1315,8 @@ yyparse ()
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
-  yytoken = 0;
-  yyss = yyssa;
-  yyvs = yyvsa;
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
   yystacksize = YYINITDEPTH;
 
   YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1495,14 +1325,6 @@ yyparse ()
   yyerrstatus = 0;
   yynerrs = 0;
   yychar = YYEMPTY; /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-  yyssp = yyss;
-  yyvsp = yyvs;
-
   goto yysetstate;
 
 /*------------------------------------------------------------.
@@ -1523,23 +1345,23 @@ yyparse ()
 
 #ifdef yyoverflow
       {
-	/* Give user a chance to reallocate the stack.  Use copies of
-	   these so that the &'s don't force the real ones into
-	   memory.  */
-	YYSTYPE *yyvs1 = yyvs;
-	yytype_int16 *yyss1 = yyss;
-
-	/* Each stack pointer address is followed by the size of the
-	   data in use in that stack, in bytes.  This used to be a
-	   conditional around just the two extra args, but that might
-	   be undefined if yyoverflow is a macro.  */
-	yyoverflow (YY_("memory exhausted"),
-		    &yyss1, yysize * sizeof (*yyssp),
-		    &yyvs1, yysize * sizeof (*yyvsp),
-		    &yystacksize);
-
-	yyss = yyss1;
-	yyvs = yyvs1;
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
       }
 #else /* no yyoverflow */
 # ifndef YYSTACK_RELOCATE
@@ -1547,22 +1369,22 @@ yyparse ()
 # else
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
-	goto yyexhaustedlab;
+        goto yyexhaustedlab;
       yystacksize *= 2;
       if (YYMAXDEPTH < yystacksize)
-	yystacksize = YYMAXDEPTH;
+        yystacksize = YYMAXDEPTH;
 
       {
-	yytype_int16 *yyss1 = yyss;
-	union yyalloc *yyptr =
-	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-	if (! yyptr)
-	  goto yyexhaustedlab;
-	YYSTACK_RELOCATE (yyss_alloc, yyss);
-	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 #  undef YYSTACK_RELOCATE
-	if (yyss1 != yyssa)
-	  YYSTACK_FREE (yyss1);
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
       }
 # endif
 #endif /* no yyoverflow */
@@ -1571,10 +1393,10 @@ yyparse ()
       yyvsp = yyvs + yysize - 1;
 
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-		  (unsigned long int) yystacksize));
+                  (unsigned long int) yystacksize));
 
       if (yyss + yystacksize - 1 <= yyssp)
-	YYABORT;
+        YYABORT;
     }
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
@@ -1603,7 +1425,7 @@ yybackup:
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
+      yychar = yylex ();
     }
 
   if (yychar <= YYEOF)
@@ -1643,7 +1465,9 @@ yybackup:
   yychar = YYEMPTY;
 
   yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
   goto yynewstate;
 
@@ -1666,7 +1490,7 @@ yyreduce:
   yylen = yyr2[yyn];
 
   /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
+     '$$ = $1'.
 
      Otherwise, the following line sets YYVAL to garbage.
      This behavior is undocumented and Bison
@@ -1682,64 +1506,73 @@ yyreduce:
         case 10:
 
     { zconf_error("unexpected end statement"); }
+
     break;
 
   case 11:
 
-    { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); }
+    { zconf_error("unknown statement \"%s\"", (yyvsp[-2].string)); }
+
     break;
 
   case 12:
 
     {
-	zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name);
+	zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[-2].id)->name);
 }
+
     break;
 
   case 13:
 
     { zconf_error("invalid statement"); }
+
     break;
 
-  case 28:
+  case 29:
+
+    { zconf_error("unknown option \"%s\"", (yyvsp[-2].string)); }
 
-    { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); }
     break;
 
-  case 29:
+  case 30:
 
     { zconf_error("invalid option"); }
+
     break;
 
-  case 30:
+  case 31:
 
     {
-	struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
+	struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
 	sym->flags |= SYMBOL_OPTIONAL;
 	menu_add_entry(sym);
-	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
+	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
 }
+
     break;
 
-  case 31:
+  case 32:
 
     {
 	menu_end_entry();
 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 32:
+  case 33:
 
     {
-	struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
+	struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
 	sym->flags |= SYMBOL_OPTIONAL;
 	menu_add_entry(sym);
-	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
+	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
 }
+
     break;
 
-  case 33:
+  case 34:
 
     {
 	if (current_entry->prompt)
@@ -1749,352 +1582,410 @@ yyreduce:
 	menu_end_entry();
 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 41:
+  case 42:
 
     {
-	menu_set_type((yyvsp[(1) - (3)].id)->stype);
+	menu_set_type((yyvsp[-2].id)->stype);
 	printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
 		zconf_curname(), zconf_lineno(),
-		(yyvsp[(1) - (3)].id)->stype);
+		(yyvsp[-2].id)->stype);
 }
+
     break;
 
-  case 42:
+  case 43:
 
     {
-	menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
+	menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 43:
+  case 44:
 
     {
-	menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));
-	if ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN)
-		menu_set_type((yyvsp[(1) - (4)].id)->stype);
+	menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr));
+	if ((yyvsp[-3].id)->stype != S_UNKNOWN)
+		menu_set_type((yyvsp[-3].id)->stype);
 	printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
 		zconf_curname(), zconf_lineno(),
-		(yyvsp[(1) - (4)].id)->stype);
+		(yyvsp[-3].id)->stype);
 }
+
     break;
 
-  case 44:
+  case 45:
 
     {
-	menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
+	menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 45:
+  case 46:
+
+    {
+	menu_add_symbol(P_COUNT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
+	printd(DEBUG_PARSE, "%s:%d:count\n", zconf_curname(), zconf_lineno());
+}
+
+    break;
+
+  case 47:
 
     {
-	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));
+	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 48:
+  case 50:
 
     {
-	const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
+	const struct kconf_id *id = kconf_id_lookup((yyvsp[-1].string), strlen((yyvsp[-1].string)));
 	if (id && id->flags & TF_OPTION)
-		menu_add_option(id->token, (yyvsp[(3) - (3)].string));
+		menu_add_option(id->token, (yyvsp[0].string));
 	else
-		zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string));
-	free((yyvsp[(2) - (3)].string));
+		zconfprint("warning: ignoring unknown option %s", (yyvsp[-1].string));
+	free((yyvsp[-1].string));
 }
+
     break;
 
-  case 49:
+  case 51:
 
     { (yyval.string) = NULL; }
+
     break;
 
-  case 50:
+  case 52:
+
+    { (yyval.string) = (yyvsp[0].string); }
 
-    { (yyval.string) = (yyvsp[(2) - (2)].string); }
     break;
 
-  case 51:
+  case 53:
 
     {
-	struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);
+	struct symbol *sym = sym_lookup((yyvsp[-1].string), SYMBOL_CHOICE);
 	sym->flags |= SYMBOL_AUTO;
 	menu_add_entry(sym);
 	menu_add_expr(P_CHOICE, NULL, NULL);
 	printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 52:
+  case 54:
 
     {
 	(yyval.menu) = menu_add_menu();
 }
+
     break;
 
-  case 53:
+  case 55:
 
     {
-	if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {
+	if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) {
 		menu_end_menu();
 		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
 	}
 }
+
     break;
 
-  case 61:
+  case 63:
 
     {
-	menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
+	menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 62:
+  case 64:
 
     {
-	if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {
-		menu_set_type((yyvsp[(1) - (3)].id)->stype);
+	if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) {
+		menu_set_type((yyvsp[-2].id)->stype);
 		printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
 			zconf_curname(), zconf_lineno(),
-			(yyvsp[(1) - (3)].id)->stype);
+			(yyvsp[-2].id)->stype);
 	} else
 		YYERROR;
 }
+
     break;
 
-  case 63:
+  case 65:
 
     {
 	current_entry->sym->flags |= SYMBOL_OPTIONAL;
 	printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 64:
+  case 66:
 
     {
-	if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {
-		menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
+	if ((yyvsp[-3].id)->stype == S_UNKNOWN) {
+		menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
 		printd(DEBUG_PARSE, "%s:%d:default\n",
 			zconf_curname(), zconf_lineno());
 	} else
 		YYERROR;
 }
+
     break;
 
-  case 67:
+  case 69:
 
     {
 	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
 	menu_add_entry(NULL);
-	menu_add_dep((yyvsp[(2) - (3)].expr));
+	menu_add_dep((yyvsp[-1].expr));
 	(yyval.menu) = menu_add_menu();
 }
+
     break;
 
-  case 68:
+  case 70:
 
     {
-	if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {
+	if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) {
 		menu_end_menu();
 		printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
 	}
 }
+
     break;
 
-  case 74:
+  case 76:
 
     {
-	menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+	menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL);
 }
+
     break;
 
-  case 75:
+  case 77:
 
     {
 	menu_add_entry(NULL);
-	menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+	menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL);
 	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 76:
+  case 78:
 
     {
 	(yyval.menu) = menu_add_menu();
 }
+
     break;
 
-  case 77:
+  case 79:
 
     {
-	if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {
+	if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) {
 		menu_end_menu();
 		printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
 	}
 }
+
     break;
 
-  case 83:
+  case 85:
 
     {
-	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
-	zconf_nextfile((yyvsp[(2) - (3)].string));
+	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
+	zconf_nextfile((yyvsp[-1].string));
 }
+
     break;
 
-  case 84:
+  case 86:
 
     {
 	menu_add_entry(NULL);
-	menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL);
+	menu_add_prompt(P_COMMENT, (yyvsp[-1].string), NULL);
 	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 85:
+  case 87:
 
     {
 	menu_end_entry();
 }
+
     break;
 
-  case 86:
+  case 88:
 
     {
 	printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
 	zconf_starthelp();
 }
+
     break;
 
-  case 87:
+  case 89:
 
     {
-	current_entry->help = (yyvsp[(2) - (2)].string);
+	current_entry->help = (yyvsp[0].string);
 }
+
     break;
 
-  case 92:
+  case 94:
 
     {
-	menu_add_dep((yyvsp[(3) - (4)].expr));
+	menu_add_dep((yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
 }
-    break;
-
-  case 96:
 
-    {
-	menu_add_visibility((yyvsp[(2) - (2)].expr));
-}
     break;
 
   case 98:
 
     {
-	menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));
+	menu_add_visibility((yyvsp[0].expr));
 }
-    break;
 
-  case 101:
-
-    { (yyval.id) = (yyvsp[(1) - (2)].id); }
     break;
 
-  case 102:
+  case 100:
+
+    {
+	menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr));
+}
 
-    { (yyval.id) = (yyvsp[(1) - (2)].id); }
     break;
 
   case 103:
 
-    { (yyval.id) = (yyvsp[(1) - (2)].id); }
+    { (yyval.id) = (yyvsp[-1].id); }
+
     break;
 
-  case 106:
+  case 104:
+
+    { (yyval.id) = (yyvsp[-1].id); }
 
-    { (yyval.expr) = NULL; }
     break;
 
-  case 107:
+  case 105:
+
+    { (yyval.id) = (yyvsp[-1].id); }
 
-    { (yyval.expr) = (yyvsp[(2) - (2)].expr); }
     break;
 
   case 108:
 
-    { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); }
+    { (yyval.expr) = NULL; }
+
     break;
 
   case 109:
 
-    { (yyval.expr) = expr_alloc_comp(E_LTH, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+    { (yyval.expr) = (yyvsp[0].expr); }
+
     break;
 
   case 110:
 
-    { (yyval.expr) = expr_alloc_comp(E_LEQ, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+    { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); }
+
     break;
 
   case 111:
 
-    { (yyval.expr) = expr_alloc_comp(E_GTH, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+    { (yyval.expr) = expr_alloc_comp(E_LTH, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
     break;
 
   case 112:
 
-    { (yyval.expr) = expr_alloc_comp(E_GEQ, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+    { (yyval.expr) = expr_alloc_comp(E_LEQ, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
     break;
 
   case 113:
 
-    { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+    { (yyval.expr) = expr_alloc_comp(E_GTH, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
     break;
 
   case 114:
 
-    { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+    { (yyval.expr) = expr_alloc_comp(E_GEQ, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
     break;
 
   case 115:
 
-    { (yyval.expr) = (yyvsp[(2) - (3)].expr); }
+    { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
     break;
 
   case 116:
 
-    { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); }
+    { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
     break;
 
   case 117:
 
-    { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
+    { (yyval.expr) = (yyvsp[-1].expr); }
+
     break;
 
   case 118:
 
-    { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
+    { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); }
+
     break;
 
   case 119:
 
-    { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); }
+    { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+
     break;
 
   case 120:
 
-    { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); }
+    { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+
     break;
 
   case 121:
 
+    { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); }
+
+    break;
+
+  case 122:
+
+    { (yyval.symbol) = sym_lookup((yyvsp[0].string), SYMBOL_CONST); free((yyvsp[0].string)); }
+
+    break;
+
+  case 123:
+
     { (yyval.string) = NULL; }
+
     break;
 
 
@@ -2120,7 +2011,7 @@ yyreduce:
 
   *++yyvsp = yyval;
 
-  /* Now `shift' the result of the reduction.  Determine what state
+  /* Now 'shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
 
@@ -2135,9 +2026,9 @@ yyreduce:
   goto yynewstate;
 
 
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
 yyerrlab:
   /* Make sure we have latest lookahead translation.  See comments at
      user semantic actions for why this is necessary.  */
@@ -2188,20 +2079,20 @@ yyerrlab:
   if (yyerrstatus == 3)
     {
       /* If just tried and failed to reuse lookahead token after an
-	 error, discard it.  */
+         error, discard it.  */
 
       if (yychar <= YYEOF)
-	{
-	  /* Return failure if at end of input.  */
-	  if (yychar == YYEOF)
-	    YYABORT;
-	}
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
       else
-	{
-	  yydestruct ("Error: discarding",
-		      yytoken, &yylval);
-	  yychar = YYEMPTY;
-	}
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval);
+          yychar = YYEMPTY;
+        }
     }
 
   /* Else will try to reuse lookahead token after shifting the error
@@ -2220,7 +2111,7 @@ yyerrorlab:
   if (/*CONSTCOND*/ 0)
      goto yyerrorlab;
 
-  /* Do not reclaim the symbols of the rule which action triggered
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
   YYPOPSTACK (yylen);
   yylen = 0;
@@ -2233,35 +2124,37 @@ yyerrorlab:
 | yyerrlab1 -- common code for both syntax error and YYERROR.  |
 `-------------------------------------------------------------*/
 yyerrlab1:
-  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
 
   for (;;)
     {
       yyn = yypact[yystate];
       if (!yypact_value_is_default (yyn))
-	{
-	  yyn += YYTERROR;
-	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-	    {
-	      yyn = yytable[yyn];
-	      if (0 < yyn)
-		break;
-	    }
-	}
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
 
       /* Pop the current state because it cannot handle the error token.  */
       if (yyssp == yyss)
-	YYABORT;
+        YYABORT;
 
 
       yydestruct ("Error: popping",
-		  yystos[yystate], yyvsp);
+                  yystos[yystate], yyvsp);
       YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
     }
 
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
 
   /* Shift the error token.  */
@@ -2304,14 +2197,14 @@ yyreturn:
       yydestruct ("Cleanup: discarding lookahead",
                   yytoken, &yylval);
     }
-  /* Do not reclaim the symbols of the rule which action triggered
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYABORT or YYACCEPT.  */
   YYPOPSTACK (yylen);
   YY_STACK_PRINT (yyss, yyssp);
   while (yyssp != yyss)
     {
       yydestruct ("Cleanup: popping",
-		  yystos[*yyssp], yyvsp);
+                  yystos[*yyssp], yyvsp);
       YYPOPSTACK (1);
     }
 #ifndef yyoverflow
@@ -2322,14 +2215,11 @@ yyreturn:
   if (yymsg != yymsgbuf)
     YYSTACK_FREE (yymsg);
 #endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
+  return yyresult;
 }
 
 
 
-
-
 void conf_parse(const char *name)
 {
 	struct symbol *sym;
@@ -2501,6 +2391,11 @@ static void print_symbol(FILE *out, struct menu *menu)
 			expr_fprint(prop->expr, out);
 			fputc('\n', out);
 			break;
+		case P_COUNT:
+			fputs( "  count ", out);
+			expr_fprint(prop->expr, out);
+			fputc('\n', out);
+			break;
 		case P_RANGE:
 			fputs( "  range ", out);
 			expr_fprint(prop->expr, out);
@@ -2577,4 +2472,3 @@ void zconfdump(FILE *out)
 #include "expr.c"
 #include "symbol.c"
 #include "menu.c"
-
-- 
2.6.2


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

* [RFC v4 8/8] mac80211: use Kconfig counters to determine feature optimisation
  2015-11-12  8:47 [RFC v4 0/8] mac80211: jump labels for HW flags Johannes Berg
                   ` (6 preceding siblings ...)
  2015-11-12  8:47 ` [RFC v4 7/8] kconfig: regenerate the shipped files Johannes Berg
@ 2015-11-12  8:47 ` Johannes Berg
  2015-11-13 16:29   ` Steven Rostedt
  7 siblings, 1 reply; 18+ messages in thread
From: Johannes Berg @ 2015-11-12  8:47 UTC (permalink / raw)
  To: linux-wireless
  Cc: Jason Baron, Peter Zijlstra, Steven Rostedt, Michal Marek, Johannes Berg

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

Drivers that would like to have feature flag optimisations are
currently required to select _ON and _OFF symbols for each one,
indicating whether they'd like to be optimised for being on or
off respectively. This handles badly, if a new feature flag is
added then all such drivers need to be updated.

Instead, use the new Kconfig counters to determine
 (a) the number of times each feature flag was selected ON
 (b) the number of mac80211 drivers built

if (a) > 0 then it was requested on by at least one driver
if (a) < (b) then it was not requested by at least one driver

This allows determining whether or not optimisations should be
made more easily, and importantly, adding new flags no longer
requires editing the Kconfig for all drivers since they won't
want the new flag - only the driver it's added for does.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/Kconfig |  21 ++-
 net/mac80211/Kconfig         |   4 +
 net/mac80211/Kconfig.hwflags | 297 +++++++++++++++----------------------------
 net/mac80211/hwflags.h       |   6 +-
 4 files changed, 122 insertions(+), 206 deletions(-)

diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index f2a8fdca5ede..26ffa28a5677 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -246,17 +246,16 @@ 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
+	count MAC80211_NUM_DRIVERS
+	count MAC80211_HW_SUPPORT_FAST_XMIT
+	count MAC80211_HW_CHANCTX_STA_CSA
+	count MAC80211_HW_SUPPORTS_HT_CCK_RATES
+	count MAC80211_HW_QUEUE_CONTROL
+	count MAC80211_HW_WANT_MONITOR_VIF
+	count MAC80211_HW_AMPDU_AGGREGATION
+	count MAC80211_HW_MFP_CAPABLE
+	count MAC80211_HW_SIGNAL_DBM
+	count MAC80211_HW_TDLS_WIDER_BW
 	---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/Kconfig b/net/mac80211/Kconfig
index 206b11598dd1..9eba9c5cea18 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -11,6 +11,10 @@ config MAC80211
 	  This option enables the hardware independent IEEE 802.11
 	  networking stack.
 
+config MAC80211_NUM_DRIVERS
+	int
+	depends on MAC80211
+
 comment "CFG80211 needs to be enabled for MAC80211"
 	depends on CFG80211=n
 
diff --git a/net/mac80211/Kconfig.hwflags b/net/mac80211/Kconfig.hwflags
index 06f6ba12c86e..c384eef7e987 100644
--- a/net/mac80211/Kconfig.hwflags
+++ b/net/mac80211/Kconfig.hwflags
@@ -1,192 +1,105 @@
-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
+config MAC80211_COUNT_DRIVERS
+	int
+	default 0
+config MAC80211_HW_HAS_RATE_CONTROL
+	int
+	default 0
+config MAC80211_HW_RX_INCLUDES_FCS
+	int
+	default 0
+config MAC80211_HW_HOST_BROADCAST_PS_BUFFERING
+	int
+	default 0
+config MAC80211_HW_SIGNAL_UNSPEC
+	int
+	default 0
+config MAC80211_HW_SIGNAL_DBM
+	int
+	default 0
+config MAC80211_HW_NEED_DTIM_BEFORE_ASSOC
+	int
+	default 0
+config MAC80211_HW_SPECTRUM_MGMT
+	int
+	default 0
+config MAC80211_HW_AMPDU_AGGREGATION
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_PS
+	int
+	default 0
+config MAC80211_HW_PS_NULLFUNC_STACK
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_DYNAMIC_PS
+	int
+	default 0
+config MAC80211_HW_MFP_CAPABLE
+	int
+	default 0
+config MAC80211_HW_WANT_MONITOR_VIF
+	int
+	default 0
+config MAC80211_HW_NO_AUTO_VIF
+	int
+	default 0
+config MAC80211_HW_SW_CRYPTO_CONTROL
+	int
+	default 0
+config MAC80211_HW_SUPPORT_FAST_XMIT
+	int
+	default 0
+config MAC80211_HW_REPORTS_TX_ACK_STATUS
+	int
+	default 0
+config MAC80211_HW_CONNECTION_MONITOR
+	int
+	default 0
+config MAC80211_HW_QUEUE_CONTROL
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_PER_STA_GTK
+	int
+	default 0
+config MAC80211_HW_AP_LINK_PS
+	int
+	default 0
+config MAC80211_HW_TX_AMPDU_SETUP_IN_HW
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_RC_TABLE
+	int
+	default 0
+config MAC80211_HW_P2P_DEV_ADDR_FOR_INTF
+	int
+	default 0
+config MAC80211_HW_TIMING_BEACON_ONLY
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_HT_CCK_RATES
+	int
+	default 0
+config MAC80211_HW_CHANCTX_STA_CSA
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_CLONED_SKBS
+	int
+	default 0
+config MAC80211_HW_SINGLE_SCAN_ALL_BANDS
+	int
+	default 0
+config MAC80211_HW_SINGLE_SCAN_ALL_BANDS_OFF
+	int
+	default 0
+config MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS
+	int
+	default 0
+config MAC80211_HW_TDLS_WIDER_BW
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_AMSDU_IN_AMPDU
+	int
+	default 0
+config MAC80211_HW_BEACON_TX_STATUS
+	int
+	default 0
diff --git a/net/mac80211/hwflags.h b/net/mac80211/hwflags.h
index 82bf89658cb7..4919d82539c4 100644
--- a/net/mac80211/hwflags.h
+++ b/net/mac80211/hwflags.h
@@ -15,11 +15,11 @@ extern struct static_key_false hwflags_keys[NUM_IEEE80211_HW_FLAGS];
 #ifdef CONFIG_JUMP_LABEL
 enum hwflags_defstates {
 #define __DEFINE_HWFLAG(_flg, _on, _off)				\
-	HWFLAGS_DEFSTATE_##_flg = -1 + ((_on) ^ (_off)) * (1 + _on),
+	HWFLAGS_DEFSTATE_##_flg = -1 + ((_on) ^ (_off)) * (1 + (_on)),
 #define DEFINE_HWFLAG(_flg)						\
 	__DEFINE_HWFLAG(_flg,						\
-			IS_ENABLED(CONFIG_MAC80211_HW_##_flg##_ON),	\
-			IS_ENABLED(CONFIG_MAC80211_HW_##_flg##_OFF))
+			CONFIG_MAC80211_HW_##_flg > 0,			\
+			CONFIG_MAC80211_HW_##_flg < CONFIG_MAC80211_NUM_DRIVERS)
 #include <net/mac80211-hwflags.h>
 #undef DEFINE_HWFLAG
 };
-- 
2.6.2


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

* Re: [RFC v4 3/8] mac80211: use static keys for hw flags
  2015-11-12  8:47 ` [RFC v4 3/8] mac80211: use static keys for hw flags Johannes Berg
@ 2015-11-13 16:22   ` Steven Rostedt
  2015-11-13 16:30     ` Johannes Berg
  0 siblings, 1 reply; 18+ messages in thread
From: Steven Rostedt @ 2015-11-13 16:22 UTC (permalink / raw)
  To: Johannes Berg
  Cc: linux-wireless, Jason Baron, Peter Zijlstra, Michal Marek, Johannes Berg

On Thu, 12 Nov 2015 09:47:48 +0100
Johannes Berg <johannes@sipsolutions.net> wrote:

> index 000000000000..e220c5e04406
> --- /dev/null
> +++ b/net/mac80211/hwflags.h
> @@ -0,0 +1,89 @@
> +/*
> + * 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_false hwflags_keys[NUM_IEEE80211_HW_FLAGS];
> +
> +#ifdef CONFIG_JUMP_LABEL
> +#define _HWFLAGS_DEFSTATE(_name, _on, _off)				\
> +	HWFLAGS_DEFSTATE_##_name = -1 + ((_on) ^ (_off)) * (1 + _on)

This sure could use a comment.

 on = 0, off = 0,  -1 + (0^0) * (1 + 0) = -1
 on = 0, off = 1,  -1 + (0^1) * (1 + 0) = 0
 on = 1, off = 0,  -1 + (1^0) * (1 + 1) = 1
 on = 1, off = 1,  -1 + (1^1) * (1 + 1) = -1

The I would also state:

  -1 means to simply use if logic (no jump labels/static keys)
   0 means to use jump label to off
   1 means to use jump label to on


> +#define HWFLAGS_DEFSTATE(_name)						\
> +	_HWFLAGS_DEFSTATE(_name,					\
> +			  IS_ENABLED(CONFIG_MAC80211_HW_##_name##_ON),	\
> +			  IS_ENABLED(CONFIG_MAC80211_HW_##_name##_OFF))
> +
> +enum hwflags_defstates {
> +HWFLAGS_DEFSTATE(HAS_RATE_CONTROL),
> +HWFLAGS_DEFSTATE(RX_INCLUDES_FCS),
> +HWFLAGS_DEFSTATE(HOST_BROADCAST_PS_BUFFERING),
> +HWFLAGS_DEFSTATE(SIGNAL_UNSPEC),
> +HWFLAGS_DEFSTATE(SIGNAL_DBM),
> +HWFLAGS_DEFSTATE(NEED_DTIM_BEFORE_ASSOC),
> +HWFLAGS_DEFSTATE(SPECTRUM_MGMT),
> +HWFLAGS_DEFSTATE(AMPDU_AGGREGATION),
> +HWFLAGS_DEFSTATE(SUPPORTS_PS),
> +HWFLAGS_DEFSTATE(PS_NULLFUNC_STACK),
> +HWFLAGS_DEFSTATE(SUPPORTS_DYNAMIC_PS),
> +HWFLAGS_DEFSTATE(MFP_CAPABLE),
> +HWFLAGS_DEFSTATE(WANT_MONITOR_VIF),
> +HWFLAGS_DEFSTATE(NO_AUTO_VIF),
> +HWFLAGS_DEFSTATE(SW_CRYPTO_CONTROL),
> +HWFLAGS_DEFSTATE(SUPPORT_FAST_XMIT),
> +HWFLAGS_DEFSTATE(REPORTS_TX_ACK_STATUS),
> +HWFLAGS_DEFSTATE(CONNECTION_MONITOR),
> +HWFLAGS_DEFSTATE(QUEUE_CONTROL),
> +HWFLAGS_DEFSTATE(SUPPORTS_PER_STA_GTK),
> +HWFLAGS_DEFSTATE(AP_LINK_PS),
> +HWFLAGS_DEFSTATE(TX_AMPDU_SETUP_IN_HW),
> +HWFLAGS_DEFSTATE(SUPPORTS_RC_TABLE),
> +HWFLAGS_DEFSTATE(P2P_DEV_ADDR_FOR_INTF),
> +HWFLAGS_DEFSTATE(TIMING_BEACON_ONLY),
> +HWFLAGS_DEFSTATE(SUPPORTS_HT_CCK_RATES),
> +HWFLAGS_DEFSTATE(CHANCTX_STA_CSA),
> +HWFLAGS_DEFSTATE(SUPPORTS_CLONED_SKBS),
> +HWFLAGS_DEFSTATE(SINGLE_SCAN_ON_ALL_BANDS),
> +HWFLAGS_DEFSTATE(TDLS_WIDER_BW),
> +HWFLAGS_DEFSTATE(SUPPORTS_AMSDU_IN_AMPDU),
> +HWFLAGS_DEFSTATE(BEACON_TX_STATUS),
> +};
> +

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

* Re: [RFC v4 5/8] mac80211: generate hw flags from include file
  2015-11-12  8:47 ` [RFC v4 5/8] mac80211: generate hw flags from include file Johannes Berg
@ 2015-11-13 16:25   ` Steven Rostedt
  2015-11-13 16:31     ` Johannes Berg
  0 siblings, 1 reply; 18+ messages in thread
From: Steven Rostedt @ 2015-11-13 16:25 UTC (permalink / raw)
  To: Johannes Berg
  Cc: linux-wireless, Jason Baron, Peter Zijlstra, Michal Marek, Johannes Berg

On Thu, 12 Nov 2015 09:47:50 +0100
Johannes Berg <johannes@sipsolutions.net> wrote:


> +#define __DEFINE_HWFLAG(_flg, _on, _off)				\
> +	HWFLAGS_DEFSTATE_##_flg = -1 + ((_on) ^ (_off)) * (1 + _on),
> +#define DEFINE_HWFLAG(_flg)						\
> +	__DEFINE_HWFLAG(_flg,						\
> +			IS_ENABLED(CONFIG_MAC80211_HW_##_flg##_ON),	\
> +			IS_ENABLED(CONFIG_MAC80211_HW_##_flg##_OFF))
> +#include <net/mac80211-hwflags.h>
> +#undef DEFINE_HWFLAG

You learned to use the MACRO force well, young Skywalker.

-- Steve

>  };
>  
>  bool _____optimisation_missing(void);


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

* Re: [RFC v4 6/8] kconfig: introduce "count"
  2015-11-12  8:47 ` [RFC v4 6/8] kconfig: introduce "count" Johannes Berg
@ 2015-11-13 16:26   ` Steven Rostedt
  2015-11-13 16:32     ` Johannes Berg
  0 siblings, 1 reply; 18+ messages in thread
From: Steven Rostedt @ 2015-11-13 16:26 UTC (permalink / raw)
  To: Johannes Berg
  Cc: linux-wireless, Jason Baron, Peter Zijlstra, Michal Marek, Johannes Berg

On Thu, 12 Nov 2015 09:47:51 +0100
Johannes Berg <johannes@sipsolutions.net> wrote:

> From: Johannes Berg <johannes.berg@intel.com>
> 
> "count" works similar to "select"; take, for example, this snippet:
> 
>     config MY_COUNTER
>             int
> 
>     config MY_DRIVER_1
>             bool "my driver 1"
>             count MY_COUNTER
> 
>     config MY_DRIVER_2
>             bool "my driver 2"
>             count MY_COUNTER
> 
> This will get MY_COUNTER to have a value of 0, 1 or 2, depending
> on whether or not MY_DRIVER_1/MY_DRIVER_2 are not at all, one or
> both selected respectively.

I find the name "count" ambiguous. What happened to "increment" or
something?

-- Steve

> 
> This can be useful for certain optimization purposes but I'm sure
> people will come up with other creative usage.
> 
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---


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

* Re: [RFC v4 8/8] mac80211: use Kconfig counters to determine feature optimisation
  2015-11-12  8:47 ` [RFC v4 8/8] mac80211: use Kconfig counters to determine feature optimisation Johannes Berg
@ 2015-11-13 16:29   ` Steven Rostedt
  2015-11-13 16:35     ` Johannes Berg
  0 siblings, 1 reply; 18+ messages in thread
From: Steven Rostedt @ 2015-11-13 16:29 UTC (permalink / raw)
  To: Johannes Berg
  Cc: linux-wireless, Jason Baron, Peter Zijlstra, Michal Marek, Johannes Berg

On Thu, 12 Nov 2015 09:47:53 +0100
Johannes Berg <johannes@sipsolutions.net> wrote:

> From: Johannes Berg <johannes.berg@intel.com>
> 
> Drivers that would like to have feature flag optimisations are
> currently required to select _ON and _OFF symbols for each one,
> indicating whether they'd like to be optimised for being on or
> off respectively. This handles badly, if a new feature flag is
> added then all such drivers need to be updated.
> 
> Instead, use the new Kconfig counters to determine
>  (a) the number of times each feature flag was selected ON
>  (b) the number of mac80211 drivers built
> 
> if (a) > 0 then it was requested on by at least one driver
> if (a) < (b) then it was not requested by at least one driver
> 
> This allows determining whether or not optimisations should be
> made more easily, and importantly, adding new flags no longer
> requires editing the Kconfig for all drivers since they won't
> want the new flag - only the driver it's added for does.
> 
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
>  drivers/net/wireless/Kconfig |  21 ++-
>  net/mac80211/Kconfig         |   4 +
>  net/mac80211/Kconfig.hwflags | 297 +++++++++++++++----------------------------
>  net/mac80211/hwflags.h       |   6 +-
>  4 files changed, 122 insertions(+), 206 deletions(-)
> 
> diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
> index f2a8fdca5ede..26ffa28a5677 100644
> --- a/drivers/net/wireless/Kconfig
> +++ b/drivers/net/wireless/Kconfig
> @@ -246,17 +246,16 @@ 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

What happened to these two?

> +	count MAC80211_NUM_DRIVERS
> +	count MAC80211_HW_SUPPORT_FAST_XMIT
> +	count MAC80211_HW_CHANCTX_STA_CSA
> +	count MAC80211_HW_SUPPORTS_HT_CCK_RATES
> +	count MAC80211_HW_QUEUE_CONTROL
> +	count MAC80211_HW_WANT_MONITOR_VIF
> +	count MAC80211_HW_AMPDU_AGGREGATION
> +	count MAC80211_HW_MFP_CAPABLE
> +	count MAC80211_HW_SIGNAL_DBM
> +	count MAC80211_HW_TDLS_WIDER_BW
>  	---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/Kconfig b/net/mac80211/Kconfig
> index 206b11598dd1..9eba9c5cea18 100644
> --- a/net/mac80211/Kconfig
> +++ b/net/mac80211/Kconfig
> @@ -11,6 +11,10 @@ config MAC80211
>  	  This option enables the hardware independent IEEE 802.11
>  	  networking stack.
>  
> +config MAC80211_NUM_DRIVERS
> +	int
> +	depends on MAC80211

Why the depends? Does it make it 1 to start with?

-- Steve

> +
>  comment "CFG80211 needs to be enabled for MAC80211"
>  	depends on CFG80211=n
>  

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

* Re: [RFC v4 3/8] mac80211: use static keys for hw flags
  2015-11-13 16:22   ` Steven Rostedt
@ 2015-11-13 16:30     ` Johannes Berg
  0 siblings, 0 replies; 18+ messages in thread
From: Johannes Berg @ 2015-11-13 16:30 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: linux-wireless, Jason Baron, Peter Zijlstra, Michal Marek

On Fri, 2015-11-13 at 11:22 -0500, Steven Rostedt wrote:

> This sure could use a comment.
> 
>  on = 0, off = 0,  -1 + (0^0) * (1 + 0) = -1
>  on = 0, off = 1,  -1 + (0^1) * (1 + 0) = 0
>  on = 1, off = 0,  -1 + (1^0) * (1 + 1) = 1
>  on = 1, off = 1,  -1 + (1^1) * (1 + 1) = -1
> 
> The I would also state:
> 
>   -1 means to simply use if logic (no jump labels/static keys)
>    0 means to use jump label to off
>    1 means to use jump label to on

Yeah, fair enough :)

FWIW, I changed my mind and redid all of this without the jump labels,
just actually eliding the code completely if possible. I've put it in
the hwflags-elide branch in my mac80211-next tree:
https://git.kernel.org/cgit/linux/kernel/git/jberg/mac80211-next.git/log/?h=hwflags-elide

johannes

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

* Re: [RFC v4 5/8] mac80211: generate hw flags from include file
  2015-11-13 16:25   ` Steven Rostedt
@ 2015-11-13 16:31     ` Johannes Berg
  0 siblings, 0 replies; 18+ messages in thread
From: Johannes Berg @ 2015-11-13 16:31 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: linux-wireless, Jason Baron, Peter Zijlstra, Michal Marek

On Fri, 2015-11-13 at 11:25 -0500, Steven Rostedt wrote:

> > +	__DEFINE_HWFLAG(_flg,					
> > 	\
> > +			IS_ENABLED(CONFIG_MAC80211_HW_##_flg##_ON)
> > ,	\
> > +			IS_ENABLED(CONFIG_MAC80211_HW_##_flg##_OFF
> > ))
> > +#include <net/mac80211-hwflags.h>
> > +#undef DEFINE_HWFLAG
> 
> You learned to use the MACRO force well, young Skywalker.
> 

Heh. Sadly, this breaks the automatic Kconfig dependency tracking,
since it doesn't realize it should have a dependency on
include/config/mac80211/hw/.../{on,off}.h

Not sure what to do about that - I'm tempted to just ignore it.

johannes

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

* Re: [RFC v4 6/8] kconfig: introduce "count"
  2015-11-13 16:26   ` Steven Rostedt
@ 2015-11-13 16:32     ` Johannes Berg
  0 siblings, 0 replies; 18+ messages in thread
From: Johannes Berg @ 2015-11-13 16:32 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: linux-wireless, Jason Baron, Peter Zijlstra, Michal Marek

On Fri, 2015-11-13 at 11:26 -0500, Steven Rostedt wrote:
> 
> >     config MY_DRIVER_2
> >             bool "my driver 2"
> >             count MY_COUNTER
> > 
> > This will get MY_COUNTER to have a value of 0, 1 or 2, depending
> > on whether or not MY_DRIVER_1/MY_DRIVER_2 are not at all, one or
> > both selected respectively.
> 
> I find the name "count" ambiguous. What happened to "increment" or
> something?
> 

I forgot about it :)

I'll go change it to "increment", that does indeed seem better.

johannes

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

* Re: [RFC v4 8/8] mac80211: use Kconfig counters to determine feature optimisation
  2015-11-13 16:29   ` Steven Rostedt
@ 2015-11-13 16:35     ` Johannes Berg
  2015-11-13 16:49       ` Steven Rostedt
  0 siblings, 1 reply; 18+ messages in thread
From: Johannes Berg @ 2015-11-13 16:35 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: linux-wireless, Jason Baron, Peter Zijlstra, Michal Marek

On Fri, 2015-11-13 at 11:29 -0500, Steven Rostedt wrote:

> > -	select MAC80211_HW_HAS_RATE_CONTROL_OFF
> > -	select MAC80211_HW_RX_INCLUDES_FCS_OFF
> 
> What happened to these two?

I removed the _OFF ones entirely, and instead with this patch am now
relying on modified logic:

 _on  = flags_counter > 0
 _off = flags_counter < driver_counter

So the ones that are requested _OFF no longer need to be listed in
Kconfig - that was the entire point of doing the count (increment)
thing since we can then add new flags without touching all the drivers
to select them to _OFF.

> > +config MAC80211_NUM_DRIVERS
> > +	int
> > +	depends on MAC80211
> 
> Why the depends? Does it make it 1 to start with?
> 

No, it just removes it from the Kconfig entirely when you don't even
have MAC80211 instead of leaving it set there to 0. Probably not really
necessary, or could be better to put them all inside an "if mac80211"
block.

johannes

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

* Re: [RFC v4 8/8] mac80211: use Kconfig counters to determine feature optimisation
  2015-11-13 16:35     ` Johannes Berg
@ 2015-11-13 16:49       ` Steven Rostedt
  0 siblings, 0 replies; 18+ messages in thread
From: Steven Rostedt @ 2015-11-13 16:49 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Jason Baron, Peter Zijlstra, Michal Marek

On Fri, 13 Nov 2015 17:35:39 +0100
Johannes Berg <johannes@sipsolutions.net> wrote:

> On Fri, 2015-11-13 at 11:29 -0500, Steven Rostedt wrote:
> 
> > > -	select MAC80211_HW_HAS_RATE_CONTROL_OFF
> > > -	select MAC80211_HW_RX_INCLUDES_FCS_OFF  
> > 
> > What happened to these two?  
> 
> I removed the _OFF ones entirely, and instead with this patch am now
> relying on modified logic:
> 
>  _on  = flags_counter > 0
>  _off = flags_counter < driver_counter
> 
> So the ones that are requested _OFF no longer need to be listed in
> Kconfig - that was the entire point of doing the count (increment)
> thing since we can then add new flags without touching all the drivers
> to select them to _OFF.
> 

Ah, I missed that they were "_OFF".

-- Steve

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

end of thread, other threads:[~2015-11-13 16:50 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-12  8:47 [RFC v4 0/8] mac80211: jump labels for HW flags Johannes Berg
2015-11-12  8:47 ` [RFC v4 1/8] mac80211: add ieee80211_hw_clear() Johannes Berg
2015-11-12  8:47 ` [RFC v4 2/8] mac80211: introduce ieee80211_local_check() Johannes Berg
2015-11-12  8:47 ` [RFC v4 3/8] mac80211: use static keys for hw flags Johannes Berg
2015-11-13 16:22   ` Steven Rostedt
2015-11-13 16:30     ` Johannes Berg
2015-11-12  8:47 ` [RFC v4 4/8] mac80211: test the static key code Johannes Berg
2015-11-12  8:47 ` [RFC v4 5/8] mac80211: generate hw flags from include file Johannes Berg
2015-11-13 16:25   ` Steven Rostedt
2015-11-13 16:31     ` Johannes Berg
2015-11-12  8:47 ` [RFC v4 6/8] kconfig: introduce "count" Johannes Berg
2015-11-13 16:26   ` Steven Rostedt
2015-11-13 16:32     ` Johannes Berg
2015-11-12  8:47 ` [RFC v4 7/8] kconfig: regenerate the shipped files Johannes Berg
2015-11-12  8:47 ` [RFC v4 8/8] mac80211: use Kconfig counters to determine feature optimisation Johannes Berg
2015-11-13 16:29   ` Steven Rostedt
2015-11-13 16:35     ` Johannes Berg
2015-11-13 16:49       ` Steven Rostedt

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.