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:

committed by
Madan Koyyalamudi

父節點
7f36fdf121
當前提交
7469335fa4
@@ -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
|
||||
|
134
umac/mlo_mgr/inc/wlan_mlo_mgr_msgq.h
Normal file
134
umac/mlo_mgr/inc/wlan_mlo_mgr_msgq.h
Normal file
@@ -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
|
||||
|
544
umac/mlo_mgr/src/wlan_mlo_mgr_aid.c
Normal file
544
umac/mlo_mgr/src/wlan_mlo_mgr_aid.c
Normal file
@@ -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);
|
||||
}
|
||||
|
216
umac/mlo_mgr/src/wlan_mlo_mgr_msgq.c
Normal file
216
umac/mlo_mgr/src/wlan_mlo_mgr_msgq.c
Normal file
@@ -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
Normal file
606
umac/mlo_mgr/src/wlan_mlo_mgr_peer.c
Normal file
@@ -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
Normal file
373
umac/mlo_mgr/src/wlan_mlo_mgr_peer_list.c
Normal file
@@ -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
Normal file
62
umac/mlo_mgr/src/wlan_mlo_mgr_primary_umac.c
Normal file
@@ -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;
|
||||
}
|
Reference in New Issue
Block a user