Browse Source

qcacld-3.0: Add radio combination matrix vendor command support

Create radio combination matrix list from target mac phy information.
Return the supported radio matrix to apps by vendor command
QCA_NL80211_VENDOR_SUBCMD_GET_RADIO_COMBINATION_MATRIX.

Change-Id: I9732eadf10e8634336dbdac21e10f60e81cbaca6
CRs-Fixed: 3214050
Liangwei Dong 2 years ago
parent
commit
d6e9616054

+ 16 - 0
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h

@@ -4249,6 +4249,22 @@ QDF_STATUS policy_mgr_check_mon_concurrency(struct wlan_objmgr_psoc *psoc);
 void policy_mgr_get_hw_dbs_max_bw(struct wlan_objmgr_psoc *psoc,
 				  struct dbs_bw *bw_dbs);
 
+/**
+ * policy_mgr_get_radio_combinations() - Query the supported radio combinations
+ * @psoc: soc object
+ * @comb: combination buffer
+ * @comb_max: max combination number can be saved to comb buffer
+ * @comb_num: returned combination number
+ *
+ * This function returns the radio combination information supported by target.
+ *
+ * Return: QDF_STATUS_SUCCESS if query successfully
+ */
+QDF_STATUS policy_mgr_get_radio_combinations(struct wlan_objmgr_psoc *psoc,
+					     struct radio_combination *comb,
+					     uint32_t comb_max,
+					     uint32_t *comb_num);
+
 #ifdef WLAN_FEATURE_11BE_MLO
 /**
  * policy_mgr_is_mlo_sap_concurrency_allowed() - Check for mlo sap allowed

+ 17 - 0
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h

@@ -1560,6 +1560,23 @@ struct dbs_nss {
 	uint32_t single_mac0_band_cap;
 };
 
+/**
+ * Max radio combination numbers
+ */
+#define MAX_RADIO_COMBINATION 16
+
+/**
+ * struct radio_combination - Radio combination
+ * @hw_mode: hw mode type
+ * @band_mask: band support type for each mac
+ * @antenna: antenna support for each mac
+ */
+struct radio_combination {
+	enum policy_mgr_mode hw_mode;
+	uint8_t band_mask[MAX_MAC];
+	uint8_t antenna[MAX_MAC];
+};
+
 /**
  * struct connection_info - connection information
  * @mac_id: The HW mac it is running

+ 20 - 1
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_ucfg.h

@@ -21,7 +21,7 @@
 #include "wlan_objmgr_psoc_obj.h"
 #include "wlan_objmgr_global_obj.h"
 #include "qdf_status.h"
-
+#include "wlan_policy_mgr_public_struct.h"
 
 /**
  * ucfg_policy_mgr_psoc_open() - This API sets CFGs to policy manager context
@@ -62,6 +62,25 @@ QDF_STATUS ucfg_policy_mgr_get_mcc_scc_switch(struct wlan_objmgr_psoc *psoc,
 	return QDF_STATUS_SUCCESS;
 }
 #endif //FEATURE_WLAN_MCC_TO_SCC_SWITCH
+
+/**
+ * ucfg_policy_mgr_get_radio_combinations() - Query the supported radio
+ * combinations
+ * @psoc: soc object
+ * @comb: combination buffer
+ * @comb_max: max combination number can be saved to comb buffer
+ * @comb_num: returned combination number
+ *
+ * This function returns the radio combination information supported by target.
+ *
+ * Return: QDF_STATUS_SUCCESS if query successfully
+ */
+QDF_STATUS
+ucfg_policy_mgr_get_radio_combinations(struct wlan_objmgr_psoc *psoc,
+				       struct radio_combination *comb,
+				       uint32_t comb_max,
+				       uint32_t *comb_num);
+
 /**
  * ucfg_policy_mgr_get_sys_pref() - to get system preference
  * @psoc: pointer to psoc

+ 214 - 0
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -669,6 +669,8 @@ static void policy_mgr_get_hw_mode_params(
 		struct wlan_psoc_host_mac_phy_caps *caps,
 		struct policy_mgr_mac_ss_bw_info *info)
 {
+	qdf_freq_t max_5g_freq;
+
 	if (!caps) {
 		policy_mgr_err("Invalid capabilities");
 		return;
@@ -684,6 +686,17 @@ static void policy_mgr_get_hw_mode_params(
 		QDF_MAX(caps->max_bw_supported_2G,
 		caps->max_bw_supported_5G));
 	info->mac_band_cap = caps->supported_bands;
+
+	if (caps->supported_bands & WMI_HOST_WLAN_5G_CAPABILITY) {
+		max_5g_freq = wlan_reg_max_6ghz_chan_freq() ?
+				wlan_reg_max_6ghz_chan_freq() :
+				wlan_reg_max_5ghz_chan_freq();
+		max_5g_freq = caps->reg_cap_ext.high_5ghz_chan ?
+				QDF_MIN(caps->reg_cap_ext.high_5ghz_chan,
+					max_5g_freq) : max_5g_freq;
+		info->support_6ghz_band =
+			max_5g_freq > wlan_reg_min_6ghz_chan_freq();
+	}
 }
 
 /**
@@ -758,6 +771,200 @@ static void policy_mgr_set_hw_mode_params(struct wlan_objmgr_psoc *psoc,
 	    legacy_hwmode_lst, emlsr_mode);
 }
 
+QDF_STATUS policy_mgr_get_radio_combinations(struct wlan_objmgr_psoc *psoc,
+					     struct radio_combination *comb,
+					     uint32_t comb_max,
+					     uint32_t *comb_num)
+{
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	struct radio_combination *radio_comb;
+	uint32_t i;
+	bool dbs_or_sbs_enabled = false;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	*comb_num = 0;
+	if (policy_mgr_is_hw_dbs_capable(psoc) ||
+	    policy_mgr_is_hw_sbs_capable(psoc))
+		dbs_or_sbs_enabled = true;
+
+	for (i = 0; i < pm_ctx->radio_comb_num; i++) {
+		radio_comb = &pm_ctx->radio_combinations[i];
+		if (!dbs_or_sbs_enabled && radio_comb->hw_mode != MODE_SMM)
+			continue;
+		if (*comb_num >= comb_max) {
+			policy_mgr_err("out of buffer %d max %d",
+				       pm_ctx->radio_comb_num,
+				       comb_max);
+			return QDF_STATUS_E_FAILURE;
+		}
+		policy_mgr_debug("radio %d: mode %d mac0 (0x%x, 0x%x), mac1 (0x%x 0x%x)",
+				 *comb_num,
+				 radio_comb->hw_mode,
+				 radio_comb->band_mask[0],
+				 radio_comb->antenna[0],
+				 radio_comb->band_mask[1],
+				 radio_comb->antenna[1]);
+		qdf_mem_copy(&comb[*comb_num], radio_comb,
+			     sizeof(*radio_comb));
+		(*comb_num)++;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * policy_mgr_add_radio_comb() - Add radio combination
+ * @pm_ctx: bandwidth in terms of wmi_channel_width
+ * @radio: radio combination
+ *
+ * This function adds one radio combination to list
+ *
+ * Return: void
+ */
+static void policy_mgr_add_radio_comb(struct policy_mgr_psoc_priv_obj *pm_ctx,
+				      struct radio_combination *radio)
+{
+	uint32_t i;
+	struct radio_combination *comb;
+
+	/* don't add duplicated item */
+	for (i = 0; i < pm_ctx->radio_comb_num; i++) {
+		comb = &pm_ctx->radio_combinations[i];
+		if (radio->hw_mode == comb->hw_mode &&
+		    radio->band_mask[0] == comb->band_mask[0] &&
+		    radio->band_mask[1] == comb->band_mask[1] &&
+		    radio->antenna[0] == comb->antenna[0] &&
+		    radio->antenna[1] == comb->antenna[1])
+			return;
+	}
+	if (pm_ctx->radio_comb_num == MAX_RADIO_COMBINATION) {
+		policy_mgr_err("radio combination overflow %d",
+			       pm_ctx->radio_comb_num);
+		return;
+	}
+	policy_mgr_debug("radio %d: mode %d mac0 (0x%x, 0x%x), mac1 (0x%x 0x%x)",
+			 pm_ctx->radio_comb_num,
+			 radio->hw_mode,
+			 radio->band_mask[0],
+			 radio->antenna[0],
+			 radio->band_mask[1],
+			 radio->antenna[1]);
+
+	qdf_mem_copy(&pm_ctx->radio_combinations[pm_ctx->radio_comb_num],
+		     radio, sizeof(*radio));
+	pm_ctx->radio_comb_num++;
+}
+
+#define SET_RADIO(_radio, _mode, _mac0_band, _mac1_band,\
+		  _mac0_antenna, _mac1_antenna) \
+do { \
+	(_radio)->hw_mode = _mode; \
+	(_radio)->band_mask[0] = _mac0_band; \
+	(_radio)->band_mask[1] = _mac1_band; \
+	(_radio)->antenna[0] = _mac0_antenna; \
+	(_radio)->antenna[1] = _mac1_antenna; \
+} while (0)
+
+/**
+ * policy_mgr_update_radio_combination_matrix() - Update radio combination
+ * list
+ * @psoc: psoc object
+ * @mac0_ss_bw_info: mac 0 band/bw info
+ * @mac1_ss_bw_info: mac 1 band/bw info
+ * @dbs_mode: dbs mode
+ * @sbs_mode: sbs mode
+ *
+ * This function updates radio combination list based on hw mode information.
+ *
+ * Return: void
+ */
+static void
+policy_mgr_update_radio_combination_matrix(
+			struct wlan_objmgr_psoc *psoc,
+			struct policy_mgr_mac_ss_bw_info mac0_ss_bw_info,
+			struct policy_mgr_mac_ss_bw_info mac1_ss_bw_info,
+			uint32_t dbs_mode, uint32_t sbs_mode)
+{
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	struct radio_combination radio;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return;
+	}
+
+	if (!dbs_mode && !sbs_mode) {
+		if (mac0_ss_bw_info.mac_band_cap &
+					WMI_HOST_WLAN_2G_CAPABILITY) {
+			SET_RADIO(&radio, MODE_SMM, BIT(REG_BAND_2G), 0,
+				  mac0_ss_bw_info.mac_tx_stream, 0);
+			policy_mgr_add_radio_comb(pm_ctx, &radio);
+		}
+		if (mac0_ss_bw_info.mac_band_cap &
+					WMI_HOST_WLAN_5G_CAPABILITY) {
+			SET_RADIO(&radio, MODE_SMM, BIT(REG_BAND_5G), 0,
+				  mac0_ss_bw_info.mac_tx_stream, 0);
+			policy_mgr_add_radio_comb(pm_ctx, &radio);
+			if (mac0_ss_bw_info.support_6ghz_band) {
+				SET_RADIO(&radio, MODE_SMM, BIT(REG_BAND_6G),
+					  0, mac0_ss_bw_info.mac_tx_stream, 0);
+				policy_mgr_add_radio_comb(pm_ctx, &radio);
+			}
+		}
+		return;
+	}
+	if ((mac0_ss_bw_info.mac_band_cap & WMI_HOST_WLAN_2G_CAPABILITY) &&
+	    (mac1_ss_bw_info.mac_band_cap & WMI_HOST_WLAN_5G_CAPABILITY)) {
+		SET_RADIO(&radio, MODE_DBS, BIT(REG_BAND_2G), BIT(REG_BAND_5G),
+			  mac0_ss_bw_info.mac_tx_stream,
+			  mac1_ss_bw_info.mac_tx_stream);
+		policy_mgr_add_radio_comb(pm_ctx, &radio);
+		if (mac1_ss_bw_info.support_6ghz_band) {
+			SET_RADIO(&radio, MODE_DBS, BIT(REG_BAND_2G),
+				  BIT(REG_BAND_6G),
+				  mac0_ss_bw_info.mac_tx_stream,
+				  mac1_ss_bw_info.mac_tx_stream);
+			policy_mgr_add_radio_comb(pm_ctx, &radio);
+		}
+	}
+	if ((mac0_ss_bw_info.mac_band_cap & WMI_HOST_WLAN_5G_CAPABILITY) &&
+	    (mac1_ss_bw_info.mac_band_cap & WMI_HOST_WLAN_2G_CAPABILITY)) {
+		SET_RADIO(&radio, MODE_DBS, BIT(REG_BAND_2G), BIT(REG_BAND_5G),
+			  mac1_ss_bw_info.mac_tx_stream,
+			  mac0_ss_bw_info.mac_tx_stream);
+		policy_mgr_add_radio_comb(pm_ctx, &radio);
+		if (mac0_ss_bw_info.support_6ghz_band) {
+			SET_RADIO(&radio, MODE_DBS, BIT(REG_BAND_2G),
+				  BIT(REG_BAND_6G),
+				  mac1_ss_bw_info.mac_tx_stream,
+				  mac0_ss_bw_info.mac_tx_stream);
+			policy_mgr_add_radio_comb(pm_ctx, &radio);
+		}
+	}
+	if ((mac0_ss_bw_info.mac_band_cap & WMI_HOST_WLAN_5G_CAPABILITY) &&
+	    (mac1_ss_bw_info.mac_band_cap & WMI_HOST_WLAN_5G_CAPABILITY)) {
+		if (mac0_ss_bw_info.support_6ghz_band) {
+			SET_RADIO(&radio, MODE_SBS, BIT(REG_BAND_5G),
+				  BIT(REG_BAND_6G),
+				  mac1_ss_bw_info.mac_tx_stream,
+				  mac0_ss_bw_info.mac_tx_stream);
+			policy_mgr_add_radio_comb(pm_ctx, &radio);
+		} else if (mac1_ss_bw_info.support_6ghz_band) {
+			SET_RADIO(&radio, MODE_SBS, BIT(REG_BAND_5G),
+				  BIT(REG_BAND_6G),
+				  mac0_ss_bw_info.mac_tx_stream,
+				  mac1_ss_bw_info.mac_tx_stream);
+			policy_mgr_add_radio_comb(pm_ctx, &radio);
+		}
+	}
+}
+
 static void
 policy_mgr_update_24Ghz_freq_info(struct policy_mgr_freq_range *mac_range,
 				  struct wlan_psoc_host_mac_phy_caps *mac_cap)
