diff mbox series

wifi: iwlwifi: Fix survey dump for be200 radios.

Message ID 20241212044522.922351-1-greearb@candelatech.com
State New
Headers show
Series wifi: iwlwifi: Fix survey dump for be200 radios. | expand

Commit Message

Ben Greear Dec. 12, 2024, 4:45 a.m. UTC
From: Ben Greear <greearb@candelatech.com>

The old code did not assign channel, so survey dump was always
empty.  Instead, return the info from the phy ctxts since we
can at least fake out the channel busy time with that.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 19 +++++++++++++++++++
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h  |  4 ++++
 drivers/net/wireless/intel/iwlwifi/mvm/rx.c   | 18 ++++++++++++++++++
 3 files changed, 41 insertions(+)
diff mbox series

Patch

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index fb341d8e8cdb..ec01350bbb34 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -6080,6 +6080,25 @@  int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
 
 	memset(survey, 0, sizeof(*survey));
 
+	if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_BZ) {
+		/* None of the code below this if clause appears to work
+		 * on be200 radios, primarily because 'channel' is not assigned.
+		 * So special case this to do something useful on be200
+		 * radio:  Return channel and busy-time for the first 3
+		 * phy contexts.
+		 */
+
+		survey->filled = SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY;
+		if (idx > 2)
+			return -ENOENT;
+
+		survey->channel = mvm->phy_ctxts[idx].channel;
+
+		survey->time = jiffies64_to_msecs(mvm->phy_ctxts[idx].channel_time_accum);
+		survey->time_busy = jiffies64_to_msecs(mvm->phy_ctxts[idx].channel_busy_accum);
+		return 0;
+	}
+
 	if (!fw_has_capa(&mvm->fw->ucode_capa,
 			 IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS))
 		return -ENOENT;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 42545b611b97..a4e789290dd6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -105,6 +105,10 @@  struct iwl_mvm_phy_ctxt {
 	u32 channel_load;
 	u32 channel_load_by_us;
 	u32 channel_load_not_by_us;
+
+	u64 channel_time_accum; /* in jiffies */
+	u64 channel_busy_accum; /* in jiffies */
+	u64 last_jiffies; /* last time we accumulated the above */
 };
 
 struct iwl_mvm_time_event_data {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 8230a9576428..3ac62ad0144b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -865,6 +865,8 @@  static void iwl_mvm_handle_per_phy_stats(struct iwl_mvm *mvm,
 					 struct iwl_stats_ntfy_per_phy *per_phy)
 {
 	int i;
+	unsigned long jdiff;
+	u64 j = jiffies_64;
 
 	for (i = 0; i < NUM_PHY_CTX; i++) {
 		if (!mvm->phy_ctxts[i].ref)
@@ -875,6 +877,22 @@  static void iwl_mvm_handle_per_phy_stats(struct iwl_mvm *mvm,
 			le32_to_cpu(per_phy[i].channel_load_by_us);
 		mvm->phy_ctxts[i].channel_load_not_by_us =
 			le32_to_cpu(per_phy[i].channel_load_not_by_us);
+
+		if (mvm->phy_ctxts[i].last_jiffies) {
+			if (j > mvm->phy_ctxts[i].last_jiffies)
+				jdiff = j - mvm->phy_ctxts[i].last_jiffies;
+			else
+				/* jiffies wrapped, just count from zero, close enough. */
+				jdiff = j;
+
+			/* We know busy percentage, back convert this to total
+			 * time and total busy time.
+			 */
+			mvm->phy_ctxts[i].channel_time_accum += jdiff;
+			mvm->phy_ctxts[i].channel_busy_accum +=
+				(jdiff * mvm->phy_ctxts[i].channel_load) / 100;
+		}
+		mvm->phy_ctxts[i].last_jiffies = j;
 	}
 }