qcacmn: Add support for primary TQM migration

Add support for primary TQM migration.

Change-Id: Ifd62eb7e731bbd9e86c462642fd2e20d50d5495a
CRs-Fixed: 3410900
This commit is contained in:
Neha Bisht
2023-01-31 12:38:19 +05:30
committed by Madan Koyyalamudi
parent 031d51614e
commit 80ee0f60c6
8 changed files with 456 additions and 4 deletions

View File

@@ -1464,6 +1464,11 @@ struct ol_if_ops {
qdf_nbuf_t nbuf,
uint16_t hdr_space);
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
void (*update_primary_link)(struct cdp_ctrl_objmgr_psoc *psoc,
uint8_t *mac_addr);
#endif
uint8_t (*freq_to_channel)(struct cdp_ctrl_objmgr_psoc *psoc,
uint8_t pdev_id, uint16_t freq);

View File

@@ -2763,3 +2763,214 @@ void dp_initialize_arch_ops_be(struct dp_arch_ops *arch_ops)
dp_initialize_arch_ops_be_ipa(arch_ops);
dp_initialize_arch_ops_be_single_dev(arch_ops);
}
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
static void
dp_primary_link_migration(struct dp_soc *soc, void *cb_ctxt,
union hal_reo_status *reo_status)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
struct dp_soc *pr_soc = NULL;
struct dp_peer_info *pr_peer_info = (struct dp_peer_info *)cb_ctxt;
struct dp_peer *new_primary_peer = NULL;
struct dp_peer *mld_peer = NULL;
uint8_t primary_vdev_id;
struct cdp_txrx_peer_params_update params = {0};
pr_soc = dp_mlo_get_soc_ref_by_chip_id(dp_mlo, pr_peer_info->chip_id);
if (!pr_soc) {
dp_htt_err("Invalid soc");
qdf_mem_free(pr_peer_info);
return;
}
new_primary_peer = pr_soc->peer_id_to_obj_map[
pr_peer_info->primary_peer_id];
mld_peer = DP_GET_MLD_PEER_FROM_PEER(new_primary_peer);
if (!mld_peer) {
dp_htt_err("Invalid peer");
qdf_mem_free(pr_peer_info);
return;
}
new_primary_peer->primary_link = 1;
if (pr_soc && pr_soc->cdp_soc.ol_ops->update_primary_link)
pr_soc->cdp_soc.ol_ops->update_primary_link(pr_soc->ctrl_psoc,
new_primary_peer->mac_addr.raw);
primary_vdev_id = new_primary_peer->vdev->vdev_id;
dp_vdev_unref_delete(soc, mld_peer->vdev, DP_MOD_ID_CHILD);
mld_peer->vdev = dp_vdev_get_ref_by_id(pr_soc, primary_vdev_id,
DP_MOD_ID_CHILD);
mld_peer->txrx_peer->vdev = mld_peer->vdev;
params.osif_vdev = (void *)new_primary_peer->vdev->osif_vdev;
params.peer_mac = new_primary_peer->mac_addr.raw;
params.chip_id = pr_peer_info->chip_id;
params.pdev_id = new_primary_peer->vdev->pdev->pdev_id;
if (new_primary_peer->vdev->opmode == wlan_op_mode_sta) {
dp_wdi_event_handler(
WDI_EVENT_STA_PRIMARY_UMAC_UPDATE,
pr_soc, (void *)&params,
new_primary_peer->peer_id,
WDI_NO_VAL, params.pdev_id);
} else {
dp_wdi_event_handler(
WDI_EVENT_PEER_PRIMARY_UMAC_UPDATE,
pr_soc, (void *)&params,
new_primary_peer->peer_id,
WDI_NO_VAL, params.pdev_id);
}
qdf_mem_free(pr_peer_info);
}
QDF_STATUS dp_htt_reo_migration(struct dp_soc *soc, uint16_t peer_id,
uint16_t ml_peer_id, uint16_t vdev_id,
uint8_t pdev_id, uint8_t chip_id)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
uint16_t mld_peer_id = dp_gen_ml_peer_id(soc, ml_peer_id);
struct dp_soc *pr_soc = NULL;
struct dp_soc *current_pr_soc = NULL;
struct hal_reo_cmd_params params;
struct dp_rx_tid *rx_tid;
struct dp_peer *pr_peer = NULL;
struct dp_peer *mld_peer = NULL;
struct dp_soc *mld_soc = NULL;
struct dp_peer *current_pr_peer = NULL;
struct dp_peer_info *peer_info;
struct dp_vdev_be *be_vdev;
struct cdp_ds_vp_params vp_params = {0};
struct cdp_soc_t *cdp_soc;
struct dp_soc_be *be_soc_mld = NULL;
struct dp_ppe_vp_profile *ppe_vp_profile;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
uint16_t src_info;
QDF_STATUS status;
if (!dp_mlo) {
dp_htt_err("Invalid dp_mlo ctxt");
return QDF_STATUS_E_FAILURE;
}
pr_soc = dp_mlo_get_soc_ref_by_chip_id(dp_mlo, chip_id);
if (!pr_soc) {
dp_htt_err("Invalid soc");
return QDF_STATUS_E_FAILURE;
}
pr_peer = pr_soc->peer_id_to_obj_map[peer_id];
if (!pr_peer || !(IS_MLO_DP_LINK_PEER(pr_peer))) {
dp_htt_err("Invalid peer");
return QDF_STATUS_E_FAILURE;
}
mld_peer = DP_GET_MLD_PEER_FROM_PEER(pr_peer);
if (!mld_peer || (mld_peer->peer_id != mld_peer_id)) {
dp_htt_err("Invalid mld peer");
return QDF_STATUS_E_FAILURE;
}
current_pr_peer = dp_get_primary_link_peer_by_id(
pr_soc,
mld_peer->peer_id,
DP_MOD_ID_HTT);
if (!current_pr_peer || (current_pr_peer == pr_peer)) {
dp_htt_err("Invalid peer");
return QDF_STATUS_E_FAILURE;
}
be_vdev = dp_get_be_vdev_from_dp_vdev(pr_peer->vdev);
if (!be_vdev) {
dp_htt_err("Invalid be vdev");
return QDF_STATUS_E_FAILURE;
}
mld_soc = mld_peer->vdev->pdev->soc;
cdp_soc = &mld_soc->cdp_soc;
/*
* Extract the VP profile from the VAP
*/
if (!cdp_soc->ol_ops->get_ppeds_profile_info_for_vap) {
dp_err("%pK: Register get ppeds profile info first\n", cdp_soc);
return QDF_STATUS_E_NULL_VALUE;
}
/*
* Check if PPE DS routing is enabled on the associated vap.
*/
qdf_status = cdp_soc->ol_ops->get_ppeds_profile_info_for_vap(
mld_soc->ctrl_psoc,
pr_peer->vdev->vdev_id,
&vp_params);
if (qdf_status == QDF_STATUS_E_NULL_VALUE) {
dp_err("%pK: Could not find ppeds profile info \n", be_vdev);
return QDF_STATUS_E_NULL_VALUE;
}
/* Check if PPE DS routing is enabled on
* the associated vap.
*/
if (vp_params.ppe_vp_type != PPE_VP_USER_TYPE_DS)
return qdf_status;
be_soc_mld = dp_get_be_soc_from_dp_soc(mld_soc);
ppe_vp_profile = &be_soc_mld->ppe_vp_profile[
vp_params.ppe_vp_profile_idx];
src_info = ppe_vp_profile->vp_num;
current_pr_soc = current_pr_peer->vdev->pdev->soc;
/* Making existing primary peer as non primary */
current_pr_peer->primary_link = 0;
dp_peer_unref_delete(current_pr_peer, DP_MOD_ID_HTT);
dp_peer_rx_reo_shared_qaddr_delete(current_pr_soc, mld_peer);
peer_info = qdf_mem_malloc(sizeof(struct dp_peer_info));
if (!peer_info) {
dp_htt_err("Malloc failed");
return QDF_STATUS_E_FAILURE;
}
peer_info->primary_peer_id = peer_id;
peer_info->chip_id = chip_id;
qdf_mem_zero(&params, sizeof(params));
rx_tid = &mld_peer->rx_tid[0];
params.std.need_status = 1;
params.std.addr_lo = rx_tid->hw_qdesc_paddr & 0xffffffff;
params.std.addr_hi = (uint64_t)(rx_tid->hw_qdesc_paddr) >> 32;
params.u.fl_cache_params.flush_no_inval = 0;
params.u.fl_cache_params.flush_entire_cache = 1;
status = dp_reo_send_cmd(current_pr_soc, CMD_FLUSH_CACHE, &params,
dp_primary_link_migration,
(void *)peer_info);
if (status != QDF_STATUS_SUCCESS) {
dp_htt_err("Reo flush failed");
qdf_mem_free(peer_info);
dp_h2t_ptqm_migration_msg_send(pr_soc, vdev_id, pdev_id,
chip_id, peer_id, ml_peer_id,
src_info, QDF_STATUS_E_FAILURE);
}
qdf_mem_zero(&params, sizeof(params));
params.std.need_status = 0;
params.std.addr_lo = rx_tid->hw_qdesc_paddr & 0xffffffff;
params.std.addr_hi = (uint64_t)(rx_tid->hw_qdesc_paddr) >> 32;
params.u.unblk_cache_params.type = UNBLOCK_CACHE;
dp_reo_send_cmd(current_pr_soc, CMD_UNBLOCK_CACHE, &params, NULL, NULL);
dp_h2t_ptqm_migration_msg_send(pr_soc, vdev_id, pdev_id,
chip_id, peer_id, ml_peer_id,
src_info, QDF_STATUS_SUCCESS);
return QDF_STATUS_SUCCESS;
}
#endif

