qcacld-3.0: Fill correct txpower information

As a part of 802.11ax amendment, 6GHz band operation is added.
Since the 6 GHz channel numbers are overlapping with existing 2.4GHz
and 5GHz channel numbers, use frequency to identify unique channel
operation instead of channel number. Channel frequency is unique across
bands.

As a part of above requirement frequency attribute is added to the
struct sSirMacChanInfo, in driver some APIs directly copies this
structure info considering as every member of the structure as uint8_t,
as frequency is uint32_t this breaks above asumption and results into
corrupt info and gives undefined behaviour.

To address above issue, use the structure members individually and
give the information by member-by-member copy.

Change-Id: Ied6ad30d8a0800211f99371969ddd192ff40545c
CRs-Fixed: 2537975
This commit is contained in:
Ashish Kumar Dhanotiya 2019-09-19 18:06:30 +05:30 committed by nshrivas
parent 3548a66560
commit b035570f53
10 changed files with 272 additions and 69 deletions

View File

@ -1710,17 +1710,17 @@ static void mlme_init_power_cfg(struct wlan_objmgr_psoc *psoc,
power->tx_power_2g = cfg_get(psoc, CFG_SET_TXPOWER_LIMIT2G);
power->tx_power_5g = cfg_get(psoc, CFG_SET_TXPOWER_LIMIT5G);
power->max_tx_power_24.max_len = CFG_MAX_TX_POWER_2_4_LEN;
power->max_tx_power_24_chan.max_len = CFG_MAX_TX_POWER_2_4_LEN;
qdf_uint8_array_parse(cfg_default(CFG_MAX_TX_POWER_2_4),
power->max_tx_power_24.data,
sizeof(power->max_tx_power_24.data),
&power->max_tx_power_24.len);
power->max_tx_power_24_chan.data,
sizeof(power->max_tx_power_24_chan.data),
&power->max_tx_power_24_chan.len);
power->max_tx_power_5.max_len = CFG_MAX_TX_POWER_5_LEN;
power->max_tx_power_5_chan.max_len = CFG_MAX_TX_POWER_5_LEN;
qdf_uint8_array_parse(cfg_default(CFG_MAX_TX_POWER_5),
power->max_tx_power_5.data,
sizeof(power->max_tx_power_5.data),
&power->max_tx_power_5.len);
power->max_tx_power_5_chan.data,
sizeof(power->max_tx_power_5_chan.data),
&power->max_tx_power_5_chan.len);
power->power_usage.max_len = CFG_POWER_USAGE_MAX_LEN;
power->power_usage.len = CFG_POWER_USAGE_MAX_LEN;

View File

@ -29,6 +29,9 @@
* @Min: 0 minimum length of tx power
* @Max: default data length of tx power in string format
* @Default: 1, 14, 20
*
* This ini contains the string in the form of first_channel number,
* number of channels and max tx power triplets
*/
#define CFG_MAX_TX_POWER_2_4_DATA "1, 14, 20"
#define CFG_MAX_TX_POWER_2_4 CFG_STRING( \
@ -44,6 +47,9 @@
* @Min: 0 minimum length of tx power
* @Max: default data length of tx power in string format
* @Default: 36, 126, 20
*
* This ini contains the string in the form of first_channel number,
* number of channels and max tx power triplets
*/
#define CFG_MAX_TX_POWER_5_DATA "36, 126, 20"
#define CFG_MAX_TX_POWER_5 CFG_STRING( \

View File

