diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index bb992eff76f9..997af35553ee 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/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 diff --git a/core/cds/inc/cds_utils.h b/core/cds/inc/cds_utils.h index 1bc711484120..daaa1647c03e 100644 --- a/core/cds/inc/cds_utils.h +++ b/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); diff --git a/core/cds/src/cds_utils.c b/core/cds/src/cds_utils.c index c818f4980a2c..68726fdee775 100644 --- a/core/cds/src/cds_utils.c +++ b/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; diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index a52bc2d9dd80..2b272e3d3ca2 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/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 diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index b62923e31c91..ceb21734f77c 100644 --- a/core/mac/inc/sir_api.h +++ b/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 diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index bbef6cad952f..668b3700db8e 100644 --- a/core/sme/inc/csr_api.h +++ b/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; diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index c4eb5ea257e6..2dd264655bdc 100644 --- a/core/sme/inc/csr_internal.h +++ b/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 */ diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 3a06d55dcf2a..da177d66d690 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/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)); diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index a80887894351..69aba4c84d06 100644 --- a/core/wma/inc/wma_api.h +++ b/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 diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index d1cb9f37c658..41843c27859d 100644 --- a/core/wma/src/wma_main.c +++ b/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