From 29a2b597504ea5557f7c4ed1c75a8756f3c3a3ba Mon Sep 17 00:00:00 2001
From: Owen Huang <Owen.Huang@infineon.com>
Date: Wed, 15 Jan 2025 04:29:57 -0600
Subject: [PATCH] brcmfmac: fix core dump in dump survey w/o 5g band

If support 2.4G band only, core dump will happen in dump survey due to
band from 5g is NULL and try to access it (band->n_channels).

Fixes SWLINUX-4950

Signed-off-by: Owen Huang <Owen.Huang@infineon.com>
---
 .../broadcom/brcm80211/brcmfmac/cfg80211.c    | 45 ++++++++++++-------
 1 file changed, 28 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 02baba1f60ae..049d8bc80b40 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -10344,6 +10344,13 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
 	}
 
 	for (band_id = 0; band_id < NUM_NL80211_BANDS; band_id++) {
+		/* FIXME SWLINUX-4979, the firmware cannot report the survey info of 6GHz,
+		 * once the firmware can report it in someday.
+		 * This condition can be removed.
+		 */
+		if (band_id == NL80211_BAND_6GHZ)
+			continue;
+
 		band = wiphy->bands[band_id];
 		if (!band)
 			continue;
@@ -10425,11 +10432,11 @@ brcmf_cfg80211_dump_survey_2(struct wiphy *wiphy, struct net_device *ndev,
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
 	struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
 	struct ieee80211_supported_band *band;
-	struct ieee80211_channel *chan;
 	struct cca_survey_req *survey = NULL;
 	struct cca_survey  *secs;
 	struct cfg80211_chan_def chandef;
 	struct wireless_dev *wdev;
+	enum nl80211_band band_id;
 	int err = 0;
 	u32 noise;
 
@@ -10440,22 +10447,27 @@ brcmf_cfg80211_dump_survey_2(struct wiphy *wiphy, struct net_device *ndev,
 		return -EBUSY;
 	}
 
-	band = wiphy->bands[NL80211_BAND_2GHZ];
-	if (band && idx >= band->n_channels) {
-		idx -= band->n_channels;
-		band = NULL;
-	}
+	for (band_id = 0; band_id < NUM_NL80211_BANDS; band_id++) {
+		/* FIXME SWLINUX-4979, the firmware cannot report the survey info of 6GHz,
+		 * once the firmware can report it in someday.
+		 * This condition can be removed.
+		 */
+		if (band_id == NL80211_BAND_6GHZ)
+			continue;
 
-	if (!band || idx >= band->n_channels) {
-		band = wiphy->bands[NL80211_BAND_5GHZ];
+		band = wiphy->bands[band_id];
+		if (!band)
+			continue;
 		if (idx >= band->n_channels) {
-			brcmf_dbg(TRACE, "not support channel idx=%d\n", idx);
-			return -ENOENT;
+			idx -= band->n_channels;
+			continue;
 		}
-	}
 
-	/* Getting target channel */
-	chan = &band->channels[idx];
+		info->channel = &band->channels[idx];
+		break;
+	}
+	if (band_id == NUM_NL80211_BANDS)
+		return -ENOENT;
 
 	/* Set interface up, explicitly. */
 	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
@@ -10475,7 +10487,7 @@ brcmf_cfg80211_dump_survey_2(struct wiphy *wiphy, struct net_device *ndev,
 	if (!survey)
 		return -ENOMEM;
 
-	survey->chanspec = channel_to_chanspec(&cfg->d11inf, chan);
+	survey->chanspec = channel_to_chanspec(&cfg->d11inf, info->channel);
 	err = brcmf_fil_iovar_data_get(ifp, "cca_survey_dump",
 				       survey, sizeof(struct cca_survey_req));
 	if (err) {
@@ -10486,7 +10498,6 @@ brcmf_cfg80211_dump_survey_2(struct wiphy *wiphy, struct net_device *ndev,
 
 	secs = &survey->secs[0];
 
-	info->channel = chan;
 	info->noise = noise;
 	info->time = secs->usecs;
 	info->time_busy = secs->ibss + secs->txdur + secs->obss
@@ -10508,12 +10519,12 @@ brcmf_cfg80211_dump_survey_2(struct wiphy *wiphy, struct net_device *ndev,
 		err = -EINVAL;
 		goto exit;
 	}
-	if (chandef.chan->center_freq == chan->center_freq) {
+	if (chandef.chan->center_freq == info->channel->center_freq) {
 		info->filled = info->filled | SURVEY_INFO_IN_USE;
 	}
 
 	brcmf_dbg(INFO, "survey dump: channel %d: survey duration %llu\n",
-		  ieee80211_frequency_to_channel(chan->center_freq),
+		  ieee80211_frequency_to_channel(info->channel->center_freq),
 		  info->time);
 	brcmf_dbg(INFO, "noise(%d) busy(%llu) rx(%llu) tx(%llu)\n",
 		  info->noise, info->time_busy, info->time_rx, info->time_tx);
-- 
2.25.0

