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
This commit is contained in:
Srinivas Pitla
2021-04-27 10:18:30 -07:00
committed by Madan Koyyalamudi
父節點 7f36fdf121
當前提交 7469335fa4
共有 20 個文件被更改,包括 3209 次插入49 次删除

查看文件

@@ -72,6 +72,9 @@
/* Max vdev_id */
#define WLAN_UMAC_VDEV_ID_MAX 0xFF
/* TODO: MAX AID */
#define WLAN_UMAC_MAX_AID 2048
/* Invalid pdev_id */
#define WLAN_INVALID_PDEV_ID 0xFFFFFFFF

查看文件

@@ -95,6 +95,9 @@
/* node is a local mesh peer */
#define WLAN_PEER_F_LOCAL_MESH_PEER 0x80000000
/* MLO enabled peer */
#define WLAN_PEER_FEXT_MLO 0x00000001
/**
* enum wlan_peer_state - peer state
* @WLAN_INIT_STATE: Default state
@@ -121,6 +124,7 @@ enum wlan_peer_state {
* struct wlan_objmgr_peer_mlme - mlme common data of peer
* @peer_capinfo: protocol cap info
* @peer_flags: PEER OP flags
* @peer_ext_flags: PEER OP ext flags
* @peer_type: Type of PEER, (STA/AP/etc.)
* @phymode: phy mode of station
* @max_rate: Max Rate supported
@@ -132,6 +136,7 @@ enum wlan_peer_state {
struct wlan_objmgr_peer_mlme {
uint32_t peer_capinfo;
uint32_t peer_flags;
uint32_t peer_ext_flags;
enum wlan_peer_type peer_type;
enum wlan_phymode phymode;
uint32_t max_rate;
@@ -191,7 +196,7 @@ struct wlan_objmgr_peer {
WLAN_OBJ_STATE obj_state;
qdf_spinlock_t peer_lock;
#ifdef WLAN_FEATURE_11BE_MLO
struct mlo_peer_ctx *mlo_peer_ctx;
struct wlan_mlo_peer_context *mlo_peer_ctx;
uint8_t mldaddr[QDF_MAC_ADDR_SIZE];
#endif
};
@@ -840,6 +845,35 @@ static inline enum wlan_phymode wlan_peer_get_phymode(
return peer->peer_mlme.phymode;
}
/**
* wlan_peer_set_rssi() - set RSSI
* @peer: PEER object
* @rssi: RSSI
*
* API to set rssi
*
* Return: void
*/
static inline void wlan_peer_set_rssi(struct wlan_objmgr_peer *peer,
int8_t rssi)
{
peer->peer_mlme.rssi = rssi;
}
/**
* wlan_peer_get_rssi() - get RSSI
* @peer: PEER object
*
* API to get RSSI
*
* Return:
* @rssi: RSSI of PEER
*/
static inline int8_t wlan_peer_get_rssi(
struct wlan_objmgr_peer *peer)
{
return peer->peer_mlme.rssi;
}
/**
* wlan_peer_set_macaddr() - set mac addr
@@ -951,6 +985,51 @@ static inline uint8_t wlan_peer_mlme_flag_get(struct wlan_objmgr_peer *peer,
return (peer->peer_mlme.peer_flags & flag) ? 1 : 0;
}
/**
* wlan_peer_mlme_flag_ext_set() - mlme ext flag set
* @peer: PEER object
* @flag: ext flag to be set
*
* API to set ext flag in peer
*
* Return: void
*/
static inline void wlan_peer_mlme_flag_ext_set(struct wlan_objmgr_peer *peer,
uint32_t flag)
{
peer->peer_mlme.peer_ext_flags |= flag;
}
/**
* wlan_peer_mlme_flag_clear() - mlme ext flag clear
* @peer: PEER object
* @flag: ext flag to be cleared
*
* API to clear ext flag in peer
*
* Return: void
*/
static inline void wlan_peer_mlme_flag_ext_clear(struct wlan_objmgr_peer *peer,
uint32_t flag)
{
peer->peer_mlme.peer_ext_flags &= ~flag;
}
/**
* wlan_peer_mlme_flag_ext_get() - mlme ext flag get
* @peer: PEER object
* @flag: ext flag to be checked
*
* API to know, whether particular ext flag is set in peer
*
* Return: 1 (for set) or 0 (for not set)
*/
static inline uint8_t wlan_peer_mlme_flag_ext_get(struct wlan_objmgr_peer *peer,
uint32_t flag)
{
return (peer->peer_mlme.peer_ext_flags & flag) ? 1 : 0;
}
/**
* wlan_peer_mlme_set_state() - peer mlme state
* @peer: PEER object
@@ -1173,6 +1252,23 @@ static inline struct wlan_objmgr_psoc *wlan_peer_get_psoc(
return psoc;
}
/**
* wlan_peer_get_psoc_id() - get psoc id
* @peer: PEER object
*
* API to get peer's psoc id
*
* Return: @psoc_id: psoc id
*/
static inline uint8_t wlan_peer_get_psoc_id(struct wlan_objmgr_peer *peer)
{
struct wlan_objmgr_psoc *psoc;
psoc = wlan_peer_get_psoc(peer);
return wlan_psoc_get_id(psoc);
}
/*
* wlan_peer_get_pdev_id() - get pdev id
* @peer: peer object pointer

查看文件

@@ -667,6 +667,23 @@ static inline struct wlan_objmgr_psoc *wlan_vdev_get_psoc(
return psoc;
}
/**
* wlan_vdev_get_psoc_id() - get psoc id
* @vdev: VDEV object
*
* API to get VDEV's psoc id
*
* Return: @psoc_id: psoc id
*/
static inline uint8_t wlan_vdev_get_psoc_id(struct wlan_objmgr_vdev *vdev)
{
struct wlan_objmgr_psoc *psoc;
psoc = wlan_vdev_get_psoc(vdev);
return wlan_psoc_get_id(psoc);
}
/**
* wlan_vdev_mlme_set_opmode() - set vdev opmode
* @vdev: VDEV object

查看文件

@@ -349,14 +349,28 @@ struct vdev_mlme_mgmt_generic {
bool special_vdev_mode;
};
/*
* struct wlan_vdev_aid_mgr AID manager
* @aid_bitmap: AID bitmap array
* @max_aid: Max allowed AID
* @ref_cnt: to share AID across VDEVs for MBSSID
*/
struct wlan_vdev_aid_mgr {
qdf_bitmap(aid_bitmap, WLAN_UMAC_MAX_AID);
uint16_t max_aid;
qdf_atomic_t ref_cnt;
};
/**
* struct vdev_mlme_mgmt_ap - ap specific vdev mlme mgmt cfg
* @hidden_ssid: flag to indicate whether it is hidden ssid
* @cac_duration_ms: cac duration in millseconds
* @aid_mgr: AID bitmap mgr
*/
struct vdev_mlme_mgmt_ap {
bool hidden_ssid;
uint32_t cac_duration_ms;
struct wlan_vdev_aid_mgr *aid_mgr;
};
/**
@@ -1100,4 +1114,47 @@ static inline uint16_t wlan_vdev_mlme_get_he_mcs_12_13_map(
return 0;
}
#endif
/**
* wlan_vdev_mlme_set_aid_mgr() - set aid mgr
* @vdev: VDEV object
* @aid_mgr: AID mgr
*
* API to set AID mgr in VDEV MLME cmpt object
*
* Return: void
*/
static inline void wlan_vdev_mlme_set_aid_mgr(
struct wlan_objmgr_vdev *vdev,
struct wlan_vdev_aid_mgr *aid_mgr)
{
struct vdev_mlme_obj *vdev_mlme;
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
if (!vdev_mlme)
return;
vdev_mlme->mgmt.ap.aid_mgr = aid_mgr;
}
/**
* wlan_vdev_mlme_get_aid_mgr() - get aid mgr
* @vdev: VDEV object
*
* API to get AID mgr in VDEV MLME cmpt object
*
* Return: aid_mgr
*/
static inline struct wlan_vdev_aid_mgr *wlan_vdev_mlme_get_aid_mgr(
struct wlan_objmgr_vdev *vdev)
{
struct vdev_mlme_obj *vdev_mlme;
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
if (!vdev_mlme)
return NULL;
return vdev_mlme->mgmt.ap.aid_mgr;
}
#endif

