diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index d295c530f4eb..e3804377363d 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -3242,6 +3242,7 @@ void lim_process_switch_channel_rsp(struct mac_context *mac, void *body) break; case LIM_SWITCH_CHANNEL_OPERATION: + case LIM_SWITCH_CHANNEL_HT_WIDTH: /* * The above code should also use the callback. * mechanism below, there is scope for cleanup here. diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 940cfe5728ec..ea3ad9f39539 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -160,6 +160,7 @@ enum eChannelChangeReasonCodes { LIM_SWITCH_CHANNEL_JOIN, LIM_SWITCH_CHANNEL_OPERATION, /* Generic change channel */ LIM_SWITCH_CHANNEL_SAP_DFS, /* DFS channel change */ + LIM_SWITCH_CHANNEL_HT_WIDTH /* HT channel width change */ }; typedef struct sLimAuthRspTimeout { diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 8182cfb614df..7fc3c4516db9 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -1953,18 +1953,21 @@ lim_decide_sta_protection(struct mac_context *mac_ctx, * * ***NOTE: - * @param mac - Pointer to Global MAC structure + * @param pe_session - Pointer to pe session * @return None */ -static void __lim_process_channel_switch_timeout(struct mac_context *mac) +static void __lim_process_channel_switch_timeout(struct pe_session *pe_session) { - struct pe_session *pe_session = NULL; + struct mac_context *mac; uint8_t channel; /* This is received and stored from channelSwitch Action frame */ - pe_session = pe_find_session_by_session_id(mac, - mac->lim.limTimers.gLimChannelSwitchTimer.sessionId); - if (pe_session == NULL) { - pe_err("Session Does not exist for given sessionID"); + if (!pe_session) { + pe_err("Invalid pe session"); + return; + } + mac = pe_session->mac_ctx; + if (!mac) { + pe_err("Invalid mac context"); return; } @@ -2072,18 +2075,24 @@ void lim_disconnect_complete(struct pe_session *session, bool del_bss) void lim_process_channel_switch_timeout(struct mac_context *mac_ctx) { - struct pe_session *session_entry = NULL; + struct pe_session *session_entry; QDF_STATUS status; session_entry = pe_find_session_by_session_id( mac_ctx, mac_ctx->lim.limTimers.gLimChannelSwitchTimer.sessionId); + if (!session_entry) { + pe_err("Session does not exist for given sessionID"); + return; + } + + session_entry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION; mlme_set_chan_switch_in_progress(session_entry->vdev, true); status = wlan_vdev_mlme_sm_deliver_evt( session_entry->vdev, WLAN_VDEV_SM_EV_FW_VDEV_RESTART, - sizeof(*mac_ctx), - mac_ctx); + sizeof(*session_entry), + session_entry); if (QDF_IS_STATUS_ERROR(status)) { pe_err("Failed to post WLAN_VDEV_SM_EV_FW_VDEV_RESTART for vdevid %d", session_entry->smeSessionId); @@ -2103,9 +2112,19 @@ void lim_disconnect_complete(struct pe_session *session, bool del_bss) * * Return: none */ -void lim_process_channel_switch_timeout(struct mac_context *mac) +void lim_process_channel_switch_timeout(struct mac_context *mac_ctx) { - __lim_process_channel_switch_timeout(mac); + struct pe_session *session_entry; + + session_entry = pe_find_session_by_session_id( + mac_ctx, + mac_ctx->lim.limTimers.gLimChannelSwitchTimer.sessionId); + if (!session_entry) { + pe_err("Session does not exist for given sessionID"); + return; + } + + __lim_process_channel_switch_timeout(session_entry); } #endif @@ -3993,6 +4012,103 @@ QDF_STATUS lim_tx_complete(void *context, qdf_nbuf_t buf, bool free) return QDF_STATUS_SUCCESS; } +#ifdef CONFIG_VDEV_SM +static void lim_ht_width_switch_cback(struct mac_context *mac, + QDF_STATUS status, uint32_t *data, + struct pe_session *pe_session) +{ + pe_debug("status %d for ht width switch for vdev %d", status, + pe_session->smeSessionId); + if (QDF_IS_STATUS_SUCCESS(status)) + lim_switch_channel_vdev_started(pe_session); +} +#else +static void lim_ht_width_switch_cback(struct mac_context *mac, + QDF_STATUS status, uint32_t *data, + struct pe_session *pe_session) +{ + pe_debug("status %d for ht width switch for vdev %d", status, + pe_session->smeSessionId); +} +#endif + +static void lim_ht_switch_chnl_params(struct pe_session *pe_session) +{ + uint8_t center_freq = 0; + enum phy_ch_width ch_width = CH_WIDTH_20MHZ; + struct mac_context *mac; + uint8_t primary_channel; + + mac = pe_session->mac_ctx; + if (!mac) { + pe_err("Invalid mac_ctx"); + return; + } + + primary_channel = pe_session->gLimChannelSwitch.primaryChannel; + if (eHT_CHANNEL_WIDTH_40MHZ == + pe_session->htRecommendedTxWidthSet) { + ch_width = CH_WIDTH_40MHZ; + if (PHY_DOUBLE_CHANNEL_LOW_PRIMARY == + pe_session->htSecondaryChannelOffset) + center_freq = primary_channel + 2; + else if (PHY_DOUBLE_CHANNEL_HIGH_PRIMARY == + pe_session->htSecondaryChannelOffset) + center_freq = primary_channel - 2; + else + ch_width = CH_WIDTH_20MHZ; + } + + /* notify HAL */ + pe_debug("HT IE changed: Primary Channel: %d Secondary Channel Offset: %d Channel Width: %d", + primary_channel, center_freq, + pe_session->htRecommendedTxWidthSet); + pe_session->channelChangeReasonCode = + LIM_SWITCH_CHANNEL_HT_WIDTH; + mac->lim.gpchangeChannelCallback = lim_ht_width_switch_cback; + mac->lim.gpchangeChannelData = NULL; + + lim_send_switch_chnl_params(mac, primary_channel, + center_freq, 0, ch_width, + pe_session->maxTxPower, + pe_session->peSessionId, + true, 0, 0); +} + +#ifdef CONFIG_VDEV_SM +static void lim_ht_switch_chnl_req(struct pe_session *session) +{ + struct mac_context *mac; + QDF_STATUS status; + + mac = session->mac_ctx; + if (!mac) { + pe_err("Invalid mac context"); + return; + } + + session->channelChangeReasonCode = + LIM_SWITCH_CHANNEL_HT_WIDTH; + mlme_set_chan_switch_in_progress(session->vdev, true); + status = wlan_vdev_mlme_sm_deliver_evt( + session->vdev, + WLAN_VDEV_SM_EV_FW_VDEV_RESTART, + sizeof(*session), + session); + if (QDF_IS_STATUS_ERROR(status)) { + pe_err("Failed to post WLAN_VDEV_SM_EV_FW_VDEV_RESTART for vdevid %d", + session->smeSessionId); + mlme_set_chan_switch_in_progress(session->vdev, false); + } +} +#else +static void lim_ht_switch_chnl_req(struct pe_session *session) +{ + lim_ht_switch_chnl_params(session); +} +#endif + + /** * \brief This function updates lim global structure, if CB parameters in the BSS * have changed, and sends an indication to HAL also with the @@ -4018,9 +4134,6 @@ void lim_update_sta_run_time_ht_switch_chnl_params(struct mac_context *mac, uint8_t bssIdx, struct pe_session *pe_session) { - uint8_t center_freq = 0; - enum phy_ch_width ch_width = CH_WIDTH_20MHZ; - /* If self capability is set to '20Mhz only', then do not change the CB mode. */ if (!lim_get_ht_capability (mac, eHT_SUPPORTED_CHANNEL_WIDTH_SET, pe_session)) @@ -4047,51 +4160,29 @@ void lim_update_sta_run_time_ht_switch_chnl_params(struct mac_context *mac, return; } + /* If channel mismatch the CSA will take care of this change */ + if (pHTInfo->primaryChannel != pe_session->currentOperChannel) { + pe_debug("Current channel doesnt match HT info ignore"); + return; + } + if (pe_session->htSecondaryChannelOffset != (uint8_t) pHTInfo->secondaryChannelOffset || pe_session->htRecommendedTxWidthSet != (uint8_t) pHTInfo->recommendedTxWidthSet) { + pe_session->gLimChannelSwitch.primaryChannel = + pHTInfo->primaryChannel; pe_session->htSecondaryChannelOffset = (ePhyChanBondState) pHTInfo->secondaryChannelOffset; pe_session->htRecommendedTxWidthSet = (uint8_t) pHTInfo->recommendedTxWidthSet; - if (eHT_CHANNEL_WIDTH_40MHZ == - pe_session->htRecommendedTxWidthSet) { - ch_width = CH_WIDTH_40MHZ; - if (PHY_DOUBLE_CHANNEL_LOW_PRIMARY == - pHTInfo->secondaryChannelOffset) - center_freq = pHTInfo->primaryChannel + 2; - else if (PHY_DOUBLE_CHANNEL_HIGH_PRIMARY == - pHTInfo->secondaryChannelOffset) - center_freq = pHTInfo->primaryChannel - 2; - else - ch_width = CH_WIDTH_20MHZ; - } - - /* notify HAL */ - pe_debug("Channel Information in HT IE change" - "d; sending notification to HAL."); - pe_debug("Primary Channel: %d Secondary Chan" - "nel Offset: %d Channel Width: %d", - pHTInfo->primaryChannel, center_freq, - pe_session->htRecommendedTxWidthSet); - pe_session->channelChangeReasonCode = - LIM_SWITCH_CHANNEL_OPERATION; - mac->lim.gpchangeChannelCallback = NULL; - mac->lim.gpchangeChannelData = NULL; - - lim_send_switch_chnl_params(mac, (uint8_t) pHTInfo->primaryChannel, - center_freq, 0, ch_width, - pe_session->maxTxPower, - pe_session->peSessionId, - true, 0, 0); + lim_ht_switch_chnl_req(pe_session); /* In case of IBSS, if STA should update HT Info IE in its beacons. */ - if (LIM_IS_IBSS_ROLE(pe_session)) { + if (LIM_IS_IBSS_ROLE(pe_session)) sch_set_fixed_beacon_fields(mac, pe_session); - } - } + } /* End limUpdateStaRunTimeHTParams. */ /** @@ -7981,6 +8072,13 @@ QDF_STATUS lim_sta_mlme_vdev_start_send(struct vdev_mlme_obj *vdev_mlme, QDF_STATUS lim_sta_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme, uint16_t data_len, void *data) { + struct pe_session *session; + + session = (struct pe_session *)data; + if (!session) { + pe_err("Invalid session"); + return QDF_STATUS_E_INVAL; + } if (!vdev_mlme) { pe_err("vdev_mlme is NULL"); return QDF_STATUS_E_INVAL; @@ -7989,9 +8087,18 @@ QDF_STATUS lim_sta_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme, pe_err("event_data is NULL"); return QDF_STATUS_E_INVAL; } - if (mlme_is_chan_switch_in_progress(vdev_mlme->vdev)) - __lim_process_channel_switch_timeout((struct mac_context *)data); - + if (mlme_is_chan_switch_in_progress(vdev_mlme->vdev)) { + switch (session->channelChangeReasonCode) { + case LIM_SWITCH_CHANNEL_OPERATION: + __lim_process_channel_switch_timeout(session); + break; + case LIM_SWITCH_CHANNEL_HT_WIDTH: + lim_ht_switch_chnl_params(session); + break; + default: + break; + } + } return QDF_STATUS_SUCCESS; }