@ -54,7 +54,7 @@
#define CFG_STR_DATA_LEN 17
#define CFG_EDCA_DATA_LEN 17
#define CFG_MAX_TX_POWER_2_4_LEN 128
#define CFG_MAX_TX_POWER_5_LEN 128
#define CFG_MAX_TX_POWER_5_LEN 256
#define CFG_POWER_USAGE_MAX_LEN 4
#define CFG_MAX_STR_LEN 256
#define MAX_VENDOR_IES_LEN 1532
@ -1882,8 +1882,18 @@ struct mlme_power_usage {
/*
* struct wlan_mlme_power - power related config items
* @max_tx_power_24: max power Tx for 2.4 ghz
* @max_tx_power_5: max power Tx for 5 ghz
* @max_tx_power_24: max power Tx for 2.4 ghz, this is based on frequencies
* @max_tx_power_5: max power Tx for 5 ghz, this is based on frequencies
* @max_tx_power_24_chan: max power Tx for 2.4 ghz, this is based on channel
* numbers, this is added to parse the ini values to maintain the backward
* compatibility, these channel numbers are converted to frequencies and copied
* to max_tx_power_24 structure, once this conversion is done this structure
* should not be used.
* @max_tx_power_5_chan: max power Tx for 5 ghz, this is based on channel
* numbers, this is added to parse the ini values to maintain the backward
* compatibility, these channel numbers are converted to frequencies and copied
* to max_tx_power_24 structure, once this conversion is done this structure
* should not be used.
* @power_usage: power usage mode, min, max, mod
* @tx_power_2g: limit tx power in 2.4 ghz
* @tx_power_5g: limit tx power in 5 ghz
@ -1894,6 +1904,8 @@ struct mlme_power_usage {
struct wlan_mlme_power {
struct mlme_max_tx_power_24 max_tx_power_24;
struct mlme_max_tx_power_5 max_tx_power_5;
struct mlme_max_tx_power_24 max_tx_power_24_chan;
struct mlme_max_tx_power_5 max_tx_power_5_chan;
struct mlme_power_usage power_usage;
uint8_t tx_power_2g;
uint8_t tx_power_5g;

View File

@ -101,6 +101,17 @@ QDF_STATUS ucfg_mlme_global_init(void);
*/
QDF_STATUS ucfg_mlme_global_deinit(void);
/**
* ucfg_mlme_cfg_chan_to_freq() - convert channel numbers to frequencies
* @pdev: pointer to pdev object
*
* convert the channels numbers received as part of cfg items to
* frequencies.
*
* Return: None
*/
void ucfg_mlme_cfg_chan_to_freq(struct wlan_objmgr_pdev *pdev);
/**
* wlan_mlme_get_power_usage() - Get the power usage info
* @psoc: pointer to psoc object

View File

@ -155,6 +155,104 @@ QDF_STATUS ucfg_mlme_pdev_close(struct wlan_objmgr_pdev *pdev)
return QDF_STATUS_SUCCESS;
}
/**
* ucfg_mlme_convert_power_cfg_chan_to_freq() - converts channel numbers to
* frequencies and copies the triplets to power_freq_data array
* @pdev: pointer to pdev object
* @max_length: Max length of the power chan data array
* @length: length of the data present in power_chan_data array
* @power_chan_data: Power data array from which channel numbers needs to be
* converted to frequencies
* @power_freq_data: Power data array in which the power data needs to be copied
* after conversion of channel numbers to frequencies
*
* power_data is received in the form of (first_channel_number,
* number_of_channels, max_tx_power) triplet, convert the channel numbers from
* the power_chan_data array to frequencies and copy the triplets
* (first_frequency, number_of_channels, max_tx_power) values to
* the power_freq_data array
*
* Return: Number of bytes filled in power_freq_data
*/
static uint32_t ucfg_mlme_convert_power_cfg_chan_to_freq(
struct wlan_objmgr_pdev *pdev,
uint32_t max_length,
qdf_size_t length,
uint8_t *power_chan_data,
uint8_t *power_freq_data)
{
uint32_t count = 0, rem_length = length, copied_length = 0, i = 0;
tSirMacChanInfo *pwr_cfg_data;
pwr_cfg_data = qdf_mem_malloc(max_length);
if (!pwr_cfg_data)
return 0;
mlme_legacy_debug("max_length %d length %zu", max_length, length);
while ((rem_length >= 3) &&
(copied_length <= (max_length - (sizeof(tSirMacChanInfo))))) {
pwr_cfg_data[i].first_freq = wlan_reg_chan_to_freq(
pdev,
power_chan_data[count++]);
pwr_cfg_data[i].numChannels = power_chan_data[count++];
pwr_cfg_data[i].maxTxPower = power_chan_data[count++];
copied_length += sizeof(tSirMacChanInfo);
rem_length -= 3;
mlme_legacy_debug("First freq %d num channels %d max tx power %d",
pwr_cfg_data[i].first_freq,
pwr_cfg_data[i].numChannels,
pwr_cfg_data[i].maxTxPower);
i++;
}
qdf_mem_zero(power_freq_data, max_length);
qdf_mem_copy(power_freq_data, pwr_cfg_data, copied_length);
qdf_mem_free(pwr_cfg_data);
return copied_length;
}
void ucfg_mlme_cfg_chan_to_freq(struct wlan_objmgr_pdev *pdev)
{
struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
struct wlan_mlme_psoc_obj *mlme_obj;
struct wlan_mlme_cfg *mlme_cfg;
uint32_t converted_data_len = 0;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj)
return;
mlme_cfg = &mlme_obj->cfg;
mlme_cfg->power.max_tx_power_24.max_len = CFG_MAX_TX_POWER_2_4_LEN;
converted_data_len = ucfg_mlme_convert_power_cfg_chan_to_freq(
pdev,
mlme_cfg->power.max_tx_power_24_chan.max_len,
mlme_cfg->power.max_tx_power_24_chan.len,
mlme_cfg->power.max_tx_power_24_chan.data,
mlme_cfg->power.max_tx_power_24.data);
if (!converted_data_len) {
mlme_legacy_err("mlme cfg power 2_4 data chan number to freq failed");
return;
}
mlme_cfg->power.max_tx_power_24.len = converted_data_len;
mlme_cfg->power.max_tx_power_5.max_len = CFG_MAX_TX_POWER_5_LEN;
converted_data_len = ucfg_mlme_convert_power_cfg_chan_to_freq(
pdev,
mlme_cfg->power.max_tx_power_5_chan.max_len,
mlme_cfg->power.max_tx_power_5_chan.len,
mlme_cfg->power.max_tx_power_5_chan.data,
mlme_cfg->power.max_tx_power_5.data);
if (!converted_data_len) {
mlme_legacy_err("mlme cfg power 5 data chan number to freq failed");
return;
}
mlme_cfg->power.max_tx_power_5.len = converted_data_len;
}
QDF_STATUS
ucfg_mlme_get_sta_keep_alive_period(struct wlan_objmgr_psoc *psoc,
uint32_t *val)

