Kaynağa Gözat

qcacld-3.0: Update subband CCA busy info to HDD

In case of wide band scan request, FW sends subband CCA busy info
to host via a new tlv wmi_cca_busy_subband_info added in existing
event WMI_CHAN_INFO_EVENTID.

Fix is to store CCA busy info coming from FW to HDD context.

Change-Id: Ic4b439ed1c270badbe265dc8543dc6d6a1612fab
CRs-Fixed: 3469467
abhinav kumar 2 yıl önce
ebeveyn
işleme
076551fd20

+ 10 - 0
components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h

@@ -726,6 +726,16 @@ static inline QDF_STATUS wlan_cm_host_roam_start(struct scheduler_msg *msg)
 }
 #endif
 
+/**
+ * wlan_cm_get_associated_ch_width() - get associated channel width
+ * @psoc: psoc pointer
+ * @vdev_id: vdev id
+ *
+ * Return: enum phy_ch_width
+ */
+enum phy_ch_width
+wlan_cm_get_associated_ch_width(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id);
+
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 /**
  * wlan_cm_fw_roam_abort_req() - roam abort request handling

+ 6 - 0
components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_ucfg_api.h

@@ -123,6 +123,12 @@ ucfg_cm_update_session_assoc_ie(struct wlan_objmgr_psoc *psoc,
 	cm_update_session_assoc_ie(psoc, vdev_id, assoc_ie);
 }
 
+static inline enum phy_ch_width
+ucfg_cm_get_associated_ch_width(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
+{
+	return wlan_cm_get_associated_ch_width(psoc, vdev_id);
+}
+
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 #ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER
 /**

+ 26 - 0
components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c

@@ -2118,6 +2118,32 @@ QDF_STATUS wlan_cm_update_fils_ft(struct wlan_objmgr_psoc *psoc,
 }
 #endif
 
+enum phy_ch_width
+wlan_cm_get_associated_ch_width(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct mlme_legacy_priv *mlme_priv;
+	enum phy_ch_width ch_width = CH_WIDTH_INVALID;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_MLME_NB_ID);
+
+	if (!vdev) {
+		mlme_err("vdev%d: vdev object is NULL", vdev_id);
+		goto release;
+	}
+
+	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+	if (!mlme_priv)
+		goto release;
+
+	ch_width = mlme_priv->connect_info.ch_width_orig;
+	mlme_debug("vdev %d: associated_ch_width:%d", vdev_id, ch_width);
+release:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
+	return ch_width;
+}
+
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 QDF_STATUS
 wlan_cm_update_roam_scan_scheme_bitmap(struct wlan_objmgr_psoc *psoc,

+ 81 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -25508,6 +25508,81 @@ static int wlan_hdd_cfg80211_nan_change_conf(struct wiphy *wiphy,
 }
 #endif
 
+/**
+ * wlan_hdd_fill_subband_scan_info - Fill subband channel info
+ * @hdd_ctx: hdd context
+ * @info: struct scan_chan_info
+ * @chan: scan channel info
+ *
+ * update channel info into HDD context on scan done
+ *
+ * Return: None.
+ */
+static void wlan_hdd_fill_subband_scan_info(struct hdd_context *hdd_ctx,
+					    struct scan_chan_info *info,
+					    struct scan_chan_info *chan)
+{
+	uint8_t idx, info_index, freq_info_num;
+	enum phy_ch_width ch_width;
+	const struct bonded_channel_freq *range = NULL;
+	uint32_t start_freq, end_freq;
+
+	ch_width = ucfg_cm_get_associated_ch_width(hdd_ctx->psoc,
+						   info->subband_info.vdev_id);
+	if (ch_width == CH_WIDTH_INVALID) {
+		hdd_debug("vdev %d: Invalid ch width",
+			  info->subband_info.vdev_id);
+		return;
+	}
+
+	if (ch_width == CH_WIDTH_20MHZ) {
+		start_freq = info->freq;
+		end_freq = info->freq;
+	} else {
+		range = wlan_reg_get_bonded_chan_entry(info->freq, ch_width, 0);
+		if (!range) {
+			hdd_err("vdev %d: bonded_chan_array is NULL for freq %d, ch_width %d",
+				info->subband_info.vdev_id, info->freq,
+				ch_width);
+			return;
+		}
+		start_freq = range->start_freq;
+		end_freq = range->end_freq;
+	}
+
+	freq_info_num = info->subband_info.num_chan;
+	info_index = 0;
+
+	hdd_debug("vdev %d: freq :%d bw %d, range [%d-%d], num_freq:%d",
+		  info->subband_info.vdev_id, info->freq, ch_width, start_freq,
+		  end_freq, freq_info_num);
+
+	for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
+		if (chan[idx].freq == 0)
+			continue;
+
+		if (start_freq > end_freq || info_index >= freq_info_num ||
+		    info_index >= MAX_WIDE_BAND_SCAN_CHAN)
+			break;
+
+		if (chan[idx].freq == start_freq) {
+			/*update channel info as per cca busy info */
+			info->freq = start_freq;
+			info->rx_clear_count =
+			   info->subband_info.cca_busy_subband_info[info_index];
+
+			hdd_update_chan_info(hdd_ctx, &chan[idx], info,
+					     info->cmd_flag);
+
+			hdd_debug("updated info for freq:%u rcc:%d at index:%d",
+				  chan[idx].freq, chan[idx].rx_clear_count,
+				  idx);
+			start_freq += BW_20_MHZ;
+			info_index++;
+		}
+	}
+}
+
 /**
  * wlan_hdd_chan_info_cb() - channel info callback
  * @info: struct scan_chan_info
@@ -25532,6 +25607,12 @@ static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
 	}
 
 	chan = hdd_ctx->chan_info;
+
+	if (info->subband_info.is_wide_band_scan) {
+		wlan_hdd_fill_subband_scan_info(hdd_ctx, info, chan);
+		return;
+	}
+
 	for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
 		if (chan[idx].freq == info->freq) {
 			hdd_update_chan_info(hdd_ctx, &chan[idx], info,

+ 21 - 0
core/mac/inc/sir_api.h

@@ -4349,6 +4349,24 @@ struct wow_pulse_mode {
  */
 QDF_STATUS umac_send_mb_message_to_mac(void *msg);
 
