qcacmn: Add MLO STA disconnect API definitions

Add MLO STA disconnect API definitions.

Change-Id: I7da336d7c634cc1408f7e92a0276ee950eed6ed6
This commit is contained in:
Himanshu Batra
2021-05-19 14:40:15 +05:30
committed by Madan Koyyalamudi
부모 e9f5df7e52
커밋 7d92d3dd78
2개의 변경된 파일648개의 추가작업 그리고 22개의 파일을 삭제

파일 보기

@@ -27,23 +27,33 @@
#include <wlan_scan_api.h>
#ifdef WLAN_FEATURE_11BE_MLO
/**
* mlo_disconnect_no_lock - Start the disconnection process without acquiring
* ML dev lock
*
* @vdev: pointer to vdev
* @source: source of the request (can be connect or disconnect request)
* @reason_code: reason for disconnect
* @bssid: BSSID
*
* Return: QDF_STATUS
*/
static QDF_STATUS mlo_disconnect_no_lock(struct wlan_objmgr_vdev *vdev,
enum wlan_cm_source source,
enum wlan_reason_code reason_code,
struct qdf_mac_addr *bssid);
/*
* mlo_get_assoc_link_vdev - API to get assoc link vdev
*
* @mlo_dev_ctx: mlo dev ctx
* @mlo_dev_ctx: pointer to mlo dev context
*
* Return: MLD assoc link vdev
*/
static inline struct wlan_objmgr_vdev *
mlo_get_assoc_link_vdev(struct wlan_objmgr_vdev *vdev)
mlo_get_assoc_link_vdev(struct wlan_mlo_dev_context *mlo_dev_ctx)
{
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
uint8_t i = 0;
if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
return NULL;
if (!mlo_dev_ctx)
return NULL;
@@ -51,7 +61,8 @@ mlo_get_assoc_link_vdev(struct wlan_objmgr_vdev *vdev)
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
if (!wlan_vdev_mlme_is_mlo_link_vdev(mlo_dev_ctx->wlan_vdev_list[i]))
if (wlan_vdev_mlme_is_mlo_vdev(mlo_dev_ctx->wlan_vdev_list[i]) &&
!wlan_vdev_mlme_is_mlo_link_vdev(mlo_dev_ctx->wlan_vdev_list[i]))
return mlo_dev_ctx->wlan_vdev_list[i];
}
return NULL;
@@ -60,7 +71,12 @@ mlo_get_assoc_link_vdev(struct wlan_objmgr_vdev *vdev)
struct wlan_objmgr_vdev *
ucfg_mlo_get_assoc_link_vdev(struct wlan_objmgr_vdev *vdev)
{
return mlo_get_assoc_link_vdev(vdev);
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
if (!mlo_dev_ctx || !wlan_vdev_mlme_is_mlo_vdev(vdev))
return NULL;
return mlo_get_assoc_link_vdev(mlo_dev_ctx);
}
#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
@@ -68,7 +84,7 @@ static QDF_STATUS
mlo_validate_connect_req(struct wlan_mlo_dev_context *mlo_dev_ctx,
struct wlan_cm_connect_req *req)
{
/* MCC: check back to back connect handling */
/* check back to back connect handling */
return QDF_STATUS_SUCCESS;
}
#else
@@ -85,7 +101,7 @@ bool mlo_is_mld_connected(struct wlan_objmgr_vdev *vdev)
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
uint8_t i = 0;
if (!mlo_dev_ctx)
if (!mlo_dev_ctx || !wlan_vdev_mlme_is_mlo_vdev(vdev))
return true;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
@@ -118,7 +134,7 @@ bool mlo_is_mld_disconnected(struct wlan_objmgr_vdev *vdev)
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
uint8_t i = 0;
if (!mlo_dev_ctx)
if (!mlo_dev_ctx || !wlan_vdev_mlme_is_mlo_vdev(vdev))
return true;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
@@ -206,7 +222,6 @@ mlo_validate_connect_req(struct wlan_mlo_dev_context *mlo_dev_ctx,
}
#endif
#ifdef WLAN_FEATURE_11BE_MLO
QDF_STATUS mlo_connect(struct wlan_objmgr_vdev *vdev,
struct wlan_cm_connect_req *req)
{
@@ -372,18 +387,18 @@ void mlo_sta_link_connect_notify(struct wlan_objmgr_vdev *vdev,
mlo_debug("Vdev: %d", wlan_vdev_get_id(vdev));
if (wlan_cm_is_vdev_disconnected(vdev)) {
// Connect Failure
if (vdev == wlan_mlo_get_assoc_link_vdev(vdev)) {
if (vdev == mlo_get_assoc_link_vdev(mlo_dev_ctx)) {
return;
} else {
if (rsp->reason == CM_NO_CANDIDATE_FOUND ||
rsp->reason == CM_HW_MODE_FAILURE ||
rsp->reason == CM_SER_FAILURE)
mlo_disconnect_no_lock(
vdev, CM_OSIF_MLO_DISCONNECT,
vdev, CM_OSIF_DISCONNECT,
REASON_UNSPEC_FAILURE, NULL);
else
mlo_disconnect(
vdev, CM_OSIF_MLO_DISCONNECT,
vdev, CM_OSIF_DISCONNECT,
REASON_UNSPEC_FAILURE, NULL);
return;
}
@@ -411,21 +426,510 @@ void mlo_sta_link_connect_notify(struct wlan_objmgr_vdev *vdev,
}
}
/* STA disconnect */
/*
* mlo_get_connected_link_vdev - API to get 1st connected link vdev
*
* @mlo_dev_ctx: mlo dev ctx
*
* Return: 1st connected link vdev in ML dev, NULL if none of the link vdev
* is connected
*/
static struct wlan_objmgr_vdev
*mlo_get_connected_link_vdev(struct wlan_mlo_dev_context *mlo_dev_ctx)
{
uint8_t i = 0;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
if ((mlo_dev_ctx->wlan_vdev_list[i] !=
mlo_get_assoc_link_vdev(mlo_dev_ctx)) &&
wlan_cm_is_vdev_connected(mlo_dev_ctx->wlan_vdev_list[i]))
return mlo_dev_ctx->wlan_vdev_list[i];
}
return NULL;
}
/**
* mlo_send_link_disconnect- Issue the disconnect request on MLD links
*
* @mlo_dev_ctx: pointer to mlo dev context
* @source: disconnect source
* @reason_code: disconnect reason
* @bssid: bssid of AP to disconnect, can be null if not known
*
* Return: QDF_STATUS
*/
#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
static QDF_STATUS
mlo_send_link_disconnect(struct wlan_mlo_dev_context *mlo_dev_ctx,
enum wlan_cm_source source,
enum wlan_reason_code reason_code,
struct qdf_mac_addr *bssid)
{
uint8_t i = 0;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links) &&
mlo_dev_ctx->wlan_vdev_list[i] != mlo_get_assoc_link_vdev(mlo_dev_ctx))
wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i],
source, reason_code, NULL);
}
wlan_cm_disconnect(mlo_get_assoc_link_vdev(mlo_dev_ctx),
source, reason_code, NULL);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS
mlo_send_link_disconnect_sync(struct wlan_mlo_dev_context *mlo_dev_ctx,
enum wlan_cm_source source,
enum wlan_reason_code reason_code,
struct qdf_mac_addr *bssid)
{
uint8_t i = 0;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links) &&
mlo_dev_ctx->wlan_vdev_list[i] != mlo_get_assoc_link_vdev(mlo_dev_ctx))
wlan_cm_disconnect_sync(mlo_dev_ctx->wlan_vdev_list[i],
source, reason_code);
}
wlan_cm_disconnect_sync(mlo_get_assoc_link_vdev(mlo_dev_ctx),
source, reason_code);
return QDF_STATUS_SUCCESS;
}
#else
static QDF_STATUS
mlo_send_link_disconnect(struct wlan_mlo_dev_context *mlo_dev_ctx,
enum wlan_cm_source source,
enum wlan_reason_code reason_code,
struct qdf_mac_addr *bssid)
{
uint8_t i = 0;
QDF_STATUS status = QDF_STATUS_E_ALREADY;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links)) {
if (wlan_cm_is_vdev_connecting(
mlo_dev_ctx->wlan_vdev_list[i]) ||
wlan_cm_is_vdev_disconnecting(
mlo_dev_ctx->wlan_vdev_list[i]) ||
wlan_cm_is_vdev_roaming(
mlo_dev_ctx->wlan_vdev_list[i])) {
wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i],
source, reason_code, NULL);
return QDF_STATUS_SUCCESS;
}
}
}
return status;
}
static QDF_STATUS
mlo_send_link_disconnect_sync(struct wlan_mlo_dev_context *mlo_dev_ctx,
enum wlan_cm_source source,
enum wlan_reason_code reason_code,
struct qdf_mac_addr *bssid)
{
uint8_t i = 0;
QDF_STATUS status = QDF_STATUS_E_ALREADY;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links)) {
if (wlan_cm_is_vdev_connecting(
mlo_dev_ctx->wlan_vdev_list[i]) ||
wlan_cm_is_vdev_disconnecting(
mlo_dev_ctx->wlan_vdev_list[i]) ||
wlan_cm_is_vdev_roaming(
mlo_dev_ctx->wlan_vdev_list[i])) {
wlan_cm_disconnect_sync(
mlo_dev_ctx->wlan_vdev_list[i],
source, reason_code);
return QDF_STATUS_SUCCESS;
}
}
}
return status;
}
#endif
static QDF_STATUS mlo_disconnect_no_lock(struct wlan_objmgr_vdev *vdev,
enum wlan_cm_source source,
enum wlan_reason_code reason_code,
struct qdf_mac_addr *bssid)
{
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
struct wlan_objmgr_vdev *tmp_vdev = vdev;
struct wlan_mlo_sta *sta_ctx = NULL;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (mlo_dev_ctx) {
sta_ctx = mlo_dev_ctx->sta_ctx;
if (!sta_ctx)
return QDF_STATUS_E_FAILURE;
if (sta_ctx->connect_req) {
qdf_mem_free(sta_ctx->connect_req);
sta_ctx->connect_req = NULL;
}
status = mlo_send_link_disconnect(mlo_dev_ctx, source,
reason_code, bssid);
if (QDF_IS_STATUS_SUCCESS(status))
return status;
tmp_vdev = mlo_get_connected_link_vdev(mlo_dev_ctx);
if (tmp_vdev) {
status = wlan_cm_disconnect(tmp_vdev, source,
reason_code, NULL);
return status;
}
tmp_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
if (tmp_vdev) {
status = wlan_cm_disconnect(tmp_vdev, source,
reason_code, NULL);
return status;
}
}
return status;
}
QDF_STATUS mlo_disconnect(struct wlan_objmgr_vdev *vdev,
enum wlan_cm_source source,
enum wlan_reason_code reason_code,
struct qdf_mac_addr *bssid)
{
/* This API will be pass through if MLO manager/11be is disabled */
return QDF_STATUS_SUCCESS;
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
struct wlan_objmgr_vdev *tmp_vdev = NULL;
struct wlan_mlo_sta *sta_ctx = NULL;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (mlo_dev_ctx && wlan_vdev_mlme_is_mlo_vdev(vdev)) {
sta_ctx = mlo_dev_ctx->sta_ctx;
mlo_dev_lock_acquire(mlo_dev_ctx);
if (sta_ctx->connect_req) {
qdf_mem_free(sta_ctx->connect_req);
sta_ctx->connect_req = NULL;
}
status = mlo_send_link_disconnect(mlo_dev_ctx, source,
reason_code, bssid);
if (QDF_IS_STATUS_SUCCESS(status)) {
mlo_dev_lock_release(mlo_dev_ctx);
return status;
}
tmp_vdev = mlo_get_connected_link_vdev(mlo_dev_ctx);
if (tmp_vdev) {
status = wlan_cm_disconnect(tmp_vdev, source,
reason_code, NULL);
mlo_dev_lock_release(mlo_dev_ctx);
return status;
}
tmp_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
if (tmp_vdev) {
status = wlan_cm_disconnect(tmp_vdev, source,
reason_code, NULL);
mlo_dev_lock_release(mlo_dev_ctx);
return status;
}
mlo_dev_lock_release(mlo_dev_ctx);
return status;
}
return wlan_cm_disconnect(vdev, source,
reason_code, NULL);
}
void mlo_sta_link_disconn_notify(struct wlan_objmgr_vdev *vdev)
QDF_STATUS mlo_sync_disconnect(struct wlan_objmgr_vdev *vdev,
enum wlan_cm_source source,
enum wlan_reason_code reason_code,
struct qdf_mac_addr *bssid)
{
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
struct wlan_objmgr_vdev *tmp_vdev = NULL;
struct wlan_mlo_sta *sta_ctx = NULL;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (mlo_dev_ctx && wlan_vdev_mlme_is_mlo_vdev(vdev)) {
sta_ctx = mlo_dev_ctx->sta_ctx;
if (sta_ctx->connect_req) {
qdf_mem_free(sta_ctx->connect_req);
sta_ctx->connect_req = NULL;
}
status = mlo_send_link_disconnect_sync(mlo_dev_ctx, source,
reason_code, bssid);
if (QDF_IS_STATUS_SUCCESS(status))
return status;
tmp_vdev = mlo_get_connected_link_vdev(mlo_dev_ctx);
if (tmp_vdev) {
status = wlan_cm_disconnect_sync(tmp_vdev, source,
reason_code);
return status;
}
tmp_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
if (tmp_vdev) {
status = wlan_cm_disconnect_sync(tmp_vdev, source,
reason_code);
return status;
}
return status;
}
return wlan_cm_disconnect_sync(vdev, source,
reason_code);
}
/**
* mlo_handle_disconnect_resp- Issue desired actions on partner link vdev
*
* @mlo_dev_ctx: pointer to mlo dev context
* @resp: disconnect resp
*
* Return: none
*/
#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
static
void mlo_handle_disconnect_resp(struct wlan_mlo_dev_context *mlo_dev_ctx,
struct wlan_cm_discon_rsp *resp)
{
/* If it is secondary link then delete vdev object from mlo device. */
}
#else
static
void mlo_handle_disconnect_resp(struct wlan_mlo_dev_context *mlo_dev_ctx,
struct wlan_cm_discon_rsp *resp)
{
struct wlan_objmgr_vdev *assoc_vdev = NULL;
enum wlan_cm_source source;
enum wlan_reason_code reason_code;
uint8_t i = 0;
mlo_dev_lock_acquire(mlo_dev_ctx);
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links)) {
if (wlan_cm_is_vdev_connected(
mlo_dev_ctx->wlan_vdev_list[i])) {
if (wlan_vdev_mlme_is_mlo_link_vdev(
mlo_dev_ctx->wlan_vdev_list[i])) {
source = resp->req.req.source;
reason_code = resp->req.req.reason_code;
wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i],
source, reason_code, NULL);
mlo_dev_lock_release(mlo_dev_ctx);
return;
}
}
}
}
assoc_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
if (assoc_vdev && wlan_cm_is_vdev_connected(assoc_vdev)) {
source = resp->req.req.source;
reason_code = resp->req.req.reason_code;
wlan_cm_disconnect(assoc_vdev,
source, reason_code, NULL);
mlo_dev_lock_release(mlo_dev_ctx);
return;
}
mlo_dev_lock_release(mlo_dev_ctx);
}
#endif
void mlo_sta_link_disconn_notify(struct wlan_objmgr_vdev *vdev,
struct wlan_cm_discon_rsp *resp)
{
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
struct wlan_mlo_sta *sta_ctx = NULL;
if (!mlo_dev_ctx || !(wlan_vdev_mlme_is_mlo_vdev(vdev)))
return;
sta_ctx = mlo_dev_ctx->sta_ctx;
if (!sta_ctx)
return;
if (!wlan_cm_is_vdev_disconnected(vdev))
return;
if (vdev == mlo_get_assoc_link_vdev(mlo_dev_ctx)) {
if (sta_ctx->connect_req) {
mlo_connect(mlo_get_assoc_link_vdev(mlo_dev_ctx),
sta_ctx->connect_req);
qdf_mem_free(sta_ctx->connect_req);
sta_ctx->connect_req = NULL;
}
return;
}
mlo_handle_disconnect_resp(mlo_dev_ctx, resp);
}
bool mlo_is_mld_sta(struct wlan_objmgr_vdev *vdev)
{
if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
wlan_vdev_mlme_is_mlo_vdev(vdev))
return true;
return false;
}
#ifndef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
void mlo_iterate_connected_vdev_list(struct wlan_objmgr_vdev *vdev,
mlo_vdev_op_handler handler,
void *arg)
{
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
struct wlan_mlo_sta *sta_ctx = NULL;
uint8_t i = 0;
if (!mlo_dev_ctx || !(wlan_vdev_mlme_is_mlo_vdev(vdev)))
return;
sta_ctx = mlo_dev_ctx->sta_ctx;
if (!sta_ctx)
return;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
if (qdf_test_bit(i, sta_ctx->wlan_connected_links)) {
if (handler)
handler(mlo_dev_ctx->wlan_vdev_list[i], arg);
}
}
}
void mlo_update_connect_req_links(struct wlan_objmgr_vdev *vdev, uint8_t value)
{
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
struct wlan_mlo_sta *sta_ctx = NULL;
uint8_t i = 0;
if (!mlo_dev_ctx)
return;
sta_ctx = mlo_dev_ctx->sta_ctx;
if (!sta_ctx)
return;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
if (vdev == mlo_dev_ctx->wlan_vdev_list[i]) {
if (value)
qdf_set_bit(i, sta_ctx->wlan_connect_req_links);
else
qdf_clear_bit(i, sta_ctx->wlan_connect_req_links);
}
}
}
void mlo_clear_connect_req_links_bmap(struct wlan_objmgr_vdev *vdev)
{
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
struct wlan_mlo_sta *sta_ctx = NULL;
if (!mlo_dev_ctx)
return;
sta_ctx = mlo_dev_ctx->sta_ctx;
if (!sta_ctx)
return;
qdf_mem_zero(sta_ctx->wlan_connect_req_links,
sizeof(sta_ctx->wlan_connect_req_links));
}
void mlo_update_connected_links(struct wlan_objmgr_vdev *vdev, uint8_t value)
{
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
struct wlan_mlo_sta *sta_ctx = NULL;
uint8_t i = 0;
if (!mlo_dev_ctx)
return;
sta_ctx = mlo_dev_ctx->sta_ctx;
if (!sta_ctx)
return;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
if (vdev == mlo_dev_ctx->wlan_vdev_list[i]) {
if (value)
qdf_set_bit(i, sta_ctx->wlan_connected_links);
else
qdf_clear_bit(i, sta_ctx->wlan_connected_links);
}
}
}
void mlo_clear_connected_links_bmap(struct wlan_objmgr_vdev *vdev)
{
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
struct wlan_mlo_sta *sta_ctx = NULL;
if (!mlo_dev_ctx)
return;
sta_ctx = mlo_dev_ctx->sta_ctx;
if (!sta_ctx)
return;
qdf_mem_zero(sta_ctx->wlan_connected_links,
sizeof(sta_ctx->wlan_connected_links));
}
struct wlan_objmgr_vdev *
mlo_get_ml_vdev_by_mac(struct wlan_objmgr_vdev *vdev,
struct qdf_mac_addr *macaddr)
{
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
uint8_t i = 0;
if (!mlo_dev_ctx)
return NULL;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
if(qdf_mem_cmp(macaddr,
wlan_vdev_mlme_get_macaddr(mlo_dev_ctx->wlan_vdev_list[i]),
QDF_MAC_ADDR_SIZE) == 0) {
return mlo_dev_ctx->wlan_vdev_list[i];
}
}
return NULL;
}
#endif
#endif