qcacmn: MLO peer implementation
This change adds MLO support to Peer. It implements, 1) MLO peer list management 2) AID allocation 3) MLO Peer creation/deletion 4) Notifying partner links on peer creation/deletion/assoc Change-Id: Ie1b675dccdf0de1d79f6f32d9255cf3cca53fdf2 CRs-Fixed: 2967057
Este commit está contenido en:

cometido por
Madan Koyyalamudi

padre
7f36fdf121
commit
7469335fa4
544
umac/mlo_mgr/src/wlan_mlo_mgr_aid.c
Archivo normal
544
umac/mlo_mgr/src/wlan_mlo_mgr_aid.c
Archivo normal
@@ -0,0 +1,544 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "wlan_mlo_mgr_main.h"
|
||||
#include "qdf_types.h"
|
||||
#include "wlan_cmn.h"
|
||||
#include <include/wlan_vdev_mlme.h>
|
||||
#include "wlan_mlo_mgr_ap.h"
|
||||
#include "wlan_mlo_mgr_cmn.h"
|
||||
|
||||
static void mlo_peer_set_aid_bit(struct wlan_ml_vdev_aid_mgr *ml_aid_mgr,
|
||||
uint16_t assoc_id_ix)
|
||||
{
|
||||
uint16_t ix;
|
||||
struct wlan_vdev_aid_mgr *vdev_aid_mgr;
|
||||
|
||||
/* Mark this bit as AID assigned */
|
||||
for (ix = 0; ix < WLAN_UMAC_MLO_MAX_VDEVS; ix++) {
|
||||
vdev_aid_mgr = ml_aid_mgr->aid_mgr[ix];
|
||||
if (vdev_aid_mgr)
|
||||
qdf_set_bit(assoc_id_ix, vdev_aid_mgr->aid_bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t wlan_mlo_peer_alloc_aid(
|
||||
struct wlan_ml_vdev_aid_mgr *ml_aid_mgr,
|
||||
bool is_mlo_peer,
|
||||
uint8_t link_ix)
|
||||
{
|
||||
uint16_t assoc_id = (uint16_t)-1;
|
||||
uint16_t i, j;
|
||||
struct wlan_vdev_aid_mgr *vdev_aid_mgr;
|
||||
uint16_t first_aid = 0;
|
||||
struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
|
||||
|
||||
if (!mlo_mgr_ctx)
|
||||
return assoc_id;
|
||||
|
||||
if (!is_mlo_peer && link_ix == 0xff)
|
||||
return assoc_id;
|
||||
/* TODO check locking strategy */
|
||||
ml_aid_lock_acquire(mlo_mgr_ctx);
|
||||
|
||||
for (i = 0; i < ml_aid_mgr->max_aid; i++) {
|
||||
if (qdf_test_bit(i, ml_aid_mgr->aid_bitmap))
|
||||
continue;
|
||||
|
||||
if (is_mlo_peer) {
|
||||
for (j = 0; j < WLAN_UMAC_MLO_MAX_VDEVS; j++) {
|
||||
vdev_aid_mgr = ml_aid_mgr->aid_mgr[j];
|
||||
if (vdev_aid_mgr &&
|
||||
qdf_test_bit(i, vdev_aid_mgr->aid_bitmap))
|
||||
break;
|
||||
/* AID is free */
|
||||
if (j == WLAN_UMAC_MLO_MAX_VDEVS - 1) {
|
||||
assoc_id = i + 1;
|
||||
mlo_peer_set_aid_bit(ml_aid_mgr, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (assoc_id == i + 1) {
|
||||
qdf_set_bit(i, ml_aid_mgr->aid_bitmap);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
vdev_aid_mgr = ml_aid_mgr->aid_mgr[link_ix];
|
||||
if (vdev_aid_mgr)
|
||||
break;
|
||||
|
||||
if (qdf_test_bit(i, vdev_aid_mgr->aid_bitmap))
|
||||
continue;
|
||||
|
||||
if (!first_aid)
|
||||
first_aid = i + 1;
|
||||
|
||||
for (j = 0; j < WLAN_UMAC_MLO_MAX_VDEVS; j++) {
|
||||
if (j == link_ix)
|
||||
continue;
|
||||
|
||||
vdev_aid_mgr = ml_aid_mgr->aid_mgr[j];
|
||||
if (vdev_aid_mgr &&
|
||||
qdf_test_bit(i, vdev_aid_mgr->aid_bitmap)) {
|
||||
assoc_id = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (assoc_id == i + 1) {
|
||||
vdev_aid_mgr = ml_aid_mgr->aid_mgr[link_ix];
|
||||
qdf_set_bit(i, vdev_aid_mgr->aid_bitmap);
|
||||
first_aid = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((!is_mlo_peer) && first_aid) {
|
||||
vdev_aid_mgr = ml_aid_mgr->aid_mgr[link_ix];
|
||||
qdf_set_bit(first_aid, vdev_aid_mgr->aid_bitmap);
|
||||
assoc_id = first_aid;
|
||||
}
|
||||
|
||||
ml_aid_lock_release(mlo_mgr_ctx);
|
||||
|
||||
return assoc_id;
|
||||
}
|
||||
|
||||
static uint16_t wlan_mlme_peer_alloc_aid(
|
||||
struct wlan_vdev_aid_mgr *vdev_aid_mgr,
|
||||
bool no_lock)
|
||||
{
|
||||
uint16_t assoc_id = (uint16_t)-1;
|
||||
uint16_t i;
|
||||
struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
|
||||
|
||||
if (!mlo_mgr_ctx)
|
||||
return assoc_id;
|
||||
|
||||
if (!no_lock)
|
||||
ml_aid_lock_acquire(mlo_mgr_ctx);
|
||||
|
||||
for (i = 0; i < vdev_aid_mgr->max_aid; i++) {
|
||||
if (qdf_test_bit(i, vdev_aid_mgr->aid_bitmap))
|
||||
continue;
|
||||
|
||||
assoc_id = i + 1;
|
||||
qdf_set_bit(i, vdev_aid_mgr->aid_bitmap);
|
||||
}
|
||||
|
||||
if (!no_lock)
|
||||
ml_aid_lock_release(mlo_mgr_ctx);
|
||||
|
||||
return assoc_id;
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_mlo_peer_free_aid(
|
||||
struct wlan_ml_vdev_aid_mgr *ml_aid_mgr,
|
||||
uint8_t link_ix,
|
||||
uint16_t assoc_id)
|
||||
{
|
||||
uint16_t j;
|
||||
struct wlan_vdev_aid_mgr *vdev_aid_mgr;
|
||||
struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
|
||||
uint16_t assoc_id_ix;
|
||||
|
||||
if (!mlo_mgr_ctx)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
/* TODO check locking strategy */
|
||||
ml_aid_lock_acquire(mlo_mgr_ctx);
|
||||
assoc_id_ix = assoc_id - 1;
|
||||
if (qdf_test_bit(assoc_id_ix, ml_aid_mgr->aid_bitmap)) {
|
||||
qdf_clear_bit(assoc_id_ix, ml_aid_mgr->aid_bitmap);
|
||||
for (j = 0; j < WLAN_UMAC_MLO_MAX_VDEVS; j++) {
|
||||
vdev_aid_mgr = ml_aid_mgr->aid_mgr[j];
|
||||
if (vdev_aid_mgr &&
|
||||
qdf_test_bit(assoc_id_ix,
|
||||
vdev_aid_mgr->aid_bitmap)) {
|
||||
qdf_clear_bit(assoc_id_ix,
|
||||
vdev_aid_mgr->aid_bitmap);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vdev_aid_mgr = ml_aid_mgr->aid_mgr[link_ix];
|
||||
if (vdev_aid_mgr)
|
||||
qdf_clear_bit(assoc_id_ix, vdev_aid_mgr->aid_bitmap);
|
||||
}
|
||||
|
||||
ml_aid_lock_release(mlo_mgr_ctx);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void wlan_mlme_peer_free_aid(
|
||||
struct wlan_vdev_aid_mgr *vdev_aid_mgr,
|
||||
bool no_lock, uint16_t assoc_id)
|
||||
{
|
||||
struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
|
||||
|
||||
if (!mlo_mgr_ctx)
|
||||
return;
|
||||
|
||||
if (!no_lock)
|
||||
ml_aid_lock_acquire(mlo_mgr_ctx);
|
||||
|
||||
qdf_clear_bit(assoc_id - 1, vdev_aid_mgr->aid_bitmap);
|
||||
|
||||
if (!no_lock)
|
||||
ml_aid_lock_release(mlo_mgr_ctx);
|
||||
}
|
||||
|
||||
QDF_STATUS mlo_peer_allocate_aid(
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_mlo_peer_context *ml_peer)
|
||||
{
|
||||
uint16_t assoc_id = (uint16_t)-1;
|
||||
struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
|
||||
|
||||
ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
|
||||
if (!ml_aid_mgr)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
assoc_id = wlan_mlo_peer_alloc_aid(ml_aid_mgr, true, 0xff);
|
||||
if (assoc_id == (uint16_t)-1)
|
||||
return QDF_STATUS_E_NOENT;
|
||||
|
||||
ml_peer->assoc_id = assoc_id;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS mlo_peer_free_aid(struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_mlo_peer_context *ml_peer)
|
||||
{
|
||||
struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
|
||||
ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
|
||||
if (!ml_aid_mgr)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
wlan_mlo_peer_free_aid(ml_aid_mgr, 0xff, ml_peer->assoc_id);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint16_t mlo_get_aid(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct wlan_mlo_dev_context *ml_dev;
|
||||
uint16_t assoc_id = (uint16_t)-1;
|
||||
struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
|
||||
|
||||
ml_dev = vdev->mlo_dev_ctx;
|
||||
|
||||
if (!ml_dev)
|
||||
return assoc_id;
|
||||
|
||||
ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
|
||||
if (!ml_aid_mgr)
|
||||
return assoc_id;
|
||||
|
||||
return wlan_mlo_peer_alloc_aid(ml_aid_mgr, true, 0xff);
|
||||
}
|
||||
|
||||
QDF_STATUS mlo_free_aid(struct wlan_objmgr_vdev *vdev, uint16_t assoc_id)
|
||||
{
|
||||
struct wlan_mlo_dev_context *ml_dev;
|
||||
struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
|
||||
|
||||
ml_dev = vdev->mlo_dev_ctx;
|
||||
|
||||
if (!ml_dev)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
|
||||
if (!ml_aid_mgr)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
return wlan_mlo_peer_free_aid(ml_aid_mgr, true, assoc_id);
|
||||
}
|
||||
|
||||
uint16_t mlme_get_aid(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct wlan_mlo_dev_context *ml_dev;
|
||||
uint16_t assoc_id = (uint16_t)-1;
|
||||
struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
|
||||
struct wlan_vdev_aid_mgr *vdev_aid_mgr;
|
||||
bool no_lock = true;
|
||||
uint8_t link_id;
|
||||
|
||||
ml_dev = vdev->mlo_dev_ctx;
|
||||
|
||||
if (!ml_dev) {
|
||||
vdev_aid_mgr = wlan_vdev_mlme_get_aid_mgr(vdev);
|
||||
if (vdev_aid_mgr) {
|
||||
if (qdf_atomic_read(&vdev_aid_mgr->ref_cnt) > 1)
|
||||
no_lock = false;
|
||||
return wlan_mlme_peer_alloc_aid(vdev_aid_mgr, no_lock);
|
||||
}
|
||||
return assoc_id;
|
||||
}
|
||||
|
||||
ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
|
||||
if (!ml_aid_mgr)
|
||||
return assoc_id;
|
||||
|
||||
link_id = mlo_get_link_vdev_ix(ml_dev, vdev);
|
||||
|
||||
assoc_id = wlan_mlo_peer_alloc_aid(ml_aid_mgr, false, link_id);
|
||||
|
||||
return assoc_id;
|
||||
}
|
||||
|
||||
void mlme_free_aid(struct wlan_objmgr_vdev *vdev, uint16_t assoc_id)
|
||||
{
|
||||
struct wlan_mlo_dev_context *ml_dev;
|
||||
struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
|
||||
struct wlan_vdev_aid_mgr *vdev_aid_mgr;
|
||||
bool no_lock = true;
|
||||
uint8_t link_id;
|
||||
|
||||
ml_dev = vdev->mlo_dev_ctx;
|
||||
|
||||
if (!ml_dev) {
|
||||
vdev_aid_mgr = wlan_vdev_mlme_get_aid_mgr(vdev);
|
||||
if (vdev_aid_mgr) {
|
||||
if (qdf_atomic_read(&vdev_aid_mgr->ref_cnt) > 1)
|
||||
no_lock = false;
|
||||
|
||||
wlan_mlme_peer_free_aid(vdev_aid_mgr, no_lock,
|
||||
assoc_id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
|
||||
if (!ml_aid_mgr)
|
||||
return;
|
||||
|
||||
link_id = mlo_get_link_vdev_ix(ml_dev, vdev);
|
||||
|
||||
wlan_mlo_peer_free_aid(ml_aid_mgr, link_id, assoc_id);
|
||||
}
|
||||
|
||||
struct wlan_vdev_aid_mgr *wlan_vdev_aid_mgr_init(uint16_t max_aid)
|
||||
{
|
||||
struct wlan_vdev_aid_mgr *aid_mgr;
|
||||
|
||||
aid_mgr = qdf_mem_malloc(sizeof(struct wlan_vdev_aid_mgr));
|
||||
if (!aid_mgr)
|
||||
return NULL;
|
||||
|
||||
aid_mgr->max_aid = max_aid;
|
||||
qdf_atomic_init(&aid_mgr->ref_cnt);
|
||||
/* Take reference before returning */
|
||||
qdf_atomic_inc(&aid_mgr->ref_cnt);
|
||||
|
||||
return aid_mgr;
|
||||
}
|
||||
|
||||
void wlan_vdev_aid_mgr_free(struct wlan_vdev_aid_mgr *aid_mgr)
|
||||
{
|
||||
if (!aid_mgr)
|
||||
return;
|
||||
|
||||
if (!qdf_atomic_dec_and_test(&aid_mgr->ref_cnt))
|
||||
return;
|
||||
|
||||
aid_mgr->max_aid = 0;
|
||||
qdf_mem_free(aid_mgr);
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_mlo_vdev_alloc_aid_mgr(struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t is_mbss_enabled = 0;
|
||||
struct wlan_objmgr_vdev *vdev_iter;
|
||||
struct wlan_objmgr_vdev *tx_vdev = NULL;
|
||||
struct wlan_vdev_aid_mgr *aid_mgr;
|
||||
struct wlan_ml_vdev_aid_mgr *ml_aidmgr;
|
||||
uint16_t max_aid = WLAN_UMAC_MAX_AID;
|
||||
|
||||
if (!ml_dev->ap_ctx) {
|
||||
mlo_err(" ML AP context is not initialized");
|
||||
QDF_BUG(0);
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
ml_aidmgr = ml_dev->ap_ctx->ml_aid_mgr;
|
||||
if (!ml_aidmgr) {
|
||||
mlo_err(" ML AID mgr allocation failed");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
vdev_iter = ml_dev->wlan_vdev_list[i];
|
||||
if (!vdev_iter)
|
||||
continue;
|
||||
|
||||
if (vdev != vdev_iter)
|
||||
continue;
|
||||
|
||||
/* TODO */
|
||||
/* Get Tx VDEV, if VDEV is MBSSID */
|
||||
if (is_mbss_enabled) {
|
||||
aid_mgr = wlan_vdev_mlme_get_aid_mgr(tx_vdev);
|
||||
if (!aid_mgr) {
|
||||
mlo_err("AID bitmap allocation failed for Tx VDEV%d",
|
||||
wlan_vdev_get_id(tx_vdev));
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
qdf_atomic_inc(&aid_mgr->ref_cnt);
|
||||
ml_aidmgr->aid_mgr[i] = aid_mgr;
|
||||
wlan_vdev_mlme_set_aid_mgr(vdev,
|
||||
ml_aidmgr->aid_mgr[i]);
|
||||
break;
|
||||
} else {
|
||||
ml_aidmgr->aid_mgr[i] = wlan_vdev_aid_mgr_init(max_aid);
|
||||
if (!ml_aidmgr->aid_mgr[i]) {
|
||||
mlo_err("AID bitmap allocation failed for VDEV%d",
|
||||
wlan_vdev_get_id(vdev));
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
wlan_vdev_mlme_set_aid_mgr(vdev, ml_aidmgr->aid_mgr[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_mlo_vdev_free_aid_mgr(struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
uint8_t i;
|
||||
struct wlan_objmgr_vdev *vdev_iter;
|
||||
struct wlan_ml_vdev_aid_mgr *ml_aidmgr;
|
||||
|
||||
if (!ml_dev->ap_ctx) {
|
||||
mlo_err(" ML AP context is not initialized");
|
||||
QDF_BUG(0);
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
ml_aidmgr = ml_dev->ap_ctx->ml_aid_mgr;
|
||||
if (!ml_aidmgr) {
|
||||
mlo_err(" ML AID mgr allocation failed");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
vdev_iter = ml_dev->wlan_vdev_list[i];
|
||||
if (!vdev_iter)
|
||||
continue;
|
||||
|
||||
if (vdev != vdev_iter)
|
||||
continue;
|
||||
|
||||
wlan_vdev_aid_mgr_free(ml_aidmgr->aid_mgr[i]);
|
||||
ml_aidmgr->aid_mgr[i] = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_mlo_vdev_aid_mgr_init(struct wlan_mlo_dev_context *ml_dev)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t is_mbss_enabled = 0;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
struct wlan_objmgr_vdev *tx_vdev = NULL;
|
||||
struct wlan_vdev_aid_mgr *aid_mgr;
|
||||
struct wlan_ml_vdev_aid_mgr *ml_aidmgr;
|
||||
uint16_t max_aid = WLAN_UMAC_MAX_AID;
|
||||
|
||||
ml_aidmgr = qdf_mem_malloc(sizeof(struct wlan_ml_vdev_aid_mgr));
|
||||
if (!ml_aidmgr) {
|
||||
ml_dev->ap_ctx->ml_aid_mgr = NULL;
|
||||
mlo_err(" ML AID mgr allocation failed");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
ml_aidmgr->max_aid = max_aid;
|
||||
ml_dev->ap_ctx->ml_aid_mgr = ml_aidmgr;
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
vdev = ml_dev->wlan_vdev_list[i];
|
||||
if (!vdev)
|
||||
continue;
|
||||
/* TODO */
|
||||
/* Get Tx VDEV, if VDEV is MBSSID */
|
||||
if (is_mbss_enabled) {
|
||||
aid_mgr = wlan_vdev_mlme_get_aid_mgr(tx_vdev);
|
||||
if (!aid_mgr) {
|
||||
mlo_err("AID bitmap allocation failed for Tx VDEV%d",
|
||||
wlan_vdev_get_id(tx_vdev));
|
||||
goto free_ml_aid_mgr;
|
||||
}
|
||||
|
||||
qdf_atomic_inc(&aid_mgr->ref_cnt);
|
||||
ml_aidmgr->aid_mgr[i] = aid_mgr;
|
||||
} else {
|
||||
ml_aidmgr->aid_mgr[i] = wlan_vdev_aid_mgr_init(max_aid);
|
||||
if (!ml_aidmgr->aid_mgr[i]) {
|
||||
mlo_err("AID bitmap allocation failed for VDEV%d",
|
||||
wlan_vdev_get_id(vdev));
|
||||
goto free_ml_aid_mgr;
|
||||
}
|
||||
wlan_vdev_mlme_set_aid_mgr(vdev,
|
||||
ml_aidmgr->aid_mgr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
free_ml_aid_mgr:
|
||||
wlan_mlo_vdev_aid_mgr_deinit(ml_dev);
|
||||
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
void wlan_mlo_vdev_aid_mgr_deinit(struct wlan_mlo_dev_context *ml_dev)
|
||||
{
|
||||
uint8_t i;
|
||||
struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
|
||||
int32_t n;
|
||||
|
||||
ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
|
||||
if (!ml_aid_mgr)
|
||||
return;
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
if (!ml_dev->wlan_vdev_list[i])
|
||||
continue;
|
||||
|
||||
if (ml_aid_mgr->aid_mgr[i]) {
|
||||
n = qdf_atomic_read(&ml_aid_mgr->aid_mgr[i]->ref_cnt);
|
||||
mlo_info("Vdev ID %d, AID mgr ref cnt %d",
|
||||
wlan_vdev_get_id(ml_dev->wlan_vdev_list[i]),
|
||||
n);
|
||||
} else {
|
||||
mlo_err("Vdev ID %d, doesn't have associated AID mgr",
|
||||
wlan_vdev_get_id(ml_dev->wlan_vdev_list[i]));
|
||||
continue;
|
||||
}
|
||||
wlan_vdev_aid_mgr_free(ml_aid_mgr->aid_mgr[i]);
|
||||
ml_aid_mgr->aid_mgr[i] = NULL;
|
||||
}
|
||||
|
||||
qdf_mem_free(ml_aid_mgr);
|
||||
ml_dev->ap_ctx->ml_aid_mgr = NULL;
|
||||
}
|
@@ -204,3 +204,38 @@ void mlo_ap_link_down_cmpl_notify(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
mlo_ap_vdev_detach(vdev);
|
||||
}
|
||||
|
||||
uint16_t mlo_ap_ml_peerid_alloc(void)
|
||||
{
|
||||
struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
|
||||
uint16_t i;
|
||||
|
||||
ml_peerid_lock_acquire(mlo_ctx);
|
||||
for (i = 0; i < mlo_ctx->max_mlo_peer_id; i++) {
|
||||
if (qdf_test_bit(i, mlo_ctx->mlo_peer_id_bmap))
|
||||
continue;
|
||||
|
||||
qdf_set_bit(i, mlo_ctx->mlo_peer_id_bmap);
|
||||
break;
|
||||
}
|
||||
ml_peerid_lock_release(mlo_ctx);
|
||||
|
||||
if (i == mlo_ctx->max_mlo_peer_id)
|
||||
return MLO_INVALID_PEER_ID;
|
||||
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
void mlo_ap_ml_peerid_free(uint16_t mlo_peer_id)
|
||||
{
|
||||
struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
|
||||
|
||||
if (mlo_peer_id == MLO_INVALID_PEER_ID)
|
||||
return;
|
||||
|
||||
ml_peerid_lock_acquire(mlo_ctx);
|
||||
if (qdf_test_bit(mlo_peer_id - 1, mlo_ctx->mlo_peer_id_bmap))
|
||||
qdf_clear_bit(mlo_peer_id - 1, mlo_ctx->mlo_peer_id_bmap);
|
||||
|
||||
ml_peerid_lock_release(mlo_ctx);
|
||||
}
|
||||
|
@@ -53,9 +53,12 @@ struct wlan_objmgr_vdev *mlo_get_vdev_by_link_id(
|
||||
wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i]) &&
|
||||
dev_ctx->wlan_vdev_list[i]->vdev_mlme.mlo_link_id ==
|
||||
link_id) {
|
||||
wlan_objmgr_vdev_try_get_ref(dev_ctx->wlan_vdev_list[i],
|
||||
WLAN_MLO_MGR_ID);
|
||||
partner_vdev = dev_ctx->wlan_vdev_list[i];
|
||||
if (wlan_objmgr_vdev_try_get_ref(
|
||||
dev_ctx->wlan_vdev_list[i],
|
||||
WLAN_MLO_MGR_ID) ==
|
||||
QDF_STATUS_SUCCESS)
|
||||
partner_vdev = dev_ctx->wlan_vdev_list[i];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -132,7 +135,7 @@ QDF_STATUS mlo_mlme_create_link_vdev(struct wlan_objmgr_vdev *vdev,
|
||||
|
||||
void mlo_mlme_peer_create(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
struct qdf_mac_addr addr,
|
||||
struct qdf_mac_addr *addr,
|
||||
qdf_nbuf_t frm_buf)
|
||||
{
|
||||
struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
|
||||
@@ -177,3 +180,31 @@ void mlo_mlme_peer_delete(struct wlan_objmgr_peer *peer)
|
||||
|
||||
mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete(peer);
|
||||
}
|
||||
|
||||
void mlo_mlme_peer_assoc_resp(struct wlan_objmgr_peer *peer)
|
||||
{
|
||||
struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
|
||||
|
||||
if (!mlo_ctx || !mlo_ctx->mlme_ops ||
|
||||
!mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp)
|
||||
return;
|
||||
|
||||
mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp(peer);
|
||||
}
|
||||
|
||||
uint8_t mlo_get_link_vdev_ix(struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
mlo_dev_lock_acquire(ml_dev);
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
if (vdev == ml_dev->wlan_vdev_list[i]) {
|
||||
mlo_dev_lock_release(ml_dev);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
mlo_dev_lock_release(ml_dev);
|
||||
|
||||
return (uint8_t)-1;
|
||||
}
|
||||
|
@@ -17,12 +17,13 @@
|
||||
/*
|
||||
* DOC: contains MLO manager init/deinit api's
|
||||
*/
|
||||
|
||||
#include "wlan_mlo_mgr_main.h"
|
||||
#include "qdf_types.h"
|
||||
#include "wlan_cmn.h"
|
||||
#include <wlan_objmgr_cmn.h>
|
||||
#include <wlan_objmgr_global_obj.h>
|
||||
#include "wlan_mlo_mgr_cmn.h"
|
||||
#include "wlan_mlo_mgr_main.h"
|
||||
#include <wlan_mlo_mgr_ap.h>
|
||||
#include <wlan_mlo_mgr_peer.h>
|
||||
|
||||
static void mlo_global_ctx_deinit(void)
|
||||
{
|
||||
@@ -34,7 +35,9 @@ static void mlo_global_ctx_deinit(void)
|
||||
if (qdf_list_empty(&mlo_mgr_ctx->ml_dev_list))
|
||||
mlo_err("ML dev list is not empty");
|
||||
|
||||
ml_peerid_lock_destroy(mlo_mgr_ctx);
|
||||
ml_link_lock_destroy(mlo_mgr_ctx);
|
||||
ml_aid_lock_destroy(mlo_mgr_ctx);
|
||||
qdf_list_destroy(&mlo_mgr_ctx->ml_dev_list);
|
||||
|
||||
qdf_mem_free(mlo_mgr_ctx);
|
||||
@@ -60,7 +63,10 @@ static void mlo_global_ctx_init(void)
|
||||
wlan_objmgr_set_mlo_ctx(mlo_mgr_ctx);
|
||||
|
||||
qdf_list_create(&mlo_mgr_ctx->ml_dev_list, WLAN_UMAC_MLO_MAX_DEV);
|
||||
mlo_mgr_ctx->max_mlo_peer_id = MAX_MLO_PEER_ID;
|
||||
ml_peerid_lock_create(mlo_mgr_ctx);
|
||||
ml_link_lock_create(mlo_mgr_ctx);
|
||||
ml_aid_lock_create(mlo_mgr_ctx);
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_mlo_mgr_init(void)
|
||||
@@ -187,6 +193,34 @@ static inline struct wlan_mlo_dev_context
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev)
|
||||
{
|
||||
wlan_mlo_vdev_aid_mgr_deinit(ml_dev);
|
||||
qdf_mem_free(ml_dev->ap_ctx);
|
||||
ml_dev->ap_ctx = NULL;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static QDF_STATUS mlo_ap_ctx_init(struct wlan_mlo_dev_context *ml_dev)
|
||||
{
|
||||
struct wlan_mlo_ap *ap_ctx;
|
||||
|
||||
ap_ctx = qdf_mem_malloc(sizeof(*ap_ctx));
|
||||
if (!ap_ctx) {
|
||||
mlo_err("MLO AP ctx alloc failure");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
ml_dev->ap_ctx = ap_ctx;
|
||||
if (wlan_mlo_vdev_aid_mgr_init(ml_dev) != QDF_STATUS_SUCCESS) {
|
||||
mlo_ap_ctx_deinit(ml_dev);
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct wlan_mlo_dev_context *ml_dev;
|
||||
@@ -207,6 +241,10 @@ static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
|
||||
ml_dev->wlan_vdev_list[id] = vdev;
|
||||
ml_dev->wlan_vdev_count++;
|
||||
vdev->mlo_dev_ctx = ml_dev;
|
||||
|
||||
if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
|
||||
wlan_mlo_vdev_alloc_aid_mgr(ml_dev, vdev);
|
||||
|
||||
break;
|
||||
}
|
||||
mlo_dev_lock_release(ml_dev);
|
||||
@@ -224,6 +262,7 @@ static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
|
||||
ml_dev->wlan_vdev_list[0] = vdev;
|
||||
ml_dev->wlan_vdev_count++;
|
||||
vdev->mlo_dev_ctx = ml_dev;
|
||||
|
||||
mlo_dev_lock_create(ml_dev);
|
||||
if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
|
||||
ml_dev->sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_sta));
|
||||
@@ -233,15 +272,16 @@ static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
} else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
|
||||
ml_dev->ap_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_ap));
|
||||
if (!ml_dev->ap_ctx) {
|
||||
mlo_err("Failed to allocate memory for ap ctx");
|
||||
if (mlo_ap_ctx_init(ml_dev) != QDF_STATUS_SUCCESS) {
|
||||
mlo_dev_lock_destroy(ml_dev);
|
||||
qdf_mem_free(ml_dev);
|
||||
mlo_err("Failed to allocate memory for ap ctx");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
mlo_dev_mlpeer_list_init(ml_dev);
|
||||
|
||||
ml_link_lock_acquire(g_mlo_ctx);
|
||||
if (qdf_list_size(&g_mlo_ctx->ml_dev_list) < WLAN_UMAC_MLO_MAX_DEV)
|
||||
qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node);
|
||||
@@ -268,6 +308,10 @@ static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev)
|
||||
mlo_dev_lock_acquire(ml_dev);
|
||||
while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
|
||||
if (ml_dev->wlan_vdev_list[id] == vdev) {
|
||||
if (wlan_vdev_mlme_get_opmode(vdev) ==
|
||||
QDF_SAP_MODE)
|
||||
wlan_mlo_vdev_free_aid_mgr(ml_dev,
|
||||
vdev);
|
||||
ml_dev->wlan_vdev_list[id] = NULL;
|
||||
ml_dev->wlan_vdev_count--;
|
||||
vdev->mlo_dev_ctx = NULL;
|
||||
@@ -277,8 +321,13 @@ static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev)
|
||||
}
|
||||
mlo_dev_lock_release(ml_dev);
|
||||
}
|
||||
|
||||
ml_link_lock_acquire(g_mlo_ctx);
|
||||
if (!ml_dev->wlan_vdev_count) {
|
||||
if (ml_dev->ap_ctx)
|
||||
mlo_ap_ctx_deinit(ml_dev);
|
||||
|
||||
mlo_dev_mlpeer_list_deinit(ml_dev);
|
||||
qdf_list_remove_node(&g_mlo_ctx->ml_dev_list,
|
||||
&ml_dev->node);
|
||||
if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
|
||||
@@ -292,6 +341,7 @@ static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev)
|
||||
}
|
||||
else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
|
||||
qdf_mem_free(ml_dev->ap_ctx);
|
||||
|
||||
mlo_dev_lock_destroy(ml_dev);
|
||||
qdf_mem_free(ml_dev);
|
||||
}
|
||||
|
216
umac/mlo_mgr/src/wlan_mlo_mgr_msgq.c
Archivo normal
216
umac/mlo_mgr/src/wlan_mlo_mgr_msgq.c
Archivo normal
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include "wlan_mlo_mgr_main.h"
|
||||
#include "qdf_types.h"
|
||||
#include "wlan_cmn.h"
|
||||
#include "wlan_mlo_mgr_cmn.h"
|
||||
#include "wlan_mlo_mgr_msgq.h"
|
||||
#include "wlan_mlo_mgr_peer.h"
|
||||
|
||||
#ifndef MLO_MSGQ_SUPPORT
|
||||
QDF_STATUS mlo_msgq_post(enum mlo_msg_type type,
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
void *payload)
|
||||
{
|
||||
struct peer_create_notif_s *peer_create;
|
||||
struct peer_assoc_notify_s *peer_assoc;
|
||||
struct peer_assoc_fail_notify_s *peer_assoc_fail;
|
||||
struct peer_discon_notify_s *peer_disconn;
|
||||
|
||||
switch (type) {
|
||||
case MLO_PEER_CREATE:
|
||||
peer_create = (struct peer_create_notif_s *)payload;
|
||||
|
||||
mlo_mlme_peer_create(peer_create->vdev_link,
|
||||
peer_create->ml_peer,
|
||||
&peer_create->addr, peer_create->frm_buf);
|
||||
qdf_nbuf_free(peer_create->frm_buf);
|
||||
wlan_mlo_peer_release_ref(peer_create->ml_peer);
|
||||
wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
|
||||
WLAN_MLO_MGR_ID);
|
||||
break;
|
||||
|
||||
case MLO_PEER_ASSOC:
|
||||
peer_assoc = (struct peer_assoc_notify_s *)payload;
|
||||
mlo_mlme_peer_assoc(peer_assoc->peer);
|
||||
wlan_objmgr_peer_release_ref(peer_assoc->peer,
|
||||
WLAN_MLO_MGR_ID);
|
||||
break;
|
||||
|
||||
case MLO_PEER_ASSOC_FAIL:
|
||||
peer_assoc_fail = (struct peer_assoc_fail_notify_s *)payload;
|
||||
mlo_mlme_peer_assoc_fail(peer_assoc_fail->peer);
|
||||
wlan_objmgr_peer_release_ref(peer_assoc_fail->peer,
|
||||
WLAN_MLO_MGR_ID);
|
||||
break;
|
||||
|
||||
case MLO_PEER_DISCONNECT:
|
||||
peer_disconn = (struct peer_discon_notify_s *)payload;
|
||||
mlo_mlme_peer_delete(peer_disconn->peer);
|
||||
wlan_objmgr_peer_release_ref(peer_disconn->peer,
|
||||
WLAN_MLO_MGR_ID);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#else
|
||||
QDF_STATUS mlo_msgq_post(enum mlo_msg_type type,
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
void *payload)
|
||||
{
|
||||
struct mlo_ctxt_switch_msg_s *msg;
|
||||
struct peer_create_notif_s *peer_create, *peer_create_l;
|
||||
struct peer_assoc_notify_s *peer_assoc, *peer_assoc_l;
|
||||
struct peer_assoc_fail_notify_s *peer_assoc_fail, *peer_assoc_fail_l;
|
||||
struct peer_discon_notify_s *peer_disconn, *peer_disconn_l;
|
||||
|
||||
msg = qdf_mem_malloc(sizeof(*msg));
|
||||
if (!msg)
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
|
||||
msg->type = type;
|
||||
msg->ml_dev = ml_dev;
|
||||
|
||||
switch (type) {
|
||||
case MLO_PEER_CREATE:
|
||||
peer_create = &msg->m.peer_create;
|
||||
peer_create_l = (struct peer_create_notif_s *)payload;
|
||||
peer_create->frm_buf = peer_create_l->frm_buf;
|
||||
peer_create->ml_peer = peer_create_l->ml_peer;
|
||||
peer_create->vdev_link = peer_create_l->vdev_link;
|
||||
qdf_copy_macaddr(&peer_create->addr, &peer_create_l->addr);
|
||||
break;
|
||||
|
||||
case MLO_PEER_ASSOC:
|
||||
peer_assoc = &msg->m.peer_assoc;
|
||||
peer_assoc_l = (struct peer_assoc_notify_s *)payload;
|
||||
peer_assoc->peer = peer_assoc_l->peer;
|
||||
break;
|
||||
|
||||
case MLO_PEER_ASSOC_FAIL:
|
||||
peer_assoc_fail = &msg->m.peer_assoc_fail;
|
||||
peer_assoc_fail_l = (struct peer_assoc_fail_notify_s *)payload;
|
||||
peer_assoc_fail->peer = peer_assoc_fail_l->peer;
|
||||
break;
|
||||
|
||||
case MLO_PEER_DISCONNECT:
|
||||
peer_disconn = &msg->m.peer_disconn;
|
||||
peer_disconn_l = (struct peer_discon_notify_s *)payload;
|
||||
peer_disconn->peer = peer_disconn_l->peer;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* TODO queue message buffer to qdf_list */
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void mlo_msgq_msg_process_hdlr(struct mlo_ctxt_switch_msg_s *msg)
|
||||
{
|
||||
enum mlo_msg_type type;
|
||||
struct peer_create_notif_s *peer_create;
|
||||
struct peer_assoc_notify_s *peer_assoc;
|
||||
struct peer_assoc_fail_notify_s *peer_assoc_fail;
|
||||
struct peer_discon_notify_s *peer_disconn;
|
||||
|
||||
type = msg->type;
|
||||
switch (type) {
|
||||
case MLO_PEER_CREATE:
|
||||
peer_create = &msg->m.peer_create;
|
||||
mlo_mlme_peer_create(peer_create->vdev_link,
|
||||
peer_create->ml_peer,
|
||||
&peer_create->addr, peer_create->frm_buf);
|
||||
qdf_nbuf_free(peer_create->frm_buf);
|
||||
wlan_mlo_peer_release_ref(peer_create->ml_peer);
|
||||
wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
|
||||
WLAN_MLO_MGR_ID);
|
||||
break;
|
||||
|
||||
case MLO_PEER_ASSOC:
|
||||
peer_assoc = &msg->m.peer_assoc;
|
||||
mlo_mlme_peer_assoc(peer_assoc->peer);
|
||||
wlan_objmgr_peer_release_ref(peer_assoc->peer,
|
||||
WLAN_MLO_MGR_ID);
|
||||
break;
|
||||
|
||||
case MLO_PEER_ASSOC_FAIL:
|
||||
peer_assoc_fail = &msg->m.peer_assoc_fail;
|
||||
mlo_mlme_peer_assoc_fail(peer_assoc_fail->peer);
|
||||
wlan_objmgr_peer_release_ref(peer_assoc_fail->peer,
|
||||
WLAN_MLO_MGR_ID);
|
||||
break;
|
||||
|
||||
case MLO_PEER_DISCONNECT:
|
||||
peer_disconn = &msg->m.peer_disconn;
|
||||
mlo_mlme_peer_delete(peer_disconn->peer);
|
||||
wlan_objmgr_peer_release_ref(peer_disconn->peer,
|
||||
WLAN_MLO_MGR_ID);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
qdf_mem_free(msg);
|
||||
}
|
||||
|
||||
void mlo_msgq_msg_flush_hdlr(struct mlo_ctxt_switch_msg_s *msg)
|
||||
{
|
||||
enum mlo_msg_type type;
|
||||
struct peer_create_notif_s *peer_create;
|
||||
struct peer_assoc_notify_s *peer_assoc;
|
||||
struct peer_assoc_fail_notify_s *peer_assoc_fail;
|
||||
struct peer_discon_notify_s *peer_disconn;
|
||||
|
||||
type = msg->type;
|
||||
switch (type) {
|
||||
case MLO_PEER_CREATE:
|
||||
peer_create = &msg->m.peer_create;
|
||||
qdf_nbuf_free(peer_create->frm_buf);
|
||||
wlan_mlo_peer_release_ref(peer_create->ml_peer);
|
||||
wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
|
||||
WLAN_MLO_MGR_ID);
|
||||
break;
|
||||
|
||||
case MLO_PEER_ASSOC:
|
||||
peer_assoc = &msg->m.peer_assoc;
|
||||
wlan_objmgr_peer_release_ref(peer_assoc->peer,
|
||||
WLAN_MLO_MGR_ID);
|
||||
break;
|
||||
|
||||
case MLO_PEER_ASSOC_FAIL:
|
||||
peer_assoc_fail = &msg->m.peer_assoc_fail;
|
||||
wlan_objmgr_peer_release_ref(peer_assoc_fail->peer,
|
||||
WLAN_MLO_MGR_ID);
|
||||
break;
|
||||
|
||||
case MLO_PEER_DISCONNECT:
|
||||
peer_disconn = &msg->m.peer_disconn;
|
||||
wlan_objmgr_peer_release_ref(peer_disconn->peer,
|
||||
WLAN_MLO_MGR_ID);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
qdf_mem_free(msg);
|
||||
}
|
||||
#endif
|
606
umac/mlo_mgr/src/wlan_mlo_mgr_peer.c
Archivo normal
606
umac/mlo_mgr/src/wlan_mlo_mgr_peer.c
Archivo normal
@@ -0,0 +1,606 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "wlan_mlo_mgr_main.h"
|
||||
#include "qdf_types.h"
|
||||
#include "wlan_cmn.h"
|
||||
#include "wlan_mlo_mgr_msgq.h"
|
||||
#include "wlan_mlo_mgr_peer.h"
|
||||
#include "wlan_mlo_mgr_ap.h"
|
||||
|
||||
static void mlo_partner_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_objmgr_vdev *vdev_link,
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
qdf_nbuf_t frm_buf,
|
||||
struct mlo_partner_info *ml_info)
|
||||
{
|
||||
struct peer_create_notif_s peer_create;
|
||||
QDF_STATUS status;
|
||||
uint8_t i;
|
||||
uint8_t link_id;
|
||||
|
||||
if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) ==
|
||||
QDF_STATUS_SUCCESS) {
|
||||
peer_create.vdev_link = vdev_link;
|
||||
} else {
|
||||
mlo_err("VDEV is not in created state");
|
||||
return;
|
||||
}
|
||||
|
||||
wlan_mlo_peer_get_ref(ml_peer);
|
||||
peer_create.ml_peer = ml_peer;
|
||||
link_id = wlan_vdev_get_link_id(vdev_link);
|
||||
for (i = 0; i < ml_info->num_partner_links; i++) {
|
||||
if (link_id != ml_info->partner_link_info[i].link_id)
|
||||
continue;
|
||||
|
||||
qdf_copy_macaddr(&peer_create.addr,
|
||||
&ml_info->partner_link_info[i].link_addr);
|
||||
break;
|
||||
}
|
||||
|
||||
peer_create.frm_buf = qdf_nbuf_clone(frm_buf);
|
||||
if (!peer_create.frm_buf) {
|
||||
wlan_mlo_peer_release_ref(ml_peer);
|
||||
wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
|
||||
mlo_err("nbuf clone is failed");
|
||||
return;
|
||||
}
|
||||
|
||||
status = mlo_msgq_post(MLO_PEER_CREATE, ml_dev, &peer_create);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
qdf_nbuf_free(frm_buf);
|
||||
wlan_mlo_peer_release_ref(ml_peer);
|
||||
wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
|
||||
}
|
||||
}
|
||||
|
||||
static void mlo_link_peer_assoc_notify(struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_objmgr_peer *peer)
|
||||
{
|
||||
struct peer_assoc_notify_s peer_assoc;
|
||||
QDF_STATUS status;
|
||||
|
||||
peer_assoc.peer = peer;
|
||||
status = mlo_msgq_post(MLO_PEER_ASSOC, ml_dev, &peer_assoc);
|
||||
if (status != QDF_STATUS_SUCCESS)
|
||||
wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
|
||||
}
|
||||
|
||||
static void mlo_link_peer_send_assoc_fail(struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_objmgr_peer *peer)
|
||||
{
|
||||
struct peer_assoc_fail_notify_s peer_assoc_fail;
|
||||
QDF_STATUS status;
|
||||
|
||||
peer_assoc_fail.peer = peer;
|
||||
status = mlo_msgq_post(MLO_PEER_ASSOC_FAIL, ml_dev, &peer_assoc_fail);
|
||||
if (status != QDF_STATUS_SUCCESS)
|
||||
wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
|
||||
}
|
||||
|
||||
static void mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_objmgr_peer *peer)
|
||||
{
|
||||
struct peer_discon_notify_s peer_disconn;
|
||||
QDF_STATUS status;
|
||||
|
||||
peer_disconn.peer = peer;
|
||||
status = mlo_msgq_post(MLO_PEER_DISCONNECT, ml_dev, &peer_disconn);
|
||||
if (status != QDF_STATUS_SUCCESS)
|
||||
wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
wlan_mlo_peer_is_disconnect_progress(struct wlan_mlo_peer_context *ml_peer)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
mlo_peer_lock_acquire(ml_peer);
|
||||
|
||||
if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED)
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
else
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_mlo_peer_is_assoc_done(struct wlan_mlo_peer_context *ml_peer)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
mlo_peer_lock_acquire(ml_peer);
|
||||
|
||||
if (ml_peer->mlpeer_state == ML_PEER_ASSOC_DONE)
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
else
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
struct wlan_objmgr_peer *wlan_mlo_peer_get_assoc_peer(
|
||||
struct wlan_mlo_peer_context *ml_peer)
|
||||
{
|
||||
struct wlan_mlo_link_peer_entry *peer_entry;
|
||||
struct wlan_objmgr_peer *assoc_peer = NULL;
|
||||
|
||||
mlo_peer_lock_acquire(ml_peer);
|
||||
|
||||
peer_entry = &ml_peer->peer_list[0];
|
||||
|
||||
if (peer_entry->link_peer)
|
||||
assoc_peer = peer_entry->link_peer;
|
||||
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
|
||||
return assoc_peer;
|
||||
}
|
||||
|
||||
void wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer *assoc_peer)
|
||||
{
|
||||
struct wlan_mlo_dev_context *ml_dev;
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
struct wlan_objmgr_peer *link_peer;
|
||||
struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
|
||||
struct wlan_mlo_link_peer_entry *peer_entry;
|
||||
uint16_t i;
|
||||
|
||||
ml_peer = assoc_peer->mlo_peer_ctx;
|
||||
mlo_peer_lock_acquire(ml_peer);
|
||||
|
||||
if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
return;
|
||||
}
|
||||
|
||||
ml_peer->mlpeer_state = ML_PEER_ASSOC_DONE;
|
||||
ml_dev = ml_peer->ml_dev;
|
||||
|
||||
for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
|
||||
link_peers[i] = NULL;
|
||||
peer_entry = &ml_peer->peer_list[i];
|
||||
|
||||
if (!peer_entry->link_peer)
|
||||
continue;
|
||||
|
||||
if (peer_entry->link_peer == assoc_peer)
|
||||
continue;
|
||||
|
||||
link_peer = peer_entry->link_peer;
|
||||
|
||||
if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
|
||||
QDF_STATUS_SUCCESS)
|
||||
continue;
|
||||
|
||||
link_peers[i] = link_peer;
|
||||
}
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
|
||||
for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
|
||||
if (!link_peers[i])
|
||||
continue;
|
||||
|
||||
/* Prepare and queue message */
|
||||
mlo_link_peer_assoc_notify(ml_dev, link_peers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wlan_mlo_partner_peer_create_failed_notify(
|
||||
struct wlan_mlo_peer_context *ml_peer)
|
||||
{
|
||||
struct wlan_mlo_dev_context *ml_dev;
|
||||
struct wlan_objmgr_peer *link_peer;
|
||||
struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
|
||||
struct wlan_mlo_link_peer_entry *peer_entry;
|
||||
uint16_t i;
|
||||
|
||||
mlo_peer_lock_acquire(ml_peer);
|
||||
|
||||
if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
return;
|
||||
}
|
||||
|
||||
ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
|
||||
ml_dev = ml_peer->ml_dev;
|
||||
|
||||
for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
|
||||
link_peers[i] = NULL;
|
||||
peer_entry = &ml_peer->peer_list[i];
|
||||
if (!peer_entry->link_peer)
|
||||
continue;
|
||||
|
||||
link_peer = peer_entry->link_peer;
|
||||
if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
|
||||
QDF_STATUS_SUCCESS)
|
||||
continue;
|
||||
|
||||
link_peers[i] = link_peer;
|
||||
}
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
|
||||
for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
|
||||
if (!link_peers[i])
|
||||
continue;
|
||||
|
||||
/* Prepare and queue message */
|
||||
if (i == 0)
|
||||
mlo_link_peer_send_assoc_fail(ml_dev, link_peers[i]);
|
||||
else
|
||||
mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer)
|
||||
{
|
||||
struct wlan_mlo_dev_context *ml_dev;
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
struct wlan_objmgr_peer *link_peer;
|
||||
struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
|
||||
struct wlan_mlo_link_peer_entry *peer_entry;
|
||||
uint16_t i;
|
||||
|
||||
ml_peer = src_peer->mlo_peer_ctx;
|
||||
mlo_peer_lock_acquire(ml_peer);
|
||||
|
||||
if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
return;
|
||||
}
|
||||
|
||||
ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
|
||||
ml_dev = ml_peer->ml_dev;
|
||||
for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
|
||||
link_peers[i] = NULL;
|
||||
peer_entry = &ml_peer->peer_list[i];
|
||||
if (!peer_entry->link_peer)
|
||||
continue;
|
||||
|
||||
if (peer_entry->link_peer == src_peer)
|
||||
continue;
|
||||
|
||||
link_peer = peer_entry->link_peer;
|
||||
if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
|
||||
QDF_STATUS_SUCCESS)
|
||||
continue;
|
||||
|
||||
link_peers[i] = link_peer;
|
||||
}
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
|
||||
for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
|
||||
if (!link_peers[i])
|
||||
continue;
|
||||
|
||||
/* Prepare and queue message */
|
||||
mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void mlo_peer_populate_link_peer(
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
struct wlan_objmgr_peer *link_peer)
|
||||
{
|
||||
mlo_peer_lock_acquire(ml_peer);
|
||||
wlan_mlo_peer_get_ref(ml_peer);
|
||||
link_peer->mlo_peer_ctx = ml_peer;
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
}
|
||||
|
||||
static void mlo_reset_link_peer(
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
struct wlan_objmgr_peer *link_peer)
|
||||
{
|
||||
mlo_peer_lock_acquire(ml_peer);
|
||||
link_peer->mlo_peer_ctx = NULL;
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
}
|
||||
|
||||
void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer)
|
||||
{
|
||||
struct wlan_mlo_dev_context *ml_dev;
|
||||
|
||||
ml_dev = ml_peer->ml_dev;
|
||||
if (!ml_dev) {
|
||||
mlo_err("ML DEV is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
mlo_peer_lock_destroy(ml_peer);
|
||||
mlo_ap_ml_peerid_free(ml_peer->mlo_peer_id);
|
||||
mlo_peer_free_aid(ml_dev, ml_peer);
|
||||
mlo_peer_free_primary_umac(ml_dev, ml_peer);
|
||||
mlo_dev_mlpeer_detach(ml_dev, ml_peer);
|
||||
qdf_mem_free(ml_peer);
|
||||
}
|
||||
|
||||
static QDF_STATUS mlo_peer_attach_link_peer(
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
struct wlan_objmgr_peer *link_peer)
|
||||
{
|
||||
struct wlan_mlo_link_peer_entry *peer_entry;
|
||||
QDF_STATUS status = QDF_STATUS_E_RESOURCES;
|
||||
uint16_t i;
|
||||
|
||||
mlo_peer_lock_acquire(ml_peer);
|
||||
|
||||
if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
return status;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
|
||||
peer_entry = &ml_peer->peer_list[i];
|
||||
if (peer_entry->link_peer)
|
||||
continue;
|
||||
|
||||
if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
|
||||
QDF_STATUS_SUCCESS)
|
||||
break;
|
||||
|
||||
peer_entry->link_peer = link_peer;
|
||||
qdf_copy_macaddr(&peer_entry->link_addr,
|
||||
(struct qdf_mac_addr *)&link_peer->macaddr[0]);
|
||||
|
||||
peer_entry->link_ix = i + 1;
|
||||
peer_entry->hw_link_id = 1;
|
||||
/*wlan_peer_get_hw_link_id(link_peer)TODO*/
|
||||
mlo_peer_assign_primary_umac(ml_peer, peer_entry);
|
||||
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
ml_peer->link_peer_cnt++;
|
||||
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static QDF_STATUS mlo_peer_detach_link_peer(
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
struct wlan_objmgr_peer *link_peer)
|
||||
{
|
||||
struct wlan_mlo_link_peer_entry *peer_entry;
|
||||
QDF_STATUS status = QDF_STATUS_E_RESOURCES;
|
||||
uint16_t i;
|
||||
|
||||
mlo_peer_lock_acquire(ml_peer);
|
||||
|
||||
if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED) {
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
return status;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
|
||||
peer_entry = &ml_peer->peer_list[i];
|
||||
if (!peer_entry->link_peer)
|
||||
continue;
|
||||
|
||||
if (peer_entry->link_peer != link_peer)
|
||||
continue;
|
||||
|
||||
wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID);
|
||||
peer_entry->link_peer = NULL;
|
||||
ml_peer->link_peer_cnt--;
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
mlo_peer_lock_release(ml_peer);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static QDF_STATUS mlo_dev_get_link_vdevs(
|
||||
struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
struct mlo_partner_info *ml_info,
|
||||
struct wlan_objmgr_vdev *link_vdevs[])
|
||||
{
|
||||
uint16_t i, j;
|
||||
struct wlan_objmgr_vdev *vdev_link;
|
||||
uint8_t link_id;
|
||||
|
||||
for (i = 0; i < ml_info->num_partner_links; i++) {
|
||||
link_id = ml_info->partner_link_info[i].link_id;
|
||||
vdev_link = mlo_get_vdev_by_link_id(vdev, link_id);
|
||||
if (vdev_link) {
|
||||
link_vdevs[i] = vdev_link;
|
||||
} else {
|
||||
/* release ref which were taken before failure */
|
||||
for (j = 0; j < i; j++) {
|
||||
vdev_link = link_vdevs[j];
|
||||
if (!vdev_link)
|
||||
continue;
|
||||
|
||||
wlan_objmgr_vdev_release_ref(vdev_link,
|
||||
WLAN_MLO_MGR_ID);
|
||||
}
|
||||
mlo_dev_lock_release(ml_dev);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void mlo_dev_release_link_vdevs(
|
||||
struct wlan_objmgr_vdev *link_vdevs[])
|
||||
{
|
||||
uint16_t i;
|
||||
struct wlan_objmgr_vdev *vdev_link;
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
vdev_link = link_vdevs[i];
|
||||
if (!vdev_link)
|
||||
continue;
|
||||
|
||||
wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
|
||||
}
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_objmgr_peer *link_peer,
|
||||
struct mlo_partner_info *ml_info,
|
||||
qdf_nbuf_t frm_buf,
|
||||
uint16_t aid)
|
||||
{
|
||||
struct wlan_mlo_dev_context *ml_dev;
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
|
||||
struct wlan_objmgr_vdev *vdev_link;
|
||||
QDF_STATUS status;
|
||||
uint16_t i;
|
||||
|
||||
/* get ML VDEV from VDEV */
|
||||
ml_dev = vdev->mlo_dev_ctx;
|
||||
|
||||
/* Check resources of Partner VDEV */
|
||||
status = mlo_dev_get_link_vdevs(vdev, ml_dev, ml_info, link_vdevs);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
vdev_link = link_vdevs[i];
|
||||
if (!vdev_link)
|
||||
continue;
|
||||
|
||||
if (wlan_vdev_is_peer_create_allowed(vdev_link)
|
||||
!= QDF_STATUS_SUCCESS) {
|
||||
mlo_dev_release_link_vdevs(link_vdevs);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
vdev_link = link_vdevs[i];
|
||||
if (vdev_link && (vdev_link != vdev) &&
|
||||
(wlan_vdev_get_peer_count(vdev_link) >
|
||||
wlan_vdev_get_max_peer_count(vdev_link))) {
|
||||
mlo_dev_release_link_vdevs(link_vdevs);
|
||||
return QDF_STATUS_E_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate MLO peer */
|
||||
ml_peer = qdf_mem_malloc(sizeof(*ml_peer));
|
||||
if (!ml_peer) {
|
||||
mlo_dev_release_link_vdevs(link_vdevs);
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
qdf_atomic_init(&ml_peer->ref_cnt);
|
||||
mlo_peer_lock_create(ml_peer);
|
||||
ml_peer->ml_dev = ml_dev;
|
||||
ml_peer->mlpeer_state = ML_PEER_CREATED;
|
||||
ml_peer->max_links = ml_info->num_partner_links;
|
||||
ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
|
||||
ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc();
|
||||
qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr,
|
||||
(struct qdf_mac_addr *)&link_peer->mldaddr[0]);
|
||||
/* Allocate AID */
|
||||
if (aid == (uint16_t)-1)
|
||||
mlo_peer_allocate_aid(ml_dev, ml_peer);
|
||||
else
|
||||
ml_peer->assoc_id = aid;
|
||||
|
||||
/* Populate Link peer pointer, peer MAC address,
|
||||
* MLD address. HW link ID, update ref count
|
||||
*/
|
||||
mlo_peer_attach_link_peer(ml_peer, link_peer);
|
||||
|
||||
/* Allocate Primary UMAC */
|
||||
mlo_peer_allocate_primary_umac(ml_dev, ml_peer, link_vdevs);
|
||||
|
||||
/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
|
||||
mlo_peer_populate_link_peer(ml_peer, link_peer);
|
||||
|
||||
/* Attach MLO peer to ML Peer table */
|
||||
status = mlo_dev_mlpeer_attach(ml_dev, ml_peer);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
mlo_reset_link_peer(ml_peer, link_peer);
|
||||
mlo_peer_free(ml_peer);
|
||||
mlo_dev_release_link_vdevs(link_vdevs);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
|
||||
/* Notify other vdevs about link peer creation */
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
vdev_link = link_vdevs[i];
|
||||
if (!vdev_link)
|
||||
continue;
|
||||
|
||||
if (vdev_link == vdev)
|
||||
continue;
|
||||
|
||||
mlo_partner_peer_create_post(ml_dev, vdev_link,
|
||||
ml_peer, frm_buf, ml_info);
|
||||
}
|
||||
}
|
||||
mlo_dev_release_link_vdevs(link_vdevs);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer,
|
||||
struct wlan_objmgr_peer *peer)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct wlan_objmgr_peer *assoc_peer;
|
||||
|
||||
/* Populate Link peer pointer, peer MAC address,
|
||||
* MLD address. HW link ID, update ref count
|
||||
*/
|
||||
status = mlo_peer_attach_link_peer(ml_peer, peer);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
return status;
|
||||
|
||||
/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
|
||||
mlo_peer_populate_link_peer(ml_peer, peer);
|
||||
|
||||
if (ml_peer->max_links == ml_peer->link_peer_cnt) {
|
||||
assoc_peer = ml_peer->peer_list[0].link_peer;
|
||||
if (assoc_peer)
|
||||
mlo_mlme_peer_assoc_resp(assoc_peer);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer)
|
||||
{
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
|
||||
ml_peer = peer->mlo_peer_ctx;
|
||||
|
||||
if (!ml_peer)
|
||||
return QDF_STATUS_E_NOENT;
|
||||
|
||||
mlo_reset_link_peer(ml_peer, peer);
|
||||
mlo_peer_detach_link_peer(ml_peer, peer);
|
||||
wlan_mlo_peer_release_ref(ml_peer);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
373
umac/mlo_mgr/src/wlan_mlo_mgr_peer_list.c
Archivo normal
373
umac/mlo_mgr/src/wlan_mlo_mgr_peer_list.c
Archivo normal
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <wlan_mlo_mgr_public_structs.h>
|
||||
#include "wlan_mlo_mgr_main.h"
|
||||
#include "qdf_types.h"
|
||||
#include "wlan_cmn.h"
|
||||
#include "wlan_mlo_mgr_peer.h"
|
||||
|
||||
struct aid_search {
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
uint16_t aid;
|
||||
};
|
||||
|
||||
struct mlpeerid_search {
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
uint16_t ml_peerid;
|
||||
};
|
||||
|
||||
struct link_mac_search {
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
struct qdf_mac_addr mac_addr;
|
||||
};
|
||||
|
||||
static inline struct wlan_mlo_peer_context *wlan_mlo_peer_list_peek_head(
|
||||
qdf_list_t *peer_list)
|
||||
{
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
qdf_list_node_t *peer_node = NULL;
|
||||
|
||||
/* This API is invoked with lock acquired, do not add log prints */
|
||||
if (qdf_list_peek_front(peer_list, &peer_node) != QDF_STATUS_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
ml_peer = qdf_container_of(peer_node,
|
||||
struct wlan_mlo_peer_context, peer_node);
|
||||
return ml_peer;
|
||||
}
|
||||
|
||||
static inline struct wlan_mlo_peer_context *wlan_mlo_peer_get_next_mlpeer(
|
||||
qdf_list_t *peer_list,
|
||||
struct wlan_mlo_peer_context *ml_peer)
|
||||
{
|
||||
struct wlan_mlo_peer_context *next_peer;
|
||||
qdf_list_node_t *node = &ml_peer->peer_node;
|
||||
qdf_list_node_t *next_node = NULL;
|
||||
|
||||
/* This API is invoked with lock acquired, do not add log prints */
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
if (qdf_list_peek_next(peer_list, node, &next_node) !=
|
||||
QDF_STATUS_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
next_peer = qdf_container_of(next_node,
|
||||
struct wlan_mlo_peer_context, peer_node);
|
||||
|
||||
return next_peer;
|
||||
}
|
||||
|
||||
static inline struct wlan_mlo_peer_context *mlo_get_mlpeer(
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
struct qdf_mac_addr *ml_addr)
|
||||
{
|
||||
uint8_t hash_index;
|
||||
struct wlan_mlo_peer_list *mlo_peer_list;
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
struct wlan_mlo_peer_context *next_ml_peer;
|
||||
qdf_list_t *peer_hash_list;
|
||||
|
||||
mlo_peer_list = &ml_dev->mlo_peer_list;
|
||||
hash_index = WLAN_PEER_HASH(ml_addr->bytes);
|
||||
|
||||
peer_hash_list = &mlo_peer_list->peer_hash[hash_index];
|
||||
/* Get first vdev */
|
||||
ml_peer = wlan_mlo_peer_list_peek_head(peer_hash_list);
|
||||
/**
|
||||
* Iterate through pdev's vdev list, till vdev id matches with
|
||||
* entry of vdev list
|
||||
*/
|
||||
while (ml_peer) {
|
||||
if (qdf_is_macaddr_equal(&ml_peer->peer_mld_addr, ml_addr))
|
||||
return ml_peer;
|
||||
|
||||
/* get next vdev */
|
||||
next_ml_peer = wlan_mlo_peer_get_next_mlpeer(peer_hash_list,
|
||||
ml_peer);
|
||||
ml_peer = next_ml_peer;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_mlo_iterate_ml_peerlist(struct wlan_mlo_dev_context *ml_dev,
|
||||
wlan_mlo_op_handler handler,
|
||||
void *arg)
|
||||
{
|
||||
uint8_t hash_index;
|
||||
struct wlan_mlo_peer_list *peerlist;
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
struct wlan_mlo_peer_context *next;
|
||||
qdf_list_t *peer_hash_list;
|
||||
QDF_STATUS status;
|
||||
|
||||
peerlist = &ml_dev->mlo_peer_list;
|
||||
ml_peerlist_lock_acquire(peerlist);
|
||||
|
||||
for (hash_index = 0; hash_index < WLAN_PEER_HASHSIZE; hash_index++) {
|
||||
peer_hash_list = &peerlist->peer_hash[hash_index];
|
||||
/* Get first vdev */
|
||||
ml_peer = wlan_mlo_peer_list_peek_head(peer_hash_list);
|
||||
/**
|
||||
* Iterate through pdev's vdev list, till vdev id matches with
|
||||
* entry of vdev list
|
||||
*/
|
||||
while (ml_peer) {
|
||||
status = handler(ml_dev, ml_peer, arg);
|
||||
if (status == QDF_STATUS_SUCCESS) {
|
||||
ml_peerlist_lock_release(peerlist);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
/* get next ml peer */
|
||||
next = wlan_mlo_peer_get_next_mlpeer(peer_hash_list,
|
||||
ml_peer);
|
||||
ml_peer = next;
|
||||
}
|
||||
}
|
||||
ml_peerlist_lock_release(peerlist);
|
||||
|
||||
return QDF_STATUS_E_NOENT;
|
||||
}
|
||||
|
||||
static QDF_STATUS
|
||||
wlan_find_mlpeer_link_mac_addr(struct wlan_mlo_dev_context *ml_dev,
|
||||
void *iter_ml_peer,
|
||||
void *arg)
|
||||
{
|
||||
struct link_mac_search *link_mac_arg = (struct link_mac_search *)arg;
|
||||
struct wlan_mlo_link_peer_entry *link_peer;
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
uint8_t i;
|
||||
|
||||
ml_peer = (struct wlan_mlo_peer_context *)iter_ml_peer;
|
||||
for (i = 0; i < MAX_MLO_PEER; i++) {
|
||||
link_peer = &ml_peer->peer_list[i];
|
||||
if (!link_peer)
|
||||
continue;
|
||||
|
||||
if (qdf_is_macaddr_equal(&link_mac_arg->mac_addr,
|
||||
&link_peer->link_addr)) {
|
||||
link_mac_arg->ml_peer = ml_peer;
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
return QDF_STATUS_E_NOENT;
|
||||
}
|
||||
|
||||
static QDF_STATUS wlan_find_mlpeer_aid(struct wlan_mlo_dev_context *ml_dev,
|
||||
void *iter_ml_peer,
|
||||
void *arg)
|
||||
{
|
||||
struct aid_search *aid_arg = (struct aid_search *)arg;
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
|
||||
ml_peer = (struct wlan_mlo_peer_context *)iter_ml_peer;
|
||||
|
||||
if (aid_arg->aid == ml_peer->assoc_id) {
|
||||
aid_arg->ml_peer = ml_peer;
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return QDF_STATUS_E_NOENT;
|
||||
}
|
||||
|
||||
static QDF_STATUS
|
||||
wlan_find_mlpeer_ml_peerid(struct wlan_mlo_dev_context *ml_dev,
|
||||
void *iter_ml_peer,
|
||||
void *arg)
|
||||
{
|
||||
struct mlpeerid_search *mlpeer_id_arg = (struct mlpeerid_search *)arg;
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
|
||||
ml_peer = (struct wlan_mlo_peer_context *)iter_ml_peer;
|
||||
|
||||
if (mlpeer_id_arg->ml_peerid == ml_peer->mlo_peer_id) {
|
||||
mlpeer_id_arg->ml_peer = ml_peer;
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return QDF_STATUS_E_NOENT;
|
||||
}
|
||||
|
||||
struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_linkmac(
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
struct qdf_mac_addr *link_mac)
|
||||
{
|
||||
struct link_mac_search link_mac_arg;
|
||||
QDF_STATUS status;
|
||||
|
||||
qdf_copy_macaddr(&link_mac_arg.mac_addr, link_mac);
|
||||
status = wlan_mlo_iterate_ml_peerlist(ml_dev,
|
||||
wlan_find_mlpeer_link_mac_addr,
|
||||
&link_mac_arg);
|
||||
if (status == QDF_STATUS_SUCCESS)
|
||||
return link_mac_arg.ml_peer;
|
||||
|
||||
/* TODO: Take ref */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_aid(
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
uint16_t assoc_id)
|
||||
{
|
||||
struct aid_search aid_arg;
|
||||
QDF_STATUS status;
|
||||
|
||||
aid_arg.aid = assoc_id;
|
||||
status = wlan_mlo_iterate_ml_peerlist(ml_dev,
|
||||
wlan_find_mlpeer_aid,
|
||||
&aid_arg);
|
||||
if (status == QDF_STATUS_SUCCESS)
|
||||
return aid_arg.ml_peer;
|
||||
|
||||
/* TODO: Take ref */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_ml_peerid(
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
uint16_t ml_peerid)
|
||||
{
|
||||
struct mlpeerid_search peerid_arg;
|
||||
QDF_STATUS status;
|
||||
|
||||
peerid_arg.ml_peerid = ml_peerid;
|
||||
status = wlan_mlo_iterate_ml_peerlist(ml_dev,
|
||||
wlan_find_mlpeer_ml_peerid,
|
||||
&peerid_arg);
|
||||
if (status == QDF_STATUS_SUCCESS)
|
||||
return peerid_arg.ml_peer;
|
||||
|
||||
/* TODO: Take ref */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer(
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
struct qdf_mac_addr *ml_addr)
|
||||
{
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
struct wlan_mlo_peer_list *mlo_peer_list;
|
||||
|
||||
mlo_peer_list = &ml_dev->mlo_peer_list;
|
||||
ml_peerlist_lock_acquire(mlo_peer_list);
|
||||
ml_peer = mlo_get_mlpeer(ml_dev, ml_addr);
|
||||
if (!ml_peer) {
|
||||
ml_peerlist_lock_release(mlo_peer_list);
|
||||
return NULL;
|
||||
}
|
||||
/* TODO: Take ref */
|
||||
|
||||
ml_peerlist_lock_release(mlo_peer_list);
|
||||
return ml_peer;
|
||||
}
|
||||
|
||||
static void wlan_mlo_peerlist_add_tail(qdf_list_t *obj_list,
|
||||
struct wlan_mlo_peer_context *obj)
|
||||
{
|
||||
qdf_list_insert_back(obj_list, &obj->peer_node);
|
||||
}
|
||||
|
||||
static QDF_STATUS wlan_mlo_peerlist_remove_mlpeer(
|
||||
qdf_list_t *obj_list,
|
||||
struct wlan_mlo_peer_context *ml_peer)
|
||||
{
|
||||
qdf_list_node_t *peer_node = NULL;
|
||||
|
||||
if (!ml_peer)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
/* get vdev list node element */
|
||||
peer_node = &ml_peer->peer_node;
|
||||
/* list is empty, return failure */
|
||||
if (qdf_list_remove_node(obj_list, peer_node) != QDF_STATUS_SUCCESS)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS mlo_dev_mlpeer_attach(struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_mlo_peer_context *ml_peer)
|
||||
{
|
||||
uint8_t hash_index;
|
||||
struct wlan_mlo_peer_list *mlo_peer_list;
|
||||
|
||||
mlo_peer_list = &ml_dev->mlo_peer_list;
|
||||
ml_peerlist_lock_acquire(mlo_peer_list);
|
||||
if (mlo_get_mlpeer(ml_dev, &ml_peer->peer_mld_addr)) {
|
||||
ml_peerlist_lock_release(mlo_peer_list);
|
||||
return QDF_STATUS_E_EXISTS;
|
||||
}
|
||||
|
||||
hash_index = WLAN_PEER_HASH(ml_peer->peer_mld_addr.bytes);
|
||||
wlan_mlo_peerlist_add_tail(&mlo_peer_list->peer_hash[hash_index],
|
||||
ml_peer);
|
||||
ml_peerlist_lock_release(mlo_peer_list);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS mlo_dev_mlpeer_detach(struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_mlo_peer_context *ml_peer)
|
||||
{
|
||||
uint8_t hash_index;
|
||||
QDF_STATUS status;
|
||||
struct wlan_mlo_peer_list *mlo_peer_list;
|
||||
|
||||
mlo_peer_list = &ml_dev->mlo_peer_list;
|
||||
ml_peerlist_lock_acquire(mlo_peer_list);
|
||||
hash_index = WLAN_PEER_HASH(ml_peer->peer_mld_addr.bytes);
|
||||
status = wlan_mlo_peerlist_remove_mlpeer(
|
||||
&mlo_peer_list->peer_hash[hash_index],
|
||||
ml_peer);
|
||||
ml_peerlist_lock_release(mlo_peer_list);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS mlo_dev_mlpeer_list_init(struct wlan_mlo_dev_context *ml_dev)
|
||||
{
|
||||
struct wlan_mlo_peer_list *mlo_peer_list;
|
||||
uint16_t i;
|
||||
|
||||
mlo_peer_list = &ml_dev->mlo_peer_list;
|
||||
ml_peerlist_lock_create(mlo_peer_list);
|
||||
for (i = 0; i < WLAN_PEER_HASHSIZE; i++)
|
||||
qdf_list_create(&mlo_peer_list->peer_hash[i],
|
||||
WLAN_UMAC_PSOC_MAX_PEERS +
|
||||
WLAN_MAX_PSOC_TEMP_PEERS);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS mlo_dev_mlpeer_list_deinit(struct wlan_mlo_dev_context *ml_dev)
|
||||
{
|
||||
uint16_t i;
|
||||
struct wlan_mlo_peer_list *mlo_peer_list;
|
||||
|
||||
/* deinit the lock */
|
||||
mlo_peer_list = &ml_dev->mlo_peer_list;
|
||||
ml_peerlist_lock_destroy(mlo_peer_list);
|
||||
for (i = 0; i < WLAN_PEER_HASHSIZE; i++)
|
||||
qdf_list_destroy(&mlo_peer_list->peer_hash[i]);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
62
umac/mlo_mgr/src/wlan_mlo_mgr_primary_umac.c
Archivo normal
62
umac/mlo_mgr/src/wlan_mlo_mgr_primary_umac.c
Archivo normal
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "wlan_mlo_mgr_main.h"
|
||||
#include "qdf_types.h"
|
||||
#include "wlan_cmn.h"
|
||||
#include "wlan_mlo_mgr_peer.h"
|
||||
#include <wlan_mlo_mgr_ap.h>
|
||||
|
||||
void mlo_peer_assign_primary_umac(
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
struct wlan_mlo_link_peer_entry *peer_entry)
|
||||
{
|
||||
if (wlan_peer_get_psoc_id(peer_entry->link_peer) ==
|
||||
ml_peer->primary_umac_psoc_id)
|
||||
peer_entry->is_primary = true;
|
||||
else
|
||||
peer_entry->is_primary = false;
|
||||
}
|
||||
|
||||
QDF_STATUS mlo_peer_allocate_primary_umac(
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
struct wlan_objmgr_vdev *link_vdevs[])
|
||||
{
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
uint16_t link_load[WLAN_UMAC_MLO_MAX_VDEVS];
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
vdev = ml_dev->wlan_vdev_list[i];
|
||||
if (!vdev) {
|
||||
link_load[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
link_load[i] = 1/* TODO mlo_get_umac_load(vdev)*/;
|
||||
}
|
||||
ml_peer->primary_umac_psoc_id = 0;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS mlo_peer_free_primary_umac(
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
struct wlan_mlo_peer_context *ml_peer)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
Referencia en una nueva incidencia
Block a user