查看文件

@@ -159,6 +159,17 @@ QDF_STATUS wlan_vdev_mlme_is_csa_restart(struct wlan_objmgr_vdev *vdev);
*/
QDF_STATUS wlan_vdev_is_going_down(struct wlan_objmgr_vdev *vdev);
/**
* wlan_vdev_is_peer_create_allowed() - Checks whether PEER can be created
* @vdev: Object manager VDEV object
*
* API to check the VDEV MLME SM state to allow PEER association
*
* Return: SUCCESS: if peer create can be allowed
* FAILURE: otherwise failure
*/
QDF_STATUS wlan_vdev_is_peer_create_allowed(struct wlan_objmgr_vdev *vdev);
/**
* wlan_vdev_is_restart_progress() - Checks VDEV restart is in progress
* @vdev: Object manager VDEV object

查看文件

@@ -224,6 +224,22 @@ QDF_STATUS wlan_vdev_is_going_down(struct wlan_objmgr_vdev *vdev)
return QDF_STATUS_E_FAILURE;
}
QDF_STATUS wlan_vdev_is_peer_create_allowed(struct wlan_objmgr_vdev *vdev)
{
enum wlan_vdev_state state;
enum wlan_vdev_state substate;
state = wlan_vdev_mlme_get_state(vdev);
substate = wlan_vdev_mlme_get_substate(vdev);
if (!((state == WLAN_VDEV_S_INIT) ||
(state == WLAN_VDEV_S_STOP) ||
((state == WLAN_VDEV_S_SUSPEND) &&
(substate == WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN))))
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}
QDF_STATUS wlan_vdev_is_restart_progress(struct wlan_objmgr_vdev *vdev)
{
enum wlan_vdev_state state;

查看文件

@@ -82,4 +82,226 @@ void mlo_ap_vdev_detach(struct wlan_objmgr_vdev *vdev);
* Return: None
*/
void mlo_ap_link_down_cmpl_notify(struct wlan_objmgr_vdev *vdev);
/**
* wlan_vdev_aid_mgr_init() - VDEV AID mgr init
* @max_aid: max AID
*
* This function is called as part of vdev/MLO DEV initialization.
* This will allocate aid mgr structure for a VDEV
*
* Return: aid_mgr
*/
struct wlan_vdev_aid_mgr *wlan_vdev_aid_mgr_init(uint16_t max_aid);
/**
* wlan_vdev_aid_mgr_free() - VDEV AID mgr free
* @aid_mgr: AID mgr
*
* This function frees the aid mgr of the VDEV
*
* Return: void
*/
void wlan_vdev_aid_mgr_free(struct wlan_vdev_aid_mgr *aid_mgr);
/**
* wlan_mlo_vdev_aid_mgr_init() - MLO AID mgr init
* @ml_dev: MLO DEV context
*
* This function allocate AID space for all associated VDEVs of MLD
*
* Return: SUCCESS if allocated successfully
*/
QDF_STATUS wlan_mlo_vdev_aid_mgr_init(struct wlan_mlo_dev_context *ml_dev);
/**
* wlan_mlo_vdev_aid_mgr_deinit() - MLO AID mgr free
* @ml_dev: MLO DEV context
*
* This function frees AID space for all associated VDEVs of MLD
*
* Return: void
*/
void wlan_mlo_vdev_aid_mgr_deinit(struct wlan_mlo_dev_context *ml_dev);
/**
* wlan_mlo_vdev_alloc_aid_mgr() - Allocate AID space for a VDEV
* @ml_dev: MLO DEV context
* @vdev: VDEV
*
* This function allocates AID space for an associated VDEV of MLD
*
* Return: SUCCESS if allocated successfully
*/
QDF_STATUS wlan_mlo_vdev_alloc_aid_mgr(struct wlan_mlo_dev_context *ml_dev,
struct wlan_objmgr_vdev *vdev);
/**
* wlan_mlo_vdev_free_aid_mgr() - Free AID space for a VDEV
* @ml_dev: MLO DEV context
* @vdev: VDEV
*
* This function frees AID space for an associated VDEV of MLD
*
* Return: SUCCESS if freed successfully
*/
QDF_STATUS wlan_mlo_vdev_free_aid_mgr(struct wlan_mlo_dev_context *ml_dev,
struct wlan_objmgr_vdev *vdev);
/**
* mlo_peer_allocate_aid() - Allocate AID for MLO peer
* @ml_dev: MLO DEV context
* @ml_peer: MLO peer object
*
* This function allocates AID for an MLO peer
*
* Return: SUCCESS if allocated successfully
*/
QDF_STATUS mlo_peer_allocate_aid(
struct wlan_mlo_dev_context *ml_dev,
struct wlan_mlo_peer_context *ml_peer);
/**
* mlo_get_aid() - Allocate AID for a associated station
* @vdev: VDEV
*
* This function allocates AID for an associated station of MLD
*
* Return: AID
*/
uint16_t mlo_get_aid(struct wlan_objmgr_vdev *vdev);
/**
* mlo_free_aid() - Frees AID for a station
* @vdev: VDEV
* @assoc_id: Assoc ID
*
* This function frees AID for an associated station of MLD
*
* Return: SUCCESS if freed
*/
QDF_STATUS mlo_free_aid(struct wlan_objmgr_vdev *vdev, uint16_t assoc_id);
/**
* mlme_get_aid() - Allocate AID for a non-MLD station
* @vdev: VDEV
*
* This function allocates AID for an associated NON-MLD station of MLD
*
* Return: AID
*/
uint16_t mlme_get_aid(struct wlan_objmgr_vdev *vdev);
/**
* wlan_mlo_peer_free_aid() - Free assoc id
* @ml_aid_mgr: MLO AID mgr
* @link_ix: Link index
* @assoc_id: Assoc id to be freed
*
* This function frees assoc id, resets bit in all bitmaps
*
* Return: SUCCESS,if it freed
*/
QDF_STATUS wlan_mlo_peer_free_aid(
struct wlan_ml_vdev_aid_mgr *ml_aid_mgr,
uint8_t link_ix,
uint16_t assoc_id);
/**
* wlan_mlme_peer_free_aid() - Free link assoc id
* @vdev_aid_mgr: VDEV AID mgr
* @no_lock: lock needed for the operation
* @assoc_id: Assoc id to be freed
*
* This function frees assoc id of a specific VDEV
*
* Return: void
*/
void wlan_mlme_peer_free_aid(
struct wlan_vdev_aid_mgr *vdev_aid_mgr,
bool no_lock, uint16_t assoc_id);
/**
* mlo_peer_free_aid() - public API to free AID
* @ml_dev: MLO DEV context
* @ml_peer: MLO peer object
*
* This function invokes low level API to free assoc id
*
* Return: SUCCESS, if it freed
*/
QDF_STATUS mlo_peer_free_aid(struct wlan_mlo_dev_context *ml_dev,
struct wlan_mlo_peer_context *ml_peer);
/**
* mlme_free_aid() - public API to free link assoc id
* @vdev: VDEV object
* @assoc_id: Assoc id to be freed
*
* This function invokes low level API to free assoc id of a specific VDEV
*
* Return: void
*/
void mlme_free_aid(struct wlan_objmgr_vdev *vdev, uint16_t assoc_id);
/**
* mlo_ap_ml_peerid_alloc() - public API to allocate MLO peer id
*
* This function allocates MLO peer ID
*
* Return: mlo_peer_id on success,
MLO_INVALID_PEER_ID on failure
*/
uint16_t mlo_ap_ml_peerid_alloc(void);
/**
* mlo_ap_ml_peerid_free() - public API to free MLO peer id
* @ml_peer_id: ML peer id
*
* This function frees MLO peer ID
*
* Return: void
*/
void mlo_ap_ml_peerid_free(uint16_t mlo_peer_id);
#define ML_PRIMARY_UMAC_ID_INVAL 0xff
/**
* mlo_peer_assign_primary_umac() - Assign Primary UMAC
* @ml_peer: MLO peer object
* @peer_entry: Link peer entry
*
* This function assigns primary UMAC flag in peer entry
*
* Return: SUCCESS,if it allocated
*/
void mlo_peer_assign_primary_umac(
struct wlan_mlo_peer_context *ml_peer,
struct wlan_mlo_link_peer_entry *peer_entry);
/**
* mlo_peer_allocate_primary_umac() - Allocate Primary UMAC
* @ml_dev: MLO DEV context
* @ml_peer: MLO peer object
* @link_vdev: link vdev array
*
* This function allocates primary UMAC for a MLO peer
*
* Return: SUCCESS,if it allocated
*/
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[]);
/**
* mlo_peer_free_primary_umac() - Free Primary UMAC
* @ml_dev: MLO DEV context
* @ml_peer: MLO peer object
*
* This function frees primary UMAC for a MLO peer
*
* Return: SUCCESS,if it is freed
*/
QDF_STATUS mlo_peer_free_primary_umac(
struct wlan_mlo_dev_context *ml_dev,
struct wlan_mlo_peer_context *ml_peer);
#endif

