wifi: cfg80211: save power spectral density(psd) of regulatory rule
authorWen Gong <quic_wgong@quicinc.com>
Thu, 14 Sep 2023 08:20:26 +0000 (04:20 -0400)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 18 Sep 2023 07:44:05 +0000 (09:44 +0200)
6 GHz regulatory domains introduces Power Spectral Density (PSD).
The PSD value of the regulatory rule should be taken into effect
for the ieee80211_channels falling into that particular regulatory
rule. Save the values in the channel which has PSD value and add
nl80211 attributes accordingly to handle it.

Co-developed-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Link: https://lore.kernel.org/r/20230914082026.3709-1-quic_wgong@quicinc.com
[use hole in chan flags, reword docs]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
include/net/regulatory.h
include/uapi/linux/nl80211.h
net/wireless/nl80211.c
net/wireless/reg.c

index 8fcfe186942440a9795d2232d62ce51125129ac8..9af714431b22fe74e5e8ef05a13efa14709f830b 100644 (file)
@@ -76,6 +76,8 @@ struct wiphy;
  * @IEEE80211_CHAN_DISABLED: This channel is disabled.
  * @IEEE80211_CHAN_NO_IR: do not initiate radiation, this includes
  *     sending probe requests or beaconing.
+ * @IEEE80211_CHAN_PSD: Power spectral density (in dBm) is set for this
+ *     channel.
  * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel.
  * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel
  *     is not permitted.
