浏览代码

qcacld-3.0: Provide support enable RX LDPC in certain cases

In following conditions RX LDPC support needs to be enabled
1) when STA is coming up in 5G band
2) when IBSS is coming up in 5G band

for anyother cases RX LDPC needs to be disabled. If user has
choosen RX LDPC to be disabled from INI file then it needs to
be disabled for all the cases including above mentioned cases.

To achieve this, take the intersection of global, INI, and harware
specific RX LDPC settings.

Change-Id: Iae10aa4a8c0931cdb796cd9c8ff558d4bc8e0aed
CRs-Fixed: 1050004
Krunal Soni 8 年之前
父节点
当前提交
0193b6f143

+ 41 - 0
core/cds/inc/cds_concurrency.h

@@ -65,6 +65,47 @@
 
 #define WEIGHT_OF_NON_PCL_CHANNELS 1
 
+/**
+ * enum hw_mode_ss_config - Possible spatial stream configuration
+ * @SS_0x0: Unused Tx and Rx of MAC
+ * @SS_1x1: 1 Tx SS and 1 Rx SS
+ * @SS_2x2: 2 Tx SS and 2 Rx SS
+ * @SS_3x3: 3 Tx SS and 3 Rx SS
+ * @SS_4x4: 4 Tx SS and 4 Rx SS
+ *
+ * Note: Right now only 1x1 and 2x2 are being supported. Other modes should
+ * be added when supported. Asymmetric configuration like 1x2, 2x1 are also
+ * not supported now. But, they are still valid. Right now, Tx/Rx SS support is
+ * 4 bits long. So, we can go upto 15x15
+ */
+enum hw_mode_ss_config {
+	HW_MODE_SS_0x0,
+	HW_MODE_SS_1x1,
+	HW_MODE_SS_2x2,
+	HW_MODE_SS_3x3,
+	HW_MODE_SS_4x4,
+};
+
+/**
+ * enum hw_mode_dbs_capab - DBS HW mode capability
+ * @HW_MODE_DBS_NONE: Non DBS capable
+ * @HW_MODE_DBS: DFS capable
+ */
+enum hw_mode_dbs_capab {
+	HW_MODE_DBS_NONE,
+	HW_MODE_DBS,
+};
+
+/**
+ * enum hw_mode_agile_dfs_capab - Agile DFS HW mode capability
+ * @HW_MODE_AGILE_DFS_NONE: Non Agile DFS capable
+ * @HW_MODE_AGILE_DFS: Agile DFS capable
+ */
+enum hw_mode_agile_dfs_capab {
+	HW_MODE_AGILE_DFS_NONE,
+	HW_MODE_AGILE_DFS,
+};
+
 /**
  * enum cds_pcl_group_id - Identifies the pcl groups to be used
  * @CDS_PCL_GROUP_ID1_ID2: Use weights of group1 and group2

+ 6 - 6
core/cds/inc/cds_utils.h

@@ -51,8 +51,6 @@
    ------------------------------------------------------------------------*/
 #define CDS_DIGEST_SHA1_SIZE    (20)
 #define CDS_DIGEST_MD5_SIZE     (16)
-#define CDS_BAND_2GHZ          (1)
-#define CDS_BAND_5GHZ          (2)
 
 #define CDS_24_GHZ_BASE_FREQ   (2407)
 #define CDS_5_GHZ_BASE_FREQ    (5000)
