qcacmn: Add WLAN_VDEV_SS_MLO_SYNC_WAIT and WLAN_VDEV_SS_UP_ACTIVE

For MLO SAP, it can't generate beacon template until all the vdevs
start. To synchronize MLO vdevs start, we add two new substates
WLAN_VDEV_SS_MLO_SYNC_WAIT and WLAN_VDEV_SS_UP_ACTIVE whose parent
state is WLAN_VDEV_S_UP.
Once vdev gets vdev start rsp, notify MLO mgr, who checks whether all
vdevs are active, if so, trigger WLAN_VDEV_SM_EV_MLO_SYNC_COMPLETE for
the vdev which is in WLAN_VDEV_SS_MLO_SYNC_WAIT state.
After vdev translates to WLAN_VDEV_S_UP, MLO SAP will translate to
WLAN_VDEV_SS_MLO_SYNC_WAIT, while the other vdev will translate to
WLAN_VDEV_SS_UP_ACTIVE.
MLO sap will notify MLO mgr once it is in WLAN_VDEV_SS_MLO_SYNC_WAIT.
Then MLO mgr checks whether all the vdevs are active, if so, trigger
WLAN_VDEV_SM_EV_MLO_SYNC_COMPLETE for the vdev which is in
WLAN_VDEV_SS_MLO_SYNC_WAIT state.
If MLO SAP receives WLAN_VDEV_SM_EV_MLO_SYNC_COMPLETE in
WLAN_VDEV_SS_MLO_SYNC_WAIT state, it translates to WLAN_VDEV_SS_UP_ACTIVE

