diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 09b88bac167b..8bfa5663bb53 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -656,4 +656,5 @@ QDF_STATUS qdf_wait_for_connection_update(void); QDF_STATUS qdf_reset_connection_update(void); QDF_STATUS qdf_set_connection_update(void); QDF_STATUS qdf_init_connection_update(void); +QDF_STATUS cds_stop_start_opportunistic_timer(void); #endif /* __CDS_CONCURRENCY_H */ diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index dea6bf2ce9a6..adf5108a2aae 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -3614,8 +3614,8 @@ enum cds_conc_next_action cds_need_opportunistic_upgrade(void) #ifdef QCA_WIFI_3_0_EMU /* For M2M emulation only: if we have a connection on 2.4, stay in DBS */ if (hdd_ctx->config->enable_m2m_limitation && - CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) { - cds_debug("For emulation only: connection on 2.4, stay in DBS"); + CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) { + cds_debug("emulation only: conn on 2.4, stay in DBS"); goto done; } #endif @@ -7983,3 +7983,35 @@ enum cds_conc_next_action cds_get_pref_hw_mode_for_chan(uint32_t vdev_id, return CDS_NOP; } } + +/** + * cds_stop_start_opportunistic_timer() - Start and stop the opportunistic timer + * + * Stops and starts the opportunistic timer for DBS_OPPORTUNISTIC_TIME seconds + * + * Return: QDF_STATUS + */ +QDF_STATUS cds_stop_start_opportunistic_timer(void) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; + p_cds_contextType cds_ctx; + + cds_ctx = cds_get_global_context(); + if (!cds_ctx) { + cds_err("Invalid CDS context"); + return status; + } + + qdf_mc_timer_stop(&cds_ctx->dbs_opportunistic_timer); + + status = qdf_mc_timer_start( + &cds_ctx->dbs_opportunistic_timer, + DBS_OPPORTUNISTIC_TIME * 1000); + + if (!QDF_IS_STATUS_SUCCESS(status)) { + cds_err("failed to start opportunistic timer"); + return status; + } + + return status; +} diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index c44d0497b464..5e8e93efcd59 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -105,6 +105,7 @@ typedef uint8_t tSirVersionString[SIR_VERSION_STRING_LEN]; * @CDS_UPDATE_REASON_OPPORTUNISTIC: Opportunistic HW mode update * @CDS_UPDATE_REASON_NSS_UPDATE: NSS update * @CDS_UPDATE_REASON_CHANNEL_SWITCH: Channel switch + * @CDS_UPDATE_REASON_CHANNEL_SWITCH_STA: Channel switch for STA */ enum cds_conn_update_reason { CDS_UPDATE_REASON_SET_OPER_CHAN, @@ -116,6 +117,7 @@ enum cds_conn_update_reason { CDS_UPDATE_REASON_OPPORTUNISTIC, CDS_UPDATE_REASON_NSS_UPDATE, CDS_UPDATE_REASON_CHANNEL_SWITCH, + CDS_UPDATE_REASON_CHANNEL_SWITCH_STA, }; typedef enum { @@ -5518,4 +5520,39 @@ struct egap_conf_params { uint32_t wait_time; uint32_t flags; }; + +/** + * struct csa_offload_params - CSA offload request parameters + * @channel: channel + * @switch_mode: switch mode + * @sec_chan_offset: second channel offset + * @new_ch_width: new channel width + * @new_ch_freq_seg1: channel center freq 1 + * @new_ch_freq_seg2: channel center freq 2 + * @ies_present_flag: IE present flag + */ +struct csa_offload_params { + uint8_t channel; + uint8_t switch_mode; + uint8_t sec_chan_offset; + uint8_t new_ch_width; + uint8_t new_op_class; + uint8_t new_ch_freq_seg1; + uint8_t new_ch_freq_seg2; + uint32_t ies_present_flag; + tSirMacAddr bssId; +}; + +/** + * struct sir_saved_csa_params - saved csa offload params + * @message_type: Message type + * @length: Message length + * @session_id: Session id + */ +struct sir_saved_csa_params { + uint16_t message_type; + uint16_t length; + uint32_t session_id; +}; + #endif /* __SIR_API_H */ diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index affd556d5cf3..30a0ad1cb1e0 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -642,10 +642,7 @@ typedef struct sSirMbMsgP2p { #define SIR_LIM_SCH_CLEAN_MSG (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xB) /* Message from ISR upon Radar Detection */ #define SIR_LIM_RADAR_DETECT_IND (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xC) - -/* /////////////////////////////////// */ -/* message id Available */ -/* ////////////////////////////////// */ +#define SIR_LIM_CSA_POST_HW_MODE_CHANGE (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xD) /* Message from Hal to send out a DEL-TS indication */ #define SIR_LIM_DEL_TS_IND (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xE) diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index 24069b324629..a95238389f7c 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -471,6 +471,7 @@ typedef struct sPESession /* Added to Support BT-AMP */ uint8_t country_info_present; uint8_t nss; bool add_bss_failed; + struct csa_offload_params saved_csa_params; } tPESession, *tpPESession; /*------------------------------------------------------------------------- diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index 2591138c903e..664c5233cde2 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -62,6 +62,7 @@ #include "qdf_types.h" #include "cds_packet.h" #include "qdf_mem.h" +#include "cds_concurrency.h" void lim_log_session_states(tpAniSirGlobal pMac); static void lim_process_normal_hdd_msg(tpAniSirGlobal mac_ctx, @@ -1146,6 +1147,210 @@ void lim_process_oem_data_rsp(tpAniSirGlobal pMac, uint32_t *body) #endif +/** + * lim_handle_hw_mode_change_on_csa() - Do HW mode change on CSA for STA mode + * @mac_ctx: Global MAC context + * @msg: Received message + * + * Checks if hw mode change is required for the new channel. + * If MCC upgrade is required, this function will start the opportunistic + * timer and the caller will invoke the other APIs to perform vdev restart on + * the new channel. + * + * If DBS downgrade is required, this function will initiate the hw mode + * change and vdev restart will happen on the new channel after getting hw + * mode response + * + * Return: QDF_STATUS_SUCCESS if processing of csa params (and hence vdev + * restart) needs to happen or if no hw mode change is required, + * QDF_STATUS_E_FAILURE otherwise. + */ +static QDF_STATUS lim_handle_hw_mode_change_on_csa(tpAniSirGlobal mac_ctx, + tpSirMsgQ msg) +{ + tpPESession session_entry; + struct csa_offload_params *csa_params = + (struct csa_offload_params *) (msg->bodyptr); + tpDphHashNode sta_ds = NULL; + uint8_t session_id; + uint16_t aid = 0; + enum cds_conc_next_action action; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + lim_log(mac_ctx, LOG1, FL("handle hw mode change for csa")); + + if (!csa_params) { + lim_log(mac_ctx, LOGE, FL("limMsgQ body ptr is NULL")); + /* qdf_mem_free() can handle NULL values */ + goto err; + } + + session_entry = pe_find_session_by_bssid(mac_ctx, + csa_params->bssId, &session_id); + if (!session_entry) { + lim_log(mac_ctx, LOGE, FL("Session does not exist")); + goto err; + } + + sta_ds = dph_lookup_hash_entry(mac_ctx, session_entry->bssId, &aid, + &session_entry->dph.dphHashTable); + + if (!sta_ds) { + lim_log(mac_ctx, LOGE, FL("sta_ds does not exist")); + goto err; + } + + /* Since all the write to the policy manager table happens in the + * MC thread context and this channel change event is also processed + * in the MC thread context, explicit lock/unlock of qdf_conc_list_lock + * is not done here + */ + action = cds_get_pref_hw_mode_for_chan(session_entry->smeSessionId, + csa_params->channel); + + if (action == CDS_NOP) { + lim_log(mac_ctx, LOG1, FL("no need for hw mode change")); + /* Proceed with processing csa params. So, not freeing it */ + return QDF_STATUS_SUCCESS; + } + + lim_log(mac_ctx, LOG1, FL("session:%d action:%d"), + session_entry->smeSessionId, action); + + /* 1. Start opportunistic timer + * 2. Do vdev restart on the new channel (by the caller) + * 3. PM will check if MCC upgrade can be done after timer expiry + */ + if (action == CDS_MCC_UPGRADE) { + status = cds_stop_start_opportunistic_timer(); + if (QDF_IS_STATUS_SUCCESS(status)) + lim_log(mac_ctx, LOG1, + FL("opportunistic timer for MCC upgrade")); + + /* After opportunistic timer is triggered, we can go ahead + * with processing the csa params. So, not freeing the memory + * through 'err' label. + */ + return QDF_STATUS_SUCCESS; + } + + /* CDS_DBS_DOWNGRADE: + * 1. PM will initiate HW mode change to DBS rightaway + * 2. Do vdev restart on the new channel (on getting hw mode resp) + */ + status = cds_next_actions(session_entry->smeSessionId, action, + CDS_UPDATE_REASON_CHANNEL_SWITCH_STA); + if (!QDF_IS_STATUS_SUCCESS(status)) { + lim_log(mac_ctx, LOGE, FL("no set hw mode command was issued")); + /* Proceed with processing csa params. So, not freeing it */ + return QDF_STATUS_SUCCESS; + } else { + /* Save the csa params to be used after DBS downgrade */ + qdf_mem_copy(&session_entry->saved_csa_params, csa_params, + sizeof(session_entry->saved_csa_params)); + + lim_log(mac_ctx, LOG1, + FL("saved csa params for dbs downgrade for %pM"), + session_entry->saved_csa_params.bssId); + + /* Returning error so that csa params are not processed here */ + status = QDF_STATUS_E_FAILURE; + } + +err: + qdf_mem_free(csa_params); + return status; +} + +/** + * lim_handle_hw_mode_change_on_csa_event() - Handle hw mode change on csa + * @mac_ctx: Pointer to the Global Mac Context + * @msg: Received message + * + * Checks if a hw mode change is required for the received csa event. Processes + * csa params and do vdev restart immediately if the there is no need for a hw + * mode change or if MCC upgrade is required + * + * Return: None + */ +static void lim_handle_hw_mode_change_on_csa_event(tpAniSirGlobal mac_ctx, + tpSirMsgQ msg) +{ + QDF_STATUS qdf_status; + + lim_log(mac_ctx, LOG1, FL("lim received csa offload event")); + if (mac_ctx->policy_manager_enabled && + wma_is_hw_dbs_capable() == true) { + /* Check if a hw mode change is required */ + qdf_status = lim_handle_hw_mode_change_on_csa(mac_ctx, + msg); + /* Process csa params and do vdev restart immediately if + * there is no need for a hw mode change or if MCC upgrade is + * required. + */ + if (QDF_IS_STATUS_SUCCESS(qdf_status)) + lim_handle_csa_offload_msg(mac_ctx, msg); + } else { + lim_handle_csa_offload_msg(mac_ctx, msg); + } +} + +/** + * lim_handle_csa_event_post_dbs_downgrade() - Process csa event post dbs + * downgrade + * @mac_ctx: Pointer to the Global Mac Context + * @msg: Received message + * + * Process the csa event to do vdev restart on the new channel after the dbs + * downgrade. If there was a DBS downgrade as part of the event + * WMA_CSA_OFFLOAD_EVENT, SIR_LIM_CSA_POST_HW_MODE_CHANGE will be received after + * receiving the set hw mode response, where this processing will happen. + * + * Return: None + */ +static void lim_handle_csa_event_post_dbs_downgrade(tpAniSirGlobal mac_ctx, + tpSirMsgQ msg) +{ + tSirMsgQ csa_msg; + tpPESession session_entry; + + struct sir_saved_csa_params *buf = + (struct sir_saved_csa_params *)msg->bodyptr; + + /* Null check for 'msg' already done before coming here in the caller */ + + session_entry = pe_find_session_by_sme_session_id(mac_ctx, + buf->session_id); + if (!session_entry) { + lim_log(mac_ctx, LOGE, FL("Invalid session id:%d"), + buf->session_id); + return; + } + + lim_log(mac_ctx, LOG1, + FL("received csa offload event post hw change for %pM"), + session_entry->saved_csa_params.bssId); + + csa_msg.bodyptr = qdf_mem_malloc( + sizeof(struct csa_offload_params)); + if (!csa_msg.bodyptr) { + lim_log(mac_ctx, LOGE, FL("malloc failed for csa msg")); + goto clean_msg_body; + } + + qdf_mem_copy((void *)csa_msg.bodyptr, + (void *)&session_entry->saved_csa_params, + sizeof(struct csa_offload_params)); + /* If there was a DBS downgrade as part of the event + * WMA_CSA_OFFLOAD_EVENT, SIR_LIM_CSA_POST_HW_MODE_CHANGE will + * be received after receiving the set hw mode response. + */ + lim_handle_csa_offload_msg(mac_ctx, &csa_msg); +clean_msg_body: + if (msg->bodyptr) + qdf_mem_free(msg->bodyptr); +} + /** * lim_process_messages() - Process messages from upper layers. * @@ -1605,7 +1810,10 @@ void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) lim_handle_delete_bss_rsp(mac_ctx, msg); break; case WMA_CSA_OFFLOAD_EVENT: - lim_handle_csa_offload_msg(mac_ctx, msg); + lim_handle_hw_mode_change_on_csa_event(mac_ctx, msg); + break; + case SIR_LIM_CSA_POST_HW_MODE_CHANGE: + lim_handle_csa_event_post_dbs_downgrade(mac_ctx, msg); break; case WMA_SET_BSSKEY_RSP: case WMA_SET_STA_BCASTKEY_RSP: diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index dd1e592a9e13..2256f851761b 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -2016,7 +2016,8 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) { tpPESession session_entry; tSirMsgQ mmh_msg; - tpCSAOffloadParams csa_params = (tpCSAOffloadParams) (msg->bodyptr); + struct csa_offload_params *csa_params = + (struct csa_offload_params *) (msg->bodyptr); tpSmeCsaOffloadInd csa_offload_ind; tpDphHashNode sta_ds = NULL; uint8_t session_id; @@ -2027,6 +2028,8 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) tLimWiderBWChannelSwitchInfo *chnl_switch_info = NULL; tLimChannelSwitchInfo *lim_ch_switch = NULL; + lim_log(mac_ctx, LOG1, FL("handle csa offload msg")); + if (!csa_params) { lim_log(mac_ctx, LOGE, FL("limMsgQ body ptr is NULL")); return; @@ -2037,7 +2040,8 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) csa_params->bssId, &session_id); if (!session_entry) { lim_log(mac_ctx, LOGE, - FL("Session does not exist")); + FL("Session does not exists for %pM"), + csa_params->bssId); goto err; } @@ -2059,7 +2063,7 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) lim_ch_switch = &session_entry->gLimChannelSwitch; session_entry->gLimChannelSwitch.switchMode = - csa_params->switchmode; + csa_params->switch_mode; /* timer already started by firmware, switch immediately */ session_entry->gLimChannelSwitch.switchCount = 0; session_entry->gLimChannelSwitch.primaryChannel = diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index 21a7b78476f8..9c9a9976147f 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -220,6 +220,7 @@ typedef struct tagSmeStruct { ocb_callback dcc_stats_event_callback; sme_set_thermal_level_callback set_thermal_level_cb; void *saved_scan_cmd; + struct csa_offload_params saved_csa_params; } tSmeStruct, *tpSmeStruct; #endif /* #if !defined( __SMEINTERNAL_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 0a44d44f309b..423f56d2a178 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -156,6 +156,7 @@ static QDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) enum cds_conn_update_reason reason; tSmeCmd *saved_cmd; tCsrRoamInfo roam_info = {0}; + QDF_STATUS status; sms_log(mac, LOG1, FL("%s"), __func__); param = (struct sir_set_hw_mode_resp *)msg; @@ -234,6 +235,28 @@ static QDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) &roam_info, 0, eCSR_ROAM_STATUS_UPDATE_HW_MODE, eCSR_ROAM_RESULT_UPDATE_HW_MODE); + } else if (reason == CDS_UPDATE_REASON_CHANNEL_SWITCH_STA) { + struct sir_saved_csa_params *msg; + + sms_log(mac, LOG1, FL("process channel switch sta")); + msg = qdf_mem_malloc(sizeof(*msg)); + if (!msg) { + sms_log(mac, LOGE, + FL("memory alloc fail for csa ")); + goto end; + } + + msg->message_type = SIR_LIM_CSA_POST_HW_MODE_CHANGE; + msg->length = sizeof(*msg); + msg->session_id = command->u.set_hw_mode_cmd.session_id; + + status = cds_send_mb_message_to_mac(msg); + if (!QDF_IS_STATUS_SUCCESS(status)) + sms_log(mac, LOGE, + FL("failed to process csa params")); + else + sms_log(mac, LOG1, + FL("csa after hw mode change")); } else { sms_log(mac, LOGE, FL("Calling HDD callback for HW mode response")); diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 8b01d00e4830..dcce413c6700 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -921,28 +921,6 @@ typedef struct { uint8_t nss; } tSwitchChannelParams, *tpSwitchChannelParams; -/** - * struct tpCSAOffloadParams - CSA offload request parameters - * @channel: channel - * @switchmode: switch mode - * @sec_chan_offset: second channel offset - * @new_ch_width: new channel width - * @new_ch_freq_seg1: channel center freq 1 - * @new_ch_freq_seg2: channel center freq 2 - * @ies_present_flag: IE present flag - */ -typedef struct CSAOffloadParams { - uint8_t channel; - uint8_t switchmode; - uint8_t sec_chan_offset; - uint8_t new_ch_width; - uint8_t new_op_class; - uint8_t new_ch_freq_seg1; - uint8_t new_ch_freq_seg2; - uint32_t ies_present_flag; - tSirMacAddr bssId; -} *tpCSAOffloadParams, tCSAOffloadParams; - typedef void (*tpSetLinkStateCallback)(tpAniSirGlobal pMac, void *msgParam, bool status); diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 53f06fe7474e..2e5671de7746 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1143,7 +1143,7 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len) uint8_t vdev_id = 0; uint8_t cur_chan = 0; struct ieee80211_channelswitch_ie *csa_ie; - tpCSAOffloadParams csa_offload_event; + struct csa_offload_params *csa_offload_event; struct ieee80211_extendedchannelswitch_ie *xcsa_ie; struct ieee80211_ie_wide_bw_switch *wb_ie; struct wma_txrx_node *intr = wma->interfaces; @@ -1176,12 +1176,12 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len) csa_ie = (struct ieee80211_channelswitch_ie *) (&csa_event->csa_ie[0]); csa_offload_event->channel = csa_ie->newchannel; - csa_offload_event->switchmode = csa_ie->switchmode; + csa_offload_event->switch_mode = csa_ie->switchmode; } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) { xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *) (&csa_event->xcsa_ie[0]); csa_offload_event->channel = xcsa_ie->newchannel; - csa_offload_event->switchmode = xcsa_ie->switchmode; + csa_offload_event->switch_mode = xcsa_ie->switchmode; csa_offload_event->new_op_class = xcsa_ie->newClass; } else { WMA_LOGE("CSA Event error: No CSA IE present");