查看文件

@@ -172,7 +172,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);
/**
@@ -198,4 +198,23 @@ void mlo_mlme_peer_assoc_fail(struct wlan_objmgr_peer *peer);
* Return: void
*/
void mlo_mlme_peer_delete(struct wlan_objmgr_peer *peer);
/**
* mlo_mlme_peer_assoc_resp() - Initiate sending of Assoc response
* @peer: Object manager peer
*
* Return: void
*/
void mlo_mlme_peer_assoc_resp(struct wlan_objmgr_peer *peer);
/**
* mlo_get_link_vdev_ix() - Get index of link VDEV in MLD
* @ml_dev: ML device context
* @vdev: VDEV object
*
* Return: link index
*/
uint8_t mlo_get_link_vdev_ix(struct wlan_mlo_dev_context *mldev,
struct wlan_objmgr_vdev *vdev);
#endif

查看文件

@@ -179,6 +179,231 @@ void mlo_dev_lock_release(struct wlan_mlo_dev_context *mldev)
{
qdf_spin_unlock_bh(&mldev->mlo_dev_lock);
}
/**
* ml_aid_lock_create - Create MLO aid mutex/spinlock
* @mlo_ctx: MLO manager global context
*
* Creates mutex/spinlock
*
* Return: void
*/
static inline
void ml_aid_lock_create(struct mlo_mgr_context *mlo_ctx)
{
qdf_spinlock_create(&mlo_ctx->aid_lock);
}
/**
* ml_aid_lock_destroy - Destroy ml aid mutex/spinlock
* @mlo_ctx: MLO manager global context
*
* Destroy mutex/spinlock
*
* Return: void
*/
static inline void
ml_aid_lock_destroy(struct mlo_mgr_context *mlo_ctx)
{
qdf_spinlock_destroy(&mlo_ctx->aid_lock);
}
/**
* ml_aid_lock_acquire - acquire ml aid mutex/spinlock
* @mlo_ctx: MLO manager global context
*
* acquire mutex/spinlock
*
* return: void
*/
static inline
void ml_aid_lock_acquire(struct mlo_mgr_context *mlo_ctx)
{
qdf_spin_lock_bh(&mlo_ctx->aid_lock);
}
/**
* ml_aid_lock_release - release MLO aid mutex/spinlock
* @mlo_ctx: MLO manager global context
*
* release mutex/spinlock
*
* return: void
*/
static inline
void ml_aid_lock_release(struct mlo_mgr_context *mlo_ctx)
{
qdf_spin_unlock_bh(&mlo_ctx->aid_lock);
}
/**
* ml_peerid_lock_create - Create MLO peer mutex/spinlock
* @mlo_ctx: MLO manager global context
*
* Creates mutex/spinlock
*
* Return: void
*/
static inline
void ml_peerid_lock_create(struct mlo_mgr_context *mlo_ctx)
{
qdf_spinlock_create(&mlo_ctx->ml_peerid_lock);
}
/**
* ml_peerid_lock_destroy - Destroy ml peerid mutex/spinlock
* @mlo_ctx: MLO manager global context
*
* Destroy mutex/spinlock
*
* Return: void
*/
static inline void
ml_peerid_lock_destroy(struct mlo_mgr_context *mlo_ctx)
{
qdf_spinlock_destroy(&mlo_ctx->ml_peerid_lock);
}
/**
* ml_peerid_lock_acquire - acquire ml peerid mutex/spinlock
* @mlo_ctx: MLO manager global context
*
* acquire mutex/spinlock
*
* return: void
*/
static inline
void ml_peerid_lock_acquire(struct mlo_mgr_context *mlo_ctx)
{
qdf_spin_lock_bh(&mlo_ctx->ml_peerid_lock);
}
/**
* ml_peerid_lock_release - release MLO peerid mutex/spinlock
* @mlo_ctx: MLO manager global context
*
* release mutex/spinlock
*
* return: void
*/
static inline
void ml_peerid_lock_release(struct mlo_mgr_context *mlo_ctx)
{
qdf_spin_unlock_bh(&mlo_ctx->ml_peerid_lock);
}
/**
* mlo_peer_lock_create - Create MLO peer mutex/spinlock
* @mlpeer: ML peer
*
* Creates mutex/spinlock
*
* Return: void
*/
static inline void
mlo_peer_lock_create(struct wlan_mlo_peer_context *mlpeer)
{
qdf_spinlock_create(&mlpeer->mlo_peer_lock);
}
/**
* mlo_peer_lock_destroy - Destroy MLO peer mutex/spinlock
* @mlpeer: ML peer
*
* Destroy mutex/spinlock
*
* Return: void
*/
static inline void
mlo_peer_lock_destroy(struct wlan_mlo_peer_context *mlpeer)
{
qdf_spinlock_destroy(&mlpeer->mlo_peer_lock);
}
/**
* mlo_peer_lock_acquire - acquire mlo peer mutex/spinlock
* @mlpeer: MLO peer context
*
* acquire mutex/spinlock
*
* return: void
*/
static inline
void mlo_peer_lock_acquire(struct wlan_mlo_peer_context *mlpeer)
{
qdf_spin_lock_bh(&mlpeer->mlo_peer_lock);
}
/**
* mlo_peer_lock_release - release MLO peer mutex/spinlock
* @mlpeer: MLO peer context
*
* release mutex/spinlock
*
* return: void
*/
static inline
void mlo_peer_lock_release(struct wlan_mlo_peer_context *mlpeer)
{
qdf_spin_unlock_bh(&mlpeer->mlo_peer_lock);
}
/**
* ml_peerlist_lock_create - Create MLO peer list mutex/spinlock
* @ml_peerlist: ML peer list context
*
* Creates mutex/spinlock
*
* Return: void
*/
static inline void
ml_peerlist_lock_create(struct wlan_mlo_peer_list *ml_peerlist)
{
qdf_spinlock_create(&ml_peerlist->peer_list_lock);
}
/**
* ml_peerlist_lock_destroy - Destroy MLO peer list mutex/spinlock
* @ml_peerlist: ML peer list context
*
* Destroy mutex/spinlock
*
* Return: void
*/
static inline void
ml_peerlist_lock_destroy(struct wlan_mlo_peer_list *ml_peerlist)
{
qdf_spinlock_destroy(&ml_peerlist->peer_list_lock);
}
/**
* ml_peerlist_lock_acquire - acquire ML peer list mutex/spinlock
* @ml_peerlist: ML peer list context
*
* acquire mutex/spinlock
*
* return: void
*/
static inline
void ml_peerlist_lock_acquire(struct wlan_mlo_peer_list *ml_peerlist)
{
qdf_spin_lock_bh(&ml_peerlist->peer_list_lock);
}
/**
* ml_peerlist_lock_release - release ML peer list mutex/spinlock
* @ml_peerlist: ML peer list context
*
* release mutex/spinlock
*
* return: void
*/
static inline
void ml_peerlist_lock_release(struct wlan_mlo_peer_list *ml_peerlist)
{
qdf_spin_unlock_bh(&ml_peerlist->peer_list_lock);
}
#else
static inline
void ml_link_lock_create(struct mlo_mgr_context *mlo_ctx)
@@ -225,6 +450,102 @@ static inline void mlo_dev_lock_release(struct wlan_mlo_dev_context *mldev)
{
qdf_mutex_release(&mldev->mlo_dev_lock);
}
static inline
void ml_aid_lock_create(struct mlo_mgr_context *mlo_ctx)
{
qdf_mutex_create(&mlo_ctx->aid_lock);
}
static inline void
ml_aid_lock_destroy(struct mlo_mgr_context *mlo_ctx)
{
qdf_mutex_destroy(&mlo_ctx->aid_lock);
}
static inline
void ml_aid_lock_acquire(struct mlo_mgr_context *mlo_ctx)
{
qdf_mutex_acquire(&mlo_ctx->aid_lock);
}
static inline
void ml_aid_lock_release(struct mlo_mgr_context *mlo_ctx)
{
qdf_mutex_release(&mlo_ctx->aid_lock);
}
static inline
void ml_peerid_lock_create(struct mlo_mgr_context *mlo_ctx)
{
qdf_mutex_create(&mlo_ctx->ml_peerid_lock);
}
static inline void
ml_peerid_lock_destroy(struct mlo_mgr_context *mlo_ctx)
{
qdf_mutex_destroy(&mlo_ctx->ml_peerid_lock);
}
static inline
void ml_peerid_lock_acquire(struct mlo_mgr_context *mlo_ctx)
{
qdf_mutex_acquire(&mlo_ctx->ml_peerid_lock);
}
static inline
void ml_peerid_lock_release(struct mlo_mgr_context *mlo_ctx)
{
qdf_mutex_release(&mlo_ctx->ml_peerid_lock);
}
static inline void
mlo_peer_lock_create(struct wlan_mlo_peer_context *mlpeer)
{
qdf_mutex_create(&mlpeer->mlo_peer_lock);
}
static inline void
mlo_peer_lock_destroy(struct wlan_mlo_peer_context *mlpeer)
{
qdf_mutex_destroy(&mlpeer->mlo_peer_lock);
}
static inline
void mlo_peer_lock_acquire(struct wlan_mlo_peer_context *mlpeer)
{
qdf_mutex_acquire(&mlpeer->mlo_peer_lock);
}
static inline
void mlo_peer_lock_release(struct wlan_mlo_peer_context *mlpeer)
{
qdf_mutex_release(&mlpeer->mlo_peer_lock);
}
static inline void
ml_peerlist_lock_create(struct wlan_mlo_peer_list *ml_peerlist)
{
qdf_mutex_create(&ml_peerlist->peer_list_lock);
}
static inline void
ml_peerlist_lock_destroy(struct wlan_mlo_peer_list *ml_peerlist)
{
qdf_mutex_destroy(&ml_peerlist->peer_list_lock);
}
static inline
void ml_peerlist_lock_acquire(struct wlan_mlo_peer_list *ml_peerlist)
{
qdf_mutex_acquire(&ml_peerlist->peer_list_lock);
}
static inline
void ml_peerlist_lock_release(struct wlan_mlo_peer_list *ml_peerlist)
{
qdf_mutex_release(&ml_peerlist->peer_list_lock);
}
#endif /* WLAN_MLO_USE_SPINLOCK */
#else

