The old WDS 4-addr frame support is very limited, e.g.
 * no encryption is possible on such links
 * it cannot support rate/HT/VHT negotiation
 * management APIs are very restricted
These make the WDS legacy mode useless in practice.
All of these are resolved by the 4-addr AP/client support,
so there's also no reason to improve WDS in the future.
Therefore, add a Kconfig option to disable legacy WDS.
This gives people an "emergency valve" while they migrate
to the better-supported 4-addr AP/client option; we plan
to remove it (and the associated cfg80211/mac80211 code,
which is the ultimate goal) in the future.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
 if WLAN
 
+config WIRELESS_WDS
+       bool "mac80211-based legacy WDS support" if EXPERT
+       help
+         This option enables the deprecated WDS support, the newer
+         mac80211-based 4-addr AP/client support supersedes it with
+         a much better feature set (HT, VHT, ...)
+
+         We plan to remove this option and code, so if you find
+         that you have to enable it, please let us know on the
+         linux-wireless@vger.kernel.org mailing list, so we can
+         help you migrate to 4-addr AP/client (or, if it's really
+         necessary, give up on our plan of removing it).
+
 source "drivers/net/wireless/admtek/Kconfig"
 source "drivers/net/wireless/ath/Kconfig"
 source "drivers/net/wireless/atmel/Kconfig"
 
                                 BIT(NL80211_IFTYPE_P2P_GO) },
 };
 
+#ifdef CONFIG_WIRELESS_WDS
 static const struct ieee80211_iface_limit wds_limits[] = {
        { .max = 2048,  .types = BIT(NL80211_IFTYPE_WDS) },
 };
+#endif
 
 #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
 
                                        BIT(NL80211_CHAN_WIDTH_40),
 #endif
        },
+#ifdef CONFIG_WIRELESS_WDS
        {
                .limits = wds_limits,
                .n_limits = ARRAY_SIZE(wds_limits),
                .num_different_channels = 1,
                .beacon_int_infra_match = true,
        },
+#endif
 };
 
 #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
                        BIT(NL80211_IFTYPE_STATION) |
                        BIT(NL80211_IFTYPE_ADHOC) |
                        BIT(NL80211_IFTYPE_MESH_POINT) |
+#ifdef CONFIG_WIRELESS_WDS
                        BIT(NL80211_IFTYPE_WDS) |
+#endif
                        BIT(NL80211_IFTYPE_OCB);
 
                if (ath9k_is_chanctx_enabled())
 
                BIT(NL80211_IFTYPE_AP) |
                BIT(NL80211_IFTYPE_MESH_POINT) |
                BIT(NL80211_IFTYPE_STATION) |
+#ifdef CONFIG_WIRELESS_WDS
                BIT(NL80211_IFTYPE_WDS) |
+#endif
                BIT(NL80211_IFTYPE_ADHOC);
 
        hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
 
        hw->wiphy->interface_modes =
                BIT(NL80211_IFTYPE_AP) |
                BIT(NL80211_IFTYPE_STATION) |
+#ifdef CONFIG_WIRELESS_WDS
                BIT(NL80211_IFTYPE_WDS) |
+#endif
                BIT(NL80211_IFTYPE_ADHOC);
        hw->queues = 1; /* FIXME: hardware has more queues */
        hw->max_rates = 2;
 
        if (rt2x00dev->bcn->limit > 0)
                rt2x00dev->hw->wiphy->interface_modes |=
                    BIT(NL80211_IFTYPE_ADHOC) |
-                   BIT(NL80211_IFTYPE_AP) |
 #ifdef CONFIG_MAC80211_MESH
                    BIT(NL80211_IFTYPE_MESH_POINT) |
 #endif
-                   BIT(NL80211_IFTYPE_WDS);
+#ifdef CONFIG_WIRELESS_WDS
+                   BIT(NL80211_IFTYPE_WDS) |
+#endif
+                   BIT(NL80211_IFTYPE_AP);
 
        rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
 
 
                                return -EINVAL;
                }
 
+#ifndef CONFIG_WIRELESS_WDS
+               if (WARN_ON(all_iftypes & BIT(NL80211_IFTYPE_WDS)))
+                       return -EINVAL;
+#endif
+
                /* You can't even choose that many! */
                if (WARN_ON(cnt < c->max_interfaces))
                        return -EINVAL;
                     !rdev->ops->add_nan_func || !rdev->ops->del_nan_func)))
                return -EINVAL;
 
+#ifndef CONFIG_WIRELESS_WDS
+       if (WARN_ON(wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS)))
+               return -EINVAL;
+#endif
+
        /*
         * if a wiphy has unsupported modes for regulatory channel enforcement,
         * opt-out of enforcement checking