@@ -119,7 +121,7 @@ struct wiphy;
 enum ieee80211_channel_flags {
        IEEE80211_CHAN_DISABLED         = 1<<0,
        IEEE80211_CHAN_NO_IR            = 1<<1,
-       /* hole at 1<<2 */
+       IEEE80211_CHAN_PSD              = 1<<2,
        IEEE80211_CHAN_RADAR            = 1<<3,
        IEEE80211_CHAN_NO_HT40PLUS      = 1<<4,
        IEEE80211_CHAN_NO_HT40MINUS     = 1<<5,
@@ -171,6 +173,7 @@ enum ieee80211_channel_flags {
  *     on this channel.
  * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
  * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
+ * @psd: power spectral density (in dBm)
  */
 struct ieee80211_channel {
        enum nl80211_band band;
@@ -187,6 +190,7 @@ struct ieee80211_channel {
        enum nl80211_dfs_state dfs_state;
        unsigned long dfs_state_entered;
        unsigned int dfs_cac_ms;
+       s8 psd;
 };
 
 /**
index b2cb4a9eb04dc2c58f51b0964dae08573ba0da48..ebf9e028d1ef90661605f694e212df55701e9376 100644 (file)
@@ -213,6 +213,7 @@ struct ieee80211_reg_rule {
        u32 flags;
        u32 dfs_cac_ms;
        bool has_wmm;
+       s8 psd;
 };
 
 struct ieee80211_regdomain {
index f797ab7a654735b160562e4825740fa2004dbab3..367e5fbc893050cfd48c24f57cb0fb568bf7d7fc 100644 (file)
@@ -4215,6 +4215,8 @@ enum nl80211_wmm_rule {
  *     as the primary or any of the secondary channels isn't possible
  * @NL80211_FREQUENCY_ATTR_NO_EHT: EHT operation is not allowed on this channel
  *     in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_PSD: Power spectral density (in dBm) that
+ *     is allowed on this channel in current regulatory domain.
  * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
  *     currently defined
  * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
@@ -4253,6 +4255,7 @@ enum nl80211_frequency_attr {
        NL80211_FREQUENCY_ATTR_16MHZ,
        NL80211_FREQUENCY_ATTR_NO_320MHZ,
        NL80211_FREQUENCY_ATTR_NO_EHT,
+       NL80211_FREQUENCY_ATTR_PSD,
 
        /* keep last */
        __NL80211_FREQUENCY_ATTR_AFTER_LAST,
@@ -4353,6 +4356,8 @@ enum nl80211_reg_type {
  *     a given frequency range. The value is in mBm (100 * dBm).
  * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
  *     If not present or 0 default CAC time will be used.
+ * @NL80211_ATTR_POWER_RULE_PSD: power spectral density (in dBm).
+ *     This could be negative.
  * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
  *     currently defined
  * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
@@ -4370,6 +4375,8 @@ enum nl80211_reg_rule_attr {
 
        NL80211_ATTR_DFS_CAC_TIME,
 
+       NL80211_ATTR_POWER_RULE_PSD,
+
        /* keep last */
        __NL80211_REG_RULE_ATTR_AFTER_LAST,
        NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
@@ -4453,6 +4460,7 @@ enum nl80211_sched_scan_match_attr {
  * @NL80211_RRF_NO_HE: HE operation not allowed
  * @NL80211_RRF_NO_320MHZ: 320MHz operation not allowed
  * @NL80211_RRF_NO_EHT: EHT operation not allowed
+ * @NL80211_RRF_PSD: Ruleset has power spectral density value
  */
 enum nl80211_reg_rule_flags {
        NL80211_RRF_NO_OFDM             = 1<<0,
@@ -4473,6 +4481,7 @@ enum nl80211_reg_rule_flags {
        NL80211_RRF_NO_HE               = 1<<17,
        NL80211_RRF_NO_320MHZ           = 1<<18,
        NL80211_RRF_NO_EHT              = 1<<19,
+       NL80211_RRF_PSD                 = 1<<20,
 };
 
 #define NL80211_RRF_PASSIVE_SCAN       NL80211_RRF_NO_IR
index 218093607b299f5c86b10092cb0767b5f80107b9..e64bf2a58b36db94ba5bcc20ded718d6e09c00e2 100644 (file)
@@ -1115,6 +1115,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
        if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_OFFSET, chan->freq_offset))
                goto nla_put_failure;
 
+       if ((chan->flags & IEEE80211_CHAN_PSD) &&
+           nla_put_s8(msg, NL80211_FREQUENCY_ATTR_PSD, chan->psd))
+               goto nla_put_failure;
+
        if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
            nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
                goto nla_put_failure;
@@ -8529,6 +8533,11 @@ static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom,
                                reg_rule->dfs_cac_ms))
                        goto nla_put_failure;
 
+               if ((reg_rule->flags & NL80211_RRF_PSD) &&
+                   nla_put_s8(msg, NL80211_ATTR_POWER_RULE_PSD,
+                              reg_rule->psd))
+                       goto nla_put_failure;
+
                nla_nest_end(msg, nl_reg_rule);
        }
 
index 33e2570f2bd6cd86204e710fa213864d3d85f414..eb2fa97457b4606dac3586742f8b66359d45a221 100644 (file)
@@ -1589,6 +1589,8 @@ static u32 map_regdom_flags(u32 rd_flags)
                channel_flags |= IEEE80211_CHAN_NO_320MHZ;
        if (rd_flags & NL80211_RRF_NO_EHT)
                channel_flags |= IEEE80211_CHAN_NO_EHT;
+       if (rd_flags & NL80211_RRF_PSD)
+               channel_flags |= IEEE80211_CHAN_PSD;
        return channel_flags;
 }
 
@@ -1795,6 +1797,9 @@ static void handle_channel_single_rule(struct wiphy *wiphy,
                                chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
                }
 
+               if (chan->flags & IEEE80211_CHAN_PSD)
+                       chan->psd = reg_rule->psd;
+
                return;
        }
 
@@ -1815,6 +1820,9 @@ static void handle_channel_single_rule(struct wiphy *wiphy,
                        chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
        }
 
+       if (chan->flags & IEEE80211_CHAN_PSD)
+               chan->psd = reg_rule->psd;
+
        if (chan->orig_mpwr) {
                /*
                 * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER
@@ -1884,6 +1892,12 @@ static void handle_channel_adjacent_rules(struct wiphy *wiphy,
                                                         rrule2->dfs_cac_ms);
                }
 
+               if ((rrule1->flags & NL80211_RRF_PSD) &&
+                   (rrule2->flags & NL80211_RRF_PSD))
+                       chan->psd = min_t(s8, rrule1->psd, rrule2->psd);
+               else
+                       chan->flags &= ~NL80211_RRF_PSD;
+
                return;
        }
 
@@ -2570,6 +2584,9 @@ static void handle_channel_custom(struct wiphy *wiphy,
                        chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
        }
 
+       if (chan->flags & IEEE80211_CHAN_PSD)
+               chan->psd = reg_rule->psd;
+
        chan->max_power = chan->max_reg_power;
 }