@@ -82,9 +80,11 @@
 		cds_logfl(QDF_TRACE_LEVEL_INFO_HIGH, format, ## args)
 #define cds_debug(format, args...) \
 		cds_logfl(QDF_TRACE_LEVEL_DEBUG, format, ## args)
-/*--------------------------------------------------------------------------
-   Type declarations
-   ------------------------------------------------------------------------*/
+
+enum cds_band_type {
+	CDS_BAND_2GHZ = 1,
+	CDS_BAND_5GHZ = 2
+};
 
 /*-------------------------------------------------------------------------
    Function declarations and documenation
@@ -178,7 +178,7 @@ QDF_STATUS cds_decrypt_aes(uint32_t cryptHandle,        /* Handle */
 
 uint32_t cds_chan_to_freq(uint8_t chan);
 uint8_t cds_freq_to_chan(uint32_t freq);
-uint8_t cds_chan_to_band(uint32_t chan);
+enum cds_band_type cds_chan_to_band(uint32_t chan);
 #ifdef WLAN_FEATURE_11W
 bool cds_is_mmie_valid(uint8_t *key, uint8_t *ipn,
 		       uint8_t *frm, uint8_t *efrm);

+ 1 - 1
core/cds/src/cds_utils.c

@@ -1128,7 +1128,7 @@ uint8_t cds_freq_to_chan(uint32_t freq)
 	return chan;
 }
 
-uint8_t cds_chan_to_band(uint32_t chan)
+enum cds_band_type cds_chan_to_band(uint32_t chan)
 {
 	if (chan <= CDS_24_GHZ_CHANNEL_14)
 		return CDS_BAND_2GHZ;

+ 1 - 0
core/hdd/src/wlan_hdd_cfg.c

@@ -7148,6 +7148,7 @@ QDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx)
 	smeConfig->csrConfig.scanCfgAgingTime = pConfig->scanAgingTimeout;
 
 	smeConfig->csrConfig.enableTxLdpc = pConfig->enableTxLdpc;
+	smeConfig->csrConfig.enableRxLDPC = pConfig->enableRxLDPC;
 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
 	smeConfig->csrConfig.cc_switch_mode = pConfig->WlanMccToSccSwitchMode;
 #endif

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

@@ -3181,26 +3181,6 @@ struct sir_wifi_start_log {
 	uint32_t flag;
 };
 
-/**
- * enum hw_mode_ss_config - Possible spatial stream configuration
- * @SS_0x0: Unused Tx and Rx of MAC
- * @SS_1x1: 1 Tx SS and 1 Rx SS
- * @SS_2x2: 2 Tx SS and 2 Rx SS
- * @SS_3x3: 3 Tx SS and 3 Rx SS
- * @SS_4x4: 4 Tx SS and 4 Rx SS
- *
- * Note: Right now only 1x1 and 2x2 are being supported. Other modes should
- * be added when supported. Asymmetric configuration like 1x2, 2x1 are also
- * not supported now. But, they are still valid. Right now, Tx/Rx SS support is
- * 4 bits long. So, we can go upto 15x15
- */
-enum hw_mode_ss_config {
-	HW_MODE_SS_0x0,
-	HW_MODE_SS_1x1,
-	HW_MODE_SS_2x2,
-	HW_MODE_SS_3x3,
-	HW_MODE_SS_4x4,
-};
 
 /**
  * enum hw_mode_bandwidth - bandwidth of wifi channel.
@@ -3229,26 +3209,6 @@ enum hw_mode_bandwidth {
 	HW_MODE_MAX_BANDWIDTH
 };
 
-/**
- * enum hw_mode_dbs_capab - DBS HW mode capability
- * @HW_MODE_DBS_NONE: Non DBS capable
- * @HW_MODE_DBS: DFS capable
- */
-enum hw_mode_dbs_capab {
-	HW_MODE_DBS_NONE,
-	HW_MODE_DBS,
-};
-
-/**
- * enum hw_mode_agile_dfs_capab - Agile DFS HW mode capability
- * @HW_MODE_AGILE_DFS_NONE: Non Agile DFS capable
- * @HW_MODE_AGILE_DFS: Agile DFS capable
- */
-enum hw_mode_agile_dfs_capab {
-	HW_MODE_AGILE_DFS_NONE,
-	HW_MODE_AGILE_DFS,
-};
-
 /**
  * enum set_hw_mode_status - Status of set HW mode command
  * @SET_HW_MODE_STATUS_OK: command successful

+ 1 - 0
core/sme/inc/csr_api.h

@@ -1209,6 +1209,7 @@ typedef struct tagCsrConfigParam {
 	bool bFastRoamInConIniFeatureEnabled;
 	uint8_t scanCfgAgingTime;
 	uint8_t enableTxLdpc;
+	uint8_t enableRxLDPC;
 	uint8_t isAmsduSupportInAMPDU;
 	uint8_t nSelect5GHzMargin;
 	uint8_t isCoalesingInIBSSAllowed;

+ 1 - 0
core/sme/inc/csr_internal.h

@@ -612,6 +612,7 @@ typedef struct tagCsrConfig {
 	uint8_t htSmps;
 	bool send_smps_action;
 	uint8_t txLdpcEnable;
+	uint8_t rxLdpcEnable;
 	/*
 	 * Enable/Disable heartbeat offload
 	 */

+ 55 - 0
core/sme/src/csr/csr_api_roam.c

@@ -2327,6 +2327,7 @@ QDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac,
 		pMac->roam.configParam.send_smps_action =
 			pParam->send_smps_action;
 		pMac->roam.configParam.txLdpcEnable = pParam->enableTxLdpc;
+		pMac->roam.configParam.rxLdpcEnable = pParam->enableRxLDPC;
 		pMac->roam.configParam.ignore_peer_erp_info =
 			pParam->ignore_peer_erp_info;
 		pMac->roam.configParam.isAmsduSupportInAMPDU =
@@ -2549,6 +2550,7 @@ QDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam)
 	pParam->cc_switch_mode = cfg_params->cc_switch_mode;
 #endif
 	pParam->enableTxLdpc = cfg_params->txLdpcEnable;
