Blob Blame History Raw
From 4ef2f53e50cba9780057b51357ef45cb5f49859d Mon Sep 17 00:00:00 2001
From: Ilan Peer <ilan.peer@intel.com>
Date: Mon, 19 Jun 2023 16:26:52 +0300
Subject: [PATCH] wifi: cfg80211: Retrieve PSD information from RNR AP information
Git-commit: 4ef2f53e50cba9780057b51357ef45cb5f49859d
Patch-mainline: v6.5-rc1
References: jsc#PED-6081 jsc#PED-6130

Retrieve the Power Spectral Density (PSD) value from RNR AP
information entry and store it so it could be used by the drivers.

PSD value is explained in Section 9.4.2.170 of Draft
P802.11Revme_D2.0.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230619161906.067ded2b8fc3.I9f407ab5800cbb07045a0537a513012960ced740@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 include/linux/ieee80211.h |  7 +++++--
 include/net/cfg80211.h    |  2 ++
 net/wireless/scan.c       | 13 +++++++++++++
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 15c4e12b6fc7..6f1747a9c106 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -4504,6 +4504,9 @@ static inline bool for_each_element_completed(const struct element *element,
 #define IEEE80211_RNR_TBTT_PARAMS_PROBE_ACTIVE			0x20
 #define IEEE80211_RNR_TBTT_PARAMS_COLOC_AP			0x40
 
+#define IEEE80211_RNR_TBTT_PARAMS_PSD_NO_LIMIT			127
+#define IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED			-128
+
 struct ieee80211_neighbor_ap_info {
 	u8 tbtt_info_hdr;
 	u8 tbtt_info_len;
@@ -4539,7 +4542,7 @@ struct ieee80211_tbtt_info_7_8_9 {
 
 	/* The following element is optional, structure may not grow */
 	u8 bss_params;
-	u8 psd_20;
+	s8 psd_20;
 } __packed;
 
 /* Format of the TBTT information element if it has >= 11 bytes */
@@ -4550,7 +4553,7 @@ struct ieee80211_tbtt_info_ge_11 {
 
 	/* The following elements are optional, structure may grow */
 	u8 bss_params;
-	u8 psd_20;
+	s8 psd_20;
 	struct ieee80211_rnr_mld_params mld_params;
 } __packed;
 
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 3a736f9286b0..7c7d03aa9d06 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2466,6 +2466,7 @@ struct cfg80211_scan_info {
  * @short_ssid_valid: @short_ssid is valid and can be used
  * @psc_no_listen: when set, and the channel is a PSC channel, no need to wait
  *       20 TUs before starting to send probe requests.
+ * @psd_20: The AP's 20 MHz PSD value.
  */
 struct cfg80211_scan_6ghz_params {
 	u32 short_ssid;
@@ -2474,6 +2475,7 @@ struct cfg80211_scan_6ghz_params {
 	bool unsolicited_probe;
 	bool short_ssid_valid;
 	bool psc_no_listen;
+	s8 psd_20;
 };
 
 /**
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ede95caecb34..8bf00caf5d29 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -96,6 +96,7 @@ MODULE_PARM_DESC(bss_entries_limit,
  *	colocated and can be discovered via legacy bands.
  * @short_ssid_valid: short_ssid is valid and can be used
  * @short_ssid: the short SSID for this SSID
+ * @psd_20: The 20MHz PSD EIRP of the primary 20MHz channel for the reported AP
  */
 struct cfg80211_colocated_ap {
 	struct list_head list;
@@ -111,6 +112,7 @@ struct cfg80211_colocated_ap {
 	   transmitted_bssid:1,
 	   colocated_ess:1,
 	   short_ssid_valid:1;
+	s8 psd_20;
 };
 
 static void bss_free(struct cfg80211_internal_bss *bss)
@@ -578,6 +580,8 @@ static int cfg80211_parse_ap_info(struct cfg80211_colocated_ap *entry,
 {
 	u8 bss_params;
 
+	entry->psd_20 = IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED;
+
 	/* The length is already verified by the caller to contain bss_params */
 	if (length > sizeof(struct ieee80211_tbtt_info_7_8_9)) {
 		struct ieee80211_tbtt_info_ge_11 *tbtt_info = (void *)pos;
@@ -594,12 +598,20 @@ static int cfg80211_parse_ap_info(struct cfg80211_colocated_ap *entry,
 					  IEEE80211_RNR_MLD_PARAMS_DISABLED_LINK))
 				return -EINVAL;
 		}
+
+		if (length >= offsetofend(struct ieee80211_tbtt_info_ge_11,
+					  psd_20))
+			entry->psd_20 = tbtt_info->psd_20;
 	} else {
 		struct ieee80211_tbtt_info_7_8_9 *tbtt_info = (void *)pos;
 
 		memcpy(entry->bssid, tbtt_info->bssid, ETH_ALEN);
 
 		bss_params = tbtt_info->bss_params;
+
+		if (length == offsetofend(struct ieee80211_tbtt_info_7_8_9,
+					  psd_20))
+			entry->psd_20 = tbtt_info->psd_20;
 	}
 
 	/* ignore entries with invalid BSSID */
@@ -904,6 +916,7 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
 		scan_6ghz_params->short_ssid = ap->short_ssid;
 		scan_6ghz_params->short_ssid_valid = ap->short_ssid_valid;
 		scan_6ghz_params->unsolicited_probe = ap->unsolicited_probe;
+		scan_6ghz_params->psd_20 = ap->psd_20;
 
 		/*
 		 * If a PSC channel is added to the scan and 'need_scan_psc' is
-- 
2.35.3