cfg80211: rework chandef checking and export it
authorJohannes Berg <johannes.berg@intel.com>
Thu, 22 Nov 2012 15:59:45 +0000 (16:59 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 27 Nov 2012 08:18:25 +0000 (09:18 +0100)
Some of the chandef checking that we do in cfg80211
to check if a channel is supported or not is also
needed in mac80211, so rework that a bit and export
the functions that are needed.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
net/wireless/chan.c
net/wireless/core.h
net/wireless/nl80211.c

index e78db2cf3d1b2f40fd49b345036bf89d7885bcc6..a238f41e55c24d8559a4d7cdd4f5970647810c5f 100644 (file)
@@ -58,6 +58,8 @@
  * structures here describe these capabilities in detail.
  */
 
+struct wiphy;
+
 /*
  * wireless hardware capability structures
  */
@@ -387,6 +389,22 @@ const struct cfg80211_chan_def *
 cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1,
                            const struct cfg80211_chan_def *chandef2);
 
+/**
+ * cfg80211_chandef_valid - check if a channel definition is valid
+ * @chandef: the channel definition to check
+ */
+bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef);
+
+/**
+ * cfg80211_chandef_usable - check if secondary channels can be used
+ * @wiphy: the wiphy to validate against
+ * @chandef: the channel definition to check
+ * @prohibited_flags: the regulatory chanenl flags that must not be set
+ */
+bool cfg80211_chandef_usable(struct wiphy *wiphy,
+                            const struct cfg80211_chan_def *chandef,
+                            u32 prohibited_flags);
+
 /**
  * enum survey_info_flags - survey information flags
  *
@@ -1045,9 +1063,6 @@ struct ieee80211_txq_params {
        u8 aifs;
 };
 
-/* from net/wireless.h */
-struct wiphy;
-
 /**
  * DOC: Scanning and BSS list handling
  *
index bf2dfd54ff3ba6c0b2f673d37f790dca0a4aedce..b5f69831e31848ec2af3fb46d4bf594ee17e9319 100644 (file)
@@ -44,7 +44,7 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
 }
 EXPORT_SYMBOL(cfg80211_chandef_create);
 
-bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef)
+bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
 {
        u32 control_freq;
 
@@ -105,6 +105,7 @@ bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef)
 
        return true;
 }
+EXPORT_SYMBOL(cfg80211_chandef_valid);
 
 static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
                                  int *pri40, int *pri80)
@@ -187,9 +188,9 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
 }
 EXPORT_SYMBOL(cfg80211_chandef_compatible);
 
-bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
-                                u32 center_freq, u32 bandwidth,
-                                u32 prohibited_flags)
+static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
+                                       u32 center_freq, u32 bandwidth,
+                                       u32 prohibited_flags)
 {
        struct ieee80211_channel *c;
        u32 freq;
@@ -205,55 +206,88 @@ bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
        return true;
 }
 
-static bool cfg80211_check_beacon_chans(struct wiphy *wiphy,
-                                       u32 center_freq, u32 bw)
+bool cfg80211_chandef_usable(struct wiphy *wiphy,
+                            const struct cfg80211_chan_def *chandef,
+                            u32 prohibited_flags)
 {
-       return cfg80211_secondary_chans_ok(wiphy, center_freq, bw,
-                                          IEEE80211_CHAN_DISABLED |
-                                          IEEE80211_CHAN_PASSIVE_SCAN |
-                                          IEEE80211_CHAN_NO_IBSS |
-                                          IEEE80211_CHAN_RADAR);
-}
+       struct ieee80211_sta_ht_cap *ht_cap;
+       struct ieee80211_sta_vht_cap *vht_cap;
+       u32 width, control_freq;
 
-bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
-                            struct cfg80211_chan_def *chandef)
-{
-       u32 width;
-       bool res;
+       if (WARN_ON(!cfg80211_chandef_valid(chandef)))
+               return false;
 
-       trace_cfg80211_reg_can_beacon(wiphy, chandef);
+       ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap;
+       vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap;
 
-       if (WARN_ON(!cfg80211_chan_def_valid(chandef))) {
-               trace_cfg80211_return_bool(false);
-               return false;
-       }
+       control_freq = chandef->chan->center_freq;
 
        switch (chandef->width) {
-       case NL80211_CHAN_WIDTH_20_NOHT:
        case NL80211_CHAN_WIDTH_20:
+               if (!ht_cap->ht_supported)
+                       return false;
+       case NL80211_CHAN_WIDTH_20_NOHT:
                width = 20;
                break;
        case NL80211_CHAN_WIDTH_40:
                width = 40;
+               if (!ht_cap->ht_supported)
+                       return false;
+               if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
+                   ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
+                       return false;
+               if (chandef->center_freq1 < control_freq &&
+                   chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
+                       return false;
+               if (chandef->center_freq1 > control_freq &&
+                   chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
+                       return false;
                break;
-       case NL80211_CHAN_WIDTH_80:
        case NL80211_CHAN_WIDTH_80P80:
+               if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
+                       return false;
+       case NL80211_CHAN_WIDTH_80:
+               if (!vht_cap->vht_supported)
+                       return false;
                width = 80;
                break;
        case NL80211_CHAN_WIDTH_160:
+               if (!vht_cap->vht_supported)
+                       return false;
+               if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
+                       return false;
                width = 160;
                break;
        default:
                WARN_ON_ONCE(1);
-               trace_cfg80211_return_bool(false);
                return false;
        }
 
-       res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq1, width);
+       /* TODO: missing regulatory check on 80/160 bandwidth */
+
+       if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1,
+                                        width, prohibited_flags))
+               return false;
+
+       if (!chandef->center_freq2)
+               return true;
+       return cfg80211_secondary_chans_ok(wiphy, chandef->center_freq2,
+                                          width, prohibited_flags);
+}
+EXPORT_SYMBOL(cfg80211_chandef_usable);
+
+bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
+                            struct cfg80211_chan_def *chandef)
+{
+       bool res;
+
+       trace_cfg80211_reg_can_beacon(wiphy, chandef);
 
-       if (res && chandef->center_freq2)
-               res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq2,
-                                                 width);
+       res = cfg80211_chandef_usable(wiphy, chandef,
+                                     IEEE80211_CHAN_DISABLED |
+                                     IEEE80211_CHAN_PASSIVE_SCAN |
+                                     IEEE80211_CHAN_NO_IBSS |
+                                     IEEE80211_CHAN_RADAR);
 
        trace_cfg80211_return_bool(res);
        return res;
