Kaynağa Gözat

qcacld-3.0: Process ML Channel Measurement request

Host parse newely added vendor command
QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS and trigger
scan to get connected channel stats from FW in case of MLO
connection.

On scan done host sends scan done indication to upper layer
via QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS vendor
command.

Change-Id: Iff09b6dfe88b5f075a4c81d8f0bfff5bbb0fedaa
CRs-Fixed: 3491058
abhinav kumar 1 yıl önce
ebeveyn
işleme
f231c54eb9
1 değiştirilmiş dosya ile 311 ekleme ve 36 silme
  1. 311 36
      components/mlme/core/src/wlan_mlme_main.c

+ 311 - 36
components/mlme/core/src/wlan_mlme_main.c

@@ -174,6 +174,301 @@ mlme_fill_freq_in_scan_start_request(struct wlan_objmgr_vdev *vdev,
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_FEATURE_11BE
+static enum scan_phy_mode mlme_get_scan_phy_mode(void)
+{
+	return SCAN_PHY_MODE_11BE_EHT160;
+}
+
+static enum scan_phy_mode
+wlan_scan_get_11be_scan_phy_mode(enum wlan_phymode ch_phymode)
+{
+	enum scan_phy_mode scan_phymode;
+
+	switch (ch_phymode) {
+	case WLAN_PHYMODE_11BEA_EHT20:
+		scan_phymode = SCAN_PHY_MODE_11BE_EHT20;
+		break;
+	case WLAN_PHYMODE_11BEG_EHT20:
+		scan_phymode = SCAN_PHY_MODE_11BE_EHT20_2G;
+		break;
+	case WLAN_PHYMODE_11BEA_EHT40:
+		scan_phymode = SCAN_PHY_MODE_11BE_EHT40;
+		break;
+	case WLAN_PHYMODE_11BEG_EHT40:
+		scan_phymode = SCAN_PHY_MODE_11BE_EHT40_2G;
+		break;
+	case WLAN_PHYMODE_11BEA_EHT80:
+		scan_phymode = SCAN_PHY_MODE_11BE_EHT80;
+		break;
+	case WLAN_PHYMODE_11BEG_EHT80:
+		scan_phymode = SCAN_PHY_MODE_11BE_EHT80_2G;
+		break;
+	case WLAN_PHYMODE_11BEA_EHT160:
+		scan_phymode = SCAN_PHY_MODE_11BE_EHT160;
+		break;
+	case WLAN_PHYMODE_11BEA_EHT320:
+		scan_phymode = SCAN_PHY_MODE_11BE_EHT320;
+		break;
+	default:
+		scan_phymode = SCAN_PHY_MODE_UNKNOWN;
+		break;
+	}
+
+	return scan_phymode;
+}
+#else
+static inline enum scan_phy_mode mlme_get_scan_phy_mode(void)
+{
+	return SCAN_PHY_MODE_UNKNOWN;
+}
+
+static inline enum scan_phy_mode
+wlan_scan_get_11be_scan_phy_mode(enum wlan_phymode ch_phymode)
+{
+	return SCAN_PHY_MODE_UNKNOWN;
+}
+#endif
+
+/**
+ * wlan_scan_get_scan_phy_mode() - get scan phymode from channel phy mode
+ * @vdev: vdev common object
+ * @op_freq: operational frequency
+ * @vdev_id: vdev id
+ *
+ * Return: enum scan_phy_mode
+ */
+static enum scan_phy_mode
+wlan_scan_get_scan_phy_mode(struct wlan_objmgr_vdev *vdev, qdf_freq_t op_freq,
+			    uint32_t vdev_id)
+{
+	struct wlan_channel *des_chan;
+	enum scan_phy_mode scan_phymode = SCAN_PHY_MODE_UNKNOWN;
+
+	des_chan = wlan_vdev_mlme_get_des_chan(vdev);
+	if (!des_chan) {
+		mlme_debug("vdev %d : des_chan is null", vdev_id);
+		return scan_phymode;
+	}
+
+	switch (des_chan->ch_phymode) {
+	case WLAN_PHYMODE_11A:
+		scan_phymode = SCAN_PHY_MODE_11A;
+		break;
+	case WLAN_PHYMODE_11B:
+		scan_phymode = SCAN_PHY_MODE_11B;
+		break;
+	case WLAN_PHYMODE_11G:
+		scan_phymode = SCAN_PHY_MODE_11G;
+		break;
+	case WLAN_PHYMODE_11G_ONLY:
+		scan_phymode = SCAN_PHY_MODE_11GONLY;
+		break;
+	case WLAN_PHYMODE_11NA_HT20:
+		scan_phymode = SCAN_PHY_MODE_11NA_HT20;
+		break;
+	case WLAN_PHYMODE_11NG_HT20:
+		scan_phymode = SCAN_PHY_MODE_11NG_HT20;
+		break;
+	case WLAN_PHYMODE_11NA_HT40:
+		scan_phymode = SCAN_PHY_MODE_11NA_HT40;
+		break;
+	case WLAN_PHYMODE_11NG_HT40:
+		scan_phymode = SCAN_PHY_MODE_11NG_HT40;
+		break;
+	case WLAN_PHYMODE_11AC_VHT20:
+		scan_phymode = SCAN_PHY_MODE_11AC_VHT20;
+		break;
+	case WLAN_PHYMODE_11AC_VHT40:
+		scan_phymode = SCAN_PHY_MODE_11AC_VHT40;
+		break;
+	case WLAN_PHYMODE_11AC_VHT80:
+		scan_phymode = SCAN_PHY_MODE_11AC_VHT80;
+		break;
+	case WLAN_PHYMODE_11AC_VHT20_2G:
+		scan_phymode = SCAN_PHY_MODE_11AC_VHT20_2G;
+		break;
+	case WLAN_PHYMODE_11AC_VHT40_2G:
+		scan_phymode = SCAN_PHY_MODE_11AC_VHT40_2G;
+		break;
+	case WLAN_PHYMODE_11AC_VHT80_2G:
+		scan_phymode = SCAN_PHY_MODE_11AC_VHT80_2G;
+		break;
+	case WLAN_PHYMODE_11AC_VHT80_80:
+		scan_phymode = SCAN_PHY_MODE_11AC_VHT80_80;
+		break;
+	case WLAN_PHYMODE_11AC_VHT160:
+		scan_phymode = SCAN_PHY_MODE_11AC_VHT160;
+		break;
+	case WLAN_PHYMODE_11AXA_HE20:
+		scan_phymode = SCAN_PHY_MODE_11AX_HE20;
+		break;
+	case WLAN_PHYMODE_11AXG_HE20:
+		scan_phymode = SCAN_PHY_MODE_11AX_HE20_2G;
+		break;
+	case WLAN_PHYMODE_11AXA_HE40:
+		scan_phymode = SCAN_PHY_MODE_11AX_HE40;
+		break;
+	case WLAN_PHYMODE_11AXG_HE40:
+		scan_phymode = SCAN_PHY_MODE_11AX_HE40_2G;
+		break;
+	case WLAN_PHYMODE_11AXA_HE80:
+		scan_phymode = SCAN_PHY_MODE_11AX_HE80;
+		break;
+	case WLAN_PHYMODE_11AXG_HE80:
+		scan_phymode = SCAN_PHY_MODE_11AX_HE80_2G;
+		break;
+	case WLAN_PHYMODE_11AXA_HE80_80:
+		scan_phymode = SCAN_PHY_MODE_11AX_HE80_80;
+		break;
+	case WLAN_PHYMODE_11AXA_HE160:
+		scan_phymode = SCAN_PHY_MODE_11AX_HE160;
+		break;
+	default:
+		scan_phymode = SCAN_PHY_MODE_UNKNOWN;
+		break;
+	}
+
+	if (scan_phymode != SCAN_PHY_MODE_UNKNOWN)
+		return scan_phymode;
+
+	scan_phymode = wlan_scan_get_11be_scan_phy_mode(des_chan->ch_phymode);
+
+	return scan_phymode;
+}
+
+/**
+ * mlme_update_freq_in_scan_start_req() - Fill frequencies in wide
+ * band scan req for mlo connection
+ * @vdev: vdev common object
+ * @req: pointer to scan request
+ * @associated_ch_width: channel width at the time of initial connection
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+mlme_update_freq_in_scan_start_req(struct wlan_objmgr_vdev *vdev,
+				   struct scan_start_request *req,
+				   enum phy_ch_width associated_ch_width)
+{
+	const struct bonded_channel_freq *range;
+	uint8_t num_chan;
+	qdf_freq_t op_freq;
+	enum scan_phy_mode phymode = SCAN_PHY_MODE_UNKNOWN;
+
+	op_freq = wlan_get_operation_chan_freq(vdev);
+
+	if (associated_ch_width == CH_WIDTH_320MHZ) {
+		range = wlan_reg_get_bonded_chan_entry(op_freq,
+						       associated_ch_width, 0);
+		if (!range) {
+			mlme_debug("vdev %d : range is null for freq %d",
+				   req->scan_req.vdev_id,
+				   op_freq);
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		phymode = mlme_get_scan_phy_mode();
+		if (phymode == SCAN_PHY_MODE_UNKNOWN) {
+			mlme_debug("vdev %d : invalid scan phymode for freq %d",
+				   req->scan_req.vdev_id,
+				   op_freq);
+			return QDF_STATUS_E_FAILURE;
+		}
+		num_chan = req->scan_req.chan_list.num_chan;
+		req->scan_req.chan_list.chan[num_chan].freq = range->start_freq;
+		req->scan_req.chan_list.chan[num_chan].phymode = phymode;
+		num_chan += 1;
+		req->scan_req.chan_list.chan[num_chan].freq = range->end_freq;
+		req->scan_req.chan_list.chan[num_chan].phymode = phymode;
+		num_chan += 1;
+		req->scan_req.chan_list.num_chan = num_chan;
+	} else {
+		phymode = wlan_scan_get_scan_phy_mode(vdev, op_freq,
+						      req->scan_req.vdev_id);
+		if (phymode == SCAN_PHY_MODE_UNKNOWN) {
+			mlme_debug("vdev %d : invalid scan phymode for freq %d",
+				   req->scan_req.vdev_id,
+				   op_freq);
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		num_chan = req->scan_req.chan_list.num_chan;
+		req->scan_req.chan_list.chan[num_chan].freq = op_freq;
+		req->scan_req.chan_list.chan[num_chan].phymode = phymode;
+		req->scan_req.chan_list.num_chan += 1;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * mlme_fill_freq_in_mlo_wide_band_scan_start_req() - Fill frequencies in wide
+ * band scan req for mlo connection
+ * @vdev: vdev common object
+ * @req: pointer to scan request
+ * @associated_ch_width: channel width at the time of initial connection
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+mlme_fill_freq_in_mlo_wide_band_scan_start_req(struct wlan_objmgr_vdev *vdev,
+					struct scan_start_request *req,
+					enum phy_ch_width associated_ch_width)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct wlan_mlo_sta *sta_ctx = NULL;
+	struct wlan_channel *chan;
+	uint8_t i;
+	QDF_STATUS status;
+	struct wlan_objmgr_vdev *mlo_vdev;
+
+	mlo_dev_ctx = vdev->mlo_dev_ctx;
+	if (!mlo_dev_ctx) {
+		mlme_err("vdev %d :mlo_dev_ctx is NULL", req->scan_req.vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	sta_ctx = mlo_dev_ctx->sta_ctx;
+	if (!sta_ctx) {
+		mlme_err("vdev %d :mlo_dev_ctx is NULL", req->scan_req.vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
+		if (!mlo_dev_ctx->wlan_vdev_list[i])
+			continue;
+		if (qdf_test_bit(i, sta_ctx->wlan_connected_links)) {
+			chan = wlan_vdev_get_active_channel(vdev);
+			if (!chan) {
+				mlme_err("vdev %d :failed to get freq info",
+					 req->scan_req.vdev_id);
+				return QDF_STATUS_E_FAILURE;
+			}
+
+			mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
+			status = mlme_update_freq_in_scan_start_req(mlo_vdev,
+						req, associated_ch_width);
+			if (QDF_IS_STATUS_ERROR(status))
+				return QDF_STATUS_E_FAILURE;
+		}
+	}
+
+	mlme_debug("vdev %d :trigger wide band scan for mlo conn, num freq %d",
+		   req->scan_req.vdev_id, req->scan_req.chan_list.num_chan);
+	return QDF_STATUS_SUCCESS;
+}
+#else
+static inline QDF_STATUS
+mlme_fill_freq_in_mlo_wide_band_scan_start_req(struct wlan_objmgr_vdev *vdev,
+					struct scan_start_request *req,
+					enum phy_ch_width associated_ch_width)
+{
+	return QDF_STATUS_E_FAILURE;
+}
+#endif
+
 /**
  * mlme_fill_freq_in_wide_scan_start_request() - Fill frequencies in wide band
  * scan req
@@ -186,50 +481,37 @@ static QDF_STATUS
 mlme_fill_freq_in_wide_scan_start_request(struct wlan_objmgr_vdev *vdev,
 					  struct scan_start_request *req)
 {
-	const struct bonded_channel_freq *range;
 	struct mlme_legacy_priv *mlme_priv;
 	enum phy_ch_width associated_ch_width;
-	qdf_freq_t operation_chan_freq;
+	QDF_STATUS status;
 
 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
 	if (!mlme_priv)
 		return QDF_STATUS_E_FAILURE;
 
-	operation_chan_freq = wlan_get_operation_chan_freq(vdev);
 	associated_ch_width = mlme_priv->connect_info.ch_width_orig;
-
 	if (associated_ch_width == CH_WIDTH_INVALID) {
-		mlme_debug("vdev %d :Invalid assoc ch width, freq %d",
-			   req->scan_req.vdev_id, operation_chan_freq);
+		mlme_debug("vdev %d :Invalid associated ch_width",
+			   req->scan_req.vdev_id);
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	if (associated_ch_width == CH_WIDTH_320MHZ) {
-		range = wlan_reg_get_bonded_chan_entry(operation_chan_freq,
-						       associated_ch_width, 0);
-		if (!range) {
-			mlme_debug("vdev %d : range is null for freq %d",
-				   req->scan_req.vdev_id, operation_chan_freq);
-			return QDF_STATUS_E_FAILURE;
-		}
-
-		mlme_debug("vdev %d :trigger wide band scan for freq %d bw %d, range [%d-%d], total freq %d",
-			   req->scan_req.vdev_id, operation_chan_freq,
-			   associated_ch_width, range->start_freq,
-			   range->end_freq, req->scan_req.chan_list.num_chan);
+	req->scan_req.chan_list.num_chan = 0;
 
-
-		req->scan_req.chan_list.num_chan = 2;
-		req->scan_req.chan_list.chan[0].freq = range->start_freq;
-		req->scan_req.chan_list.chan[1].freq = range->end_freq;
-	} else {
-		mlme_debug("vdev %d : trigger wide band scan for freq %d bw %d",
-			   req->scan_req.vdev_id, operation_chan_freq,
-			   associated_ch_width);
-		req->scan_req.chan_list.num_chan = 1;
-		req->scan_req.chan_list.chan[0].freq = operation_chan_freq;
+	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
+		status = mlme_fill_freq_in_mlo_wide_band_scan_start_req(vdev,
+						req, associated_ch_width);
+		if (QDF_IS_STATUS_ERROR(status))
+			return QDF_STATUS_E_FAILURE;
+		goto update_param;
 	}
 
+	status = mlme_update_freq_in_scan_start_req(vdev, req,
+						    associated_ch_width);
+	if (QDF_IS_STATUS_ERROR(status))
+		return QDF_STATUS_E_FAILURE;
+
+update_param:
 	req->scan_req.dwell_time_passive =
 			MLME_GET_CHAN_STATS_WIDE_BAND_PASSIVE_SCAN_TIME;
 	req->scan_req.dwell_time_passive_6g =
@@ -266,13 +548,6 @@ QDF_STATUS mlme_connected_chan_stats_request(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
-		mlme_debug("vdev %d :reject get_cu req for mlo connection",
-			   vdev_id);
-		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
-		return QDF_STATUS_E_NOSUPPORT;
-	}
-
 	req = qdf_mem_malloc(sizeof(*req));
 	if (!req) {
 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);