diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h index 11012ed0cd..02d307ad00 100644 --- a/core/mac/inc/sir_mac_prot_def.h +++ b/core/mac/inc/sir_mac_prot_def.h @@ -977,6 +977,15 @@ typedef struct sSirMacRateSet { uint8_t rate[SIR_MAC_RATESET_EID_MAX]; } qdf_packed tSirMacRateSet; +/** struct merged_mac_rate_set - merged mac rate set + * @num_rates: num of rates + * @rate: rate list + */ +struct merged_mac_rate_set { + uint8_t num_rates; + uint8_t rate[2 * SIR_MAC_RATESET_EID_MAX]; +}; + typedef struct sSirMacSSid { uint8_t length; uint8_t ssId[SIR_MAC_MAX_SSID_LENGTH]; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 0ba4d54d13..8331c8b0a6 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -12912,41 +12912,105 @@ csr_convert_mode_to_nw_type(eCsrCfgDot11Mode dot11_mode, eCsrBand band) } /** - * csr_populate_supported_rates_from_hostapd() - populates operational - * and extended rates. - * from hostapd.conf file - * @opr_rates: rate struct to populate operational rates - * @ext_rates: rate struct to populate extended rates - * @profile: bss profile + * csr_merge_supported_and_extended_rates() - merge supported rates and + * extended rates + * @rates: merged rates + * @supported_rates: supported rates + * @extended_rates: extended rates * - * Return: void + * Return: None */ -static void csr_populate_supported_rates_from_hostapd(tSirMacRateSet *opr_rates, - tSirMacRateSet *ext_rates, - tCsrRoamProfile *pProfile) +static void csr_merge_supported_and_extended_rates( + struct merged_mac_rate_set *rates, + tSirMacRateSet *supported_rates, + tSirMacRateSet *extended_rates) { - int i = 0; + int i; - if (pProfile->supported_rates.numRates) { - opr_rates->numRates = pProfile->supported_rates.numRates; - qdf_mem_copy(opr_rates->rate, - pProfile->supported_rates.rate, - pProfile->supported_rates.numRates); - for (i = 0; i < opr_rates->numRates; i++) - QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, - ("Supported Rate is %2x"), opr_rates->rate[i]); + qdf_mem_copy(rates->rate, + supported_rates->rate, + supported_rates->numRates); + rates->num_rates = supported_rates->numRates; + + qdf_mem_copy(rates->rate + rates->num_rates, + extended_rates->rate, + extended_rates->numRates); + rates->num_rates += extended_rates->numRates; + + for (i = 0; i < rates->num_rates; i++) + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, + FL("Merge rate is %2x"), rates->rate[i]); +} + +/** + * csr_populate_intersection_driver_and_hostpd_rates() - populate + * intersection of driver rates and hostapd rates + * @pParam: csr roam start bss params + * @driver_rates: rates generated by driver + * @hostapd_rates: rates generated by hostapd + * + * Return: None + */ +static void csr_populate_intersection_driver_and_hostpd_rates( + struct tagCsrRoamStartBssParams *param, + struct merged_mac_rate_set *driver_rates, + struct merged_mac_rate_set *hostapd_rates) +{ + int i, j; + struct merged_mac_rate_set rates; + uint8_t driver_rate, hostapd_rate; + tSirMacRateSet *opr_rates = ¶m->operationalRateSet; + tSirMacRateSet *ext_rates = ¶m->extendedRateSet; + + rates.num_rates = 0; + + for (i = 0; i < driver_rates->num_rates; i++) { + driver_rate = driver_rates->rate[i]; + if (CSR_IS_BASIC_RATE(driver_rate)) + BITS_OFF(driver_rate, + CSR_DOT11_BASIC_RATE_MASK); + + for (j = 0; j < hostapd_rates->num_rates; j++) { + hostapd_rate = hostapd_rates->rate[j]; + if (CSR_IS_BASIC_RATE(hostapd_rate)) + BITS_OFF(hostapd_rate, + CSR_DOT11_BASIC_RATE_MASK); + + if (driver_rate == hostapd_rate) { + if (CSR_IS_BASIC_RATE(driver_rates->rate[i]) || + CSR_IS_BASIC_RATE(hostapd_rates->rate[j])) + BITS_ON(driver_rate, + CSR_DOT11_BASIC_RATE_MASK); + + rates.rate[rates.num_rates++] = driver_rate; + break; + } + } } - if (pProfile->extended_rates.numRates) { - ext_rates->numRates = - pProfile->extended_rates.numRates; + + for (i = 0; i < rates.num_rates; i++) + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, + FL("Intersection rate is %2x"), rates.rate[i]); + + opr_rates->numRates = 0; + ext_rates->numRates = 0; + if (rates.num_rates <= MAX_NUM_SUPPORTED_RATES) { + opr_rates->numRates = rates.num_rates; + qdf_mem_copy(opr_rates->rate, + rates.rate, + opr_rates->numRates); + } else { + opr_rates->numRates = MAX_NUM_SUPPORTED_RATES; + qdf_mem_copy(opr_rates->rate, + rates.rate, + MAX_NUM_SUPPORTED_RATES); + ext_rates->numRates = rates.num_rates - MAX_NUM_SUPPORTED_RATES; qdf_mem_copy(ext_rates->rate, - pProfile->extended_rates.rate, - pProfile->extended_rates.numRates); - for (i = 0; i < ext_rates->numRates; i++) - QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, - ("Extended Rate is %2x"), ext_rates->rate[i]); + rates.rate + MAX_NUM_SUPPORTED_RATES, + ext_rates->numRates); } } + /** * csr_roam_get_bss_start_parms() - get bss start param from profile * @pMac: mac global context @@ -12990,20 +13054,8 @@ csr_roam_get_bss_start_parms(tpAniSirGlobal pMac, nw_type = csr_convert_mode_to_nw_type(pParam->uCfgDot11Mode, band); ext_rates->numRates = 0; - /* - * hostapd.conf will populate its basic and extended rates - * as per hw_mode but if acs in ini is enabled, driver should - * ignore basic and extended rates from hostapd.conf and should - * populate default rates. - */ - if (!cds_is_sub_20_mhz_enabled() && !skip_hostapd_rate && - (pProfile->supported_rates.numRates || - pProfile->extended_rates.numRates)) { - csr_populate_supported_rates_from_hostapd(opr_rates, - ext_rates, pProfile); - pParam->operationChn = tmp_opr_ch; - } else { - switch (nw_type) { + + switch (nw_type) { default: sme_err( "sees an unknown pSirNwType (%d)", @@ -13061,7 +13113,30 @@ csr_roam_get_bss_start_parms(tpAniSirGlobal pMac, break; } pParam->operationChn = opr_ch; + + if (pProfile->supported_rates.numRates || + pProfile->extended_rates.numRates) { + struct merged_mac_rate_set rates_driver, rates_hostapd; + + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, + "Merge rates driver"); + csr_merge_supported_and_extended_rates(&rates_driver, + opr_rates, + ext_rates); + + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, + "Merge rates hostapd"); + csr_merge_supported_and_extended_rates(&rates_hostapd, + &pProfile->supported_rates, + &pProfile->extended_rates); + + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, + "Populate rates intersection"); + csr_populate_intersection_driver_and_hostpd_rates(pParam, + &rates_driver, + &rates_hostapd); } + pParam->sirNwType = nw_type; pParam->ch_params.ch_width = pProfile->ch_params.ch_width; pParam->ch_params.center_freq_seg0 =