qcacmn: Add support for ptqm migration
Add support for ptqm migration Change-Id: I3f3d6e410bee554477e8e058b1da51f2af5abb23 CRs-Fixed: 3529926
Dieser Commit ist enthalten in:

committet von
Rahul Choudhary

Ursprung
6f407b1a93
Commit
be34bbe6fc
@@ -650,6 +650,52 @@ QDF_STATUS target_if_mlo_send_vdev_pause(struct wlan_objmgr_psoc *psoc,
|
||||
return wmi_send_mlo_vdev_pause(wmi_handle, info);
|
||||
}
|
||||
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
static QDF_STATUS target_if_mlo_send_peer_ptqm_migrate_cmd(
|
||||
struct wlan_objmgr_vdev *vdev,
|
||||
struct peer_ptqm_migrate_params *param)
|
||||
{
|
||||
struct wlan_objmgr_pdev *pdev = NULL;
|
||||
struct wmi_unified *wmi_handle;
|
||||
QDF_STATUS status;
|
||||
|
||||
if (!vdev || !param) {
|
||||
target_if_err("Invalid input");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
pdev = wlan_vdev_get_pdev(vdev);
|
||||
if (!pdev) {
|
||||
target_if_err("null pdev");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
wmi_handle = lmac_get_pdev_wmi_handle(pdev);
|
||||
if (!wmi_handle) {
|
||||
target_if_err("Failed to get WMI handle!");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
status = wmi_unified_peer_ptqm_migrate_send(wmi_handle, param);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
target_if_err("Failed to send peer ptqm migration WMI");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void target_if_mlo_register_peer_ptqm_migrate_send(
|
||||
struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops)
|
||||
{
|
||||
mlo_tx_ops->peer_ptqm_migrate_send =
|
||||
target_if_mlo_send_peer_ptqm_migrate_cmd;
|
||||
}
|
||||
#else
|
||||
static void target_if_mlo_register_peer_ptqm_migrate_send(
|
||||
struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* target_if_mlo_register_tx_ops() - lmac handler to register mlo tx ops
|
||||
* callback functions
|
||||
@@ -685,6 +731,7 @@ target_if_mlo_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
|
||||
target_if_request_ml_link_state_info;
|
||||
mlo_tx_ops->send_vdev_pause = target_if_mlo_send_vdev_pause;
|
||||
|
||||
target_if_mlo_register_peer_ptqm_migrate_send(mlo_tx_ops);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@@ -1512,6 +1512,7 @@ struct wlan_lmac_if_son_rx_ops {
|
||||
* @send_tid_to_link_mapping: function to send T2LM command to FW
|
||||
* @send_link_removal_cmd: function to send MLO link removal command to FW
|
||||
* @send_vdev_pause: function to send MLO vdev pause to FW
|
||||
* @peer_ptqm_migrate_send: API to send peer ptqm migration request to FW
|
||||
*/
|
||||
struct wlan_lmac_if_mlo_tx_ops {
|
||||
QDF_STATUS (*register_events)(struct wlan_objmgr_psoc *psoc);
|
||||
@@ -1532,6 +1533,11 @@ struct wlan_lmac_if_mlo_tx_ops {
|
||||
const struct mlo_link_removal_cmd_params *param);
|
||||
QDF_STATUS (*send_vdev_pause)(struct wlan_objmgr_psoc *psoc,
|
||||
struct mlo_vdev_pause *info);
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
QDF_STATUS (*peer_ptqm_migrate_send)(
|
||||
struct wlan_objmgr_vdev *vdev,
|
||||
struct peer_ptqm_migrate_params *param);
|
||||
#endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -579,4 +579,21 @@ QDF_STATUS mlo_peer_create_get_frm_buf(
|
||||
*/
|
||||
uint16_t wlan_mlo_ap_get_active_links(struct wlan_objmgr_vdev *vdev);
|
||||
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
/**
|
||||
* mlo_ap_ml_ptqm_peerid_free() - API to clear ml peer id bmap set for
|
||||
* ptqm migration
|
||||
* @ml_dev: ML dev pointer
|
||||
* @mlo_peer_id: MLO peer id
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void mlo_ap_ml_ptqm_peerid_free(struct wlan_mlo_dev_context *ml_dev,
|
||||
uint16_t mlo_peer_id);
|
||||
#else
|
||||
static inline
|
||||
void mlo_ap_ml_ptqm_peerid_free(struct wlan_mlo_dev_context *ml_dev,
|
||||
uint16_t mlo_peer_id)
|
||||
{ }
|
||||
#endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */
|
||||
#endif
|
||||
|
@@ -625,3 +625,28 @@ util_parse_bw_ind(struct wlan_ie_bw_ind *bw_ind, uint8_t *ccfs0,
|
||||
uint8_t *ccfs1, enum phy_ch_width *ch_width,
|
||||
uint16_t *puncture_bitmap);
|
||||
#endif
|
||||
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
/**
|
||||
* mlo_mlme_ptqm_migrate_timer_cb() - Timer callback for ptqm migration
|
||||
* @arg: timer function argument
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void mlo_mlme_ptqm_migrate_timer_cb(void *arg);
|
||||
|
||||
/*
|
||||
* wlan_mlo_set_ptqm_migration() - API to trigger ptqm migration.
|
||||
* @vdev: vdev object
|
||||
* @ml_peer: ml peer object
|
||||
* @link_migration: flag to indicate if all peers of vdev need migration
|
||||
* or individual peer migration
|
||||
* @link_id: link id for new ptqm
|
||||
*
|
||||
* Return: Success if migration is triggered, else failure
|
||||
*/
|
||||
QDF_STATUS wlan_mlo_set_ptqm_migration(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
bool link_migration,
|
||||
uint32_t link_id);
|
||||
#endif
|
||||
|
@@ -468,6 +468,11 @@ struct wlan_mlo_peer_list {
|
||||
* @ap_ctx: AP related information
|
||||
* @t2lm_ctx: T2LM related information
|
||||
* @epcs_ctx: EPCS related information
|
||||
* @ptqm_migrate_timer: timer for ptqm migration
|
||||
* @mlo_peer_id_bmap: mlo_peer_id bitmap for ptqm migration
|
||||
*
|
||||
* NB: Not using kernel-doc format since the kernel-doc script doesn't
|
||||
* handle the qdf_bitmap() macro
|
||||
*/
|
||||
struct wlan_mlo_dev_context {
|
||||
qdf_list_node_t node;
|
||||
@@ -490,6 +495,10 @@ struct wlan_mlo_dev_context {
|
||||
struct wlan_mlo_ap *ap_ctx;
|
||||
struct wlan_t2lm_context t2lm_ctx;
|
||||
struct wlan_epcs_context epcs_ctx;
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
qdf_timer_t ptqm_migrate_timer;
|
||||
qdf_bitmap(mlo_peer_id_bmap, MAX_MLO_PEER_ID);
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1152,4 +1161,90 @@ struct mlo_link_disable_request_evt_params {
|
||||
struct qdf_mac_addr mld_addr;
|
||||
uint32_t link_id_bitmap;
|
||||
};
|
||||
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
/**
|
||||
* struct peer_ptqm_migrate_entry - peer ptqm migrate entry
|
||||
* @ml_peer_id: ML peer id
|
||||
* @hw_link_id: HW link id
|
||||
*/
|
||||
struct peer_ptqm_migrate_entry {
|
||||
uint16_t ml_peer_id;
|
||||
uint16_t hw_link_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct peer_ptqm_migrate_params - peer ptqm migrate request parameter
|
||||
* @vdev_id: vdev id
|
||||
* @num_peers: peer count
|
||||
* @peer_list: list of peers to be migrated
|
||||
*/
|
||||
struct peer_ptqm_migrate_params {
|
||||
uint8_t vdev_id;
|
||||
uint16_t num_peers;
|
||||
struct peer_ptqm_migrate_entry *peer_list;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct peer_ptqm_migrate_list_entry - peer ptqm migrate list
|
||||
* @peer: objmgr peer object
|
||||
* @mlo_peer_id: mlo peer id
|
||||
* @new_hw_link_id: hw link id of new primary
|
||||
* @peer_list_elem: peer ptqm migrate entry list
|
||||
*/
|
||||
struct peer_ptqm_migrate_list_entry {
|
||||
struct wlan_objmgr_peer *peer;
|
||||
uint32_t mlo_peer_id;
|
||||
uint8_t new_hw_link_id;
|
||||
|
||||
TAILQ_ENTRY(peer_ptqm_migrate_list_entry) peer_list_elem;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct peer_migrate_ptqm_multi_entries - multi ptqm migrate peer entry params
|
||||
* @num_entries: Number of entries in the peer_list list
|
||||
* @peer_list: List to hold the peer entries to be migrated
|
||||
*
|
||||
* NB: Not using kernel-doc format since the kernel-doc script doesn't
|
||||
* handle the TAILQ_HEAD() macro
|
||||
*/
|
||||
struct peer_migrate_ptqm_multi_entries {
|
||||
uint16_t num_entries;
|
||||
|
||||
TAILQ_HEAD(, peer_ptqm_migrate_list_entry) peer_list;
|
||||
};
|
||||
|
||||
enum primary_link_peer_migration_evenr_status {
|
||||
PRIMARY_LINK_PEER_MIGRATION_SUCCESS,
|
||||
PRIMARY_LINK_PEER_MIGRATION_IN_PROGRESS,
|
||||
PRIMARY_LINK_PEER_MIGRATION_DELETE_IN_PROGRESS,
|
||||
PRIMARY_LINK_PEER_MIGRATION_DELETED,
|
||||
PRIMARY_LINK_PEER_MIGRATION_TX_PIPES_FAILED,
|
||||
PRIMARY_LINK_PEER_MIGRATION_RX_PIPES_FAILED,
|
||||
|
||||
/* Add any new status above this line */
|
||||
PRIMARY_LINK_PEER_MIGRATION_FAIL = 255,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct peer_ptqm_migrate_event_params - peer ptqm migrate event parameter
|
||||
* @vdev_id: vdev id
|
||||
* @num_peers: peer count
|
||||
*/
|
||||
struct peer_ptqm_migrate_event_params {
|
||||
uint8_t vdev_id;
|
||||
uint16_t num_peers;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct peer_entry_ptqm_migrate_event_params - peer entry ptqm migrate
|
||||
* event parameter
|
||||
* @ml_peer_id: ML peer id
|
||||
* @status: migration status
|
||||
*/
|
||||
struct peer_entry_ptqm_migrate_event_params {
|
||||
uint16_t ml_peer_id;
|
||||
enum primary_link_peer_migration_evenr_status status;
|
||||
};
|
||||
#endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */
|
||||
#endif
|
||||
|
@@ -478,6 +478,16 @@ uint16_t mlo_ap_ml_peerid_alloc(void)
|
||||
return mlo_peer_id;
|
||||
}
|
||||
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
void mlo_ap_ml_ptqm_peerid_free(struct wlan_mlo_dev_context *ml_dev,
|
||||
uint16_t mlo_peer_id)
|
||||
{
|
||||
/* Free the bitmap for ptqm migration */
|
||||
if (qdf_test_bit(mlo_peer_id, ml_dev->mlo_peer_id_bmap))
|
||||
qdf_clear_bit(mlo_peer_id, ml_dev->mlo_peer_id_bmap);
|
||||
}
|
||||
#endif
|
||||
|
||||
void mlo_ap_ml_peerid_free(uint16_t mlo_peer_id)
|
||||
{
|
||||
struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
|
||||
|
@@ -686,6 +686,24 @@ static inline void mlo_epcs_ctx_init(struct wlan_mlo_dev_context *ml_dev)
|
||||
qdf_mem_zero(epcs_ctx, sizeof(struct wlan_epcs_context));
|
||||
}
|
||||
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
/**
|
||||
* mlo_ptqm_migration_init() - API to initialize ptqm migration timer
|
||||
* @ml_dev: Pointer to ML Dev context
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static inline void mlo_ptqm_migration_init(struct wlan_mlo_dev_context *ml_dev)
|
||||
{
|
||||
qdf_timer_init(NULL, &ml_dev->ptqm_migrate_timer,
|
||||
mlo_mlme_ptqm_migrate_timer_cb, (void *)(ml_dev),
|
||||
QDF_TIMER_TYPE_WAKE_APPS);
|
||||
}
|
||||
#else
|
||||
static inline void mlo_ptqm_migration_init(struct wlan_mlo_dev_context *ml_dev)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct wlan_mlo_dev_context *ml_dev;
|
||||
@@ -763,10 +781,29 @@ static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
|
||||
|
||||
mlo_t2lm_ctx_init(ml_dev, vdev);
|
||||
mlo_epcs_ctx_init(ml_dev);
|
||||
mlo_ptqm_migration_init(ml_dev);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
/**
|
||||
* mlo_ptqm_migration_deinit() - API to deinitialize ptqm migration timer
|
||||
* @ml_dev: Pointer to ML Dev context
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static inline void mlo_ptqm_migration_deinit(
|
||||
struct wlan_mlo_dev_context *ml_dev)
|
||||
{
|
||||
qdf_timer_free(&ml_dev->ptqm_migrate_timer);
|
||||
}
|
||||
#else
|
||||
static inline void mlo_ptqm_migration_deinit(
|
||||
struct wlan_mlo_dev_context *ml_dev)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* mlo_t2lm_ctx_deinit() - API to deinitialize the t2lm context with the default
|
||||
* values.
|
||||
@@ -857,6 +894,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_ptqm_migration_deinit(ml_dev);
|
||||
mlo_t2lm_ctx_deinit(vdev);
|
||||
tsf_recalculation_lock_destroy(ml_dev);
|
||||
mlo_dev_lock_destroy(ml_dev);
|
||||
|
@@ -714,6 +714,7 @@ static void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer)
|
||||
mlo_debug("ML Peer " QDF_MAC_ADDR_FMT " is freed",
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
mlo_peer_lock_destroy(ml_peer);
|
||||
mlo_ap_ml_ptqm_peerid_free(ml_dev, ml_peer->mlo_peer_id);
|
||||
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);
|
||||
|
@@ -350,6 +350,8 @@ struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_ml_peerid(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qdf_export_symbol(wlan_mlo_get_mlpeer_by_ml_peerid);
|
||||
|
||||
struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer(
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
struct qdf_mac_addr *ml_addr)
|
||||
|
@@ -55,6 +55,8 @@ struct mlo_all_link_rssi {
|
||||
#define ML_INVALID_PRIMARY_TQM 0xff
|
||||
/* Congestion value */
|
||||
#define ML_PRIMARY_TQM_CONGESTION 30
|
||||
/* PTQM migration timeout value in ms */
|
||||
#define ML_PRIMARY_TQM_MIGRATRION_TIMEOUT 4000
|
||||
|
||||
static void wlan_mlo_peer_get_rssi(struct wlan_objmgr_psoc *psoc,
|
||||
void *obj, void *args)
|
||||
@@ -728,4 +730,505 @@ void wlan_objmgr_mlo_update_primary_info(struct wlan_objmgr_peer *peer)
|
||||
}
|
||||
|
||||
qdf_export_symbol(wlan_objmgr_mlo_update_primary_info);
|
||||
#endif
|
||||
|
||||
void mlo_mlme_ptqm_migrate_timer_cb(void *arg)
|
||||
{
|
||||
struct wlan_mlo_dev_context *ml_dev = (struct wlan_mlo_dev_context *)arg;
|
||||
struct wlan_mlo_peer_context *ml_peer = NULL;
|
||||
uint16_t i = 0;
|
||||
|
||||
if (!ml_dev)
|
||||
return;
|
||||
|
||||
/* Check for pending bitmaps and issue disconnect */
|
||||
for (i = 0; i < MAX_MLO_PEER_ID; i++) {
|
||||
if (qdf_test_bit(i, ml_dev->mlo_peer_id_bmap)) {
|
||||
ml_peer = wlan_mlo_get_mlpeer_by_ml_peerid(ml_dev, i);
|
||||
if (ml_peer && ml_peer->primary_umac_migration_in_progress) {
|
||||
ml_peer->primary_umac_migration_in_progress = false;
|
||||
mlo_err("Issue disconnect for ml peer with ml peer id:%d", i);
|
||||
wlan_mlo_peer_deauth_init(ml_peer,
|
||||
NULL, 0);
|
||||
}
|
||||
qdf_clear_bit(i, ml_dev->mlo_peer_id_bmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_mlo_send_ptqm_migrate_cmd() - API to send WMI to trigger ptqm migration
|
||||
* @vdev: objmgr vdev object
|
||||
* @list: peer list to be migrated
|
||||
*
|
||||
* API to send WMI to trigger ptqm migration
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
static QDF_STATUS
|
||||
wlan_mlo_send_ptqm_migrate_cmd(struct wlan_objmgr_vdev *vdev,
|
||||
struct peer_migrate_ptqm_multi_entries *list)
|
||||
{
|
||||
struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
QDF_STATUS status;
|
||||
struct peer_ptqm_migrate_params param = {0};
|
||||
struct peer_ptqm_migrate_entry *peer_list = NULL;
|
||||
struct peer_ptqm_migrate_list_entry *peer_entry, *tmp_entry;
|
||||
struct wlan_mlo_dev_context *ml_dev = NULL;
|
||||
uint16_t i = 0;
|
||||
|
||||
ml_dev = vdev->mlo_dev_ctx;
|
||||
if (!ml_dev)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
psoc = wlan_vdev_get_psoc(vdev);
|
||||
if (!psoc) {
|
||||
mlo_err("null psoc");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops;
|
||||
if (!mlo_tx_ops || !mlo_tx_ops->peer_ptqm_migrate_send) {
|
||||
mlo_err("mlo_tx_ops is null!");
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
param.vdev_id = wlan_vdev_get_id(vdev);
|
||||
param.num_peers = list->num_entries;
|
||||
|
||||
param.peer_list = qdf_mem_malloc(sizeof(struct peer_ptqm_migrate_entry) *
|
||||
list->num_entries);
|
||||
if (!param.peer_list) {
|
||||
mlo_err("Failed to allocate memory for ptqm migration command");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
peer_list = param.peer_list;
|
||||
|
||||
TAILQ_FOREACH_SAFE(peer_entry, &list->peer_list,
|
||||
peer_list_elem, tmp_entry) {
|
||||
peer_list[i].ml_peer_id = peer_entry->mlo_peer_id;
|
||||
peer_list[i].hw_link_id = peer_entry->new_hw_link_id;
|
||||
|
||||
qdf_set_bit(peer_entry->mlo_peer_id,
|
||||
ml_dev->mlo_peer_id_bmap);
|
||||
|
||||
mlo_debug("idx:%d, ml_peer_id:%d, hw_link_id:%d",
|
||||
i, peer_list[i].ml_peer_id,
|
||||
peer_list[i].hw_link_id);
|
||||
i++;
|
||||
}
|
||||
|
||||
status = mlo_tx_ops->peer_ptqm_migrate_send(vdev, ¶m);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
mlo_err("Failed to send WMI for ptqm migration");
|
||||
qdf_mem_free(param.peer_list);
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
/* Set timeout equal to peer delete timeout as requested by FW.
|
||||
* Timeout value to be optimized later. Timeout value will be
|
||||
* updated later based on stress testings.
|
||||
*/
|
||||
qdf_timer_mod(&ml_dev->ptqm_migrate_timer,
|
||||
ML_PRIMARY_TQM_MIGRATRION_TIMEOUT);
|
||||
|
||||
qdf_mem_free(param.peer_list);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_mlo_get_new_ptqm_id() - API to get new ptqm ID
|
||||
* @curr_vdev: objmgr vdev object for current primary link
|
||||
* @ml_peer: ml peer object
|
||||
* @new_primary_link_id: new primary link id
|
||||
* @new_hw_link_id: hw link id for new primary TQM
|
||||
*
|
||||
* API to get new ptqm ID
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
static QDF_STATUS
|
||||
wlan_mlo_get_new_ptqm_id(struct wlan_objmgr_vdev *curr_vdev,
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
uint8_t new_primary_link_id,
|
||||
uint16_t *new_hw_link_id)
|
||||
{
|
||||
uint8_t current_primary_link_id = WLAN_LINK_ID_INVALID;
|
||||
struct wlan_objmgr_vdev *tmp_vdev = NULL;
|
||||
struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
|
||||
struct wlan_mlo_link_peer_entry *peer_entry;
|
||||
QDF_STATUS status;
|
||||
uint8_t i = 0, idx = 0;
|
||||
|
||||
if (wlan_vdev_mlme_get_opmode(curr_vdev) == QDF_SAP_MODE &&
|
||||
QDF_IS_STATUS_ERROR(wlan_mlo_peer_is_assoc_done(ml_peer))) {
|
||||
mlo_err("ML peer " QDF_MAC_ADDR_FMT " is not associated",
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
*new_hw_link_id = INVALID_HW_LINK_ID;
|
||||
current_primary_link_id =
|
||||
wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(ml_peer);
|
||||
if (current_primary_link_id == WLAN_LINK_ID_INVALID) {
|
||||
mlo_err("ML peer " QDF_MAC_ADDR_FMT "current primary link id is invalid",
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
if (current_primary_link_id == new_primary_link_id) {
|
||||
mlo_err("current and requested link_id are same");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
|
||||
peer_entry = &ml_peer->peer_list[i];
|
||||
if (!peer_entry || !peer_entry->link_peer)
|
||||
continue;
|
||||
|
||||
if (wlan_peer_get_peer_type(peer_entry->link_peer) ==
|
||||
WLAN_PEER_MLO_BRIDGE)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
|
||||
peer_entry = &ml_peer->peer_list[i];
|
||||
if (!peer_entry || !peer_entry->link_peer)
|
||||
continue;
|
||||
|
||||
tmp_vdev = wlan_peer_get_vdev(peer_entry->link_peer);
|
||||
if (!tmp_vdev || tmp_vdev == curr_vdev)
|
||||
continue;
|
||||
|
||||
status = wlan_objmgr_vdev_try_get_ref(tmp_vdev,
|
||||
WLAN_MLME_SB_ID);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
mlo_err("failed to get vdev ref");
|
||||
continue;
|
||||
}
|
||||
wlan_vdev_list[idx++] = tmp_vdev;
|
||||
}
|
||||
|
||||
if (new_primary_link_id == WLAN_LINK_ID_INVALID) {
|
||||
mlo_debug("Invalid link id provided, select new link id");
|
||||
ml_peer->migrate_primary_umac_psoc_id =
|
||||
wlan_mld_get_best_primary_umac_w_rssi(ml_peer, wlan_vdev_list);
|
||||
if (ml_peer->migrate_primary_umac_psoc_id ==
|
||||
ML_PRIMARY_UMAC_ID_INVAL) {
|
||||
mlo_err("Unable to fetch new primary link id for ml peer " QDF_MAC_ADDR_FMT,
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
goto exit;
|
||||
}
|
||||
for (i = 0; i < idx; i++) {
|
||||
if (ml_peer->migrate_primary_umac_psoc_id ==
|
||||
wlan_vdev_get_psoc_id(wlan_vdev_list[i])) {
|
||||
*new_hw_link_id = wlan_mlo_get_pdev_hw_link_id(
|
||||
wlan_vdev_get_pdev(wlan_vdev_list[i]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* check if provided link id is part of current ml peer links */
|
||||
for (i = 0; i < idx; i++) {
|
||||
if (new_primary_link_id == wlan_vdev_get_link_id(wlan_vdev_list[i])) {
|
||||
/* Check if the soc is enabled to be pumac or not */
|
||||
if (wlan_vdev_skip_pumac(wlan_vdev_list[i])) {
|
||||
mlo_err("Given link %d cannot be selected as primary",
|
||||
new_primary_link_id);
|
||||
goto exit;
|
||||
}
|
||||
*new_hw_link_id = wlan_mlo_get_pdev_hw_link_id(
|
||||
wlan_vdev_get_pdev(wlan_vdev_list[i]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*new_hw_link_id == INVALID_HW_LINK_ID) {
|
||||
mlo_err("New primary link id not found for ml peer " QDF_MAC_ADDR_FMT,
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (i < idx) {
|
||||
if (wlan_vdev_mlme_op_flags_get(wlan_vdev_list[i],
|
||||
WLAN_VDEV_OP_MLO_LINK_REMOVAL_IN_PROGRESS)) {
|
||||
mlo_err("New selected primary link is going for removal, skip migration");
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < idx; i++)
|
||||
wlan_objmgr_vdev_release_ref(wlan_vdev_list[i],
|
||||
WLAN_MLME_SB_ID);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
ml_peer->migrate_primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
|
||||
|
||||
for (i = 0; i < idx; i++)
|
||||
wlan_objmgr_vdev_release_ref(wlan_vdev_list[i],
|
||||
WLAN_MLME_SB_ID);
|
||||
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_mlo_free_ptqm_migrate_list() - API to free peer ptqm migration list
|
||||
* @list: peer ptqm migration list
|
||||
*
|
||||
* API to free peer ptqm migration list
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void wlan_mlo_free_ptqm_migrate_list(
|
||||
struct peer_migrate_ptqm_multi_entries *list)
|
||||
{
|
||||
struct peer_ptqm_migrate_list_entry *peer_entry, *tmp_entry;
|
||||
|
||||
TAILQ_FOREACH_SAFE(peer_entry, &list->peer_list,
|
||||
peer_list_elem, tmp_entry) {
|
||||
TAILQ_REMOVE(&list->peer_list, peer_entry, peer_list_elem);
|
||||
list->num_entries--;
|
||||
if (peer_entry->peer)
|
||||
wlan_objmgr_peer_release_ref(peer_entry->peer,
|
||||
WLAN_MLME_SB_ID);
|
||||
qdf_mem_free(peer_entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_mlo_reset_ptqm_migrate_list() - API to reset peer ptqm migration list
|
||||
* @ml_dev: MLO dev context
|
||||
* @list: peer ptqm migration list
|
||||
*
|
||||
* API to reset peer ptqm migration list
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void wlan_mlo_reset_ptqm_migrate_list(
|
||||
struct wlan_mlo_dev_context *ml_dev,
|
||||
struct peer_migrate_ptqm_multi_entries *list)
|
||||
{
|
||||
struct peer_ptqm_migrate_list_entry *peer_entry, *tmp_entry;
|
||||
|
||||
if (!ml_dev)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH_SAFE(peer_entry, &list->peer_list,
|
||||
peer_list_elem, tmp_entry) {
|
||||
if (peer_entry->peer) {
|
||||
qdf_clear_bit(peer_entry->mlo_peer_id, ml_dev->mlo_peer_id_bmap);
|
||||
peer_entry->peer->mlo_peer_ctx->primary_umac_migration_in_progress = false;
|
||||
peer_entry->peer->mlo_peer_ctx->migrate_primary_umac_psoc_id =
|
||||
ML_PRIMARY_UMAC_ID_INVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_mlo_build_ptqm_migrate_list() - API to build peer ptqm migration list
|
||||
* @vdev: objmgr vdev list
|
||||
* @object: peer object
|
||||
* @arg: list pointer
|
||||
*
|
||||
* API to build peer ptqm migration list
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void wlan_mlo_build_ptqm_migrate_list(struct wlan_objmgr_vdev *vdev,
|
||||
void *object, void *arg)
|
||||
{
|
||||
struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)object;
|
||||
struct peer_migrate_ptqm_multi_entries *list =
|
||||
(struct peer_migrate_ptqm_multi_entries *)arg;
|
||||
struct peer_ptqm_migrate_list_entry *peer_entry;
|
||||
struct wlan_mlo_peer_context *ml_peer;
|
||||
uint16_t new_hw_link_id = INVALID_HW_LINK_ID;
|
||||
uint8_t current_primary_link_id = WLAN_LINK_ID_INVALID;
|
||||
QDF_STATUS status;
|
||||
|
||||
if (!wlan_peer_is_mlo(peer) || !peer->mlo_peer_ctx)
|
||||
return;
|
||||
|
||||
ml_peer = peer->mlo_peer_ctx;
|
||||
|
||||
if (ml_peer->link_peer_cnt == 1)
|
||||
return;
|
||||
|
||||
if (ml_peer->primary_umac_migration_in_progress) {
|
||||
mlo_err("peer " QDF_MAC_ADDR_FMT " primary umac migration already in progress",
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
return;
|
||||
}
|
||||
|
||||
current_primary_link_id = wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(ml_peer);
|
||||
if (current_primary_link_id == WLAN_LINK_ID_INVALID ||
|
||||
current_primary_link_id != wlan_vdev_get_link_id(vdev)) {
|
||||
mlo_debug("peer " QDF_MAC_ADDR_FMT " not having primary on current vdev",
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
return;
|
||||
}
|
||||
|
||||
status = wlan_mlo_get_new_ptqm_id(vdev, ml_peer,
|
||||
WLAN_LINK_ID_INVALID,
|
||||
&new_hw_link_id);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
mlo_err("peer " QDF_MAC_ADDR_FMT " unable to get new ptqm id",
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
return;
|
||||
}
|
||||
ml_peer->primary_umac_migration_in_progress = true;
|
||||
|
||||
peer_entry = (struct peer_ptqm_migrate_list_entry *)
|
||||
qdf_mem_malloc(sizeof(struct peer_ptqm_migrate_list_entry));
|
||||
if (!peer_entry) {
|
||||
mlo_err("peer " QDF_MAC_ADDR_FMT " unable to allocate peer entry",
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
return;
|
||||
}
|
||||
|
||||
status = wlan_objmgr_peer_try_get_ref(peer, WLAN_MLME_SB_ID);
|
||||
peer_entry->peer = peer;
|
||||
peer_entry->new_hw_link_id = new_hw_link_id;
|
||||
peer_entry->mlo_peer_id = ml_peer->mlo_peer_id;
|
||||
TAILQ_INSERT_TAIL(&list->peer_list, peer_entry, peer_list_elem);
|
||||
list->num_entries++;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_mlo_trigger_link_ptqm_migration() - API to trigger ptqm migration
|
||||
* for a link
|
||||
* @vdev: objmgr vdev object
|
||||
*
|
||||
* API to trigger ptqm migration of all peers having primary on given link
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
static QDF_STATUS wlan_mlo_trigger_link_ptqm_migration(
|
||||
struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct peer_migrate_ptqm_multi_entries migrate_list = {0};
|
||||
QDF_STATUS status;
|
||||
|
||||
TAILQ_INIT(&migrate_list.peer_list);
|
||||
wlan_objmgr_iterate_peerobj_list(vdev,
|
||||
wlan_mlo_build_ptqm_migrate_list,
|
||||
&migrate_list, WLAN_MLME_NB_ID);
|
||||
|
||||
/* trigger WMI */
|
||||
if (migrate_list.num_entries == 0) {
|
||||
mlo_err("No peer found");
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
status = wlan_mlo_send_ptqm_migrate_cmd(vdev, &migrate_list);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
wlan_mlo_reset_ptqm_migrate_list(vdev->mlo_dev_ctx,
|
||||
&migrate_list);
|
||||
wlan_mlo_free_ptqm_migrate_list(&migrate_list);
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS wlan_mlo_set_ptqm_migration(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_mlo_peer_context *ml_peer,
|
||||
bool link_migration,
|
||||
uint32_t link_id)
|
||||
{
|
||||
uint16_t new_hw_link_id = INVALID_HW_LINK_ID;
|
||||
struct peer_migrate_ptqm_multi_entries migrate_list = {0};
|
||||
struct peer_ptqm_migrate_list_entry *peer_entry;
|
||||
struct wlan_objmgr_vdev *curr_vdev = NULL;
|
||||
uint8_t current_primary_link_id = WLAN_LINK_ID_INVALID;
|
||||
QDF_STATUS status;
|
||||
|
||||
if (!vdev) {
|
||||
mlo_err("Vdev is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
if (link_migration == false && !ml_peer) {
|
||||
mlo_err("ML peer is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
if (link_migration) {
|
||||
if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_LINK_REMOVAL_IN_PROGRESS)) {
|
||||
mlo_err("Link removal in progress, skip umac migration for vdev:%d",
|
||||
wlan_vdev_get_id(vdev));
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
mlo_err("Trigger migration for full link");
|
||||
// trigger full link migration
|
||||
status = wlan_mlo_trigger_link_ptqm_migration(vdev);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
mlo_err("Failed to trigger link migration");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (ml_peer->link_peer_cnt == 1) {
|
||||
mlo_err("peer " QDF_MAC_ADDR_FMT " is SLO",
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
if (ml_peer->primary_umac_migration_in_progress) {
|
||||
mlo_err("peer " QDF_MAC_ADDR_FMT " primary umac migration already in progress",
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
current_primary_link_id = wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(ml_peer);
|
||||
if (current_primary_link_id == WLAN_LINK_ID_INVALID) {
|
||||
mlo_err("Current primary link id is invalid");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
curr_vdev = mlo_get_vdev_by_link_id(vdev, current_primary_link_id);
|
||||
if (!curr_vdev) {
|
||||
mlo_err("Unable to get current primary vdev");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
status = wlan_mlo_get_new_ptqm_id(curr_vdev, ml_peer,
|
||||
link_id, &new_hw_link_id);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
mlo_err("peer " QDF_MAC_ADDR_FMT " unable to get new ptqm id",
|
||||
QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
|
||||
goto exit;
|
||||
}
|
||||
ml_peer->primary_umac_migration_in_progress = true;
|
||||
|
||||
peer_entry = (struct peer_ptqm_migrate_list_entry *)
|
||||
qdf_mem_malloc(sizeof(struct peer_ptqm_migrate_list_entry));
|
||||
if (!peer_entry) {
|
||||
mlo_err("Failed to allocate peer entry");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
peer_entry->new_hw_link_id = new_hw_link_id;
|
||||
peer_entry->mlo_peer_id = ml_peer->mlo_peer_id;
|
||||
TAILQ_INIT(&migrate_list.peer_list);
|
||||
TAILQ_INSERT_TAIL(&migrate_list.peer_list, peer_entry, peer_list_elem);
|
||||
migrate_list.num_entries = 1;
|
||||
|
||||
//trigger WMI
|
||||
status = wlan_mlo_send_ptqm_migrate_cmd(curr_vdev, &migrate_list);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
wlan_mlo_reset_ptqm_migrate_list(curr_vdev->mlo_dev_ctx,
|
||||
&migrate_list);
|
||||
wlan_mlo_free_ptqm_migrate_list(&migrate_list);
|
||||
|
||||
mlo_release_vdev_ref(curr_vdev);
|
||||
|
||||
return status;
|
||||
|
||||
exit:
|
||||
if (curr_vdev)
|
||||
mlo_release_vdev_ref(curr_vdev);
|
||||
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
#endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */
|
||||
|
@@ -219,4 +219,46 @@ QDF_STATUS wmi_extract_mlo_link_disable_request_evt(
|
||||
struct mlo_link_disable_request_evt_params *params);
|
||||
#endif /* WLAN_FEATURE_11BE */
|
||||
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
/**
|
||||
* wmi_unified_peer_ptqm_migrate_send() - send PEER ptqm migrate command to fw
|
||||
* @wmi_hdl: wmi handle
|
||||
* @param: pointer to hold peer ptqm migrate parameters
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
|
||||
*/
|
||||
QDF_STATUS wmi_unified_peer_ptqm_migrate_send(
|
||||
wmi_unified_t wmi_hdl,
|
||||
struct peer_ptqm_migrate_params *param);
|
||||
|
||||
/**
|
||||
* wmi_extract_peer_ptqm_migrate_event() - extract peer ptqm migrate event params
|
||||
* @wmi: wmi handle
|
||||
* @evt_buf: pointer to event buffer
|
||||
* @resp: Pointer to host structure to get the event params
|
||||
*
|
||||
* This function gets called to extract peer ptqm migrate event params
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
|
||||
*/
|
||||
QDF_STATUS
|
||||
wmi_extract_peer_ptqm_migrate_event(
|
||||
wmi_unified_t wmi, void *evt_buf,
|
||||
struct peer_ptqm_migrate_event_params *resp);
|
||||
|
||||
/**
|
||||
* wmi_extract_peer_ptqm_entry_param() - extract peer entry ptqm migrate param
|
||||
* @wmi_handle: wmi handle
|
||||
* @evt_buf: pointer to event buffer
|
||||
* @index: Index into pdev stats
|
||||
* @entry: Pointer to peer entry params
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
|
||||
*/
|
||||
QDF_STATUS
|
||||
wmi_extract_peer_ptqm_entry_param(
|
||||
wmi_unified_t wmi_handle, void *evt_buf,
|
||||
uint32_t index,
|
||||
struct peer_entry_ptqm_migrate_event_params *entry);
|
||||
#endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */
|
||||
#endif /*_WMI_UNIFIED_11BE_API_H_*/
|
||||
|
@@ -5309,6 +5309,9 @@ typedef enum {
|
||||
wmi_csa_ie_received_event_id,
|
||||
#ifdef WLAN_FEATURE_11BE_MLO
|
||||
wmi_mlo_link_state_info_eventid,
|
||||
#endif
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
wmi_peer_ptqm_migration_response_eventid,
|
||||
#endif
|
||||
wmi_events_max,
|
||||
} wmi_conv_event_id;
|
||||
|
@@ -3311,6 +3311,22 @@ QDF_STATUS
|
||||
(*extract_csa_ie_received_ev_params)(wmi_unified_t wmi_handle,
|
||||
void *evt_buf, uint8_t *vdev_id,
|
||||
struct csa_offload_params *csa_event);
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
QDF_STATUS (*send_peer_ptqm_migrate_cmd)(
|
||||
wmi_unified_t wmi,
|
||||
struct peer_ptqm_migrate_params *param);
|
||||
|
||||
QDF_STATUS (*extract_peer_ptqm_migrate_event)(
|
||||
struct wmi_unified *wmi_handle,
|
||||
uint8_t *buf,
|
||||
struct peer_ptqm_migrate_event_params *params);
|
||||
|
||||
QDF_STATUS (*extract_peer_entry_ptqm_migrate_event)(
|
||||
struct wmi_unified *wmi_handle,
|
||||
uint8_t *buf,
|
||||
uint32_t index,
|
||||
struct peer_entry_ptqm_migrate_event_params *entry);
|
||||
#endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */
|
||||
};
|
||||
|
||||
/* Forward declaration for psoc*/
|
||||
|
@@ -211,3 +211,42 @@ QDF_STATUS wmi_extract_mgmt_rx_mlo_link_removal_info(
|
||||
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
QDF_STATUS wmi_unified_peer_ptqm_migrate_send(
|
||||
wmi_unified_t wmi_hdl,
|
||||
struct peer_ptqm_migrate_params *param)
|
||||
{
|
||||
if (wmi_hdl->ops->send_peer_ptqm_migrate_cmd)
|
||||
return wmi_hdl->ops->send_peer_ptqm_migrate_cmd(wmi_hdl, param);
|
||||
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
wmi_extract_peer_ptqm_migrate_event(
|
||||
wmi_unified_t wmi, void *evt_buf,
|
||||
struct peer_ptqm_migrate_event_params *resp)
|
||||
{
|
||||
if (wmi->ops->extract_peer_ptqm_migrate_event) {
|
||||
return wmi->ops->extract_peer_ptqm_migrate_event(wmi,
|
||||
evt_buf,
|
||||
resp);
|
||||
}
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
wmi_extract_peer_ptqm_entry_param(
|
||||
wmi_unified_t wmi_handle, void *evt_buf,
|
||||
uint32_t index,
|
||||
struct peer_entry_ptqm_migrate_event_params *entry)
|
||||
{
|
||||
if (wmi_handle->ops->extract_peer_entry_ptqm_migrate_event)
|
||||
return wmi_handle->ops->extract_peer_entry_ptqm_migrate_event(
|
||||
wmi_handle, evt_buf,
|
||||
index, entry);
|
||||
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
#endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */
|
||||
|
@@ -1876,6 +1876,171 @@ QDF_STATUS extract_mgmt_rx_ml_cu_params_tlv(wmi_unified_t wmi_handle,
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
/**
|
||||
* send_peer_ptqm_migrate_cmd_tlv() - send PEER ptqm migrate command to fw
|
||||
* @wmi_handle: wmi handle
|
||||
* @param: pointer to hold peer ptqm migrate parameter
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS for success else error code
|
||||
*/
|
||||
static QDF_STATUS send_peer_ptqm_migrate_cmd_tlv(
|
||||
wmi_unified_t wmi_handle,
|
||||
struct peer_ptqm_migrate_params *param)
|
||||
{
|
||||
/* Todo: copy send_peer_delete_all_cmd_tlv */
|
||||
uint16_t i = 0;
|
||||
wmi_buf_t buf;
|
||||
uint8_t *buf_ptr;
|
||||
wmi_mlo_primary_link_peer_migration_fixed_param *cmd;
|
||||
uint32_t len = sizeof(*cmd);
|
||||
uint16_t num_entry = 0;
|
||||
uint16_t max_entry_per_cmd = 0, max_entry_cnt = 0;
|
||||
struct peer_ptqm_migrate_entry *param_list = param->peer_list;
|
||||
wmi_mlo_new_primary_link_peer_info *entry;
|
||||
uint32_t pending_cnt = param->num_peers;
|
||||
|
||||
/* Get max entries which can be send in a single WMI command.
|
||||
* If no. of entries is more than max entries supported, multiple
|
||||
* WMI commands will be send.
|
||||
*/
|
||||
max_entry_per_cmd = (wmi_get_max_msg_len(wmi_handle) -
|
||||
sizeof(*cmd) - WMI_TLV_HDR_SIZE) /
|
||||
(sizeof(wmi_mlo_new_primary_link_peer_info));
|
||||
|
||||
if (param->num_peers > max_entry_per_cmd)
|
||||
max_entry_cnt = max_entry_per_cmd;
|
||||
else
|
||||
max_entry_cnt = param->num_peers;
|
||||
|
||||
wmi_debug("Setting max entry limit as %u", max_entry_cnt);
|
||||
while (pending_cnt > 0) {
|
||||
len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
|
||||
if (pending_cnt >= max_entry_cnt)
|
||||
num_entry = max_entry_cnt;
|
||||
else
|
||||
num_entry = pending_cnt;
|
||||
|
||||
len += num_entry * sizeof(wmi_mlo_new_primary_link_peer_info);
|
||||
buf = wmi_buf_alloc(wmi_handle, len);
|
||||
if (!buf)
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
|
||||
buf_ptr = (uint8_t *)wmi_buf_data(buf);
|
||||
|
||||
cmd = (wmi_mlo_primary_link_peer_migration_fixed_param *)
|
||||
wmi_buf_data(buf);
|
||||
WMITLV_SET_HDR(
|
||||
&cmd->tlv_header,
|
||||
WMITLV_TAG_STRUC_wmi_mlo_primary_link_peer_migration_fixed_param,
|
||||
WMITLV_GET_STRUCT_TLVLEN
|
||||
(wmi_mlo_primary_link_peer_migration_fixed_param));
|
||||
buf_ptr += sizeof(*cmd);
|
||||
cmd->vdev_id = param->vdev_id;
|
||||
WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
|
||||
num_entry * sizeof(wmi_mlo_new_primary_link_peer_info));
|
||||
buf_ptr += WMI_TLV_HDR_SIZE;
|
||||
entry = (wmi_mlo_new_primary_link_peer_info *)buf_ptr;
|
||||
for (i = 0; i < num_entry; i++) {
|
||||
WMITLV_SET_HDR(&entry[i].tlv_header,
|
||||
WMITLV_TAG_STRUC_wmi_mlo_new_primary_link_peer_info,
|
||||
WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_new_primary_link_peer_info));
|
||||
WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_ML_PEER_ID_SET(
|
||||
entry[i].new_link_info,
|
||||
param_list[i].ml_peer_id);
|
||||
WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_HW_LINK_ID_SET(
|
||||
entry[i].new_link_info,
|
||||
param_list[i].hw_link_id);
|
||||
wmi_debug("i:%d, ml_peer_id:%d, hw_link_id:%d",
|
||||
i, entry[i].ml_peer_id, entry[i].hw_link_id);
|
||||
}
|
||||
pending_cnt -= num_entry;
|
||||
param_list += num_entry;
|
||||
|
||||
wmi_mtrace(WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_CMDID,
|
||||
cmd->vdev_id, 0);
|
||||
|
||||
if (wmi_unified_cmd_send(wmi_handle, buf, len,
|
||||
WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_CMDID)) {
|
||||
wmi_err("num_entries:%d failed!",
|
||||
param->num_peers);
|
||||
wmi_buf_free(buf);
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
wmi_debug("num_entries:%d done!",
|
||||
num_entry);
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static QDF_STATUS
|
||||
extract_peer_ptqm_migrate_evt_param_tlv(
|
||||
struct wmi_unified *wmi_handle,
|
||||
uint8_t *buf,
|
||||
struct peer_ptqm_migrate_event_params *params)
|
||||
{
|
||||
WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_EVENTID_param_tlvs *param_buf;
|
||||
wmi_mlo_primary_link_peer_migration_compl_fixed_param *ev;
|
||||
|
||||
param_buf =
|
||||
(WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_EVENTID_param_tlvs *)buf;
|
||||
if (!param_buf) {
|
||||
wmi_err_rl("Param_buf is NULL");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
if (!param_buf->primary_link_peer_migration_status) {
|
||||
wmi_err_rl("primary_link_peer_migration_status not present in event");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
ev = (wmi_mlo_primary_link_peer_migration_compl_fixed_param *)
|
||||
param_buf->fixed_param;
|
||||
|
||||
params->vdev_id = ev->vdev_id;
|
||||
params->num_peers = param_buf->num_primary_link_peer_migration_status;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static QDF_STATUS
|
||||
extract_peer_entry_ptqm_migrate_evt_param_tlv(
|
||||
struct wmi_unified *wmi_handle,
|
||||
uint8_t *buf,
|
||||
uint32_t index,
|
||||
struct peer_entry_ptqm_migrate_event_params *params)
|
||||
{
|
||||
WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_EVENTID_param_tlvs *param_buf;
|
||||
|
||||
param_buf =
|
||||
(WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_EVENTID_param_tlvs *)buf;
|
||||
if (!param_buf) {
|
||||
wmi_err_rl("Param_buf is NULL");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
if (index > param_buf->num_primary_link_peer_migration_status) {
|
||||
wmi_err_rl("Index greater than total peer entries");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
if (!param_buf->primary_link_peer_migration_status) {
|
||||
wmi_err_rl("primary_link_peer_migration_status not present in event");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
params->ml_peer_id =
|
||||
WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_STATUS_ML_PEER_ID_GET(
|
||||
param_buf->primary_link_peer_migration_status[index].status_info);
|
||||
|
||||
params->status =
|
||||
WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_STATUS_STATUS_GET(
|
||||
param_buf->primary_link_peer_migration_status[index].status_info);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */
|
||||
|
||||
void wmi_11be_attach_tlv(wmi_unified_t wmi_handle)
|
||||
{
|
||||
struct wmi_ops *ops = wmi_handle->ops;
|
||||
@@ -1912,4 +2077,9 @@ void wmi_11be_attach_tlv(wmi_unified_t wmi_handle)
|
||||
extract_mlo_link_disable_request_evt_param_tlv;
|
||||
ops->send_mlo_vdev_pause =
|
||||
send_mlo_vdev_pause_cmd_tlv;
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
ops->send_peer_ptqm_migrate_cmd = send_peer_ptqm_migrate_cmd_tlv;
|
||||
ops->extract_peer_ptqm_migrate_event = extract_peer_ptqm_migrate_evt_param_tlv;
|
||||
ops->extract_peer_entry_ptqm_migrate_event = extract_peer_entry_ptqm_migrate_evt_param_tlv;
|
||||
#endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */
|
||||
}
|
||||
|
@@ -21774,6 +21774,11 @@ static void populate_tlv_events_id(WMI_EVT_ID *event_ids)
|
||||
#endif
|
||||
event_ids[wmi_csa_ie_received_event_id] =
|
||||
WMI_CSA_IE_RECEIVED_EVENTID;
|
||||
|
||||
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
|
||||
event_ids[wmi_peer_ptqm_migration_response_eventid] =
|
||||
WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_EVENTID;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren