qcacmn: Support HW Tx delay for MLO

Add delta_tqm, delta_tsf2 and mlo timestamp offset for BE.
These offsets are used to calculate hardware Tx completion delay.
delta_tsf2 and delta_tqm are updated during init. mlo timestamp
offset is updated whenever target sends the update event.

Also, adding CDP ops to set the offsets.

Change-Id: I55665982798c3a795481fa96c023bb851ea17476
CRs-Fixed: 3220906
This commit is contained in:
Ripan Deuri
2022-05-16 15:39:44 +05:30
committed by Madan Koyyalamudi
parent 460260d38a
commit b8fadd7061
8 changed files with 285 additions and 1 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. 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
@@ -107,4 +107,50 @@ static inline void cdp_mlo_setup_complete(ol_txrx_soc_handle soc,
soc->ops->mlo_ops->mlo_setup_complete(mlo_ctx);
}
/*
* cdp_mlo_update_delta_tsf2 - Update delta_tsf2
* @soc: soc handle
* @pdev_id: pdev id
* @delta_tsf2: delta_tsf2
*
* return: none
*/
static inline void cdp_mlo_update_delta_tsf2(ol_txrx_soc_handle soc,
uint8_t pdev_id,
uint64_t delta_tsf2)
{
if (!soc || !soc->ops) {
QDF_BUG(0);
return;
}
if (!soc->ops->mlo_ops ||
!soc->ops->mlo_ops->mlo_update_delta_tsf2)
return;
soc->ops->mlo_ops->mlo_update_delta_tsf2(soc, pdev_id, delta_tsf2);
}
/*
* cdp_mlo_update_delta_tqm - Update delta_tqm
* @soc: soc handle
* @delta_tqm: delta_tqm
*
* return: none
*/
static inline void cdp_mlo_update_delta_tqm(ol_txrx_soc_handle soc,
uint64_t delta_tqm)
{
if (!soc || !soc->ops) {
QDF_BUG(0);
return;
}
if (!soc->ops->mlo_ops ||
!soc->ops->mlo_ops->mlo_update_delta_tqm)
return;
soc->ops->mlo_ops->mlo_update_delta_tqm(soc, delta_tqm);
}
#endif /*_CDP_TXRX_MLO_H_*/

View File