查看文件

@@ -0,0 +1,134 @@
/*
* 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.
*/
/*
* DOC: contains mlo manager msgq structure definitions
*/
#ifndef __MLO_MGR_MSGQ_H
#define __MLO_MGR_MSGQ_H
/*
* struct ctxt_switch_mgr - MLO context switch manager
* @ctxt_mgr_timer: Timer to process messages
* @msgq_list: list to hold pending messages
* @ctxt_lock: Lock to have atomic context
* @timer_started: indicates whether timer is running
* @max_messages_procd: Max messages can be stored
*/
struct ctxt_switch_mgr {
qdf_timer_t ctxt_mgr_timer;
qdf_list_t msgq_list;
qdf_spinlock_t ctxt_lock;
bool timer_started;
uint16_t max_messages_procd;
};
/*
* enum mlo_msg_type MLO partner peer message type
* @MLO_PEER_CREATE: Partner peer create
* @MLO_PEER_ASSOC: Partner peer ASSOC
* @MLO_PEER_ASSOC_FAIL: Partner peer ASSOC failure
* @MLO_PEER_DISCONNECT: Partner peer Disconnect
*/
enum mlo_msg_type {
MLO_PEER_CREATE,
MLO_PEER_ASSOC,
MLO_PEER_ASSOC_FAIL,
MLO_PEER_DISCONNECT,
};
/*
* struct peer_create_notif_s - MLO partner peer create notification
* @vdev_link: Link VDEV
* @ml_peer: ML peer to attached
* @addr: Link MAC address
* @frm_buf: Assoc request buffer
*/
struct peer_create_notif_s {
struct wlan_objmgr_vdev *vdev_link;
struct wlan_mlo_peer_context *ml_peer;
struct qdf_mac_addr addr;
qdf_nbuf_t frm_buf;
};
/*
* struct peer_assoc_notify_s - MLO partner peer assoc notification
* @peer: Link peer on which Peer ASSOC to be sent
*/
struct peer_assoc_notify_s {
struct wlan_objmgr_peer *peer;
};
/*
* struct peer_assoc_fail_notify_s - MLO partner peer assoc fail notification
* @peer: Link peer on which Peer assoc resp failure to be sent
*/
struct peer_assoc_fail_notify_s {
struct wlan_objmgr_peer *peer;
};
/*
* struct peer_discon_notify_s - MLO partner peer disconnect notification
* @peer: Link peer on which Peer disconnect to be sent
*/
struct peer_discon_notify_s {
struct wlan_objmgr_peer *peer;
};
/*
* union msg_payload - MLO message payload
* @peer_create: peer create notification structure
* @peer_assoc: peer assoc notification structure
* @peer_assoc_fail: peer assoc fail notification structure
* @peer_disconn: peer disconnect notification structure
*/
union msg_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;
};
#define MLO_MAX_MSGQ_SIZE 256
/*
* struct mlo_ctxt_switch_msg_s - MLO ctxt switch message
* @type: peer create notification structure
* @peer_assoc: peer assoc notification structure
* @peer_assoc_fail: peer assoc fail notification structure
* @peer_disconn: peer disconnect notification structure
*/
struct mlo_ctxt_switch_msg_s {
qdf_list_node_t node;
enum mlo_msg_type type;
struct wlan_mlo_dev_context *ml_dev;
union msg_payload m;
};
/**
* mlo_msgq_post() - Posts message to defer context
* @type: msg tupe
* @ml_dev: MLO dev context
* @payload: msg buf
*
* This function post message to defer conext queue for defer processing
*
* Return: SUCCESS if msg is posted
*/
QDF_STATUS mlo_msgq_post(enum mlo_msg_type type,
struct wlan_mlo_dev_context *ml_dev,
void *payload);
#endif

