diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 14a5f860d63e..45e37f8b0f94 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -47,6 +47,51 @@ #define CONNECTION_UPDATE_TIMEOUT 1000 #endif +/* Some max value greater than the max length of the channel list */ +#define MAX_WEIGHT_OF_PCL_CHANNELS 255 +/* Some fixed weight difference between the groups */ +#define PCL_GROUPS_WEIGHT_DIFFERENCE 20 + +/* Currently max, only 3 groups are possible as per 'enum cds_pcl_type'. + * i.e., in a PCL only 3 groups of channels can be present + * e.g., SCC channel on 2.4 Ghz, SCC channel on 5 Ghz & 5 Ghz channels. + * Group 1 has highest priority, group 2 has the next higher priority + * and so on. + */ +#define WEIGHT_OF_GROUP1_PCL_CHANNELS MAX_WEIGHT_OF_PCL_CHANNELS +#define WEIGHT_OF_GROUP2_PCL_CHANNELS \ + (WEIGHT_OF_GROUP1_PCL_CHANNELS - PCL_GROUPS_WEIGHT_DIFFERENCE) +#define WEIGHT_OF_GROUP3_PCL_CHANNELS \ + (WEIGHT_OF_GROUP2_PCL_CHANNELS - PCL_GROUPS_WEIGHT_DIFFERENCE) + +#define WEIGHT_OF_NON_PCL_CHANNELS 1 + +/** + * enum cds_pcl_group_id - Identifies the pcl groups to be used + * @CDS_PCL_GROUP_ID1_ID2: Use weights of group1 and group2 + * @CDS_PCL_GROUP_ID2_ID2: Use weights of group2 and group3 + * + * Since maximum of three groups are possible, this will indicate which + * PCL group needs to be used. + */ +enum cds_pcl_group_id { + CDS_PCL_GROUP_ID1_ID2, + CDS_PCL_GROUP_ID2_ID3, +}; + +/** + * cds_pcl_channel_order - Order in which the PCL is requested + * @CDS_PCL_ORDER_NONE: no order + * @CDS_PCL_ORDER_24G_THEN_5G: 2.4 Ghz channel followed by 5 Ghz channel + * @CDS_PCL_ORDER_5G_THEN_2G: 5 Ghz channel followed by 2.4 Ghz channel + * + * Order in which the PCL is requested + */ +enum cds_pcl_channel_order { + CDS_PCL_ORDER_NONE, + CDS_PCL_ORDER_24G_THEN_5G, + CDS_PCL_ORDER_5G_THEN_2G, +}; /** * enum cds_max_rx_ss - Maximum number of receive spatial streams @@ -588,7 +633,8 @@ void cds_decr_session_set_pcl(enum tQDF_ADAPTER_MODE mode, QDF_STATUS cds_init_policy_mgr(void); QDF_STATUS cds_deinit_policy_mgr(void); QDF_STATUS cds_get_pcl(enum cds_con_mode mode, - uint8_t *pcl_Channels, uint32_t *len); + uint8_t *pcl_channels, uint32_t *len, + uint8_t *pcl_weight, uint32_t weight_len); uint8_t cds_get_nondfs_preferred_channel(enum cds_con_mode mode, bool for_existing_conn); bool cds_is_any_nondfs_chnl_present(uint8_t *channel); @@ -697,5 +743,7 @@ QDF_STATUS cds_register_sap_restart_channel_switch_cb( void (*sap_restart_chan_switch_cb)(void *, uint32_t, uint32_t)); #endif QDF_STATUS cds_get_pcl_for_existing_conn(enum cds_con_mode mode, - uint8_t *pcl_ch, uint32_t *len); + uint8_t *pcl_ch, uint32_t *len, + uint8_t *weight_list, uint32_t weight_len); +QDF_STATUS cds_get_valid_chan_weights(struct sir_pcl_chan_weights *weight); #endif /* __CDS_CONCURRENCY_H */ diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 2e8d9002b8ed..f211ace0dfc5 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -3438,16 +3438,16 @@ void cds_clear_concurrency_mode(enum tQDF_ADAPTER_MODE mode) } /** - * cds_soc_set_pcl() - Sets PCL to FW + * cds_pdev_set_pcl() - Sets PCL to FW * @mode: adapter mode * * Fetches the PCL and sends the PCL to SME * module which in turn will send the WMI - * command WMI_SOC_SET_PCL_CMDID to the fw + * command WMI_PDEV_SET_PCL_CMDID to the fw * * Return: None */ -static void cds_soc_set_pcl(enum tQDF_ADAPTER_MODE mode) +static void cds_pdev_set_pcl(enum tQDF_ADAPTER_MODE mode) { QDF_STATUS status; enum cds_con_mode con_mode; @@ -3485,13 +3485,14 @@ static void cds_soc_set_pcl(enum tQDF_ADAPTER_MODE mode) cds_debug("get pcl to set it to the FW"); status = cds_get_pcl(con_mode, - pcl.pcl_list, &pcl.pcl_len); + pcl.pcl_list, &pcl.pcl_len, + pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list)); if (status != QDF_STATUS_SUCCESS) { cds_err("Unable to set PCL to FW, Get PCL failed"); return; } - status = sme_soc_set_pcl(hdd_ctx->hHal, pcl); + status = sme_pdev_set_pcl(hdd_ctx->hHal, pcl); if (status != QDF_STATUS_SUCCESS) cds_err("Send soc set PCL to SME failed"); else @@ -3552,7 +3553,7 @@ void cds_incr_active_session(enum tQDF_ADAPTER_MODE mode, */ if (mode == QDF_STA_MODE) { /* Set PCL of STA to the FW */ - cds_soc_set_pcl(mode); + cds_pdev_set_pcl(mode); cds_info("Set PCL of STA to FW"); } cds_incr_connection_count(session_id); @@ -3671,7 +3672,7 @@ static void cds_set_pcl_for_existing_combo(enum cds_con_mode mode) /* Check, store and temp delete the mode's parameter */ cds_store_and_del_conn_info(mode, &info); /* Set the PCL to the FW since connection got updated */ - cds_soc_set_pcl(pcl_mode); + cds_pdev_set_pcl(pcl_mode); cds_info("Set PCL to FW for mode:%d", mode); /* Restore the connection info */ cds_restore_deleted_conn_info(&info); @@ -3681,13 +3682,18 @@ static void cds_set_pcl_for_existing_combo(enum cds_con_mode mode) /** * cds_get_pcl_for_existing_conn() - Get PCL for existing connection * @mode: Connection mode of type 'cds_con_mode' + * @pcl_ch: Pointer to the PCL + * @len: Pointer to the length of the PCL + * @pcl_weight: Pointer to the weights of the PCL + * @weight_len: Max length of the weights list * * Get the PCL for an existing connection * * Return: None */ QDF_STATUS cds_get_pcl_for_existing_conn(enum cds_con_mode mode, - uint8_t *pcl_ch, uint32_t *len) + uint8_t *pcl_ch, uint32_t *len, + uint8_t *pcl_weight, uint32_t weight_len) { struct cds_conc_connection_info info; @@ -3703,7 +3709,7 @@ QDF_STATUS cds_get_pcl_for_existing_conn(enum cds_con_mode mode, /* Check, store and temp delete the mode's parameter */ cds_store_and_del_conn_info(mode, &info); /* Set the PCL to the FW since connection got updated */ - status = cds_get_pcl(mode, pcl_ch, len); + status = cds_get_pcl(mode, pcl_ch, len, pcl_weight, weight_len); cds_info("Get PCL to FW for mode:%d", mode); /* Restore the connection info */ cds_restore_deleted_conn_info(&info); @@ -4289,6 +4295,10 @@ QDF_STATUS cds_decr_connection_count(uint32_t vdev_id) * @order: no order OR 2.4 Ghz channel followed by 5 Ghz * channel OR 5 Ghz channel followed by 2.4 Ghz channel * @skip_dfs_channel: if this flag is true then skip the dfs channel + * @pcl_weight: Pointer to the weights of PCL + * @weight_len: Max length of the weight list + * @index: Index from which the weight list needs to be populated + * @group_id: Next available groups for weight assignment * * * This function provides the channel(s) on which current @@ -4297,11 +4307,14 @@ QDF_STATUS cds_decr_connection_count(uint32_t vdev_id) * Return: QDF_STATUS */ QDF_STATUS cds_get_connection_channels(uint8_t *channels, - uint32_t *len, uint8_t order, - bool skip_dfs_channel) + uint32_t *len, enum cds_pcl_channel_order order, + bool skip_dfs_channel, + uint8_t *pcl_weight, uint32_t weight_len, + uint32_t *index, enum cds_pcl_group_id group_id) { QDF_STATUS status = QDF_STATUS_SUCCESS; uint32_t conn_index = 0, num_channels = 0; + uint32_t weight1, weight2; if ((NULL == channels) || (NULL == len)) { cds_err("channels or len is NULL"); @@ -4309,58 +4322,99 @@ QDF_STATUS cds_get_connection_channels(uint8_t *channels, return status; } - if (0 == order) { + /* CDS_PCL_GROUP_ID1_ID2 indicates that all three weights are + * available for assignment. i.e., WEIGHT_OF_GROUP1_PCL_CHANNELS, + * WEIGHT_OF_GROUP2_PCL_CHANNELS and WEIGHT_OF_GROUP3_PCL_CHANNELS + * are all available. Since in this function only two weights are + * assigned at max, only group1 and group2 weights are considered. + * + * The other possible group id CDS_PCL_GROUP_ID2_ID3 indicates that + * group1 was assigned the weight WEIGHT_OF_GROUP1_PCL_CHANNELS and + * only weights WEIGHT_OF_GROUP2_PCL_CHANNELS and + * WEIGHT_OF_GROUP3_PCL_CHANNELS are available for further weight + * assignments. + * + * e.g., when order is CDS_PCL_ORDER_24G_THEN_5G and group id is + * CDS_PCL_GROUP_ID2_ID3, WEIGHT_OF_GROUP2_PCL_CHANNELS is assigned to + * 2.4GHz channels and the weight WEIGHT_OF_GROUP3_PCL_CHANNELS is + * assigned to the 5GHz channels. + */ + if (group_id == CDS_PCL_GROUP_ID1_ID2) { + weight1 = WEIGHT_OF_GROUP1_PCL_CHANNELS; + weight2 = WEIGHT_OF_GROUP2_PCL_CHANNELS; + } else { + weight1 = WEIGHT_OF_GROUP2_PCL_CHANNELS; + weight2 = WEIGHT_OF_GROUP3_PCL_CHANNELS; + } + + if (CDS_PCL_ORDER_NONE == order) { while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { if (skip_dfs_channel && CDS_IS_DFS_CH( - conc_connection_list[conn_index].chan)) + conc_connection_list[conn_index].chan)) { conn_index++; - else + } else { channels[num_channels++] = conc_connection_list[conn_index++].chan; + if (*index < weight_len) + pcl_weight[(*index)++] = weight1; + } } *len = num_channels; - } else if (1 == order) { + } else if (CDS_PCL_ORDER_24G_THEN_5G == order) { while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { if (CDS_IS_CHANNEL_24GHZ( - conc_connection_list[conn_index].chan)) + conc_connection_list[conn_index].chan)) { channels[num_channels++] = conc_connection_list[conn_index++].chan; - else + if (*index < weight_len) + pcl_weight[(*index)++] = weight1; + } else { conn_index++; + } } conn_index = 0; while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { if (skip_dfs_channel && CDS_IS_DFS_CH( - conc_connection_list[conn_index].chan)) + conc_connection_list[conn_index].chan)) { conn_index++; - else if (CDS_IS_CHANNEL_5GHZ( - conc_connection_list[conn_index].chan)) + } else if (CDS_IS_CHANNEL_5GHZ( + conc_connection_list[conn_index].chan)) { channels[num_channels++] = conc_connection_list[conn_index++].chan; - else + if (*index < weight_len) + pcl_weight[(*index)++] = weight2; + } else { conn_index++; + } } *len = num_channels; - } else if (2 == order) { + } else if (CDS_PCL_ORDER_5G_THEN_2G == order) { while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { if (skip_dfs_channel && CDS_IS_DFS_CH( - conc_connection_list[conn_index].chan)) + conc_connection_list[conn_index].chan)) { conn_index++; - else if (CDS_IS_CHANNEL_5GHZ( - conc_connection_list[conn_index].chan)) + } else if (CDS_IS_CHANNEL_5GHZ( + conc_connection_list[conn_index].chan)) { channels[num_channels++] = conc_connection_list[conn_index++].chan; - else + if (*index < weight_len) + pcl_weight[(*index)++] = weight1; + } else { conn_index++; + } } conn_index = 0; while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { if (CDS_IS_CHANNEL_24GHZ( - conc_connection_list[conn_index].chan)) + conc_connection_list[conn_index].chan)) { channels[num_channels++] = conc_connection_list[conn_index++].chan; - else + if (*index < weight_len) + pcl_weight[(*index)++] = weight2; + + } else { conn_index++; + } } *len = num_channels; } else { @@ -4376,6 +4430,8 @@ QDF_STATUS cds_get_connection_channels(uint8_t *channels, * channel list * @pcl_channels: channel list * @len: length of the list + * @weight_list: Weights of the PCL + * @weight_len: Max length of the weights list * * This function provides the safe channel list from the list * provided after consulting the channel avoidance list @@ -4383,10 +4439,12 @@ QDF_STATUS cds_get_connection_channels(uint8_t *channels, * Return: None */ #ifdef CONFIG_CNSS -void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len) +void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len, + uint8_t *weight_list, uint32_t weight_len) { uint16_t unsafe_channel_list[MAX_NUM_CHAN]; uint8_t current_channel_list[MAX_NUM_CHAN]; + uint8_t org_weight_list[MAX_NUM_CHAN]; uint16_t unsafe_channel_count = 0; uint8_t is_unsafe = 1; uint8_t i, j; @@ -4409,6 +4467,9 @@ void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len) qdf_mem_zero(pcl_channels, sizeof(*pcl_channels)*current_channel_count); + qdf_mem_copy(org_weight_list, weight_list, MAX_NUM_CHAN); + qdf_mem_zero(weight_list, weight_len); + for (i = 0; i < current_channel_count; i++) { is_unsafe = 0; for (j = 0; j < unsafe_channel_count; j++) { @@ -4424,6 +4485,9 @@ void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len) if (!is_unsafe) { pcl_channels[safe_channel_count++] = current_channel_list[i]; + if (safe_channel_count < weight_len) + weight_list[safe_channel_count++] = + org_weight_list[i]; } } *len = safe_channel_count; @@ -4431,7 +4495,8 @@ void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len) return; } #else -void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len) +void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len, + uint8_t *weight_list, uint32_t weight_len) { return; } @@ -4439,11 +4504,12 @@ void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len) /** * cds_get_channel_list() - provides the channel list * suggestion for new connection - * @hdd_ctx: HDD Context * @pcl: The preferred channel list enum * @pcl_channels: PCL channels * @len: length of the PCL * @mode: concurrency mode for which channel list is requested + * @pcl_weights: Weights of the PCL + * @weight_len: Max length of the weight list * * This function provides the actual channel list based on the * current regulatory domain derived using preferred channel @@ -4452,7 +4518,9 @@ void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len) * Return: Channel List */ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, - uint8_t *pcl_channels, uint32_t *len, enum cds_con_mode mode) + uint8_t *pcl_channels, uint32_t *len, + enum cds_con_mode mode, + uint8_t *pcl_weights, uint32_t weight_len) { QDF_STATUS status = QDF_STATUS_E_FAILURE; uint32_t num_channels = WNI_CFG_VALID_CHANNEL_LIST_LEN; @@ -4462,6 +4530,7 @@ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, uint8_t channel_list_5[MAX_NUM_CHAN] = {0}; bool skip_dfs_channel = false; hdd_context_t *hdd_ctx; + uint32_t i = 0, j = 0; hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); if (!hdd_ctx) { @@ -4529,23 +4598,61 @@ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, } num_channels = 0; + /* In the below switch case, the channel list is populated based on the + * pcl. e.g., if the pcl is CDS_SCC_CH_24G, the SCC channel group is + * populated first followed by the 2.4GHz channel group. Along with + * this, the weights are also populated in the same order for each of + * these groups. There are three weight groups: + * WEIGHT_OF_GROUP1_PCL_CHANNELS, WEIGHT_OF_GROUP2_PCL_CHANNELS and + * WEIGHT_OF_GROUP3_PCL_CHANNELS. + * + * e.g., if pcl is CDS_SCC_ON_5_SCC_ON_24_24G: scc on 5GHz (group1) + * channels take the weight WEIGHT_OF_GROUP1_PCL_CHANNELS, scc on 2.4GHz + * (group2) channels take the weight WEIGHT_OF_GROUP2_PCL_CHANNELS and + * 2.4GHz (group3) channels take the weight + * WEIGHT_OF_GROUP3_PCL_CHANNELS. + * + * When the weight to be assigned to the group is known along with the + * number of channels, the weights are directly assigned to the + * pcl_weights list. But, the channel list is populated using + * cds_get_connection_channels(), the order of weights to be used is + * passed as an argument to the function cds_get_connection_channels() + * using 'enum cds_pcl_group_id' which indicates the next available + * weights to be used and cds_get_connection_channels() will take care + * of the weight assignments. + * + * e.g., 'enum cds_pcl_group_id' value of CDS_PCL_GROUP_ID2_ID3 + * indicates that the next available groups for weight assignment are + * WEIGHT_OF_GROUP2_PCL_CHANNELS and WEIGHT_OF_GROUP3_PCL_CHANNELS and + * that the weight WEIGHT_OF_GROUP1_PCL_CHANNELS was already allocated. + * So, in the same example, when order is CDS_PCL_ORDER_24G_THEN_5G, + * cds_get_connection_channels() will assign the weight + * WEIGHT_OF_GROUP2_PCL_CHANNELS to 2.4GHz channels and assign the + * weight WEIGHT_OF_GROUP3_PCL_CHANNELS to 5GHz channels. + */ switch (pcl) { case CDS_24G: qdf_mem_copy(pcl_channels, channel_list_24, chan_index_24); *len = chan_index_24; + for (i = 0; ((i < *len) && (i < weight_len)); i++) + pcl_weights[i] = WEIGHT_OF_GROUP1_PCL_CHANNELS; status = QDF_STATUS_SUCCESS; break; case CDS_5G: qdf_mem_copy(pcl_channels, channel_list_5, chan_index_5); *len = chan_index_5; + for (i = 0; ((i < *len) && (i < weight_len)); i++) + pcl_weights[i] = WEIGHT_OF_GROUP1_PCL_CHANNELS; status = QDF_STATUS_SUCCESS; break; case CDS_SCC_CH: case CDS_MCC_CH: cds_get_connection_channels( - channel_list, &num_channels, 0, skip_dfs_channel); + channel_list, &num_channels, CDS_PCL_ORDER_NONE, + skip_dfs_channel, pcl_weights, weight_len, &i, + CDS_PCL_GROUP_ID1_ID2); qdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; status = QDF_STATUS_SUCCESS; @@ -4553,24 +4660,33 @@ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, case CDS_SCC_CH_24G: case CDS_MCC_CH_24G: cds_get_connection_channels( - channel_list, &num_channels, 0, skip_dfs_channel); + channel_list, &num_channels, CDS_PCL_ORDER_NONE, + skip_dfs_channel, pcl_weights, weight_len, &i, + CDS_PCL_GROUP_ID1_ID2); qdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; qdf_mem_copy(&pcl_channels[num_channels], channel_list_24, chan_index_24); *len += chan_index_24; + for (j = 0; ((j < chan_index_24) && (i < weight_len)); i++, j++) + pcl_weights[i] = WEIGHT_OF_GROUP2_PCL_CHANNELS; + status = QDF_STATUS_SUCCESS; break; case CDS_SCC_CH_5G: case CDS_MCC_CH_5G: cds_get_connection_channels( - channel_list, &num_channels, 0, skip_dfs_channel); + channel_list, &num_channels, CDS_PCL_ORDER_NONE, + skip_dfs_channel, pcl_weights, weight_len, &i, + CDS_PCL_GROUP_ID1_ID2); qdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; qdf_mem_copy(&pcl_channels[num_channels], channel_list_5, chan_index_5); *len += chan_index_5; + for (j = 0; ((j < chan_index_5) && (i < weight_len)); i++, j++) + pcl_weights[i] = WEIGHT_OF_GROUP2_PCL_CHANNELS; status = QDF_STATUS_SUCCESS; break; case CDS_24G_SCC_CH: @@ -4578,8 +4694,12 @@ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, qdf_mem_copy(pcl_channels, channel_list_24, chan_index_24); *len = chan_index_24; + for (i = 0; ((i < chan_index_24) && (i < weight_len)); i++) + pcl_weights[i] = WEIGHT_OF_GROUP1_PCL_CHANNELS; cds_get_connection_channels( - channel_list, &num_channels, 0, skip_dfs_channel); + channel_list, &num_channels, CDS_PCL_ORDER_NONE, + skip_dfs_channel, pcl_weights, weight_len, &i, + CDS_PCL_GROUP_ID2_ID3); qdf_mem_copy(&pcl_channels[chan_index_24], channel_list, num_channels); *len += num_channels; @@ -4590,8 +4710,12 @@ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, qdf_mem_copy(pcl_channels, channel_list_5, chan_index_5); *len = chan_index_5; + for (i = 0; ((i < chan_index_5) && (i < weight_len)); i++) + pcl_weights[i] = WEIGHT_OF_GROUP1_PCL_CHANNELS; cds_get_connection_channels( - channel_list, &num_channels, 0, skip_dfs_channel); + channel_list, &num_channels, CDS_PCL_ORDER_NONE, + skip_dfs_channel, pcl_weights, weight_len, &i, + CDS_PCL_GROUP_ID2_ID3); qdf_mem_copy(&pcl_channels[chan_index_5], channel_list, num_channels); *len += num_channels; @@ -4599,7 +4723,9 @@ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, break; case CDS_SCC_ON_24_SCC_ON_5: cds_get_connection_channels( - channel_list, &num_channels, 1, skip_dfs_channel); + channel_list, &num_channels, CDS_PCL_ORDER_24G_THEN_5G, + skip_dfs_channel, pcl_weights, weight_len, &i, + CDS_PCL_GROUP_ID1_ID2); qdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; @@ -4607,49 +4733,67 @@ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, break; case CDS_SCC_ON_5_SCC_ON_24: cds_get_connection_channels( - channel_list, &num_channels, 2, skip_dfs_channel); + channel_list, &num_channels, CDS_PCL_ORDER_5G_THEN_2G, + skip_dfs_channel, pcl_weights, weight_len, &i, + CDS_PCL_GROUP_ID1_ID2); qdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; status = QDF_STATUS_SUCCESS; break; case CDS_SCC_ON_24_SCC_ON_5_24G: cds_get_connection_channels( - channel_list, &num_channels, 1, skip_dfs_channel); + channel_list, &num_channels, CDS_PCL_ORDER_24G_THEN_5G, + skip_dfs_channel, pcl_weights, weight_len, &i, + CDS_PCL_GROUP_ID1_ID2); qdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; qdf_mem_copy(&pcl_channels[num_channels], channel_list_24, chan_index_24); *len += chan_index_24; + for (j = 0; ((j < chan_index_24) && (i < weight_len)); i++, j++) + pcl_weights[i] = WEIGHT_OF_GROUP3_PCL_CHANNELS; status = QDF_STATUS_SUCCESS; break; case CDS_SCC_ON_24_SCC_ON_5_5G: cds_get_connection_channels( - channel_list, &num_channels, 1, skip_dfs_channel); + channel_list, &num_channels, CDS_PCL_ORDER_24G_THEN_5G, + skip_dfs_channel, pcl_weights, weight_len, &i, + CDS_PCL_GROUP_ID1_ID2); qdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; qdf_mem_copy(&pcl_channels[num_channels], channel_list_5, chan_index_5); *len += chan_index_5; + for (j = 0; ((j < chan_index_5) && (i < weight_len)); i++, j++) + pcl_weights[i] = WEIGHT_OF_GROUP3_PCL_CHANNELS; status = QDF_STATUS_SUCCESS; break; case CDS_SCC_ON_5_SCC_ON_24_24G: cds_get_connection_channels( - channel_list, &num_channels, 2, skip_dfs_channel); + channel_list, &num_channels, CDS_PCL_ORDER_5G_THEN_2G, + skip_dfs_channel, pcl_weights, weight_len, &i, + CDS_PCL_GROUP_ID1_ID2); qdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; qdf_mem_copy(&pcl_channels[num_channels], channel_list_24, chan_index_24); *len += chan_index_24; + for (j = 0; ((j < chan_index_24) && (i < weight_len)); i++, j++) + pcl_weights[i] = WEIGHT_OF_GROUP3_PCL_CHANNELS; status = QDF_STATUS_SUCCESS; break; case CDS_SCC_ON_5_SCC_ON_24_5G: cds_get_connection_channels( - channel_list, &num_channels, 2, skip_dfs_channel); + channel_list, &num_channels, CDS_PCL_ORDER_5G_THEN_2G, + skip_dfs_channel, pcl_weights, weight_len, &i, + CDS_PCL_GROUP_ID1_ID2); qdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; qdf_mem_copy(&pcl_channels[num_channels], channel_list_5, chan_index_5); *len += chan_index_5; + for (j = 0; ((j < chan_index_5) && (i < weight_len)); i++, j++) + pcl_weights[i] = WEIGHT_OF_GROUP3_PCL_CHANNELS; status = QDF_STATUS_SUCCESS; break; default: @@ -4657,8 +4801,13 @@ QDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, break; } + if ((*len != 0) && (*len != i)) + cds_info("pcl len (%d) and weight list len mismatch (%d)", + *len, i); + /* check the channel avoidance list */ - cds_update_with_safe_channel_list(pcl_channels, len); + cds_update_with_safe_channel_list(pcl_channels, len, + pcl_weights, weight_len); return status; } @@ -4708,6 +4857,8 @@ bool cds_map_concurrency_mode(enum tQDF_ADAPTER_MODE *old_mode, * @mode: Device mode * @pcl_channels: PCL channels * @len: lenght of the PCL + * @pcl_weight: Weights of the PCL + * @weight_len: Max length of the weights list * * This function provides the preferred channel list on which * policy manager wants the new connection to come up. Various @@ -4717,7 +4868,8 @@ bool cds_map_concurrency_mode(enum tQDF_ADAPTER_MODE *old_mode, * Return: QDF_STATUS */ QDF_STATUS cds_get_pcl(enum cds_con_mode mode, - uint8_t *pcl_channels, uint32_t *len) + uint8_t *pcl_channels, uint32_t *len, + uint8_t *pcl_weight, uint32_t weight_len) { QDF_STATUS status = QDF_STATUS_E_FAILURE; uint32_t num_connections = 0; @@ -4805,12 +4957,14 @@ QDF_STATUS cds_get_pcl(enum cds_con_mode mode, /* once the PCL enum is obtained find out the exact channel list with * help from sme_get_cfg_valid_channels */ - status = cds_get_channel_list(pcl, pcl_channels, len, mode); + status = cds_get_channel_list(pcl, pcl_channels, len, mode, + pcl_weight, weight_len); if (status == QDF_STATUS_SUCCESS) { uint32_t i; cds_debug("pcl len:%d", *len); for (i = 0; i < *len; i++) - cds_debug("chan:%d", pcl_channels[i]); + cds_debug("chan:%d weight:%d", + pcl_channels[i], pcl_weight[i]); } return status; @@ -8217,6 +8371,8 @@ cds_get_nondfs_preferred_channel(enum cds_con_mode mode, bool for_existing_conn) { uint8_t pcl_channels[NUM_CHANNELS]; + uint8_t pcl_weight[NUM_CHANNELS]; + /* * in worst case if we can't find any channel at all * then return 2.4G channel, so atleast we won't fall @@ -8235,11 +8391,13 @@ cds_get_nondfs_preferred_channel(enum cds_con_mode mode, return channel; if (QDF_STATUS_SUCCESS != cds_get_pcl_for_existing_conn(mode, - &pcl_channels[0], &pcl_len)) + &pcl_channels[0], &pcl_len, + pcl_weight, QDF_ARRAY_SIZE(pcl_weight))) return channel; } else { if (QDF_STATUS_SUCCESS != cds_get_pcl(mode, - &pcl_channels[0], &pcl_len)) + &pcl_channels[0], &pcl_len, + pcl_weight, QDF_ARRAY_SIZE(pcl_weight))) return channel; } @@ -8263,6 +8421,8 @@ cds_get_nondfs_preferred_channel(enum cds_con_mode mode, } return channel; } + + /** * cds_is_any_nondfs_chnl_present() - Find any non-dfs channel from conc table * @channel: pointer to channel which needs to be filled @@ -8296,3 +8456,47 @@ bool cds_is_any_nondfs_chnl_present(uint8_t *channel) return status; } +/** + * cds_get_valid_chan_weights() - Get the weightage for all valid channels + * @weight: Pointer to the structure containing pcl, saved channel list and + * weighed channel list + * + * Provides the weightage for all valid channels. This compares the PCL list + * with the valid channel list. The channels present in the PCL get their + * corresponding weightage and the non-PCL channels get the default weightage + * of WEIGHT_OF_NON_PCL_CHANNELS. + * + * Return: QDF_STATUS + */ +QDF_STATUS cds_get_valid_chan_weights(struct sir_pcl_chan_weights *weight) +{ + uint32_t i, j; + + if (!weight->pcl_list) { + cds_err("Invalid pcl"); + return QDF_STATUS_E_FAILURE; + } + + if (!weight->saved_chan_list) { + cds_err("Invalid valid channel list"); + return QDF_STATUS_E_FAILURE; + } + + if (!weight->weighed_valid_list) { + cds_err("Invalid weighed valid channel list"); + return QDF_STATUS_E_FAILURE; + } + + for (i = 0; i < weight->saved_num_chan; i++) { + weight->weighed_valid_list[i] = WEIGHT_OF_NON_PCL_CHANNELS; + for (j = 0; j < weight->pcl_len; j++) { + if (weight->saved_chan_list[i] == weight->pcl_list[j]) { + weight->weighed_valid_list[i] = + weight->weight_list[j]; + break; + } + } + } + + return QDF_STATUS_SUCCESS; +} diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 7db20291e808..c8af93844f02 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -1396,6 +1396,7 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1]; bool ht_enabled, ht40_enabled, vht_enabled; uint8_t ch_width; + uint8_t weight_list[MAX_NUM_CHAN]; /* ***Note*** Donot set SME config related to ACS operation here because * ACS operation is not synchronouse and ACS for Second AP may come when @@ -1532,8 +1533,9 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, /* consult policy manager to get PCL */ status = cds_get_pcl(CDS_SAP_MODE, - sap_config->acs_cfg.pcl_channels, - &sap_config->acs_cfg.pcl_ch_count); + sap_config->acs_cfg.pcl_channels, + &sap_config->acs_cfg.pcl_ch_count, + weight_list, QDF_ARRAY_SIZE(weight_list)); if (QDF_STATUS_SUCCESS != status) hddLog(LOGE, FL("Get PCL failed")); @@ -4215,7 +4217,7 @@ static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy, hdd_context_t *hdd_ctx = wiphy_priv(wiphy); int i, ret = 0; QDF_STATUS status; - uint8_t pcl[MAX_NUM_CHAN]; + uint8_t pcl[MAX_NUM_CHAN], weight_list[MAX_NUM_CHAN]; uint32_t pcl_len = 0; uint32_t freq_list[MAX_NUM_CHAN]; enum cds_con_mode intf_mode; @@ -4249,7 +4251,8 @@ static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy, hdd_debug("Userspace requested pref freq list"); - status = cds_get_pcl(intf_mode, pcl, &pcl_len); + status = cds_get_pcl(intf_mode, pcl, &pcl_len, + weight_list, QDF_ARRAY_SIZE(weight_list)); if (status != QDF_STATUS_SUCCESS) { hdd_err("Get pcl failed"); return -EINVAL; diff --git a/core/hdd/src/wlan_hdd_conc_ut.c b/core/hdd/src/wlan_hdd_conc_ut.c index 8b7882e3990d..d42391602485 100644 --- a/core/hdd/src/wlan_hdd_conc_ut.c +++ b/core/hdd/src/wlan_hdd_conc_ut.c @@ -625,7 +625,7 @@ void wlan_hdd_one_connection_scenario(hdd_context_t *hdd_ctx) enum cds_con_mode sub_type; enum cds_conc_priority_mode system_pref = hdd_ctx->config->conc_system_pref; - uint8_t pcl[MAX_NUM_CHAN] = {0}; + uint8_t pcl[MAX_NUM_CHAN] = {0}, weight_list[MAX_NUM_CHAN] = {0}; uint32_t pcl_len = 0; bool status = false; enum cds_pcl_type pcl_type; @@ -651,7 +651,8 @@ void wlan_hdd_one_connection_scenario(hdd_context_t *hdd_ctx) pcl_type = get_pcl_from_first_conn_table(sub_type, system_pref); /* check PCL value for second connection is correct or no */ - cds_get_pcl(sub_type, pcl, &pcl_len); + cds_get_pcl(sub_type, pcl, &pcl_len, + weight_list, QDF_ARRAY_SIZE(weight_list)); status = wlan_hdd_validate_pcl(hdd_ctx, pcl_type, pcl, pcl_len, 0, 0, reason, sizeof(reason)); @@ -671,7 +672,7 @@ void wlan_hdd_two_connections_scenario(hdd_context_t *hdd_ctx, { uint8_t vdevid = 0, tx_stream = 2, rx_stream = 2; uint8_t type = WMI_VDEV_TYPE_STA, channel_id = first_chnl, mac_id = 1; - uint8_t pcl[MAX_NUM_CHAN] = {0}; + uint8_t pcl[MAX_NUM_CHAN] = {0}, weight_list[MAX_NUM_CHAN] = {0}; uint32_t pcl_len = 0; enum cds_chain_mode chain_mask = first_chain_mask; enum cds_con_mode sub_type, next_sub_type, dummy_type; @@ -723,7 +724,8 @@ void wlan_hdd_two_connections_scenario(hdd_context_t *hdd_ctx, next_sub_type, system_pref, wma_is_hw_dbs_capable()); /* check PCL for second connection is correct or no */ - cds_get_pcl(next_sub_type, pcl, &pcl_len); + cds_get_pcl(next_sub_type, pcl, &pcl_len, + weight_list, QDF_ARRAY_SIZE(weight_list)); status = wlan_hdd_validate_pcl(hdd_ctx, pcl_type, pcl, pcl_len, channel_id, 0, reason, sizeof(reason)); @@ -749,7 +751,7 @@ void wlan_hdd_three_connections_scenario(hdd_context_t *hdd_ctx, uint8_t channel_id_1 = first_chnl, channel_id_2 = second_chnl; uint8_t mac_id_1, mac_id_2; uint8_t type_1 = WMI_VDEV_TYPE_STA, type_2 = WMI_VDEV_TYPE_STA; - uint8_t pcl[MAX_NUM_CHAN] = {0}; + uint8_t pcl[MAX_NUM_CHAN] = {0}, weight_list[MAX_NUM_CHAN] = {0}; uint32_t pcl_len = 0; enum cds_chain_mode chain_mask_1; enum cds_chain_mode chain_mask_2; @@ -838,7 +840,9 @@ void wlan_hdd_three_connections_scenario(hdd_context_t *hdd_ctx, system_pref, wma_is_hw_dbs_capable()); cds_get_pcl(next_sub_type, - pcl, &pcl_len); + pcl, &pcl_len, + weight_list, + QDF_ARRAY_SIZE(weight_list)); status = wlan_hdd_validate_pcl(hdd_ctx, pcl_type, pcl, pcl_len, channel_id_1, channel_id_2, diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 124d601a2cdb..f8f4137c4e6c 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -7927,13 +7927,15 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, case WE_POLICY_MANAGER_PCL_CMD: { uint8_t pcl[MAX_NUM_CHAN] = {0}; + uint8_t weight_list[MAX_NUM_CHAN] = {0}; uint32_t pcl_len = 0, i = 0; hddLog(LOGE, FL(" is called\n")); cds_get_pcl(apps_args[0], - pcl, &pcl_len); + pcl, &pcl_len, + weight_list, QDF_ARRAY_SIZE(weight_list)); pr_info("PCL list for role[%d] is {", apps_args[0]); for (i = 0 ; i < pcl_len; i++) pr_info(" %d, ", pcl[i]); diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index cf0870c5f891..5c5ff30e87f9 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3205,13 +3205,36 @@ enum set_hw_mode_status { /** * struct sir_pcl_list - Format of PCL * @pcl_list: List of preferred channels + * @weight_list: Weights of the PCL * @pcl_len: Number of channels in the PCL */ struct sir_pcl_list { uint8_t pcl_list[128]; + uint8_t weight_list[128]; uint32_t pcl_len; }; +/** + * struct sir_pcl_chan_weights - Params to get the valid weighed list + * @pcl_list: Preferred channel list already sorted in the order of preference + * @pcl_len: Length of the PCL + * @saved_chan_list: Valid channel list updated as part of + * WMA_UPDATE_CHAN_LIST_REQ + * @saved_num_chan: Length of the valid channel list + * @weighed_valid_list: Weights of the valid channel list. This will have one + * to one mapping with valid_chan_list. FW expects channel order and size to be + * as per the list provided in WMI_SCAN_CHAN_LIST_CMDID. + * @weight_list: Weights assigned by policy manager + */ +struct sir_pcl_chan_weights { + uint8_t pcl_list[128]; + uint32_t pcl_len; + uint8_t saved_chan_list[128]; + uint32_t saved_num_chan; + uint8_t weighed_valid_list[128]; + uint8_t weight_list[128]; +}; + /** * struct sir_hw_mode_params - HW mode params * @mac0_tx_ss: MAC0 Tx spatial stream diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index b1e08297c0ed..6287638b2b8f 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -421,7 +421,7 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_FLUSH_LOG_TO_FW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 160) -#define SIR_HAL_SOC_SET_PCL_TO_FW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 161) +#define SIR_HAL_PDEV_SET_PCL_TO_FW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 161) /* 162 unused */ diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c index 75b4b5a06be0..db836f05c46f 100644 --- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c +++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c @@ -526,7 +526,7 @@ uint8_t *mac_trace_get_wma_msg_string(uint16_t wma_msg) CASE_RETURN_STRING(SIR_HAL_CONFIG_GUARD_TIME); CASE_RETURN_STRING(SIR_HAL_START_STOP_LOGGING); CASE_RETURN_STRING(SIR_HAL_FLUSH_LOG_TO_FW); - CASE_RETURN_STRING(SIR_HAL_SOC_SET_PCL_TO_FW); + CASE_RETURN_STRING(SIR_HAL_PDEV_SET_PCL_TO_FW); CASE_RETURN_STRING(SIR_HAL_SOC_SET_HW_MODE); CASE_RETURN_STRING(SIR_HAL_SOC_DUAL_MAC_CFG_REQ); CASE_RETURN_STRING(WMA_RADAR_DETECTED_IND); diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index fbb94a8b3394..9be884d40020 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -4488,7 +4488,8 @@ static QDF_STATUS sap_get_5ghz_channel_list(ptSapContext sapContext) } status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE, - pcl.pcl_list, &pcl.pcl_len); + pcl.pcl_list, &pcl.pcl_len, + pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list)); if (status != QDF_STATUS_SUCCESS) { cds_err("Get PCL failed"); return status; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index a41f85b5a9bf..d836a36a0389 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -986,7 +986,7 @@ QDF_STATUS sme_update_nss(tHalHandle h_hal, uint8_t nss); bool sme_is_any_session_in_connected_state(tHalHandle h_hal); -QDF_STATUS sme_soc_set_pcl(tHalHandle hal, +QDF_STATUS sme_pdev_set_pcl(tHalHandle hal, struct sir_pcl_list msg); QDF_STATUS sme_soc_set_hw_mode(tHalHandle hal, struct sir_hw_mode msg); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 52439872e079..c12aef820c50 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -14797,20 +14797,20 @@ QDF_STATUS sme_fw_mem_dump(tHalHandle hHal, void *recvd_req) #endif /* WLAN_FEATURE_MEMDUMP */ /* - * sme_soc_set_pcl() - Send WMI_SOC_SET_PCL_CMDID to the WMA + * sme_pdev_set_pcl() - Send WMI_PDEV_SET_PCL_CMDID to the WMA * @hal: Handle returned by macOpen * @msg: PCL channel list and length structure * - * Sends the command to WMA to send WMI_SOC_SET_PCL_CMDID to FW + * Sends the command to WMA to send WMI_PDEV_SET_PCL_CMDID to FW * Return: QDF_STATUS_SUCCESS on successful posting */ -QDF_STATUS sme_soc_set_pcl(tHalHandle hal, +QDF_STATUS sme_pdev_set_pcl(tHalHandle hal, struct sir_pcl_list msg) { QDF_STATUS status = QDF_STATUS_SUCCESS; tpAniSirGlobal mac = PMAC_STRUCT(hal); cds_msg_t cds_message; - struct sir_pcl_list *req_msg; + struct wmi_pcl_chan_weights *req_msg; uint32_t len, i; len = sizeof(*req_msg); @@ -14823,8 +14823,10 @@ QDF_STATUS sme_soc_set_pcl(tHalHandle hal, qdf_mem_zero(req_msg, len); - for (i = 0; i < msg.pcl_len; i++) + for (i = 0; i < msg.pcl_len; i++) { req_msg->pcl_list[i] = msg.pcl_list[i]; + req_msg->weight_list[i] = msg.weight_list[i]; + } req_msg->pcl_len = msg.pcl_len; @@ -14839,7 +14841,7 @@ QDF_STATUS sme_soc_set_pcl(tHalHandle hal, /* Serialize the req through MC thread */ cds_message.bodyptr = req_msg; - cds_message.type = SIR_HAL_SOC_SET_PCL_TO_FW; + cds_message.type = SIR_HAL_PDEV_SET_PCL_TO_FW; status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); if (!QDF_IS_STATUS_SUCCESS(status)) { sms_log(mac, LOGE, diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index a7cd0987b30c..87ceec5baa58 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -1991,6 +1991,7 @@ csr_parse_scan_results(tpAniSirGlobal pMac, eCsrAuthType auth = eCSR_AUTH_TYPE_OPEN_SYSTEM; uint32_t len = 0; enum cds_con_mode new_mode; + uint8_t weight_list[MAX_NUM_CHAN]; csr_ll_lock(&pMac->scan.scanResultList); @@ -1999,7 +2000,8 @@ csr_parse_scan_results(tpAniSirGlobal pMac, if (cds_map_concurrency_mode( &pFilter->csrPersona, &new_mode)) { status = cds_get_pcl(new_mode, - &pFilter->pcl_channels.channelList[0], &len); + &pFilter->pcl_channels.channelList[0], &len, + weight_list, QDF_ARRAY_SIZE(weight_list)); pFilter->pcl_channels.numChannels = (uint8_t)len; } } diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index e9553ffe94f6..ff9dca2f5a70 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1041,6 +1041,17 @@ struct wma_ini_config { uint8_t max_no_of_peers; }; +/** + * struct wmi_valid_channels - Channel details part of WMI_SCAN_CHAN_LIST_CMDID + * @num_channels: Number of channels + * @channel_list: Channel list + */ +struct wma_valid_channels { + uint8_t num_channels; + uint8_t channel_list[MAX_NUM_CHAN]; +}; + + /** * struct t_wma_handle - wma context * @wmi_handle: wmi handle @@ -1165,6 +1176,7 @@ struct wma_ini_config { * @service_ready_ext_evt: Wait event for service ready ext * @wmi_cmd_rsp_wake_lock: wmi command response wake lock * @wmi_cmd_rsp_runtime_lock: wmi command response bus lock + * @saved_chan: saved channel list sent as part of WMI_SCAN_CHAN_LIST_CMDID */ typedef struct { void *wmi_handle; @@ -1350,6 +1362,7 @@ typedef struct { qdf_runtime_lock_t wma_runtime_resume_lock; uint32_t fine_time_measurement_cap; struct wma_ini_config ini_config; + struct wma_valid_channels saved_chan; } t_wma_handle, *tp_wma_handle; /** @@ -1956,8 +1969,8 @@ void wma_log_completion_timeout(void *data); QDF_STATUS wma_set_rssi_monitoring(tp_wma_handle wma, struct rssi_monitor_req *req); -QDF_STATUS wma_send_soc_set_pcl_cmd(tp_wma_handle wma_handle, - struct sir_pcl_list *msg); +QDF_STATUS wma_send_pdev_set_pcl_cmd(tp_wma_handle wma_handle, + struct wmi_pcl_chan_weights *msg); QDF_STATUS wma_send_soc_set_hw_mode_cmd(tp_wma_handle wma_handle, struct sir_hw_mode *msg); diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 06e5da0b548a..723ff4921eb8 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -1798,6 +1798,7 @@ QDF_STATUS wma_open(void *cds_context, wma_handle->dfs_radar_indication_cb = radar_ind_cb; wma_handle->old_hw_mode_index = WMA_DEFAULT_HW_MODE_INDEX; wma_handle->new_hw_mode_index = WMA_DEFAULT_HW_MODE_INDEX; + wma_handle->saved_chan.num_channels = 0; qdf_status = qdf_event_create(&wma_handle->wma_ready_event); if (qdf_status != QDF_STATUS_SUCCESS) { @@ -5165,9 +5166,9 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) (struct fw_dump_req *)msg->bodyptr); qdf_mem_free(msg->bodyptr); break; - case SIR_HAL_SOC_SET_PCL_TO_FW: - wma_send_soc_set_pcl_cmd(wma_handle, - (struct sir_pcl_list *)msg->bodyptr); + case SIR_HAL_PDEV_SET_PCL_TO_FW: + wma_send_pdev_set_pcl_cmd(wma_handle, + (struct wmi_pcl_chan_weights *)msg->bodyptr); qdf_mem_free(msg->bodyptr); break; case SIR_HAL_SOC_SET_HW_MODE: @@ -5297,30 +5298,49 @@ void wma_log_completion_timeout(void *data) } /** - * wma_send_soc_set_pcl_cmd() - Send WMI_SOC_SET_PCL_CMDID to FW + * wma_send_pdev_set_pcl_cmd() - Send WMI_SOC_SET_PCL_CMDID to FW * @wma_handle: WMA handle * @msg: PCL structure containing the PCL and the number of channels * - * WMI_SOC_SET_PCL_CMDID provides a Preferred Channel List (PCL) to the WLAN + * WMI_PDEV_SET_PCL_CMDID provides a Preferred Channel List (PCL) to the WLAN * firmware. The DBS Manager is the consumer of this information in the WLAN * firmware. The channel list will be used when a Virtual DEVice (VDEV) needs * to migrate to a new channel without host driver involvement. An example of * this behavior is Legacy Fast Roaming (LFR 3.0). Generally, the host will * manage the channel selection without firmware involvement. * + * WMI_PDEV_SET_PCL_CMDID will carry only the weight list and not the actual + * channel list. The weights corresponds to the channels sent in + * WMI_SCAN_CHAN_LIST_CMDID. The channels from PCL would be having a higher + * weightage compared to the non PCL channels. + * * Return: Success if the cmd is sent successfully to the firmware */ -QDF_STATUS wma_send_soc_set_pcl_cmd(tp_wma_handle wma_handle, - struct sir_pcl_list *msg) +QDF_STATUS wma_send_pdev_set_pcl_cmd(tp_wma_handle wma_handle, + struct wmi_pcl_chan_weights *msg) { + uint32_t i; + QDF_STATUS status; + if (!wma_handle) { WMA_LOGE("%s: WMA handle is NULL. Cannot issue command", __func__); return QDF_STATUS_E_NULL_VALUE; } - if (wmi_unified_soc_set_pcl_cmd(wma_handle->wmi_handle, - (struct wmi_pcl_list *) msg)) + for (i = 0; i < wma_handle->saved_chan.num_channels; i++) { + msg->saved_chan_list[i] = + wma_handle->saved_chan.channel_list[i]; + } + + msg->saved_num_chan = wma_handle->saved_chan.num_channels; + status = cds_get_valid_chan_weights((struct sir_pcl_chan_weights *)msg); + if (!QDF_IS_STATUS_SUCCESS(status)) { + WMA_LOGE("%s: Error in creating weighed pcl", __func__); + return status; + } + + if (wmi_unified_pdev_set_pcl_cmd(wma_handle->wmi_handle, msg)) return QDF_STATUS_E_FAILURE; return QDF_STATUS_SUCCESS; diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 78d57ac32921..295cde659da1 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -642,6 +642,7 @@ QDF_STATUS wma_update_channel_list(WMA_HANDLE handle, WMA_LOGD("no of channels = %d", chan_list->numChan); tchan_info = scan_ch_param.chan_info; scan_ch_param.num_scan_chans = chan_list->numChan; + wma_handle->saved_chan.num_channels = chan_list->numChan; for (i = 0; i < chan_list->numChan; ++i) { tchan_info->mhz = @@ -649,8 +650,11 @@ QDF_STATUS wma_update_channel_list(WMA_HANDLE handle, tchan_info->band_center_freq1 = tchan_info->mhz; tchan_info->band_center_freq2 = 0; + wma_handle->saved_chan.channel_list[i] = + chan_list->chanParam[i].chanId; - WMA_LOGD("chan[%d] = %u", i, tchan_info->mhz); + WMA_LOGD("chan[%d] = freq:%u chan:%d", i, tchan_info->mhz, + chan_list->chanParam[i].chanId); if (chan_list->chanParam[i].dfsSet) { WMI_SET_CHANNEL_FLAG(tchan_info, WMI_CHAN_FLAG_PASSIVE); WMA_LOGI("chan[%d] DFS[%d]\n",