@@ -1276,6 +1483,9 @@ QDF_STATUS policy_mgr_update_hw_mode_list(struct wlan_objmgr_psoc *psoc,
 		pm_ctx->num_dbs_hw_modes = 0;
 		return QDF_STATUS_E_NOMEM;
 	}
+	pm_ctx->radio_comb_num = 0;
+	qdf_mem_zero(pm_ctx->radio_combinations,
+		     sizeof(pm_ctx->radio_combinations));
 
 	policy_mgr_debug("Updated HW mode list: Num modes:%d",
 		pm_ctx->num_dbs_hw_modes);
@@ -1330,6 +1540,10 @@ QDF_STATUS policy_mgr_update_hw_mode_list(struct wlan_objmgr_psoc *psoc,
 		policy_mgr_set_hw_mode_params(psoc, mac0_ss_bw_info,
 			mac1_ss_bw_info, i, tmp->hw_mode_id, dbs_mode,
 			sbs_mode, emlsr_mode);
+		/* Update radio combination info */
+		policy_mgr_update_radio_combination_matrix(
+			psoc, mac0_ss_bw_info, mac1_ss_bw_info,
+			dbs_mode, sbs_mode);
 	}
 
 	/*

+ 6 - 0
components/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h

@@ -337,6 +337,8 @@ struct policy_mgr_cfg {
  * @new_hw_mode_index: New HW mode from hw_mode table
  * @dual_mac_cfg: DBS configuration currenctly used by FW for
  *              scan & connections
+ * @radio_comb_num: radio combination number
+ * @radio_combinations: radio combination list
  * @hw_mode_change_in_progress: This is to track if HW mode
  *                            change is in progress
  * @enable_mcc_adaptive_scheduler: Enable MCC adaptive scheduler
@@ -381,6 +383,8 @@ struct policy_mgr_psoc_priv_obj {
 	uint32_t old_hw_mode_index;
 	uint32_t new_hw_mode_index;
 	struct dual_mac_config dual_mac_cfg;
+	uint32_t radio_comb_num;
+	struct radio_combination radio_combinations[MAX_RADIO_COMBINATION];
 	uint32_t hw_mode_change_in_progress;
 	struct policy_mgr_user_cfg user_cfg;
 	uint32_t unsafe_channel_list[NUM_CHANNELS];
@@ -408,12 +412,14 @@ struct policy_mgr_psoc_priv_obj {
  * @mac_bw: Max bandwidth(wmi_channel_width enum type)
  * @mac_band_cap: supported Band bit map(WLAN_2G_CAPABILITY = 0x1,
  *                            WLAN_5G_CAPABILITY = 0x2)
+ * @support_6ghz_band: support 6 GHz band
  */
 struct policy_mgr_mac_ss_bw_info {
 	uint32_t mac_tx_stream;
 	uint32_t mac_rx_stream;
 	uint32_t mac_bw;
 	uint32_t mac_band_cap;
+	bool support_6ghz_band;
 };
 
 #ifdef WLAN_FEATURE_11BE_MLO