index a0c8decf6a4758a9f50796d06396696a3072f1c8..6183a0d25b8bcd1649152a57bf6dd4aff239e86e 100644 (file)
@@ -483,12 +483,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
 void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
                               enum nl80211_iftype iftype, int num);
 
-bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef);
-
-bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
-                                u32 center_freq, u32 bandwidth,
-                                u32 prohibited_flags);
-
 #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
 
 #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
index d038fa45ecd1bf38a5ee3b83a51b5dde9df40744..eb0aa71a02b3a4fdaaf6546966180b7813d918ab 100644 (file)
@@ -1420,63 +1420,33 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
        ht_cap = &rdev->wiphy.bands[chandef->chan->band]->ht_cap;
        vht_cap = &rdev->wiphy.bands[chandef->chan->band]->vht_cap;
 
-       if (!cfg80211_chan_def_valid(chandef))
+       if (!cfg80211_chandef_valid(chandef))
                return -EINVAL;
 
        switch (chandef->width) {
        case NL80211_CHAN_WIDTH_20:
-               if (!ht_cap->ht_supported)
-                       return -EINVAL;
        case NL80211_CHAN_WIDTH_20_NOHT:
                width = 20;
                break;
        case NL80211_CHAN_WIDTH_40:
                width = 40;
-               /* quick early regulatory check */
-               if (chandef->center_freq1 < control_freq &&
-                   chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
-                       return -EINVAL;
-               if (chandef->center_freq1 > control_freq &&
-                   chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
-                       return -EINVAL;
-               if (!ht_cap->ht_supported)
-                       return -EINVAL;
-               if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
-                   ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
-                       return -EINVAL;
                break;
        case NL80211_CHAN_WIDTH_80:
                width = 80;
-               if (!vht_cap->vht_supported)
-                       return -EINVAL;
                break;
        case NL80211_CHAN_WIDTH_80P80:
                width = 80;
-               if (!vht_cap->vht_supported)
-                       return -EINVAL;
-               if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
-                       return -EINVAL;
                break;
        case NL80211_CHAN_WIDTH_160:
                width = 160;
-               if (!vht_cap->vht_supported)
-                       return -EINVAL;
-               if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
-                       return -EINVAL;
                break;
        default:
                return -EINVAL;
        }
 
-       if (!cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq1,
-                                        width, IEEE80211_CHAN_DISABLED))
+       if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
+                                    IEEE80211_CHAN_DISABLED))
                return -EINVAL;
-       if (chandef->center_freq2 &&
-           !cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq2,
-                                        width, IEEE80211_CHAN_DISABLED))
-               return -EINVAL;
-
-       /* TODO: missing regulatory check on bandwidth */
 
        return 0;
 }
@@ -1841,7 +1811,7 @@ static inline u64 wdev_id(struct wireless_dev *wdev)
 static int nl80211_send_chandef(struct sk_buff *msg,
                                 struct cfg80211_chan_def *chandef)
 {
-       WARN_ON(!cfg80211_chan_def_valid(chandef));
+       WARN_ON(!cfg80211_chandef_valid(chandef));
 
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
                        chandef->chan->center_freq))