+/* Max supported bandwidth is 320Mhz, so max 16 subbands fo 20Mhz */
+#define MAX_WIDE_BAND_SCAN_CHAN 16
+
+/**
+ * struct wide_band_scan_chan_info - wide band scan channel info
+ * @vdev_id: vdev id
+ * @num_chan: number of channels (for each subbands fo 20Mhz)
+ * @is_wide_band_scan: wide band scan or not
+ * @cca_busy_subband_info: CCA busy for each possible 20Mhz subbands
+ * of the wideband scan channel
+ */
+struct wide_band_scan_chan_info {
+	uint32_t vdev_id;
+	uint8_t num_chan;
+	bool is_wide_band_scan;
+	uint32_t cca_busy_subband_info[MAX_WIDE_BAND_SCAN_CHAN];
+};
+
 /**
  * struct scan_chan_info - channel info
  * @freq: radio frequence
@@ -4358,6 +4376,8 @@ QDF_STATUS umac_send_mb_message_to_mac(void *msg);
  * @rx_clear_count: rx clear count
  * @tx_frame_count: TX frame count
  * @clock_freq: clock frequence MHZ
+ * @cca_busy_subband_info: CCA busy for each possible 20Mhz subbands
+ * of the wideband scan channel
  */
 struct scan_chan_info {
 	uint32_t freq;
@@ -4367,6 +4387,7 @@ struct scan_chan_info {
 	uint32_t rx_clear_count;
 	uint32_t tx_frame_count;
 	uint32_t clock_freq;
+	struct wide_band_scan_chan_info subband_info;
 };
 
 /**

+ 54 - 12
core/wma/src/wma_features.c

@@ -5343,6 +5343,49 @@ wma_vdev_bcn_latency_event_handler(void *handle,
 }
 #endif
 
+static void
+wma_update_sacn_channel_info_buf(wmi_unified_t wmi_handle,
+				 wmi_chan_info_event_fixed_param *event,
+				 struct scan_chan_info *buf,
+				 wmi_cca_busy_subband_info *cca_info,
+				 uint32_t num_tlvs)
+{
+	uint32_t i;
+	bool is_cca_busy_info;
+
+	buf->tx_frame_count = event->tx_frame_cnt;
+	buf->clock_freq = event->mac_clk_mhz;
+	buf->cmd_flag = event->cmd_flags;
+	buf->freq = event->freq;
+	buf->noise_floor = event->noise_floor;
+	buf->cycle_count = event->cycle_count;
+	buf->rx_clear_count = event->rx_clear_count;
+
+	is_cca_busy_info = wmi_service_enabled(wmi_handle,
+				wmi_service_cca_busy_info_for_each_20mhz);
+
+	if (!is_cca_busy_info || num_tlvs == 0)
+		return;
+
+	wma_debug("is_cca_busy_info: %d, num_tlvs:%d", is_cca_busy_info,
+		  num_tlvs);
+
+	if (cca_info && num_tlvs > 0) {
+		buf->subband_info.num_chan = 0;
+		for (i = 0; i < num_tlvs && i < MAX_WIDE_BAND_SCAN_CHAN; i++) {
+			buf->subband_info.cca_busy_subband_info[i] =
+						cca_info->rx_clear_count;
+			wma_debug("cca_info->rx_clear_count:%d",
+				  cca_info->rx_clear_count);
+			buf->subband_info.num_chan++;
+			cca_info++;
+		}
+
+		buf->subband_info.is_wide_band_scan = true;
+		buf->subband_info.vdev_id = event->vdev_id;
+	}
+}
+
 int wma_chan_info_event_handler(void *handle, uint8_t *event_buf,
 				uint32_t len)
 {
@@ -5356,6 +5399,8 @@ int wma_chan_info_event_handler(void *handle, uint8_t *event_buf,
 	struct wlan_objmgr_vdev *vdev;
 	enum QDF_OPMODE mode;
 	struct scheduler_msg sme_msg = {0};
+	wmi_cca_busy_subband_info *cca_info = NULL;
+	uint32_t num_tlvs = 0;
 
 	if (wma && wma->cds_context)
 		mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
@@ -5374,18 +5419,6 @@ int wma_chan_info_event_handler(void *handle, uint8_t *event_buf,
 		return -EINVAL;
 	}
 
-	snr_monitor_enabled = wlan_scan_is_snr_monitor_enabled(mac->psoc);
-	if (snr_monitor_enabled && mac->chan_info_cb) {
-		buf.tx_frame_count = event->tx_frame_cnt;
-		buf.clock_freq = event->mac_clk_mhz;
-		buf.cmd_flag = event->cmd_flags;
-		buf.freq = event->freq;
-		buf.noise_floor = event->noise_floor;
-		buf.cycle_count = event->cycle_count;
-		buf.rx_clear_count = event->rx_clear_count;
-		mac->chan_info_cb(&buf);
-	}
-
 	/* Ignore the last channel event data whose command flag is set to 1.
 	 * It’s basically an event with empty data only to indicate scan event
 	 * completion.
@@ -5393,6 +5426,15 @@ int wma_chan_info_event_handler(void *handle, uint8_t *event_buf,
 	if (event->cmd_flags == WMI_CHAN_INFO_END_RESP)
 		return 0;
 
+	snr_monitor_enabled = wlan_scan_is_snr_monitor_enabled(mac->psoc);
+	if (snr_monitor_enabled && mac->chan_info_cb) {
+		cca_info = param_buf->cca_busy_subband_info;
+		num_tlvs  = param_buf->num_cca_busy_subband_info;
+		wma_update_sacn_channel_info_buf(wma->wmi_handle, event,
+						 &buf, cca_info, num_tlvs);
+		mac->chan_info_cb(&buf);
+	}
+
 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, event->vdev_id,
 						    WLAN_LEGACY_WMA_ID);