@@ -141,6 +141,9 @@ enum cdp_peer_txq_flush_policy {
* @mlo_soc_setup: setup DP mlo for SOC
* @mlo_soc_teardown: teardown DP mlo for SOC
* @mlo_setup_complete: indication to DP that all SOCs mlo is setup
* @mlo_update_delta_tsf2: update delta tsf2 for link
* @mlo_update_delta_tqm: update delta tqm for SOC
* @mlo_update_mlo_ts_offset: update MLO timestamp offset for SOC
*/
#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
struct cdp_mlo_ops {
@@ -152,6 +155,13 @@ struct cdp_mlo_ops {
int8_t *vdev_ids, uint8_t num_vdevs,
uint8_t vdev_id);
void (*mlo_setup_complete)(struct cdp_mlo_ctxt *mlo_ctxt);
void (*mlo_update_delta_tsf2)(struct cdp_soc_t *soc_hdl,
uint8_t pdev_id,
uint64_t delta_tsf2);
void (*mlo_update_delta_tqm)(struct cdp_soc_t *soc_hdl,
uint64_t delta_tqm);
void (*mlo_update_mlo_ts_offset)(struct cdp_soc_t *soc_hdl,
uint64_t offset);
};
#endif

View File

@@ -687,11 +687,15 @@ static QDF_STATUS dp_pdev_attach_be(struct dp_pdev *pdev,
struct cdp_pdev_attach_params *params)
{
dp_pdev_mlo_fill_params(pdev, params);
dp_mlo_update_link_to_pdev_map(pdev->soc, pdev);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dp_pdev_detach_be(struct dp_pdev *pdev)
{
dp_mlo_update_link_to_pdev_unmap(pdev->soc, pdev);
return QDF_STATUS_SUCCESS;
}

View File

@@ -223,6 +223,8 @@ struct dp_ppe_vp_profile {
* @mlo_enabled: Flag to indicate MLO is enabled or not
* @mlo_chip_id: MLO chip_id
* @ml_ctxt: pointer to global ml_context
* @delta_tqm: delta_tqm
* @mlo_tstamp_offset: mlo timestamp offset
* @mld_peer_hash: peer hash table for ML peers
* Associated peer with this MAC address)
* @mld_peer_hash_lock: lock to protect mld_peer_hash
@@ -259,6 +261,8 @@ struct dp_soc_be {
uint8_t mlo_enabled;
uint8_t mlo_chip_id;
struct dp_mlo_ctxt *ml_ctxt;
uint64_t delta_tqm;
uint64_t mlo_tstamp_offset;
#else
/* Protect mld peer hash table */
DP_MUTEX_TYPE mld_peer_hash_lock;
@@ -280,11 +284,13 @@ struct dp_soc_be {
* @pdev: dp pdev structure
* @monitor_pdev_be: BE specific monitor object
* @mlo_link_id: MLO link id for PDEV
* @delta_tsf2: delta_tsf2
*/
struct dp_pdev_be {
struct dp_pdev pdev;
#ifdef WLAN_MLO_MULTI_CHIP
uint8_t mlo_link_id;
uint64_t delta_tsf2;
#endif
};
@@ -770,6 +776,16 @@ void dp_pdev_mlo_fill_params(struct dp_pdev *pdev,
struct cdp_pdev_attach_params *params)
{
}
static inline
void dp_mlo_update_link_to_pdev_map(struct dp_soc *soc, struct dp_pdev *pdev)
{
}
static inline
void dp_mlo_update_link_to_pdev_unmap(struct dp_soc *soc, struct dp_pdev *pdev)
{
}
#endif
/*

View File

@@ -381,11 +381,51 @@ static void dp_mlo_setup_complete(struct cdp_mlo_ctxt *cdp_ml_ctxt)
}
}
static void dp_mlo_update_delta_tsf2(struct cdp_soc_t *soc_hdl,
uint8_t pdev_id, uint64_t delta_tsf2)
{
struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
struct dp_pdev *pdev;
struct dp_pdev_be *be_pdev;
pdev = dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc,
pdev_id);
if (!pdev) {
dp_err("pdev is NULL for pdev_id %u", pdev_id);
return;
}
be_pdev = dp_get_be_pdev_from_dp_pdev(pdev);
be_pdev->delta_tsf2 = delta_tsf2;
}
static void dp_mlo_update_delta_tqm(struct cdp_soc_t *soc_hdl,
uint64_t delta_tqm)
{
struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
be_soc->delta_tqm = delta_tqm;
}
static void dp_mlo_update_mlo_ts_offset(struct cdp_soc_t *soc_hdl,
uint64_t offset)
{
struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
be_soc->mlo_tstamp_offset = offset;
}
static struct cdp_mlo_ops dp_mlo_ops = {
.mlo_soc_setup = dp_mlo_soc_setup,
.mlo_soc_teardown = dp_mlo_soc_teardown,
.update_mlo_ptnr_list = dp_update_mlo_ptnr_list,
.mlo_setup_complete = dp_mlo_setup_complete,
.mlo_update_delta_tsf2 = dp_mlo_update_delta_tsf2,
.mlo_update_delta_tqm = dp_mlo_update_delta_tqm,
.mlo_update_mlo_ts_offset = dp_mlo_update_mlo_ts_offset,
};
void dp_soc_mlo_fill_params(struct dp_soc *soc,
@@ -404,6 +444,57 @@ void dp_soc_mlo_fill_params(struct dp_soc *soc,
soc->cdp_soc.ops->mlo_ops = &dp_mlo_ops;
}
void dp_mlo_update_link_to_pdev_map(struct dp_soc *soc, struct dp_pdev *pdev)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_pdev_be *be_pdev = dp_get_be_pdev_from_dp_pdev(pdev);
struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt;
uint8_t link_id;
if (!be_soc->mlo_enabled)
return;
if (!ml_ctxt)
return;
link_id = be_pdev->mlo_link_id;
if (link_id < WLAN_MAX_MLO_CHIPS * WLAN_MAX_MLO_LINKS_PER_SOC) {
if (!ml_ctxt->link_to_pdev_map[link_id])
ml_ctxt->link_to_pdev_map[link_id] = be_pdev;
else
dp_alert("Attempt to update existing map for link %u",
link_id);
}
}
void dp_mlo_update_link_to_pdev_unmap(struct dp_soc *soc, struct dp_pdev *pdev)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_pdev_be *be_pdev = dp_get_be_pdev_from_dp_pdev(pdev);
struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt;
uint8_t link_id;
if (!be_soc->mlo_enabled)
return;
if (!ml_ctxt)
return;
link_id = be_pdev->mlo_link_id;
if (link_id < WLAN_MAX_MLO_CHIPS * WLAN_MAX_MLO_LINKS_PER_SOC)
ml_ctxt->link_to_pdev_map[link_id] = NULL;
}
static struct dp_pdev_be *
dp_mlo_get_be_pdev_from_link_id(struct dp_mlo_ctxt *ml_ctxt, uint8_t link_id)
{
if (link_id < WLAN_MAX_MLO_CHIPS * WLAN_MAX_MLO_LINKS_PER_SOC)
return ml_ctxt->link_to_pdev_map[link_id];
return NULL;
}
void dp_pdev_mlo_fill_params(struct dp_pdev *pdev,
struct cdp_pdev_attach_params *params)
{
@@ -655,3 +746,57 @@ struct dp_vdev *dp_mlo_get_mcast_primary_vdev(struct dp_soc_be *be_soc,
qdf_export_symbol(dp_mlo_get_mcast_primary_vdev);
#endif
static inline uint64_t dp_mlo_get_mlo_ts_offset(struct dp_pdev_be *be_pdev)
{
struct dp_soc *soc;
struct dp_pdev *pdev;
struct dp_soc_be *be_soc;
uint32_t mlo_offset;
pdev = &be_pdev->pdev;
soc = pdev->soc;
be_soc = dp_get_be_soc_from_dp_soc(soc);
mlo_offset = be_soc->mlo_tstamp_offset;
return mlo_offset;
}
int32_t dp_mlo_get_delta_tsf2_wrt_mlo_offset(struct dp_soc *soc,
uint8_t hw_link_id)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt;
struct dp_pdev_be *be_pdev;
int32_t delta_tsf2_mlo_offset;
int32_t mlo_offset, delta_tsf2;
if (!ml_ctxt)
return 0;
be_pdev = dp_mlo_get_be_pdev_from_link_id(ml_ctxt, hw_link_id);
if (!be_pdev)
return 0;
mlo_offset = dp_mlo_get_mlo_ts_offset(be_pdev);
delta_tsf2 = be_pdev->delta_tsf2;
delta_tsf2_mlo_offset = mlo_offset - delta_tsf2;
return delta_tsf2_mlo_offset;
}
int32_t dp_mlo_get_delta_tqm_wrt_mlo_offset(struct dp_soc *soc)
{
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
int32_t delta_tqm_mlo_offset;
int32_t mlo_offset, delta_tqm;
mlo_offset = be_soc->mlo_tstamp_offset;
delta_tqm = be_soc->delta_tqm;
delta_tqm_mlo_offset = mlo_offset - delta_tqm;
return delta_tqm_mlo_offset;
}

View File

@@ -38,6 +38,7 @@
* @mld_peer_hash: peer hash table for ML peers
* Associated peer with this MAC address)
* @mld_peer_hash_lock: lock to protect mld_peer_hash
* @link_to_pdev_map: link to pdev mapping
*/
struct dp_mlo_ctxt {
struct cdp_ctrl_mlo_mgr *ctrl_ctxt;
@@ -53,6 +54,8 @@ struct dp_mlo_ctxt {
qdf_spinlock_t mld_peer_hash_lock;
uint32_t toeplitz_hash_ipv4[LRO_IPV4_SEED_ARR_SZ];
uint32_t toeplitz_hash_ipv6[LRO_IPV6_SEED_ARR_SZ];
struct dp_pdev_be *link_to_pdev_map[WLAN_MAX_MLO_CHIPS *
WLAN_MAX_MLO_LINKS_PER_SOC];
};
/**
@@ -110,4 +113,42 @@ dp_mlo_get_soc_ref_by_chip_id(struct dp_mlo_ctxt *ml_ctxt, uint8_t chip_id);
*/
void dp_mlo_get_rx_hash_key(struct dp_soc *soc,
struct cdp_lro_hash_config *lro_hash);
/**
* dp_mlo_update_link_to_pdev_map : map link-id to pdev mapping
* @soc: DP SOC
* @pdev: DP PDEV
*
* Return: none
*/
void dp_mlo_update_link_to_pdev_map(struct dp_soc *soc, struct dp_pdev *pdev);
/**
* dp_mlo_update_link_to_pdev_unmap : unmap link-id to pdev mapping
* @soc: DP SOC
* @pdev: DP PDEV
*
* Return: none
*/
void dp_mlo_update_link_to_pdev_unmap(struct dp_soc *soc, struct dp_pdev *pdev);
/**
* dp_mlo_get_delta_tsf2_wrt_mlo_offset() - Get delta between mlo timestamp
* offset and delta tsf2
* @soc: DP SOC
* @hw_link_id: link id
*
* Return: int32_t
*/
int32_t dp_mlo_get_delta_tsf2_wrt_mlo_offset(struct dp_soc *soc,
uint8_t hw_link_id);
/**
* dp_mlo_get_delta_tqm_wrt_mlo_offset() - Get delta between mlo timestamp
* offset and delta tqm
* @soc: DP SOC
*
* Return: int32_t
*/
int32_t dp_mlo_get_delta_tqm_wrt_mlo_offset(struct dp_soc *soc);
#endif /* __DP_MLO_H */

View File

@@ -2943,6 +2943,21 @@ dp_offload_ind_handler(struct htt_soc *soc, uint32_t *msg_word)
#endif
#ifdef WLAN_FEATURE_11BE_MLO
#ifdef WLAN_MLO_MULTI_CHIP
static inline void dp_update_mlo_ts_offset(struct dp_soc *soc,
uint32_t ts_lo, uint32_t ts_hi)
{
uint64_t mlo_offset;
mlo_offset = ((uint64_t)(ts_hi) << 32 | ts_lo);
soc->cdp_soc.ops->mlo_ops->mlo_update_mlo_ts_offset
((struct cdp_soc_t *)soc, mlo_offset);
}
#else
static inline void dp_update_mlo_ts_offset(struct dp_soc *soc,
uint32_t ts_lo, uint32_t ts_hi)
{}
#endif
static void dp_htt_mlo_peer_map_handler(struct htt_soc *soc,
uint32_t *msg_word)
{
@@ -3097,6 +3112,10 @@ dp_rx_mlo_timestamp_ind_handler(struct dp_soc *soc,
pdev->timestamp.mlo_offset_hi_us);
qdf_spin_unlock_bh(&soc->htt_stats.lock);
dp_update_mlo_ts_offset(soc,
pdev->timestamp.mlo_offset_lo_us,
pdev->timestamp.mlo_offset_hi_us);
}
#else
static void dp_htt_mlo_peer_map_handler(struct htt_soc *soc,

View File

@@ -5722,6 +5722,7 @@ static QDF_STATUS dp_pdev_detach_wifi3(struct cdp_soc_t *psoc, uint8_t pdev_id,
int force)
{
struct dp_pdev *pdev;
struct dp_soc *soc = (struct dp_soc *)psoc;
pdev = dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)psoc,
pdev_id);
@@ -5732,6 +5733,8 @@ static QDF_STATUS dp_pdev_detach_wifi3(struct cdp_soc_t *psoc, uint8_t pdev_id,
return QDF_STATUS_E_FAILURE;
}
soc->arch_ops.txrx_pdev_detach(pdev);
dp_pdev_detach((struct cdp_pdev *)pdev, force);
return QDF_STATUS_SUCCESS;
}