qcacld-3.0: Trigger roam if no active MLO link
In multilink ML STA, if one link is removed by AP, and no other active link, trigger roam by roaming invoke command. Change-Id: I61d9413e2102315b258f946af2193f7cfb7b91aa CRs-Fixed: 3352870
This commit is contained in:

committed by
Madan Koyyalamudi

parent
7a18b22c41
commit
ff974bc970
@@ -3458,6 +3458,85 @@ bool policy_mgr_is_ml_vdev_id(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
|
|||||||
return is_mlo;
|
return is_mlo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* policy_mgr_get_ml_sta_info() - Get number of ML STA vdev ids and freq list
|
||||||
|
* @pm_ctx: pm_ctx ctx
|
||||||
|
* @num_ml_sta: Return number of ML STA present
|
||||||
|
* @num_disabled_ml_sta: Return number of disabled ML STA links
|
||||||
|
* @ml_vdev_lst: Return ML STA vdev id list
|
||||||
|
* @ml_freq_lst: Return ML STA freq list
|
||||||
|
* @num_non_ml: Return number of non-ML STA present
|
||||||
|
* @non_ml_vdev_lst: Return non-ML STA vdev id list
|
||||||
|
* @non_ml_freq_lst: Return non-ML STA freq list
|
||||||
|
*
|
||||||
|
* Return: void
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
policy_mgr_get_ml_sta_info(struct policy_mgr_psoc_priv_obj *pm_ctx,
|
||||||
|
uint8_t *num_ml_sta,
|
||||||
|
uint8_t *num_disabled_ml_sta,
|
||||||
|
uint8_t *ml_vdev_lst,
|
||||||
|
qdf_freq_t *ml_freq_lst,
|
||||||
|
uint8_t *num_non_ml,
|
||||||
|
uint8_t *non_ml_vdev_lst,
|
||||||
|
qdf_freq_t *non_ml_freq_lst)
|
||||||
|
{
|
||||||
|
struct wlan_objmgr_vdev *vdev;
|
||||||
|
uint8_t vdev_id, conn_index;
|
||||||
|
qdf_freq_t freq;
|
||||||
|
|
||||||
|
*num_ml_sta = 0;
|
||||||
|
*num_disabled_ml_sta = 0;
|
||||||
|
if (num_non_ml)
|
||||||
|
*num_non_ml = 0;
|
||||||
|
|
||||||
|
qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
|
||||||
|
for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS;
|
||||||
|
conn_index++) {
|
||||||
|
if (!pm_conc_connection_list[conn_index].in_use)
|
||||||
|
continue;
|
||||||
|
if (pm_conc_connection_list[conn_index].mode != PM_STA_MODE)
|
||||||
|
continue;
|
||||||
|
vdev_id = pm_conc_connection_list[conn_index].vdev_id;
|
||||||
|
freq = pm_conc_connection_list[conn_index].freq;
|
||||||
|
|
||||||
|
/* add ml sta vdev and freq list */
|
||||||
|
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(pm_ctx->psoc,
|
||||||
|
vdev_id,
|
||||||
|
WLAN_POLICY_MGR_ID);
|
||||||
|
if (!vdev) {
|
||||||
|
policy_mgr_err("invalid vdev for id %d", vdev_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
|
||||||
|
ml_vdev_lst[*num_ml_sta] = vdev_id;
|
||||||
|
ml_freq_lst[(*num_ml_sta)++] = freq;
|
||||||
|
} else if (num_non_ml) {
|
||||||
|
if (non_ml_vdev_lst)
|
||||||
|
non_ml_vdev_lst[*num_non_ml] = vdev_id;
|
||||||
|
if (non_ml_freq_lst)
|
||||||
|
non_ml_freq_lst[*num_non_ml] = freq;
|
||||||
|
(*num_non_ml)++;
|
||||||
|
}
|
||||||
|
wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
|
||||||
|
}
|
||||||
|
/* Get disabled link info as well and keep it at last */
|
||||||
|
for (conn_index = 0; conn_index < MAX_NUMBER_OF_DISABLE_LINK;
|
||||||
|
conn_index++) {
|
||||||
|
if (!pm_disabled_ml_links[conn_index].in_use)
|
||||||
|
continue;
|
||||||
|
if (pm_disabled_ml_links[conn_index].mode != PM_STA_MODE)
|
||||||
|
continue;
|
||||||
|
ml_vdev_lst[*num_ml_sta] =
|
||||||
|
pm_disabled_ml_links[conn_index].vdev_id;
|
||||||
|
ml_freq_lst[(*num_ml_sta)++] =
|
||||||
|
pm_disabled_ml_links[conn_index].freq;
|
||||||
|
(*num_disabled_ml_sta)++;
|
||||||
|
}
|
||||||
|
qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t policy_mgr_get_disabled_ml_links_count(struct wlan_objmgr_psoc *psoc)
|
uint32_t policy_mgr_get_disabled_ml_links_count(struct wlan_objmgr_psoc *psoc)
|
||||||
{
|
{
|
||||||
uint32_t i, count = 0;
|
uint32_t i, count = 0;
|
||||||
@@ -3710,6 +3789,137 @@ policy_mgr_get_link_in_progress(struct policy_mgr_psoc_priv_obj *pm_ctx)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* policy_mgr_trigger_roam_on_link_removal() - Trigger roam on link removal
|
||||||
|
* @vdev: vdev object
|
||||||
|
*
|
||||||
|
* In multilink ML STA, if one link is removed by AP, and no other active
|
||||||
|
* link, trigger roam by roaming invoke command.
|
||||||
|
*
|
||||||
|
* Return: void
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
policy_mgr_trigger_roam_on_link_removal(struct wlan_objmgr_vdev *vdev)
|
||||||
|
{
|
||||||
|
struct wlan_objmgr_psoc *psoc;
|
||||||
|
struct wlan_objmgr_pdev *pdev;
|
||||||
|
struct wlan_objmgr_vdev *ml_vdev;
|
||||||
|
struct policy_mgr_psoc_priv_obj *pm_ctx;
|
||||||
|
uint8_t num_ml_sta = 0, num_disabled_ml_sta = 0;
|
||||||
|
uint8_t num_active_ml_sta;
|
||||||
|
uint8_t ml_sta_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
|
||||||
|
qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
|
||||||
|
uint8_t vdev_id = wlan_vdev_get_id(vdev);
|
||||||
|
uint8_t assoc_vdev_id = WLAN_INVALID_VDEV_ID;
|
||||||
|
uint8_t removed_vdev_id = WLAN_INVALID_VDEV_ID;
|
||||||
|
struct qdf_mac_addr bssid;
|
||||||
|
QDF_STATUS status;
|
||||||
|
bool ml_sta_is_not_connected = false;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
psoc = wlan_vdev_get_psoc(vdev);
|
||||||
|
if (!psoc) {
|
||||||
|
policy_mgr_err("Failed to get psoc");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pdev = wlan_vdev_get_pdev(vdev);
|
||||||
|
if (!pdev) {
|
||||||
|
policy_mgr_err("Failed to get pdev");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pm_ctx = policy_mgr_get_context(psoc);
|
||||||
|
if (!pm_ctx) {
|
||||||
|
policy_mgr_err("Invalid Context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
policy_mgr_get_ml_sta_info(pm_ctx, &num_ml_sta, &num_disabled_ml_sta,
|
||||||
|
ml_sta_vdev_lst, ml_freq_lst,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
if (!num_ml_sta) {
|
||||||
|
policy_mgr_debug("unexpected event, no ml sta");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (num_ml_sta > MAX_NUMBER_OF_CONC_CONNECTIONS ||
|
||||||
|
num_disabled_ml_sta > MAX_NUMBER_OF_CONC_CONNECTIONS ||
|
||||||
|
num_ml_sta <= num_disabled_ml_sta) {
|
||||||
|
policy_mgr_debug("unexpected ml sta num %d %d",
|
||||||
|
num_ml_sta, num_disabled_ml_sta);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
num_active_ml_sta = num_ml_sta;
|
||||||
|
if (num_ml_sta >= num_disabled_ml_sta)
|
||||||
|
num_active_ml_sta = num_ml_sta - num_disabled_ml_sta;
|
||||||
|
|
||||||
|
for (i = 0; i < num_active_ml_sta; i++) {
|
||||||
|
if (!wlan_get_vdev_link_removed_flag_by_vdev_id(
|
||||||
|
psoc, ml_sta_vdev_lst[i]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* After link removal, one link is still active, no need invoke
|
||||||
|
* roaming.
|
||||||
|
* For Single link MLO, FW will do roaming automatically.
|
||||||
|
*/
|
||||||
|
if (i < num_active_ml_sta || num_ml_sta < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* For multi-link MLO STA, if one link is removed and no other active
|
||||||
|
* link, then trigger roaming. the other link may have concurrency
|
||||||
|
* limitation and can't be active.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < num_ml_sta; i++) {
|
||||||
|
if (removed_vdev_id == WLAN_INVALID_VDEV_ID &&
|
||||||
|
wlan_get_vdev_link_removed_flag_by_vdev_id(
|
||||||
|
psoc, ml_sta_vdev_lst[i])) {
|
||||||
|
policy_mgr_debug("removal link vdev %d is removed ",
|
||||||
|
vdev_id);
|
||||||
|
removed_vdev_id = ml_sta_vdev_lst[i];
|
||||||
|
}
|
||||||
|
ml_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
|
||||||
|
pm_ctx->psoc,
|
||||||
|
ml_sta_vdev_lst[i],
|
||||||
|
WLAN_POLICY_MGR_ID);
|
||||||
|
if (!ml_vdev) {
|
||||||
|
policy_mgr_err("invalid vdev for id %d",
|
||||||
|
ml_sta_vdev_lst[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!wlan_cm_is_vdev_connected(ml_vdev)) {
|
||||||
|
policy_mgr_debug("ml sta vdev %d is not connected state",
|
||||||
|
ml_sta_vdev_lst[i]);
|
||||||
|
ml_sta_is_not_connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlan_objmgr_vdev_release_ref(ml_vdev, WLAN_POLICY_MGR_ID);
|
||||||
|
|
||||||
|
if (assoc_vdev_id == WLAN_INVALID_VDEV_ID &&
|
||||||
|
!wlan_vdev_mlme_get_is_mlo_link(psoc,
|
||||||
|
ml_sta_vdev_lst[i]))
|
||||||
|
assoc_vdev_id = ml_sta_vdev_lst[i];
|
||||||
|
}
|
||||||
|
if (removed_vdev_id == WLAN_INVALID_VDEV_ID) {
|
||||||
|
policy_mgr_debug("no link removed, unexpected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (assoc_vdev_id == WLAN_INVALID_VDEV_ID) {
|
||||||
|
policy_mgr_debug("no find assoc vdev, unexpected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ml_sta_is_not_connected) {
|
||||||
|
policy_mgr_debug("ml sta is non-connected state, don't trigger roam");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* trigger roaming */
|
||||||
|
policy_mgr_debug("link removal detected, try roaming on vdev id: %d",
|
||||||
|
assoc_vdev_id);
|
||||||
|
qdf_zero_macaddr(&bssid);
|
||||||
|
status = wlan_cm_roam_invoke(pdev, assoc_vdev_id, &bssid, 0,
|
||||||
|
CM_ROAMING_LINK_REMOVAL);
|
||||||
|
if (QDF_IS_STATUS_ERROR(status))
|
||||||
|
policy_mgr_err("roam invoke failed");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
policy_mgr_handle_link_enable_disable_resp(struct wlan_objmgr_vdev *vdev,
|
policy_mgr_handle_link_enable_disable_resp(struct wlan_objmgr_vdev *vdev,
|
||||||
void *arg,
|
void *arg,
|
||||||
@@ -3803,6 +4013,8 @@ policy_mgr_handle_link_enable_disable_resp(struct wlan_objmgr_vdev *vdev,
|
|||||||
req->param.force_mode);
|
req->param.force_mode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (req->param.reason == MLO_LINK_FORCE_REASON_LINK_REMOVAL)
|
||||||
|
policy_mgr_trigger_roam_on_link_removal(vdev);
|
||||||
|
|
||||||
complete_evnt:
|
complete_evnt:
|
||||||
policy_mgr_set_link_in_progress(pm_ctx, false);
|
policy_mgr_set_link_in_progress(pm_ctx, false);
|
||||||
@@ -4767,85 +4979,6 @@ policy_mgr_fill_ml_inactive_link_vdev_bitmap(
|
|||||||
req->param.inactive_vdev_bitmap[1]);
|
req->param.inactive_vdev_bitmap[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* policy_mgr_get_ml_sta_info() - Get number of ML STA vdev ids and freq list
|
|
||||||
* @pm_ctx: pm_ctx ctx
|
|
||||||
* @num_ml_sta: Return number of ML STA present
|
|
||||||
* @num_disabled_ml_sta: Return number of disabled ML STA links
|
|
||||||
* @ml_vdev_lst: Return ML STA vdev id list
|
|
||||||
* @ml_freq_lst: Return ML STA freq list
|
|
||||||
* @num_non_ml: Return number of non-ML STA present
|
|
||||||
* @non_ml_vdev_lst: Return non-ML STA vdev id list
|
|
||||||
* @non_ml_freq_lst: Return non-ML STA freq list
|
|
||||||
*
|
|
||||||
* Return: void
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
policy_mgr_get_ml_sta_info(struct policy_mgr_psoc_priv_obj *pm_ctx,
|
|
||||||
uint8_t *num_ml_sta,
|
|
||||||
uint8_t *num_disabled_ml_sta,
|
|
||||||
uint8_t *ml_vdev_lst,
|
|
||||||
qdf_freq_t *ml_freq_lst,
|
|
||||||
uint8_t *num_non_ml,
|
|
||||||
uint8_t *non_ml_vdev_lst,
|
|
||||||
qdf_freq_t *non_ml_freq_lst)
|
|
||||||
{
|
|
||||||
struct wlan_objmgr_vdev *vdev;
|
|
||||||
uint8_t vdev_id, conn_index;
|
|
||||||
qdf_freq_t freq;
|
|
||||||
|
|
||||||
*num_ml_sta = 0;
|
|
||||||
*num_disabled_ml_sta = 0;
|
|
||||||
if (num_non_ml)
|
|
||||||
*num_non_ml = 0;
|
|
||||||
|
|
||||||
qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
|
|
||||||
for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS;
|
|
||||||
conn_index++) {
|
|
||||||
if (!pm_conc_connection_list[conn_index].in_use)
|
|
||||||
continue;
|
|
||||||
if (pm_conc_connection_list[conn_index].mode != PM_STA_MODE)
|
|
||||||
continue;
|
|
||||||
vdev_id = pm_conc_connection_list[conn_index].vdev_id;
|
|
||||||
freq = pm_conc_connection_list[conn_index].freq;
|
|
||||||
|
|
||||||
/* add ml sta vdev and freq list */
|
|
||||||
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(pm_ctx->psoc,
|
|
||||||
vdev_id,
|
|
||||||
WLAN_POLICY_MGR_ID);
|
|
||||||
if (!vdev) {
|
|
||||||
policy_mgr_err("invalid vdev for id %d", vdev_id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
|
|
||||||
ml_vdev_lst[*num_ml_sta] = vdev_id;
|
|
||||||
ml_freq_lst[(*num_ml_sta)++] = freq;
|
|
||||||
} else if (num_non_ml) {
|
|
||||||
if (non_ml_vdev_lst)
|
|
||||||
non_ml_vdev_lst[*num_non_ml] = vdev_id;
|
|
||||||
if (non_ml_freq_lst)
|
|
||||||
non_ml_freq_lst[*num_non_ml] = freq;
|
|
||||||
(*num_non_ml)++;
|
|
||||||
}
|
|
||||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
|
|
||||||
}
|
|
||||||
/* Get disabled link info as well and keep it at last */
|
|
||||||
for (conn_index = 0; conn_index < MAX_NUMBER_OF_DISABLE_LINK;
|
|
||||||
conn_index++) {
|
|
||||||
if (!pm_disabled_ml_links[conn_index].in_use)
|
|
||||||
continue;
|
|
||||||
if (pm_disabled_ml_links[conn_index].mode != PM_STA_MODE)
|
|
||||||
continue;
|
|
||||||
ml_vdev_lst[*num_ml_sta] =
|
|
||||||
pm_disabled_ml_links[conn_index].vdev_id;
|
|
||||||
ml_freq_lst[(*num_ml_sta)++] =
|
|
||||||
pm_disabled_ml_links[conn_index].freq;
|
|
||||||
(*num_disabled_ml_sta)++;
|
|
||||||
}
|
|
||||||
qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* policy_mgr_handle_ml_sta_link_state_allowed() - Check ml sta connection to
|
* policy_mgr_handle_ml_sta_link_state_allowed() - Check ml sta connection to
|
||||||
* allow link state change.
|
* allow link state change.
|
||||||
|
@@ -1238,7 +1238,9 @@ QDF_STATUS cm_fw_roam_invoke_fail(struct wlan_objmgr_psoc *psoc,
|
|||||||
*/
|
*/
|
||||||
if (qdf_is_macaddr_broadcast(&bssid))
|
if (qdf_is_macaddr_broadcast(&bssid))
|
||||||
mlme_debug("Keep current connection");
|
mlme_debug("Keep current connection");
|
||||||
else if (source == CM_ROAMING_HOST || source == CM_ROAMING_NUD_FAILURE)
|
else if (source == CM_ROAMING_HOST ||
|
||||||
|
source == CM_ROAMING_NUD_FAILURE ||
|
||||||
|
source == CM_ROAMING_LINK_REMOVAL)
|
||||||
status = mlo_disconnect(vdev, CM_ROAM_DISCONNECT,
|
status = mlo_disconnect(vdev, CM_ROAM_DISCONNECT,
|
||||||
REASON_USER_TRIGGERED_ROAM_FAILURE,
|
REASON_USER_TRIGGERED_ROAM_FAILURE,
|
||||||
NULL);
|
NULL);
|
||||||
|
@@ -5654,6 +5654,10 @@ QDF_STATUS cm_start_roam_invoke(struct wlan_objmgr_psoc *psoc,
|
|||||||
/* Ignore BSSID and channel validation for FW host roam */
|
/* Ignore BSSID and channel validation for FW host roam */
|
||||||
if (source == CM_ROAMING_FW)
|
if (source == CM_ROAMING_FW)
|
||||||
goto send_evt;
|
goto send_evt;
|
||||||
|
if (source == CM_ROAMING_LINK_REMOVAL) {
|
||||||
|
cm_req->roam_req.req.forced_roaming = true;
|
||||||
|
goto send_evt;
|
||||||
|
}
|
||||||
|
|
||||||
if (cm_dlm_is_bssid_in_reject_list(psoc, bssid, vdev_id)) {
|
if (cm_dlm_is_bssid_in_reject_list(psoc, bssid, vdev_id)) {
|
||||||
mlme_debug("BSSID is in reject list, aborting roam invoke");
|
mlme_debug("BSSID is in reject list, aborting roam invoke");
|
||||||
|
Reference in New Issue
Block a user