Change-Id: I8be9c02f62719dbdcf4af79d83173c316c64b765
CRs-Fixed: 2866103
This commit is contained in:
bings
2021-01-12 18:02:57 +08:00
committed by AnjaneeDevi Kapparapu
parent d617a3a77f
commit 4a8bafde55
5 changed files with 361 additions and 72 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -169,6 +169,10 @@
/* Fils discovery on 6G SAP*/
#define WLAN_VDEV_FEXT_FILS_DISC_6G_SAP 0x80000000
/* Feature more extension flags */
/* VDEV is MLO*/
#define WLAN_VDEV_FEXT2_MLO 0x00000001
/* VDEV OP flags */
/* if the vap destroyed by user */
#define WLAN_VDEV_OP_DELETE_PROGRESS 0x00000001
@@ -291,6 +295,7 @@ struct wlan_channel {
* @vdev_caps: VDEV capabilities
* @vdev_feat_caps: VDEV feature caps
* @vdev_feat_ext_caps: VDEV Extended feature caps
* @vdev_feat_ext2_caps: More VDEV Extended feature caps
* @vdev_op_flags: Operation flags
* @mataddr[]: MAT address
* @macaddr[]: VDEV self MAC address
@@ -313,6 +318,7 @@ struct wlan_objmgr_vdev_mlme {
uint32_t vdev_caps;
uint32_t vdev_feat_caps;
uint32_t vdev_feat_ext_caps;
uint32_t vdev_feat_ext2_caps;
uint32_t vdev_op_flags;
uint8_t mataddr[QDF_MAC_ADDR_SIZE];
uint8_t macaddr[QDF_MAC_ADDR_SIZE];
@@ -979,6 +985,55 @@ static inline uint8_t wlan_vdev_mlme_feat_ext_cap_get(
return (vdev->vdev_mlme.vdev_feat_ext_caps & cap) ? 1 : 0;
}
/**
* wlan_vdev_mlme_feat_ext2_cap_set() - set ext2 feature caps
* @vdev: VDEV object
* @cap: capabilities to be set
*
* API to set the MLME more extensive feature capabilities
*
* Return: void
*/
static inline void wlan_vdev_mlme_feat_ext2_cap_set(
struct wlan_objmgr_vdev *vdev,
uint32_t cap)
{
vdev->vdev_mlme.vdev_feat_ext2_caps |= cap;
}
/**
* wlan_vdev_mlme_feat_ext2_cap_clear() - clear ext2 feature caps
* @vdev: VDEV object
* @cap: capabilities to be cleared
*
* API to clear the MLME more extensive feature capabilities
*
* Return: void
*/
static inline void wlan_vdev_mlme_feat_ext2_cap_clear(
struct wlan_objmgr_vdev *vdev,
uint32_t cap)
{
vdev->vdev_mlme.vdev_feat_ext2_caps &= ~cap;
}
/**
* wlan_vdev_mlme_feat_ext2_cap_get() - get feature ext2 caps
* @vdev: VDEV object
* @cap: capabilities to be checked
*
* API to know MLME more ext feature capability is set or not
*
* Return: 1 -- if capabilities set
* 0 -- if capabilities clear
*/
static inline uint8_t wlan_vdev_mlme_feat_ext2_cap_get(
struct wlan_objmgr_vdev *vdev,
uint32_t cap)
{
return (vdev->vdev_mlme.vdev_feat_ext2_caps & cap) ? 1 : 0;
}
/**
* wlan_vdev_mlme_cap_set() - mlme caps set
* @vdev: VDEV object
@@ -1185,6 +1240,25 @@ static inline uint16_t wlan_vdev_get_peer_count(struct wlan_objmgr_vdev *vdev)
return vdev->vdev_objmgr.wlan_peer_count;
}
#ifdef WLAN_FEATURE_11BE_MLO
/**
* wlan_vdev_mlme_is_mlo_ap() - whether it is mlo ap or not
* @vdev: VDEV object
*
* Return: True if it is mlo ap, otherwise false.
*/
static inline bool wlan_vdev_mlme_is_mlo_ap(struct wlan_objmgr_vdev *vdev)
{
return (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
wlan_vdev_mlme_feat_ext2_cap_get(vdev, WLAN_VDEV_FEXT2_MLO);
}
#else
static inline bool wlan_vdev_mlme_is_mlo_ap(struct wlan_objmgr_vdev *vdev)
{
return false;
}
#endif
/**
* DOC: Examples to use VDEV ref count APIs
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -65,6 +65,8 @@ wlan_mlme_get_lmac_tx_ops(struct wlan_objmgr_psoc *psoc)
* @WLAN_VDEV_SS_STOP_DOWN_PROGRESS: Stop down progress sub state
* @WLAN_VDEV_SS_IDLE: Idle sub state (used, only if a state
* does not have substate)
* @WLAN_VDEV_SS_MLO_SYNC_WAIT: Sync wait sub state for MLO SAP
* @WLAN_VDEV_SS_UP_ACTIVE: Up active sub state
* @WLAN_VDEV_SS_MAX: Max substate
*/
enum wlan_vdev_state {
@@ -86,7 +88,9 @@ enum wlan_vdev_state {
WLAN_VDEV_SS_STOP_STOP_PROGRESS = 15,
WLAN_VDEV_SS_STOP_DOWN_PROGRESS = 16,
WLAN_VDEV_SS_IDLE = 17,
WLAN_VDEV_SS_MAX = 18,
WLAN_VDEV_SS_MLO_SYNC_WAIT = 18,
WLAN_VDEV_SS_UP_ACTIVE = 19,
WLAN_VDEV_SS_MAX = 20,
};
/**
@@ -126,6 +130,9 @@ enum wlan_vdev_state {
* @WLAN_VDEV_SM_EV_STOP_REQ: Invoke API to initiate STOP handshake
* @WLAN_VDEV_SM_EV_CHAN_SWITCH_DISABLED:Test only, CSA completes without
* change in channel
* @WLAN_VDEV_SM_EV_MLO_SYNC_COMPLETE: MLO mgr triggers this event for the mlo
* sap in vdev wait up state, if all the
* links finish vdev start rsp.
*/
enum wlan_vdev_sm_evt {
WLAN_VDEV_SM_EV_START = 0,
@@ -159,6 +166,7 @@ enum wlan_vdev_sm_evt {
WLAN_VDEV_SM_EV_ROAM = 28,
WLAN_VDEV_SM_EV_STOP_REQ = 29,
WLAN_VDEV_SM_EV_CHAN_SWITCH_DISABLED = 30,
WLAN_VDEV_SM_EV_MLO_SYNC_COMPLETE = 31,
};
/**

View File

@@ -441,78 +441,17 @@ static bool mlme_vdev_state_up_event(void *ctx, uint16_t event,
switch (event) {
case WLAN_VDEV_SM_EV_START_SUCCESS:
mlme_vdev_update_beacon(vdev_mlme, BEACON_INIT,
event_data_len, event_data);
if (mlme_vdev_up_send(vdev_mlme, event_data_len,
event_data) != QDF_STATUS_SUCCESS)
mlme_vdev_sm_deliver_event(vdev_mlme,
WLAN_VDEV_SM_EV_UP_FAIL,
event_data_len, event_data);
if (wlan_vdev_mlme_is_mlo_ap(vdev))
mlme_vdev_sm_transition_to(vdev_mlme,
WLAN_VDEV_SS_MLO_SYNC_WAIT);
else
mlme_vdev_notify_up_complete(vdev_mlme, event_data_len,
event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_SUSPEND_RESTART:
case WLAN_VDEV_SM_EV_HOST_RESTART:
case WLAN_VDEV_SM_EV_CSA_RESTART:
/* These events are not supported in STA mode */
if (mode == QDF_STA_MODE)
QDF_BUG(0);
/* fallthrough */
case WLAN_VDEV_SM_EV_DOWN:
mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND);
mlme_vdev_sm_transition_to(vdev_mlme,
WLAN_VDEV_SS_UP_ACTIVE);
mlme_vdev_sm_deliver_event(vdev_mlme, event,
event_data_len, event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_RADAR_DETECTED:
/* These events are not supported in STA mode */
if (mode == QDF_STA_MODE)
QDF_BUG(0);
mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND);
mlme_vdev_sm_deliver_event(vdev_mlme,
WLAN_VDEV_SM_EV_CSA_RESTART,
event_data_len, event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_UP_HOST_RESTART:
/* Reinit beacon, send template to FW(use ping-pong buffer) */
mlme_vdev_update_beacon(vdev_mlme, BEACON_UPDATE,
event_data_len, event_data);
/* fallthrough */
case WLAN_VDEV_SM_EV_START:
/* notify that UP command is completed */
mlme_vdev_notify_up_complete(vdev_mlme,
event_data_len, event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_FW_VDEV_RESTART:
mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_START);
mlme_vdev_sm_deliver_event(vdev_mlme,
WLAN_VDEV_SM_EV_RESTART_REQ,
event_data_len, event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_UP_FAIL:
mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND);
mlme_vdev_sm_deliver_event(vdev_mlme, event,
event_data_len, event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_ROAM:
mlme_vdev_notify_roam_start(vdev_mlme, event_data_len,
event_data);
status = true;
break;
default:
status = false;
break;
@@ -1643,6 +1582,233 @@ static bool mlme_vdev_subst_stop_down_progress_event(void *ctx,
return status;
}
/**
* mlme_vdev_subst_mlo_sync_wait_entry() - Entry API for mlo sync wait sub state
* @ctx: VDEV MLME object
*
* API to perform operations on moving to MLO-SYNC-WAIT substate
*
* Return: void
*/
static void mlme_vdev_subst_mlo_sync_wait_entry(void *ctx)
{
struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx;
struct wlan_objmgr_vdev *vdev;
vdev = vdev_mlme->vdev;
if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_UP)
QDF_BUG(0);
mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_MLO_SYNC_WAIT);
}
/**
* mlme_vdev_subst_mlo_sync_wait_exit() - Exit API for mlo sync wait sub state
* @ctx: VDEV MLME object
*
* API to perform operations on moving out of MLO-SYNC-WAIT substate
*
* Return: void
*/
static void mlme_vdev_subst_mlo_sync_wait_exit(void *ctx)
{
/* NONE */
}
/**
* mlme_vdev_subst_mlo_sync_wait_event() - Event handler API for mlo sync wait
* substate
* @ctx: VDEV MLME object
*
* API to handle events in MLO-SYNC-WAIT substate
*
* Return: SUCCESS: on handling event
* FAILURE: on ignoring the event
*/
static bool mlme_vdev_subst_mlo_sync_wait_event(void *ctx, uint16_t event,
uint16_t event_data_len,
void *event_data)
{
struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx;
bool status;
switch (event) {
case WLAN_VDEV_SM_EV_START_SUCCESS:
mlme_vdev_up_notify_mlo_mgr(vdev_mlme);
status = true;
break;
case WLAN_VDEV_SM_EV_MLO_SYNC_COMPLETE:
mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_SS_UP_ACTIVE);
mlme_vdev_sm_deliver_event(vdev_mlme, event,
event_data_len, event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_DOWN:
mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_STOP);
mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_STOP_REQ,
event_data_len, event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_RADAR_DETECTED:
mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_START);
mlme_vdev_sm_deliver_event(vdev_mlme,
WLAN_VDEV_SM_EV_RESTART_REQ,
event_data_len, event_data);
status = true;
break;
default:
status = false;
break;
}
return status;
}
/**
* mlme_vdev_subst_up_active_entry() - Entry API for up active sub state
* @ctx: VDEV MLME object
*
* API to perform operations on moving to UP-ACTIVE substate
*
* Return: void
*/
static void mlme_vdev_subst_up_active_entry(void *ctx)
{
struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx;
struct wlan_objmgr_vdev *vdev;
vdev = vdev_mlme->vdev;
if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_UP)
QDF_BUG(0);
mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_UP_ACTIVE);
}
/**
* mlme_vdev_subst_up_active_exit() - Exit API for up active sub state
* @ctx: VDEV MLME object
*
* API to perform operations on moving out of UP-ACTIVE substate
*
* Return: void
*/
static void mlme_vdev_subst_up_active_exit(void *ctx)
{
/* NONE */
}
/**
* mlme_vdev_subst_up_active_event() - Event handler API for up active substate
* @ctx: VDEV MLME object
*
* API to handle events in UP-ACTIVE substate
*
* Return: SUCCESS: on handling event
* FAILURE: on ignoring the event
*/
static bool mlme_vdev_subst_up_active_event(void *ctx, uint16_t event,
uint16_t event_data_len,
void *event_data)
{
struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx;
enum QDF_OPMODE mode;
struct wlan_objmgr_vdev *vdev;
bool status;
vdev = vdev_mlme->vdev;
mode = wlan_vdev_mlme_get_opmode(vdev);
switch (event) {
case WLAN_VDEV_SM_EV_START_SUCCESS:
if (wlan_vdev_mlme_is_mlo_ap(vdev))
QDF_BUG(0);
/* fallthrough */
case WLAN_VDEV_SM_EV_MLO_SYNC_COMPLETE:
mlme_vdev_update_beacon(vdev_mlme, BEACON_INIT,
event_data_len, event_data);
if (mlme_vdev_up_send(vdev_mlme, event_data_len,
event_data) != QDF_STATUS_SUCCESS)
mlme_vdev_sm_deliver_event(vdev_mlme,
WLAN_VDEV_SM_EV_UP_FAIL,
event_data_len, event_data);
else
mlme_vdev_notify_up_complete(vdev_mlme, event_data_len,
event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_SUSPEND_RESTART:
case WLAN_VDEV_SM_EV_HOST_RESTART:
case WLAN_VDEV_SM_EV_CSA_RESTART:
/* These events are not supported in STA mode */
if (mode == QDF_STA_MODE)
QDF_BUG(0);
/* fallthrough */
case WLAN_VDEV_SM_EV_DOWN:
mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND);
mlme_vdev_sm_deliver_event(vdev_mlme, event,
event_data_len, event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_RADAR_DETECTED:
/* These events are not supported in STA mode */
if (mode == QDF_STA_MODE)
QDF_BUG(0);
mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND);
mlme_vdev_sm_deliver_event(vdev_mlme,
WLAN_VDEV_SM_EV_CSA_RESTART,
event_data_len, event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_UP_HOST_RESTART:
/* Reinit beacon, send template to FW(use ping-pong buffer) */
mlme_vdev_update_beacon(vdev_mlme, BEACON_UPDATE,
event_data_len, event_data);
/* fallthrough */
case WLAN_VDEV_SM_EV_START:
/* notify that UP command is completed */
mlme_vdev_notify_up_complete(vdev_mlme,
event_data_len, event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_FW_VDEV_RESTART:
mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_START);
mlme_vdev_sm_deliver_event(vdev_mlme,
WLAN_VDEV_SM_EV_RESTART_REQ,
event_data_len, event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_UP_FAIL:
mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND);
mlme_vdev_sm_deliver_event(vdev_mlme, event,
event_data_len, event_data);
status = true;
break;
case WLAN_VDEV_SM_EV_ROAM:
mlme_vdev_notify_roam_start(vdev_mlme, event_data_len,
event_data);
status = true;
break;
default:
status = false;
break;
}
return status;
}
static const char *vdev_sm_event_names[] = {
"EV_START",
@@ -1676,6 +1842,7 @@ static const char *vdev_sm_event_names[] = {
"EV_ROAM",
"EV_STOP_REQ",
"EV_CHAN_SWITCH_DISABLED",
"EV_MLO_SYNC_COMPLETE",
};
struct wlan_sm_state_info sm_info[] = {
@@ -1859,6 +2026,26 @@ struct wlan_sm_state_info sm_info[] = {
NULL,
NULL,
},
{
(uint8_t)WLAN_VDEV_SS_MLO_SYNC_WAIT,
(uint8_t)WLAN_VDEV_S_UP,
(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
false,
"UP-MLO-SYNC-WAIT",
mlme_vdev_subst_mlo_sync_wait_entry,
mlme_vdev_subst_mlo_sync_wait_exit,
mlme_vdev_subst_mlo_sync_wait_event
},
{
(uint8_t)WLAN_VDEV_SS_UP_ACTIVE,
(uint8_t)WLAN_VDEV_S_UP,
(uint8_t)WLAN_SM_ENGINE_STATE_NONE,
false,
"UP-UP-ACTIVE",
mlme_vdev_subst_up_active_entry,
mlme_vdev_subst_up_active_exit,
mlme_vdev_subst_up_active_event
},
{
(uint8_t)WLAN_VDEV_SS_MAX,
(uint8_t)WLAN_SM_ENGINE_STATE_NONE,

View File

@@ -622,6 +622,23 @@ static inline QDF_STATUS mlme_vdev_dfs_cac_wait_notify(
return ret;
}
#ifdef WLAN_FEATURE_11BE_MLO
/**
* mlme_vdev_up_notify_mlo_mgr - notify mlo link is ready to up
* @vdev_mlme_obj: VDEV MLME comp object
*
* Return: VOID.
*/
static inline void mlme_vdev_up_notify_mlo_mgr(struct vdev_mlme_obj *vdev_mlme)
{
mlo_handle_link_up(vdev_mlme->vdev);
}
#else
static inline void mlme_vdev_up_notify_mlo_mgr(struct vdev_mlme_obj *vdev_mlme)
{
}
#endif
#ifdef VDEV_SM_LOCK_SUPPORT
/**
* mlme_vdev_sm_spinlock_create - Create VDEV MLME spinlock

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2019, 2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -158,7 +158,7 @@ QDF_STATUS wlan_vdev_allow_connect_n_tx(struct wlan_objmgr_vdev *vdev)
state = wlan_vdev_mlme_get_state(vdev);
substate = wlan_vdev_mlme_get_substate(vdev);
if ((state == WLAN_VDEV_S_UP) ||
if ((state == WLAN_VDEV_S_UP && substate == WLAN_VDEV_SS_UP_ACTIVE) ||
((state == WLAN_VDEV_S_SUSPEND) &&
(substate == WLAN_VDEV_SS_SUSPEND_CSA_RESTART)))
return QDF_STATUS_SUCCESS;
@@ -275,9 +275,12 @@ void wlan_vdev_mlme_cmd_unlock(struct wlan_objmgr_vdev *vdev)
QDF_STATUS wlan_vdev_mlme_is_scan_allowed(struct wlan_objmgr_vdev *vdev)
{
enum wlan_vdev_state state;
enum wlan_vdev_state substate;
state = wlan_vdev_mlme_get_state(vdev);
if ((state == WLAN_VDEV_S_INIT) || (state == WLAN_VDEV_S_UP) ||
substate = wlan_vdev_mlme_get_substate(vdev);
if ((state == WLAN_VDEV_S_INIT) ||
(state == WLAN_VDEV_S_UP && substate == WLAN_VDEV_SS_UP_ACTIVE) ||
(state == WLAN_VDEV_S_STOP))
return QDF_STATUS_SUCCESS;