+ 10 - 0
components/cmn_services/policy_mgr/src/wlan_policy_mgr_ucfg.c

@@ -238,6 +238,16 @@ QDF_STATUS ucfg_policy_mgr_set_max_conc_cxns(struct wlan_objmgr_psoc *psoc,
 	return policy_mgr_set_max_conc_cxns(psoc, max_conc_cxns);
 }
 
+QDF_STATUS
+ucfg_policy_mgr_get_radio_combinations(struct wlan_objmgr_psoc *psoc,
+				       struct radio_combination *comb,
+				       uint32_t comb_max,
+				       uint32_t *comb_num)
+{
+	return policy_mgr_get_radio_combinations(psoc, comb,
+						 comb_max, comb_num);
+}
+
 QDF_STATUS
 ucfg_policy_mgr_get_sta_sap_scc_on_dfs_chnl(struct wlan_objmgr_psoc *psoc,
 					    uint8_t *sta_sap_scc_on_dfs_chnl)

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

@@ -14168,6 +14168,160 @@ static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
 	return errno;
 }
 
+/**
+ * __wlan_hdd_cfg80211_get_radio_combination_matrix() - get radio matrix info
+ * @wiphy:   pointer to wireless wiphy structure.
+ * @wdev:    pointer to wireless_dev structure.
+ * @data:    Pointer to the data to be passed via vendor interface
+ * @data_len:Length of the data to be passed
+ *
+ * Return:   Return the Success or Failure code.
+ */
+static int
+__wlan_hdd_cfg80211_get_radio_combination_matrix(struct wiphy *wiphy,
+						 struct wireless_dev *wdev,
+						 const void *data,
+						 int data_len)
+{
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct sk_buff *reply_skb;
+	int ret;
+	int skb_len;
+	struct nlattr *combination, *combination_cfg, *radio, *radio_comb;
+	uint32_t comb_num = 0;
+	struct radio_combination comb[MAX_RADIO_COMBINATION];
+	int comb_idx, radio_idx;
+	enum qca_set_band qca_band;
+
+	hdd_enter();
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	ucfg_policy_mgr_get_radio_combinations(hdd_ctx->psoc, comb,
+					       QDF_ARRAY_SIZE(comb),
+					       &comb_num);
+	if (!comb_num) {
+		hdd_err("invalid combination 0");
+		return -EINVAL;
+	}
+
+	/* band and antenna */
+	skb_len = nla_total_size(sizeof(uint32_t)) +
+		  nla_total_size(sizeof(uint8_t));
+	/* radio nested for max 2 MACs*/
+	skb_len = nla_total_size(skb_len) * MAX_MAC;
+	/* one radio combination */
+	skb_len = nla_total_size(nla_total_size(skb_len));
+	/* total combinations */
+	skb_len = nla_total_size(comb_num * nla_total_size(skb_len));
+	skb_len = NLMSG_HDRLEN + skb_len;
+	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
+	if (!reply_skb) {
+		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed, len %d",
+			skb_len);
+		return -EINVAL;
+	}
+
+	combination_cfg = nla_nest_start(reply_skb,
+			QCA_WLAN_VENDOR_ATTR_RADIO_MATRIX_SUPPORTED_CFGS);
+	if (!combination_cfg) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	for (comb_idx = 0; comb_idx < comb_num; comb_idx++) {
+		combination = nla_nest_start(reply_skb, comb_idx);
+		if (!combination) {
+			ret = -ENOMEM;
+			goto err;
+		}
+		radio_comb = nla_nest_start(reply_skb,
+				QCA_WLAN_VENDOR_ATTR_RADIO_COMBINATIONS_CFGS);
+		if (!radio_comb) {
+			ret = -ENOMEM;
+			goto err;
+		}
+		for (radio_idx = 0; radio_idx < MAX_MAC; radio_idx++) {
+			if (!comb[comb_idx].band_mask[radio_idx])
+				break;
+			radio = nla_nest_start(reply_skb, radio_idx);
+			if (comb[comb_idx].band_mask[radio_idx] ==
+							BIT(REG_BAND_5G)) {
+				qca_band = QCA_SETBAND_5G;
+			} else if (comb[comb_idx].band_mask[radio_idx] ==
+							BIT(REG_BAND_6G)) {
+				qca_band = QCA_SETBAND_6G;
+			} else if (comb[comb_idx].band_mask[radio_idx] ==
+							BIT(REG_BAND_2G)) {
+				qca_band = QCA_SETBAND_2G;
+			} else {
+				hdd_err("invalid band mask 0 for comb %d radio %d",
+					comb_idx, radio_idx);
+				ret = -EINVAL;
+				goto err;
+			}
+
+			if (nla_put_u32(reply_skb,
+				       QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_BAND,
+				       qca_band)) {
+				ret = -ENOMEM;
+				goto err;
+			}
+			if (nla_put_u8(reply_skb,
+				       QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_ANTENNA,
+				       comb[comb_idx].antenna[radio_idx])) {
+				ret = -ENOMEM;
+				goto err;
+			}
+			hdd_debug("comb[%d]:cfg[%d]: band %d, antenna %d",
+				  comb_idx, radio_idx, qca_band,
+				  comb[comb_idx].antenna[radio_idx]);
+			nla_nest_end(reply_skb, radio);
+		}
+		nla_nest_end(reply_skb, radio_comb);
+		nla_nest_end(reply_skb, combination);
+	}
+	nla_nest_end(reply_skb, combination_cfg);
+	ret = wlan_cfg80211_vendor_cmd_reply(reply_skb);
+
+	return ret;
+err:
+	wlan_cfg80211_vendor_free_skb(reply_skb);
+
+	return ret;
+}
+
+/**
+ * wlan_hdd_cfg80211_radio_combination_matrix() - get radio matrix info
+ * @wiphy:   pointer to wireless wiphy structure.
+ * @wdev:    pointer to wireless_dev structure.
+ * @data:    Pointer to the data to be passed via vendor interface
+ * @data_len:Length of the data to be passed
+ *
+ * Return:   Return the Success or Failure code.
+ */
+static int
+wlan_hdd_cfg80211_get_radio_combination_matrix(struct wiphy *wiphy,
+					       struct wireless_dev *wdev,
+					       const void *data, int data_len)
+{
+	struct osif_psoc_sync *psoc_sync;
+	int errno;
+
+	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
+	if (errno)
+		return errno;
+
+	errno = __wlan_hdd_cfg80211_get_radio_combination_matrix(wiphy, wdev,
+								 data,
+								 data_len);
+
+	osif_psoc_sync_op_stop(psoc_sync);
+
+	return errno;
+}
+
 const struct nla_policy setband_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
 	[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = {.type = NLA_U32},
 	[QCA_WLAN_VENDOR_ATTR_SETBAND_MASK] = {.type = NLA_U32},
@@ -18200,6 +18354,14 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
 #endif
 	FEATURE_MCC_QUOTA_VENDOR_COMMANDS
 	FEATURE_PEER_FLUSH_VENDOR_COMMANDS
+	{
+		.info.vendor_id = QCA_NL80211_VENDOR_ID,
+		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RADIO_COMBINATION_MATRIX,
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+			 WIPHY_VENDOR_CMD_NEED_NETDEV,
+		.doit = wlan_hdd_cfg80211_get_radio_combination_matrix,
+		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
+	},
 };
 
 struct hdd_context *hdd_cfg80211_wiphy_alloc(void)