+	pParam->enableRxLDPC = cfg_params->rxLdpcEnable;
 	pParam->isAmsduSupportInAMPDU = cfg_params->isAmsduSupportInAMPDU;
 	pParam->nSelect5GHzMargin = cfg_params->nSelect5GHzMargin;
 	pParam->isCoalesingInIBSSAllowed = cfg_params->isCoalesingInIBSSAllowed;
@@ -13576,6 +13578,46 @@ static void csr_add_supported_5Ghz_channels(tpAniSirGlobal mac_ctx,
 	}
 }
 
+/**
+ * csr_set_ldpc_exception() - to set allow any LDPC exception permitted
+ * @mac_ctx: Pointer to mac context
+ * @session: Pointer to SME/CSR session
+ * @channel: Given channel number where connection will go
+ * @usr_cfg_rx_ldpc: User provided RX LDPC setting
+ *
+ * This API will check if hardware allows LDPC to be enabled for provided
+ * channel and user has enabled the RX LDPC selection
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS csr_set_ldpc_exception(tpAniSirGlobal mac_ctx,
+			tCsrRoamSession *session, uint8_t channel,
+			bool usr_cfg_rx_ldpc)
+{
+	if (!mac_ctx) {
+		sms_log(mac_ctx, LOGE,
+			FL("mac_ctx is NULL"));
+		return QDF_STATUS_E_FAILURE;
+	}
+	if (!session) {
+		sms_log(mac_ctx, LOGE,
+			FL("session is NULL"));
+		return QDF_STATUS_E_FAILURE;
+	}
+	if (usr_cfg_rx_ldpc && wma_is_rx_ldpc_supported_for_channel(channel)) {
+		session->htConfig.ht_rx_ldpc = 1;
+		session->vht_config.ldpc_coding = 1;
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
+			"LDPC enable for chnl[%d]", channel);
+	} else {
+		session->htConfig.ht_rx_ldpc = 0;
+		session->vht_config.ldpc_coding = 0;
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH,
+			"LDPC disable for chnl[%d]", channel);
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * The communication between HDD and LIM is thru mailbox (MB).
  * Both sides will access the data structure "tSirSmeJoinReq".
@@ -14075,6 +14117,15 @@ QDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId,
 				(&pIes->Country.triplets[0]));
 			csr_apply_power2_current(pMac);
 		}
+		/*
+		 * If RX LDPC has been disabled for 2.4GHz channels and enabled
+		 * for 5Ghz for STA like persona here is how to handle those
+		 * cases here (by now channel has been decided).
+		 */
+		if (eSIR_INFRASTRUCTURE_MODE == csr_join_req->bsstype)
+			csr_set_ldpc_exception(pMac, pSession,
+					pBssDescription->channelId,
+					pMac->roam.configParam.rxLdpcEnable);
 		qdf_mem_copy(&csr_join_req->htConfig,
 				&pSession->htConfig, sizeof(tSirHTConfig));
 		qdf_mem_copy(&csr_join_req->vht_config, &pSession->vht_config,
@@ -14871,6 +14922,10 @@ QDF_STATUS csr_send_mb_start_bss_req_msg(tpAniSirGlobal pMac, uint32_t sessionId
 	qdf_mem_copy(&pMsg->extendedRateSet,
 		     &pParam->extendedRateSet,
 		     sizeof(tSirMacRateSet));
+	if (eSIR_IBSS_MODE == pMsg->bssType)
+		csr_set_ldpc_exception(pMac, pSession,
+				pMsg->channelId,
+				pMac->roam.configParam.rxLdpcEnable);
 	qdf_mem_copy(&pMsg->vht_config,
 		     &pSession->vht_config,
 		     sizeof(pSession->vht_config));

+ 24 - 0
core/wma/inc/wma_api.h

@@ -38,6 +38,8 @@
 #include "htc_api.h"
 #endif
 #include "lim_global.h"
+#include "cds_concurrency.h"
+#include "cds_utils.h"
 
 typedef void *WMA_HANDLE;
 
@@ -71,6 +73,25 @@ typedef enum {
 	GEN_VDEV_ROAM_SYNCH_DELAY,
 } GEN_PARAM;
 
+/**
+ * struct wma_caps_per_phy - various caps per phy
+ * @ht_2g: entire HT cap for 2G band in terms of 32 bit flag
+ * @ht_5g: entire HT cap for 5G band in terms of 32 bit flag
+ * @vht_2g: entire VHT cap for 2G band in terms of 32 bit flag
+ * @vht_5g: entire VHT cap for 5G band in terms of 32 bit flag
+ * @he_2g: entire HE cap for 2G band in terms of 32 bit flag
+ * @he_5g: entire HE cap for 5G band in terms of 32 bit flag
+ */
+struct wma_caps_per_phy {
+	uint32_t ht_2g;
+	uint32_t ht_5g;
+	uint32_t vht_2g;
+	uint32_t vht_5g;
+	uint32_t he_2g;
+	uint32_t he_5g;
+};
+
+
 #define VDEV_CMD 1
 #define PDEV_CMD 2
 #define GEN_CMD  3
@@ -197,6 +218,9 @@ bool wma_get_prev_agile_dfs_config(void);
 bool wma_get_prev_dbs_scan_config(void);
 bool wma_get_prev_dbs_plus_agile_scan_config(void);
 bool wma_get_prev_single_mac_scan_with_dfs_config(void);
+QDF_STATUS wma_get_caps_for_phyidx_hwmode(struct wma_caps_per_phy *caps_per_phy,
+		enum hw_mode_dbs_capab hw_mode, enum cds_band_type band);
+bool wma_is_rx_ldpc_supported_for_channel(uint32_t channel);
 
 #define LRO_IPV4_SEED_ARR_SZ 5
 #define LRO_IPV6_SEED_ARR_SZ 11

+ 143 - 0
core/wma/src/wma_main.c

@@ -4462,6 +4462,149 @@ int wma_rx_service_ready_event(void *handle, uint8_t *cmd_param_info,
 	return 0;
 }
 
+/**
+ * wma_get_phyid_for_given_band() - to get phyid for band
+ *
+ * @wma_handle: Pointer to wma handle
+ * @map: Pointer to map which is derived from hw mode & has mapping between
+ *       hw mode and available PHYs for that hw mode.
+ * @band: enum value of for 2G or 5G band
+ * @phyid: Pointer to phyid which needs to be filled
+ *
+ * This API looks in to the map to find out which particular phy supports
+ * provided band and return the idx (also called phyid) of that phy. Caller
+ * use this phyid to fetch various caps of that phy
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS wma_get_phyid_for_given_band(
+			t_wma_handle * wma_handle,
+			struct hw_mode_idx_to_mac_cap_idx *map,
+			enum cds_band_type band, uint8_t *phyid)
+{
+	uint8_t idx, i;
+	WMI_MAC_PHY_CAPABILITIES *cap;
+
+	if (!wma_handle) {
+		WMA_LOGE("Invalid wma handle");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!map) {
+		WMA_LOGE("Invalid given map");
+		return QDF_STATUS_E_FAILURE;
+	}
+	idx = map->mac_cap_idx;
+	*phyid = idx;
+
+	for (i = 0; i < map->num_of_macs; i++) {
+		cap = &wma_handle->phy_caps.each_phy_cap_per_hwmode[idx + i];
+		if ((band == CDS_BAND_2GHZ) &&
+				(WLAN_2G_CAPABILITY == cap->supported_bands)) {
+			*phyid = idx + i;
+			WMA_LOGI("Select 2G capable phyid[%d]", *phyid);
+			return QDF_STATUS_SUCCESS;
+		} else if ((band == CDS_BAND_5GHZ) &&
+				(WLAN_5G_CAPABILITY == cap->supported_bands)) {
+			*phyid = idx + i;
+			WMA_LOGI("Select 5G capable phyid[%d]", *phyid);
+			return QDF_STATUS_SUCCESS;
+		}
+	}
+	WMA_LOGI("Using default single hw mode phyid[%d]", *phyid);
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wma_get_caps_for_phyidx_hwmode() - to fetch caps for given hw mode and band
+ * @caps_per_phy: Pointer to capabilities structure which needs to be filled
+ * @hw_mode: Provided hardware mode
+ * @band: Provide band i.e. 2G or 5G
+ *
+ * This API finds cap which suitable for provided hw mode and band. If user
+ * is provides some invalid hw mode then it will automatically falls back to
+ * default hw mode
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wma_get_caps_for_phyidx_hwmode(struct wma_caps_per_phy *caps_per_phy,
+		enum hw_mode_dbs_capab hw_mode, enum cds_band_type band)
+{
+	t_wma_handle *wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
+	struct hw_mode_idx_to_mac_cap_idx *map;
+	WMI_MAC_PHY_CAPABILITIES *phy_cap;
+	uint8_t phyid, our_hw_mode = hw_mode;
+
+	if (!wma_handle) {
+		WMA_LOGE("Invalid wma handle");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (0 == wma_handle->phy_caps.num_hw_modes.num_hw_modes) {
+		WMA_LOGE("Invalid number of hw modes");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!wma_is_dbs_enable())
+		our_hw_mode = HW_MODE_DBS_NONE;
+
+	if (!caps_per_phy) {
+		WMA_LOGE("Invalid caps pointer");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	map = &wma_handle->phy_caps.hw_mode_to_mac_cap_map[our_hw_mode];
+
+	if (QDF_STATUS_SUCCESS !=
+		wma_get_phyid_for_given_band(wma_handle, map, band, &phyid)) {
+		WMA_LOGE("Invalid phyid");
+		return QDF_STATUS_E_FAILURE;
+	}
+	phy_cap = &wma_handle->phy_caps.each_phy_cap_per_hwmode[phyid];
+
+	caps_per_phy->ht_2g = phy_cap->ht_cap_info_2G;
+	caps_per_phy->ht_5g = phy_cap->ht_cap_info_5G;
+	caps_per_phy->vht_2g = phy_cap->vht_cap_info_2G;
+	caps_per_phy->vht_5g = phy_cap->vht_cap_info_5G;
+	caps_per_phy->he_2g = phy_cap->he_cap_info_2G;
+	caps_per_phy->he_5g = phy_cap->he_cap_info_5G;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wma_is_rx_ldpc_supported_for_channel() - to find out if ldpc is supported
+ *
+ * @channel: Channel number for which it needs to check if rx ldpc is enabled
+ *
+ * This API takes channel number as argument and takes default hw mode as DBS
+ * to check if rx LDPC support is enabled for that channel or no
+ */
+bool wma_is_rx_ldpc_supported_for_channel(uint32_t channel)
+{
+	struct wma_caps_per_phy caps_per_phy = {0};
+	enum cds_band_type band;
+	bool status;
+
+	if (!CDS_IS_CHANNEL_24GHZ(channel))
+		band = CDS_BAND_5GHZ;
+	else
+		band = CDS_BAND_2GHZ;
+
+	if (QDF_STATUS_SUCCESS != wma_get_caps_for_phyidx_hwmode(
+						&caps_per_phy,
+						HW_MODE_DBS, band)) {
+		return false;
+	}
+	if (CDS_IS_CHANNEL_24GHZ(channel))
+		status = (!!(caps_per_phy.ht_2g & WMI_HT_CAP_RX_LDPC));
+	else
+		status = (!!(caps_per_phy.ht_5g & WMI_HT_CAP_RX_LDPC));
+
+	return status;
+}
+
+
 /**
  * wma_print_populate_soc_caps() - Prints all the caps populated per hw mode
  * @wma_handle: pointer to wma_handle