View File

@@ -2404,6 +2404,105 @@ dp_pktlog_msg_handler(struct htt_soc *soc,
}
#endif
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
QDF_STATUS
dp_h2t_ptqm_migration_msg_send(struct dp_soc *dp_soc, uint16_t vdev_id,
uint8_t pdev_id,
uint8_t chip_id, uint16_t peer_id,
uint16_t ml_peer_id, uint16_t src_info,
QDF_STATUS status)
{
struct htt_soc *soc = dp_soc->htt_handle;
struct dp_htt_htc_pkt *pkt;
uint8_t *htt_logger_bufp;
qdf_nbuf_t msg;
uint32_t *msg_word;
QDF_STATUS ret = QDF_STATUS_SUCCESS;
msg = qdf_nbuf_alloc(
soc->osdev,
HTT_MSG_BUF_SIZE(HTT_H2T_REO_MIGRATION_RESP_MSG_SZ),
HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
if (!msg)
return QDF_STATUS_E_NOMEM;
/*
* Set the length of the message.
* The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
* separately during the below call to qdf_nbuf_push_head.
* The contribution from the HTC header is added separately inside HTC.
*/
if (qdf_nbuf_put_tail(msg, HTT_H2T_REO_MIGRATION_RESP_MSG_SZ)
== NULL) {
dp_htt_err("Failed to expand head for"
"HTT_H2T_MSG_TYPE_PRIMARY_LINK_PEER_MIGRATE_RESP");
qdf_nbuf_free(msg);
return QDF_STATUS_E_FAILURE;
}
msg_word = (uint32_t *)qdf_nbuf_data(msg);
memset(msg_word, 0, HTT_H2T_REO_MIGRATION_RESP_MSG_SZ);
qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
htt_logger_bufp = (uint8_t *)msg_word;
*msg_word = 0;
HTT_H2T_MSG_TYPE_SET(*msg_word,
HTT_H2T_MSG_TYPE_PRIMARY_LINK_PEER_MIGRATE_RESP);
HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_PDEV_ID_SET(*msg_word, pdev_id);
HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_CHIP_ID_SET(*msg_word, chip_id);
HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_VDEV_ID_SET(*msg_word, vdev_id);
/* word 1 */
msg_word++;
*msg_word = 0;
HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_SW_LINK_PEER_ID_SET(*msg_word,
peer_id);
HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_ML_PEER_ID_SET(*msg_word,
ml_peer_id);
/* word 1 */
msg_word++;
*msg_word = 0;
HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_SRCINFO_SET(*msg_word,
src_info);
HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_STATUS_SET(*msg_word,
status);
pkt = htt_htc_pkt_alloc(soc);
if (!pkt) {
dp_htt_err("Fail to allocate dp_htt_htc_pkt buffer");
qdf_nbuf_free(msg);
return QDF_STATUS_E_NOMEM;
}
pkt->soc_ctxt = NULL;
/* macro to set packet parameters for TX */
SET_HTC_PACKET_INFO_TX(
&pkt->htc_pkt,
dp_htt_h2t_send_complete_free_netbuf,
qdf_nbuf_data(msg),
qdf_nbuf_len(msg),
soc->htc_endpoint,
HTC_TX_PACKET_TAG_RUNTIME_PUT);
SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
ret = DP_HTT_SEND_HTC_PKT(
soc, pkt,
HTT_H2T_MSG_TYPE_PRIMARY_LINK_PEER_MIGRATE_RESP,
htt_logger_bufp);
if (ret != QDF_STATUS_SUCCESS) {
qdf_nbuf_free(msg);
htt_htc_pkt_free(soc, pkt);
}
return ret;
}
#endif
#ifdef QCA_VDEV_STATS_HW_OFFLOAD_SUPPORT
/**
* dp_vdev_txrx_hw_stats_handler - Handle vdev stats received from FW
@@ -3226,6 +3325,40 @@ static void dp_htt_mlo_peer_map_handler(struct htt_soc *soc,
mlo_flow_info, mlo_link_info);
}
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
static void dp_htt_t2h_primary_link_migration(struct htt_soc *soc,
uint32_t *msg_word)
{
u_int16_t peer_id;
u_int16_t ml_peer_id;
u_int16_t vdev_id;
u_int8_t pdev_id;
u_int8_t chip_id;
vdev_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_VDEV_ID_GET(
*msg_word);
pdev_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_PDEV_ID_GET(
*msg_word);
chip_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_CHIP_ID_GET(
*msg_word);
ml_peer_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_ML_PEER_ID_GET(
*(msg_word + 1));
peer_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_SW_LINK_PEER_ID_GET(
*(msg_word + 1));
dp_htt_info("HTT_T2H_MSG_TYPE_PRIMARY_PEER_MIGRATE_IND msg"
"for peer id %d vdev id %d", peer_id, vdev_id);
dp_htt_reo_migration(soc->dp_soc, peer_id, ml_peer_id,
vdev_id, pdev_id, chip_id);
}
#else
static void dp_htt_t2h_primary_link_migration(struct htt_soc *soc,
uint32_t *msg_word)
{
}
#endif
static void dp_htt_mlo_peer_unmap_handler(struct htt_soc *soc,
uint32_t *msg_word)
{
@@ -3319,6 +3452,11 @@ dp_rx_mlo_timestamp_ind_handler(void *soc_handle,
{
qdf_assert_always(0);
}
static void dp_htt_t2h_primary_link_migration(struct htt_soc *soc,
uint32_t *msg_word)
{
}
#endif
/**
@@ -3884,6 +4022,11 @@ void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
break;
}
case HTT_T2H_MSG_TYPE_PRIMARY_LINK_PEER_MIGRATE_IND:
{
dp_htt_t2h_primary_link_migration(soc, msg_word);
break;
}
case HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP:
{
dp_htt_mlo_peer_map_handler(soc, msg_word);

View File

@@ -1199,4 +1199,51 @@ dp_htt_get_mon_htt_ring_id(struct dp_soc *soc,
QDF_STATUS htt_h2t_rx_cce_super_rule_setup(struct htt_soc *htt_soc,
void *flt_params);
#endif
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
/**
* struct dp_peer_info - Primary Peer information
* @primary_peer_id: Primary peer id
* @chip_id: Chip id of primary peer
*/
struct dp_peer_info {
uint16_t primary_peer_id;
uint8_t chip_id;
};
/**
* dp_h2t_ptqm_migration_msg_send() - Send H2T PTQM message to FW
* @dp_soc: DP SOC handle
* @vdev_id: Vdev id of primary peer
* @pdev_id: Pdev id of primary peer
* @chip_id: Chip id of primary peer
* @peer_id: Peer id of primary peer
* @ml_peer_id: Peer id of MLD peer
* @src_info: source info for DS
* @status: success or failure status of PTQM migration
*
* Return: Success when HTT message is sent, error on failure
*/
QDF_STATUS
dp_h2t_ptqm_migration_msg_send(struct dp_soc *dp_soc, uint16_t vdev_id,
uint8_t pdev_id,
uint8_t chip_id, uint16_t peer_id,
uint16_t ml_peer_id, uint16_t src_info,
QDF_STATUS status);
/**
* dp_htt_reo_migration() - Reo migration API
* @soc: DP SOC handle
* @peer_id: Peer id of primary peer
* @ml_peer_id: Peer id of MLD peer
* @vdev_id: Vdev id of primary peer
* @pdev_id: Pdev id of primary peer
* @chip_id: Chip id of primary peer
*
* Return: Success if migration completes, error on failure
*/
QDF_STATUS dp_htt_reo_migration(struct dp_soc *soc, uint16_t peer_id,
uint16_t ml_peer_id, uint16_t vdev_id,
uint8_t pdev_id, uint8_t chip_id);
#endif
#endif /* _DP_HTT_H_ */

View File

@@ -2704,14 +2704,12 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc,
#ifdef WLAN_FEATURE_11BE_MLO
#ifdef DP_USE_REDUCED_PEER_ID_FIELD_WIDTH
static inline uint16_t dp_gen_ml_peer_id(struct dp_soc *soc,
uint16_t peer_id)
uint16_t dp_gen_ml_peer_id(struct dp_soc *soc, uint16_t peer_id)
{
return ((peer_id & soc->peer_id_mask) | (1 << soc->peer_id_shift));
}
#else
static inline uint16_t dp_gen_ml_peer_id(struct dp_soc *soc,
uint16_t peer_id)
uint16_t dp_gen_ml_peer_id(struct dp_soc *soc, uint16_t peer_id)
{
return (peer_id | (1 << HTT_RX_PEER_META_DATA_V1_ML_PEER_VALID_S));
}

View File

@@ -2462,4 +2462,14 @@ static inline void dp_peer_rx_reo_shared_qaddr_delete(struct dp_soc *soc,
* Return: True for WDS ext peer, false otherwise
*/
bool dp_peer_check_wds_ext_peer(struct dp_peer *peer);
/**
* dp_gen_ml_peer_id() - Generate MLD peer id for DP
*
* @soc: DP soc context
* @peer_id: mld peer id
*
* Return: DP MLD peer id
*/
uint16_t dp_gen_ml_peer_id(struct dp_soc *soc, uint16_t peer_id);
#endif /* _DP_PEER_H_ */

View File

@@ -649,4 +649,16 @@ mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params)
* Return: true, if MLO peer can be deleted
*/
bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer);
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
/**
* wlan_objmgr_mlo_update_primary_info() - Update is_primary flag
* @peer: new primary link peer object
*
* API to update is_primary flag in peer list
*
* Return: void
*/
void wlan_objmgr_mlo_update_primary_info(struct wlan_objmgr_peer *peer);
#endif
#endif

View File

@@ -1611,3 +1611,29 @@ bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer)
return true;
}
#endif
#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
void wlan_objmgr_mlo_update_primary_info(struct wlan_objmgr_peer *peer)
{
struct wlan_mlo_peer_context *ml_peer = NULL;
struct wlan_mlo_link_peer_entry *peer_ent_iter;
uint8_t i;
ml_peer = peer->mlo_peer_ctx;
for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
peer_ent_iter = &ml_peer->peer_list[i];
if (!peer_ent_iter->link_peer)
continue;
if (peer_ent_iter->is_primary)
peer_ent_iter->is_primary = false;
if (peer_ent_iter->link_peer == peer)
peer_ent_iter->is_primary = true;
}
}
qdf_export_symbol(wlan_objmgr_mlo_update_primary_info);
#endif