查看文件

@@ -20,6 +20,7 @@
#ifndef _WLAN_MLO_MGR_PEER_H_
#define _WLAN_MLO_MGR_PEER_H_
#include "wlan_objmgr_peer_obj.h"
/**
* mlo_peer_create - Initiatiate peer create on secondary link(s)
* by posting a message
@@ -98,12 +99,311 @@ void mlo_peer_delete(struct wlan_objmgr_peer *peer);
bool is_mlo_all_peer_links_deleted(void);
/**
* mlo_get_aid - Get the association ID
* wlan_mlo_peer_is_disconnect_progress() - MLO peer is in disconnect progress
* @ml_peer: MLO peer
*
* @vdev: pointer to vdev
* This function checks whether MLO Peer is in disconnect progress
*
* Return: AID value
* Return: SUCCESS if MLO Peer is in disconnect progress
*/
uint8_t mlo_get_aid(struct wlan_objmgr_vdev *vdev);
QDF_STATUS wlan_mlo_peer_is_disconnect_progress(
struct wlan_mlo_peer_context *ml_peer);
/**
* wlan_mlo_peer_is_assoc_done() - MLO peer is Assoc complete
* @ml_peer: MLO peer
*
* This function checks whether MLO Peer's Assoc is completed
*
* Return: SUCCESS if MLO Peer Assoc is completed
*/
QDF_STATUS wlan_mlo_peer_is_assoc_done(struct wlan_mlo_peer_context *ml_peer);
/**
* wlan_mlo_peer_get_assoc_peer() - get assoc peer
* @ml_peer: MLO peer
*
* This function returns assoc peer of MLO peer
*
* Return: assoc peer, if it is found, otherwise NULL
*/
struct wlan_objmgr_peer *wlan_mlo_peer_get_assoc_peer(
struct wlan_mlo_peer_context *ml_peer);
/**
* wlan_mlo_partner_peer_assoc_post() - Notify partner peer assoc
* @peer: Link peer
*
* This function notifies link peers to send peer assoc command to FW
*
* Return: void
*/
void wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer *assoc_peer);
/**
* wlan_mlo_partner_peer_create_failed_notify() - Notify peer creation fail
* @ml_peer: MLO peer
*
* This function notifies about link peer creation failure
*
* Return: void
*/
void wlan_mlo_partner_peer_create_failed_notify(
struct wlan_mlo_peer_context *ml_peer);
/**
* wlan_mlo_partner_peer_disconnect_notify() - Notify peer disconnect
* @peer: Link peer
*
* This function notifies about disconnect is being initilated on link peer
*
* Return: void
*/
void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer);
/**
* wlan_mlo_peer_create() - MLO peer create
* @vdev: Link VDEV
* @link_peer: Link peer
* @ml_info: ML links info
* @frm_buf: Assoc req buffer
* @aid: AID, if already allocated
*
* This function creates MLO peer and notifies other partner VDEVs to create
* link peers
*
* Return: SUCCESS, if MLO peer is successfully created
*/
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);
/**
* mlo_peer_free() - Free MLO peer
* @ml_peer: MLO peer
*
* This function frees MLO peer and resets MLO peer associations
* Note, this API is ref count protected, it should be always invoked
* from wlan_mlo_peer_release_ref()
*
* Return: void
*/
void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer);
/**
* wlan_mlo_peer_get_ref() - Get ref of MLO peer
* @ml_peer: MLO peer
*
* This function gets ref of MLO peer
*
* Return: void
*/
static inline void wlan_mlo_peer_get_ref(struct wlan_mlo_peer_context *ml_peer)
{
qdf_atomic_inc(&ml_peer->ref_cnt);
}
/**
* wlan_mlo_peer_release_ref() - Release ref of MLO peer
* @ml_peer: MLO peer
*
* This function releases ref of MLO peer, if ref is 0, invokes MLO peer free
*
* Return: void
*/
static inline void wlan_mlo_peer_release_ref(
struct wlan_mlo_peer_context *ml_peer)
{
if (qdf_atomic_dec_and_test(&ml_peer->ref_cnt))
mlo_peer_free(ml_peer);
}
/**
* wlan_mlo_link_peer_attach() - MLO link peer attach
* @ml_peer: MLO peer
* @peer: Link peer
*
* This function attaches link peer to MLO peer
*
* Return: SUCCESS, if peer is successfully attached to MLO peer
*/
QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer,
struct wlan_objmgr_peer *peer);
/**
* wlan_mlo_link_peer_delete() - MLO link peer delete
* @peer: Link peer
*
* This function detaches link peer from MLO peer, if this peer is last link
* peer, then MLO peer gets deleted
*
* Return: SUCCESS, if peer is detached from MLO peer
*/
QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer);
/**
** APIs to operations on ML peer object
*/
typedef QDF_STATUS (*wlan_mlo_op_handler)(struct wlan_mlo_dev_context *ml_dev,
void *ml_peer,
void *arg);
/**
* wlan_mlo_iterate_ml_peerlist() - iterate through all ml peer objects
* @ml_dev: MLO DEV object
* @handler: the handler will be called for each ml peer
* the handler should be implemented to perform required operation
* @arg: agruments passed by caller
*
* API to be used for performing the operations on all ML PEER objects
*
* Return: SUCCESS/FAILURE
*/
QDF_STATUS wlan_mlo_iterate_ml_peerlist(struct wlan_mlo_dev_context *ml_dev,
wlan_mlo_op_handler handler,
void *arg);
/**
* wlan_mlo_get_mlpeer_by_linkmac() - find ML peer by Link MAC address
* @ml_dev: MLO DEV object
* @link_mac: Link peer MAC address
*
* API to get ML peer using link MAC address
*
* Return: ML peer object, if it is found
* otherwise, returns NULL
*/
struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_linkmac(
struct wlan_mlo_dev_context *ml_dev,
struct qdf_mac_addr *link_mac);
/**
* wlan_mlo_get_mlpeer_by_aid() - find ML peer by AID
* @ml_dev: MLO DEV object
* @aid: AID
*
* API to get ML peer using AID
*
* Return: ML peer object, if it is found
* otherwise, returns NULL
*/
struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_aid(
struct wlan_mlo_dev_context *ml_dev,
uint16_t assoc_id);
/**
* wlan_mlo_get_mlpeer_by_ml_peerid() - find ML peer by ML peer id
* @ml_dev: MLO DEV object
* @ml_peerid: ML Peer ID
*
* API to get ML peer using ML peer id
*
* Return: ML peer object, if it is found
* otherwise, returns NULL
*/
struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_ml_peerid(
struct wlan_mlo_dev_context *ml_dev,
uint16_t ml_peerid);
/**
* wlan_mlo_get_mlpeer() - find ML peer by MLD MAC address
* @ml_dev: MLO DEV object
* @ml_addr: MLO MAC address
*
* API to get ML peer using MLO MAC address
*
* Return: ML peer object, if it is found
* otherwise, returns NULL
*/
struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer(
struct wlan_mlo_dev_context *ml_dev,
struct qdf_mac_addr *ml_addr);
/**
* mlo_dev_mlpeer_attach() - Add ML PEER to ML peer list
* @ml_dev: MLO DEV object
* @ml_peer: ML peer
*
* API to attach ML PEER to MLD PEER table
*
* Return: SUCCESS, if it attached successfully
* otherwise, returns FAILURE
*/
QDF_STATUS mlo_dev_mlpeer_attach(struct wlan_mlo_dev_context *ml_dev,
struct wlan_mlo_peer_context *ml_peer);
/**
* mlo_dev_mlpeer_detach() - Delete ML PEER from ML peer list
* @ml_dev: MLO DEV object
* @ml_peer: ML peer
*
* API to detach ML PEER from MLD PEER table
*
* Return: SUCCESS, if it detached successfully
* otherwise, returns FAILURE
*/
QDF_STATUS mlo_dev_mlpeer_detach(struct wlan_mlo_dev_context *ml_dev,
struct wlan_mlo_peer_context *ml_peer);
/**
* mlo_dev_mlpeer_list_init() - Initialize ML peer list
* @ml_dev: MLO DEV object
*
* API to initialize MLO peer list
*
* Return: SUCCESS, if initialized successfully
*/
QDF_STATUS mlo_dev_mlpeer_list_init(struct wlan_mlo_dev_context *ml_dev);
/**
* mlo_dev_mlpeer_list_deinit() - destroys ML peer list
* @ml_dev: MLO DEV object
*
* API to destroys MLO peer list
*
* Return: SUCCESS, if initialized successfully
*/
QDF_STATUS mlo_dev_mlpeer_list_deinit(struct wlan_mlo_dev_context *ml_dev);
/**
* wlan_peer_is_mlo() - check whether peer is MLO link peer
* @peer: link peer object
*
* API to check link peer is part of MLO peer or not
*
* Return: true if it MLO peer
* false, if it is not MLO peer
*/
static inline uint8_t wlan_peer_is_mlo(struct wlan_objmgr_peer *peer)
{
return wlan_peer_mlme_flag_ext_get(peer, WLAN_PEER_FEXT_MLO);
}
/**
* wlan_peer_set_mlo() - Set peer as MLO link peer
* @peer: link peer object
*
* API to set MLO peer flag in link peer is part of MLO peer
*
* Return: void
*/
static inline void wlan_peer_set_mlo(struct wlan_objmgr_peer *peer)
{
return wlan_peer_mlme_flag_ext_set(peer, WLAN_PEER_FEXT_MLO);
}
/**
* wlan_peer_clear_mlo() - clear peer as MLO link peer
* @peer: link peer object
*
* API to clear MLO peer flag in link peer
*
* Return: void
*/
static inline void wlan_peer_clear_mlo(struct wlan_objmgr_peer *peer)
{
return wlan_peer_mlme_flag_ext_clear(peer, WLAN_PEER_FEXT_MLO);
}
#endif