View File

@ -2020,6 +2020,11 @@ static void hdd_update_wiphy_he_cap(struct hdd_context *hdd_ctx)
}
#endif
static void hdd_component_cfg_chan_to_freq(struct wlan_objmgr_pdev *pdev)
{
ucfg_mlme_cfg_chan_to_freq(pdev);
}
int hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
{
int ret;
@ -2063,6 +2068,11 @@ int hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
ret = qdf_status_to_os_return(status);
goto dispatcher_close;
}
/*
* For 6GHz support this api is added to convert mlme cfgs
* channel numbers to frequency
*/
hdd_component_cfg_chan_to_freq(hdd_ctx->pdev);
cdp_pdev_set_ctrl_pdev(cds_get_context(QDF_MODULE_ID_SOC),
cds_get_context(QDF_MODULE_ID_TXRX),

View File

@ -8227,10 +8227,11 @@ lim_get_dot11d_transmit_power(struct mac_context *mac, uint8_t channel)
{
uint32_t cfg_length = 0;
int8_t max_tx_pwr = 0;
uint8_t *country_info = NULL;
tSirMacChanInfo *country_info = NULL;
uint8_t count = 0;
uint8_t first_channel;
uint8_t maxChannels;
int32_t rem_length = 0;
if (WLAN_REG_IS_5GHZ_CH(channel))
cfg_length = mac->mlme_cfg->power.max_tx_power_5.len;
@ -8258,10 +8259,15 @@ lim_get_dot11d_transmit_power(struct mac_context *mac, uint8_t channel)
}
/* Identify the channel and maxtxpower */
while (count <= (cfg_length - (sizeof(tSirMacChanInfo)))) {
first_channel = country_info[count++];
maxChannels = country_info[count++];
max_tx_pwr = country_info[count++];
rem_length = cfg_length;
while (rem_length >= (sizeof(tSirMacChanInfo))) {
first_channel = wlan_reg_freq_to_chan(
mac->pdev,
country_info[count].first_freq);
maxChannels = country_info[count].numChannels;
max_tx_pwr = country_info[count].maxTxPower;
count++;
rem_length -= (sizeof(tSirMacChanInfo));
if ((channel >= first_channel) &&
(channel < (first_channel + maxChannels))) {

View File

@ -385,52 +385,80 @@ QDF_STATUS
populate_dot11f_country(struct mac_context *mac,
tDot11fIECountry *pDot11f, struct pe_session *pe_session)
{
uint32_t len;
uint32_t len, j = 0;
enum band_info rfBand;
uint8_t temp[CFG_MAX_STR_LEN], code[3];
tSirMacChanInfo *max_tx_power_data;
uint32_t rem_length = 0, copied_length = 0;
if (pe_session->lim11dEnabled) {
lim_get_rf_band_new(mac, &rfBand, pe_session);
if (rfBand == BAND_5G) {
len = mac->mlme_cfg->power.max_tx_power_5.len;
qdf_mem_copy(temp,
mac->mlme_cfg->power.max_tx_power_5.data,
len);
} else {
len = mac->mlme_cfg->power.max_tx_power_24.len;
qdf_mem_copy(temp,
mac->mlme_cfg->power.max_tx_power_24.data,
len);
if (!pe_session->lim11dEnabled)
return QDF_STATUS_SUCCESS;
lim_get_rf_band_new(mac, &rfBand, pe_session);
if (rfBand == BAND_5G) {
len = mac->mlme_cfg->power.max_tx_power_5.len;
max_tx_power_data =
(tSirMacChanInfo *)mac->mlme_cfg->power.max_tx_power_5.data;
rem_length = len;
while (rem_length >= (sizeof(tSirMacChanInfo))) {
temp[copied_length++] =
(uint8_t)wlan_reg_freq_to_chan(
mac->pdev,
max_tx_power_data[j].first_freq);
temp[copied_length++] =
max_tx_power_data[j].numChannels;
temp[copied_length++] =
max_tx_power_data[j].maxTxPower;
j++;
rem_length -= (sizeof(tSirMacChanInfo));
}
if (3 > len) {
/* no limit on tx power, cannot include the IE because at least */
/* one (channel,num,tx power) must be present */
return QDF_STATUS_SUCCESS;
} else {
len = mac->mlme_cfg->power.max_tx_power_24.len;
max_tx_power_data =
(tSirMacChanInfo *)mac->mlme_cfg->power.max_tx_power_24.data;
rem_length = len;
while (rem_length >= (sizeof(tSirMacChanInfo))) {
temp[copied_length++] =
(uint8_t)wlan_reg_freq_to_chan(
mac->pdev,
max_tx_power_data[j].first_freq);
temp[copied_length++] =
max_tx_power_data[j].numChannels;
temp[copied_length++] =
max_tx_power_data[j].maxTxPower;
j++;
rem_length -= (sizeof(tSirMacChanInfo));
}
wlan_reg_read_current_country(mac->psoc, code);
qdf_mem_copy(pDot11f->country, code, 2);
/* a wi-fi agile multiband AP shall include a country */
/* element in all beacon and probe response frames */
/* where the last octet of country string field is */
/* set to 0x04 */
if (mac->mlme_cfg->oce.oce_sap_enabled)
pDot11f->country[2] = 0x04;
if (len > MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE) {
pe_err("len:%d is out of bounds, resetting", len);
len = MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE;
}
pDot11f->num_triplets = (uint8_t) (len / 3);
qdf_mem_copy((uint8_t *) pDot11f->triplets, temp, len);
pDot11f->present = 1;
}
if (sizeof(tSirMacChanInfo) > len) {
/* no limit on tx power, cannot include the IE because at */
/* atleast one (channel,num,tx power) must be present */
return QDF_STATUS_SUCCESS;
}
wlan_reg_read_current_country(mac->psoc, code);
qdf_mem_copy(pDot11f->country, code, 2);
/* a wi-fi agile multiband AP shall include a country */
/* element in all beacon and probe response frames */
/* where the last octet of country string field is */
/* set to 0x04 */
if (mac->mlme_cfg->oce.oce_sap_enabled)
pDot11f->country[2] = 0x04;
if (copied_length > MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE) {
pe_err("len:%d is out of bounds, resetting", len);
copied_length = MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE;
}
pDot11f->num_triplets = (uint8_t)(copied_length / 3);
qdf_mem_copy((uint8_t *)pDot11f->triplets, temp, copied_length);
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_country. */
@ -5882,8 +5910,10 @@ QDF_STATUS
populate_dot11f_timing_advert_frame(struct mac_context *mac_ctx,
tDot11fTimingAdvertisementFrame *frame)
{
uint32_t val, len;
uint32_t val, len, j = 0;
uint8_t temp[CFG_MAX_STR_LEN], code[3];
tSirMacChanInfo *max_tx_power_data;
int32_t rem_length = 0, copied_length = 0;
/* Capabilities */
val = mac_ctx->mlme_cfg->wep_params.is_privacy_enabled;
@ -5910,14 +5940,28 @@ populate_dot11f_timing_advert_frame(struct mac_context *mac_ctx,
/* Country */
len = mac_ctx->mlme_cfg->power.max_tx_power_5.len;
qdf_mem_copy(temp, mac_ctx->mlme_cfg->power.max_tx_power_5.data, len);
max_tx_power_data =
(tSirMacChanInfo *)mac_ctx->mlme_cfg->power.max_tx_power_5.data;
rem_length = len;
while (rem_length >= (sizeof(tSirMacChanInfo))) {
temp[copied_length++] =
(uint8_t)wlan_reg_freq_to_chan(
mac_ctx->pdev,
max_tx_power_data[j].first_freq);
temp[copied_length++] = max_tx_power_data[j].numChannels;
temp[copied_length++] = max_tx_power_data[j].maxTxPower;
j++;
rem_length -= (sizeof(tSirMacChanInfo));
}
wlan_reg_read_current_country(mac_ctx->psoc, code);
qdf_mem_copy(&frame->Country, code, 2);
if (len > MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE)
len = MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE;
if (copied_length > MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE)
copied_length = MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE;
frame->Country.num_triplets = (uint8_t)(len / 3);
qdf_mem_copy((uint8_t *)&frame->Country.triplets, temp, len);
frame->Country.num_triplets = (uint8_t)(copied_length / 3);
qdf_mem_copy((uint8_t *)&frame->Country.triplets, temp, copied_length);
frame->Country.present = 1;
/* PowerConstraints */

View File

@ -13647,10 +13647,11 @@ int8_t csr_get_cfg_max_tx_power(struct mac_context *mac, uint8_t channel)
{
uint32_t cfg_length = 0;
int8_t maxTxPwr = 0;
uint8_t *pCountryInfo = NULL;
tSirMacChanInfo *pCountryInfo = NULL;
uint8_t count = 0;
uint8_t firstChannel;
uint8_t maxChannels;
uint8_t firstChannel;
int32_t rem_length = 0;
if (WLAN_REG_IS_5GHZ_CH(channel)) {
cfg_length = mac->mlme_cfg->power.max_tx_power_5.len;
@ -13679,10 +13680,15 @@ int8_t csr_get_cfg_max_tx_power(struct mac_context *mac, uint8_t channel)
}
/* Identify the channel and maxtxpower */
while (count <= (cfg_length - (sizeof(tSirMacChanInfo)))) {
firstChannel = pCountryInfo[count++];
maxChannels = pCountryInfo[count++];
maxTxPwr = pCountryInfo[count++];
rem_length = cfg_length;
while (rem_length >= (sizeof(tSirMacChanInfo))) {
firstChannel = wlan_reg_freq_to_chan(
mac->pdev,
pCountryInfo[count].first_freq);
maxChannels = pCountryInfo[count].numChannels;
maxTxPwr = pCountryInfo[count].maxTxPower;
count++;
rem_length -= (sizeof(tSirMacChanInfo));
if ((channel >= firstChannel) &&
(channel < (firstChannel + maxChannels))) {

View File

@ -1582,13 +1582,23 @@ static void csr_save_tx_power_to_cfg(struct mac_context *mac,
pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_LOCK);
}
if (band == BAND_2G) {
mac->mlme_cfg->power.max_tx_power_24.len = 3 * count;
mac->mlme_cfg->power.max_tx_power_24.len =
sizeof(tSirMacChanInfo) * count;
if (mac->mlme_cfg->power.max_tx_power_24.len >
CFG_MAX_TX_POWER_2_4_LEN)
mac->mlme_cfg->power.max_tx_power_24.len =
CFG_MAX_TX_POWER_2_4_LEN;
qdf_mem_copy(mac->mlme_cfg->power.max_tx_power_24.data,
(uint8_t *)p_buf,
mac->mlme_cfg->power.max_tx_power_24.len);
}
if (band == BAND_5G) {
mac->mlme_cfg->power.max_tx_power_5.len = 3 * count;
mac->mlme_cfg->power.max_tx_power_5.len =
sizeof(tSirMacChanInfo) * count;
if (mac->mlme_cfg->power.max_tx_power_5.len >
CFG_MAX_TX_POWER_5_LEN)
mac->mlme_cfg->power.max_tx_power_5.len =
CFG_MAX_TX_POWER_5_LEN;
qdf_mem_copy(mac->mlme_cfg->power.max_tx_power_5.data,
(uint8_t *)p_buf,
mac->mlme_cfg->power.max_tx_power_5.len);