qcacld-3.0: Involve VDEV SM when STA switch channel width

When found AP channel width change from beacon:
    1. Set channel switch in progress with reason
	LIM_SWITCH_CHANNEL_HT_WIDTH, Send
	WLAN_VDEV_SM_EV_FW_VDEV_RESTART.
    2. Call lim_ht_switch_chnl_params in
        mlme_vdev_restart_send if reason is
	LIM_SWITCH_CHANNEL_HT_WIDTH, set ht width switch
	callback.
    3. Send WLAN_VDEV_SM_EV_RESTART_RESP in
        wma_vdev_start_resp_handler and clear channel switch in
	progress.
    4. Send WMA_SWITCH_CHANNEL_RSP in mlme_vdev_start_continue.
    5. Send WLAN_VDEV_SM_EV_START_SUCCESS in ht width switch
	callback to up vdev.

Change-Id: I46651e9aa17ebe049e44179d3a8fcc5a214762be
CRs-Fixed: 2372486
This commit is contained in:
Jianmin Zhu 2018-12-20 13:03:19 +08:00 • committed by nshrivas
commit f2de84f371
3 changed files with 160 additions and 51 deletions

View file

@ -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.

View file

@ -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 {

View file

@ -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;
}