查看文件

@@ -66,20 +66,48 @@ struct mlo_setup_info {
/*
* struct mlo_mgr_context - MLO manager context
* @ml_dev_list_lock: ML device list lock
* @ml_dev_list_lock: ML DEV list lock
* @aid_lock: AID global lock
* @ml_peerid_lock: ML peer ID global lock
* @context: Array of MLO device context
* @mlo_peer_id_bmap: bitmap to allocate MLO Peer ID
* @max_mlo_peer_id: Max MLO Peer ID
* @info: MLO setup info
* @mlme_ops: MLO MLME callback function pointers
* @msgq_ctx: Context switch mgr
* @mlo_is_force_primary_umac: Force Primary UMAC enable
* @mlo_forced_primary_umac_id: Force Primary UMAC ID
*/
struct mlo_mgr_context {
#ifdef WLAN_MLO_USE_SPINLOCK
qdf_spinlock_t ml_dev_list_lock;
qdf_spinlock_t aid_lock;
qdf_spinlock_t ml_peerid_lock;
#else
qdf_mutex_t ml_dev_list_lock;
qdf_mutex_t aid_lock;
qdf_mutex_t ml_peerid_lock;
#endif
qdf_list_t ml_dev_list;
qdf_bitmap(mlo_peer_id_bmap, MAX_MLO_PEER_ID);
uint16_t max_mlo_peer_id;
struct mlo_setup_info info;
struct mlo_mlme_ext_ops *mlme_ops;
struct ctxt_switch_mgr *msgq_ctx;
bool mlo_is_force_primary_umac;
uint8_t mlo_forced_primary_umac_id;
};
/*
* struct wlan_ml_vdev_aid_mgr ML AID manager
* @aid_bitmap: AID bitmap array
* @max_aid: Max allowed AID
* @aid_mgr[]: Array of link vdev aid mgr
*/
struct wlan_ml_vdev_aid_mgr {
qdf_bitmap(aid_bitmap, WLAN_UMAC_MAX_AID);
uint16_t max_aid;
struct wlan_vdev_aid_mgr *aid_mgr[WLAN_UMAC_MLO_MAX_VDEVS];
};
/*
@@ -112,9 +140,11 @@ struct wlan_mlo_sta {
/*
* struct wlan_mlo_ap - MLO AP related info
* @num_ml_vdevs: number of vdevs to form MLD
* @ml_aid_mgr: ML AID mgr
*/
struct wlan_mlo_ap {
uint8_t num_ml_vdevs;
struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
};
/*
@@ -124,7 +154,11 @@ struct wlan_mlo_ap {
*/
struct wlan_mlo_peer_list {
qdf_list_t peer_hash[WLAN_PEER_HASHSIZE];
#ifdef WLAN_MLO_USE_SPINLOCK
qdf_spinlock_t peer_list_lock;
#else
qdf_mutex_t peer_list_lock;
#endif
};
/*
@@ -148,7 +182,7 @@ struct wlan_mlo_dev_context {
struct qdf_mac_addr mld_addr;
struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
uint16_t wlan_vdev_count;
struct wlan_mlo_peer_list mlo_peer;
struct wlan_mlo_peer_list mlo_peer_list;
uint16_t wlan_max_mlo_peer_count;
#ifdef WLAN_MLO_USE_SPINLOCK
qdf_spinlock_t mlo_dev_lock;
@@ -165,53 +199,64 @@ struct wlan_mlo_dev_context {
* struct wlan_mlo_link_peer_entry Link peer entry
* @link_peer: Object manager peer
* @link_addr: MAC address of link peer
* @link_index: Link index
* @link_ix: Link index
* @is_primary: sets true if the peer is primary UMAC’s peer
* @hw_link_id: HW Link id of peer
*/
struct wlan_mlo_link_peer_entry {
struct wlan_objmgr_peer *link_peer;
struct qdf_mac_addr link_addr;
uint8_t link_index;
uint8_t link_ix;
bool is_primary;
uint8_t hw_link_id;
};
/*
* struct mlo_peer_context - MLO peer context
*
* @peer_list: list of peers on the MLO link
* @link_peer_cnt: Number of link peers attached
* @mlo_peer_id: unique ID for the peer
* @peer_mld_addr: MAC address of MLD link
* @mlo_ie: MLO IE struct
* @mlo_peer_lock: lock to access peer structure
* @assoc_id: Assoc ID derived by MLO manager
* @primary_umac_psoc_id: Primary UMAC PSOC id
* @ref_cnt: Reference counter to avoid use after free
* enum mlo_peer_state MLO peer state
* @ML_PEER_CREATED: Initial state
* @ML_PEER_ASSOC_DONE: ASSOC sent on assoc link
* @ML_PEER_DISCONN_INITIATED: Disconnect initiated on one of the links
*/
struct wlan_mlo_peer_context {
struct wlan_mlo_link_peer_entry peer_list[MAX_MLO_PEER];
uint8_t link_peer_cnt;
uint32_t mlo_peer_id;
struct qdf_mac_addr peer_mld_addr;
uint8_t *mlo_ie;
qdf_spinlock_t mlo_peer_lock;
uint16_t assoc_id;
uint8_t primary_umac_psoc_id;
qdf_atomic_t ref_cnt;
enum mlo_peer_state {
ML_PEER_CREATED,
ML_PEER_ASSOC_DONE,
ML_PEER_DISCONN_INITIATED,
};
/*
* struct wlan_vdev_aid_mgr AID manager
* @aid_bitmap: AID bitmap array
* @max_aid: Max allowed AID
* @ref_cnt: to share AID across VDEVs for MBSSID
* struct wlan_mlo_peer_context - MLO peer context
*
* @peer_node: peer list node for ml_dev qdf list
* @peer_list: list of peers on the MLO link
* @link_peer_cnt: Number of link peers attached
* @max_links: Max links for this ML peer
* @mlo_peer_id: unique ID for the peer
* @peer_mld_addr: MAC address of MLD link
* @mlo_ie: MLO IE struct
* @mlo_peer_lock: lock to access peer strucutre
* @assoc_id: Assoc ID derived by MLO manager
* @ref_cnt: Reference counter to avoid use after free
* @ml_dev: MLO dev context
* @mlpeer_state: MLO peer state
*/
struct wlan_vdev_aid_mgr {
uint32_t *aid_bitmap;
uint16_t max_aid;
struct wlan_mlo_peer_context {
qdf_list_node_t peer_node;
struct wlan_mlo_link_peer_entry peer_list[MAX_MLO_LINK_PEERS];
uint8_t link_peer_cnt;
uint8_t max_links;
uint32_t mlo_peer_id;
struct qdf_mac_addr peer_mld_addr;
uint8_t *mlo_ie;
#ifdef WLAN_MLO_USE_SPINLOCK
qdf_spinlock_t mlo_peer_lock;
#else
qdf_mutex_t mlo_peer_lock;
#endif
uint16_t assoc_id;
uint8_t primary_umac_psoc_id;
qdf_atomic_t ref_cnt;
struct wlan_mlo_dev_context *ml_dev;
enum mlo_peer_state mlpeer_state;
};
/*
@@ -242,6 +287,7 @@ struct mlo_partner_info {
* @mlo_mlme_ext_peer_assoc: Callback to initiate peer assoc
* @mlo_mlme_ext_peer_assoc_fail: Callback to notify peer assoc failure
* @mlo_mlme_ext_peer_delete: Callback to initiate link peer delete
* @mlo_mlme_ext_assoc_resp: Callback to initiate assoc resp
*/
struct mlo_mlme_ext_ops {
QDF_STATUS (*mlo_mlme_ext_validate_conn_req)(
@@ -250,10 +296,11 @@ struct mlo_mlme_ext_ops {
struct vdev_mlme_obj *vdev_mlme, void *ext_data);
void (*mlo_mlme_ext_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);
void (*mlo_mlme_ext_peer_assoc)(struct wlan_objmgr_peer *peer);
void (*mlo_mlme_ext_peer_assoc_fail)(struct wlan_objmgr_peer *peer);
void (*mlo_mlme_ext_peer_delete)(struct wlan_objmgr_peer *peer);
void (*mlo_mlme_ext_assoc_resp)(struct wlan_objmgr_peer *peer);
};
#endif

查看文件

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

查看文件

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

查看文件

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

查看文件

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

查看文件

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