qcacmn: Host<->FW HTT interface for HW vdev stats in BE

Define the interface for Host and FW communication required for
configuration of HW vdev stats in BE architecture and add handler
for vdev stats received from FW.

Change-Id: I5f6a703596bd1fbb5e27e6261befda25aa0c3e12
CRs-Fixed: 3067843
This commit is contained in:
Harsh Kumar Bijlani
2021-05-15 00:30:14 +05:30
committad av Madan Koyyalamudi
förälder af17c944fb
incheckning 356b9766fd
3 ändrade filer med 404 tillägg och 0 borttagningar

Visa fil

@@ -2076,6 +2076,176 @@ dp_pktlog_msg_handler(struct htt_soc *soc,
}
#endif
#ifdef QCA_VDEV_STATS_HW_OFFLOAD_SUPPORT
/*
* dp_vdev_txrx_hw_stats_handler - Handle vdev stats received from FW
* @soc - htt soc handle
* @ msg_word - buffer containing stats
*
* Return: void
*/
static void dp_vdev_txrx_hw_stats_handler(struct htt_soc *soc,
uint32_t *msg_word)
{
struct dp_soc *dpsoc = (struct dp_soc *)soc->dp_soc;
uint8_t pdev_id;
uint8_t vdev_id;
uint8_t target_pdev_id;
uint16_t payload_size;
struct dp_pdev *pdev;
struct dp_vdev *vdev;
uint8_t *tlv_buf;
uint32_t *tlv_buf_temp;
uint32_t *tag_buf;
htt_tlv_tag_t tlv_type;
uint16_t tlv_length;
uint64_t pkt_count = 0;
uint64_t byte_count = 0;
uint64_t soc_drop_cnt = 0;
struct cdp_pkt_info tx_comp = { 0 };
struct cdp_pkt_info tx_failed = { 0 };
target_pdev_id =
HTT_T2H_VDEVS_TXRX_STATS_PERIODIC_IND_PDEV_ID_GET(*msg_word);
pdev_id = dp_get_host_pdev_id_for_target_pdev_id(dpsoc,
target_pdev_id);
if (pdev_id >= MAX_PDEV_CNT)
return;
pdev = dpsoc->pdev_list[pdev_id];
if (!pdev) {
dp_err("PDEV is NULL for pdev_id:%d", pdev_id);
return;
}
payload_size =
HTT_T2H_VDEVS_TXRX_STATS_PERIODIC_IND_PAYLOAD_SIZE_GET(*msg_word);
qdf_trace_hex_dump(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
(void *)msg_word, payload_size + 16);
/* Adjust msg_word to point to the first TLV in buffer */
msg_word = msg_word + 4;
/* Parse the received buffer till payload size reaches 0 */
while (payload_size > 0) {
tlv_buf = (uint8_t *)msg_word;
tlv_buf_temp = msg_word;
tlv_type = HTT_STATS_TLV_TAG_GET(*msg_word);
tlv_length = HTT_STATS_TLV_LENGTH_GET(*msg_word);
/* Add header size to tlv length*/
tlv_length += 4;
switch (tlv_type) {
case HTT_STATS_SOC_TXRX_STATS_COMMON_TAG:
{
tag_buf = tlv_buf_temp +
HTT_VDEV_STATS_GET_INDEX(SOC_DROP_CNT);
soc_drop_cnt = HTT_VDEV_GET_STATS_U64(tag_buf);
DP_STATS_UPD(dpsoc, tx.tqm_drop_no_peer, soc_drop_cnt);
break;
}
case HTT_STATS_VDEV_TXRX_STATS_HW_STATS_TAG:
{
tag_buf = tlv_buf_temp +
HTT_VDEV_STATS_GET_INDEX(VDEV_ID);
vdev_id = (uint8_t)(*tag_buf);
vdev = dp_vdev_get_ref_by_id(dpsoc, vdev_id,
DP_MOD_ID_HTT);
if (!vdev)
goto invalid_vdev;
/* Extract received packet count from buffer */
tag_buf = tlv_buf_temp +
HTT_VDEV_STATS_GET_INDEX(RX_PKT_CNT);
pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
DP_STATS_UPD(vdev, rx_i.reo_rcvd_pkt.num, pkt_count);
/* Extract received packet byte count from buffer */
tag_buf = tlv_buf_temp +
HTT_VDEV_STATS_GET_INDEX(RX_BYTE_CNT);
byte_count = HTT_VDEV_GET_STATS_U64(tag_buf);
DP_STATS_UPD(vdev, rx_i.reo_rcvd_pkt.bytes, byte_count);
/* Extract tx success packet count from buffer */
tag_buf = tlv_buf_temp +
HTT_VDEV_STATS_GET_INDEX(TX_SUCCESS_PKT_CNT);
pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
tx_comp.num += pkt_count;
/* Extract tx success packet byte count from buffer */
tag_buf = tlv_buf_temp +
HTT_VDEV_STATS_GET_INDEX(TX_SUCCESS_BYTE_CNT);
byte_count = HTT_VDEV_GET_STATS_U64(tag_buf);
tx_comp.bytes += byte_count;
/* Extract tx retry packet count from buffer */
tag_buf = tlv_buf_temp +
HTT_VDEV_STATS_GET_INDEX(TX_RETRY_PKT_CNT);
pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
tx_comp.num += pkt_count;
tx_failed.num += pkt_count;
/* Extract tx retry packet byte count from buffer */
tag_buf = tlv_buf_temp +
HTT_VDEV_STATS_GET_INDEX(TX_RETRY_BYTE_CNT);
pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
tx_comp.bytes += byte_count;
tx_failed.bytes += byte_count;
/* Extract tx drop packet count from buffer */
tag_buf = tlv_buf_temp +
HTT_VDEV_STATS_GET_INDEX(TX_DROP_PKT_CNT);
pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
tx_comp.num += pkt_count;
tx_failed.num += pkt_count;
/* Extract tx drop packet byte count from buffer */
tag_buf = tlv_buf_temp +
HTT_VDEV_STATS_GET_INDEX(TX_DROP_BYTE_CNT);
pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
tx_comp.bytes += byte_count;
tx_failed.bytes += byte_count;
/* Extract tx age-out packet count from buffer */
tag_buf = tlv_buf_temp +
HTT_VDEV_STATS_GET_INDEX(TX_AGE_OUT_PKT_CNT);
pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
tx_comp.num += pkt_count;
tx_failed.num += pkt_count;
/* Extract tx age-out packet byte count from buffer */
tag_buf = tlv_buf_temp +
HTT_VDEV_STATS_GET_INDEX(TX_AGE_OUT_BYTE_CNT);
pkt_count = HTT_VDEV_GET_STATS_U64(tag_buf);
tx_comp.bytes += byte_count;
tx_failed.bytes += byte_count;
DP_STATS_UPD(vdev, tx.comp_pkt.num, tx_comp.num);
DP_STATS_UPD(vdev, tx.comp_pkt.bytes, tx_comp.bytes);
DP_STATS_UPD(vdev, tx.tx_failed, tx_failed.num);
dp_vdev_unref_delete(dpsoc, vdev, DP_MOD_ID_HTT);
break;
}
default:
qdf_assert(0);
}
invalid_vdev:
msg_word = (uint32_t *)((uint8_t *)tlv_buf + tlv_length);
payload_size -= tlv_length;
}
}
#else
static void dp_vdev_txrx_hw_stats_handler(struct htt_soc *soc,
uint32_t *msg_word)
{}
#endif
/*
* time_allow_print() - time allow print
* @htt_ring_tt: ringi_id array of timestamps
@@ -3052,6 +3222,11 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
dp_rx_mlo_timestamp_ind_handler(soc->dp_soc, msg_word);
break;
}
case HTT_T2H_MSG_TYPE_VDEVS_TXRX_STATS_PERIODIC_IND:
{
dp_vdev_txrx_hw_stats_handler(soc, msg_word);
break;
}
default:
break;
};
@@ -3385,6 +3560,125 @@ QDF_STATUS dp_h2t_ext_stats_msg_send(struct dp_pdev *pdev,
return status;
}
#ifdef QCA_VDEV_STATS_HW_OFFLOAD_SUPPORT
#define HTT_VDEV_TXRX_STATS_RESET_BITMASK_L32_MASK 0xFFFFFFFF
#define HTT_VDEV_TXRX_STATS_RESET_BITMASK_U32_MASK 0xFFFFFFFF00000000
#define HTT_VDEV_TXRX_STATS_RESET_BITMASK_U32_SHIFT 32
QDF_STATUS dp_h2t_hw_vdev_stats_config_send(struct dp_soc *dpsoc,
uint8_t pdev_id, bool enable,
bool reset, uint64_t reset_bitmask)
{
struct htt_soc *soc = dpsoc->htt_handle;
struct dp_htt_htc_pkt *pkt;
qdf_nbuf_t msg;
uint32_t *msg_word;
uint8_t *htt_logger_bufp;
QDF_STATUS status;
int duration;
uint32_t bitmask;
int target_pdev_id;
msg = qdf_nbuf_alloc(
soc->osdev,
HTT_MSG_BUF_SIZE(sizeof(struct htt_h2t_vdevs_txrx_stats_cfg)),
HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, true);
if (!msg) {
dp_htt_err("%pK: Fail to allocate "
"HTT_H2T_HW_VDEV_TXRX_STATS_CFG_MSG_SZ msg buffer", dpsoc);
return QDF_STATUS_E_NOMEM;
}
if (pdev_id != INVALID_PDEV_ID)
target_pdev_id = DP_SW2HW_MACID(pdev_id);
else
target_pdev_id = 0;
duration =
wlan_cfg_get_vdev_stats_hw_offload_timer(dpsoc->wlan_cfg_ctx);
/*
* 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,
sizeof(struct htt_h2t_vdevs_txrx_stats_cfg))) {
dp_htt_err("%pK: Failed to expand head for HTT_HW_VDEV_STATS"
, dpsoc);
qdf_nbuf_free(msg);
return QDF_STATUS_E_FAILURE;
}
msg_word = (uint32_t *)qdf_nbuf_data(msg);
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_VDEVS_TXRX_STATS_CFG);
HTT_RX_VDEVS_TXRX_STATS_PDEV_ID_SET(*msg_word, target_pdev_id);
HTT_RX_VDEVS_TXRX_STATS_ENABLE_SET(*msg_word, enable);
HTT_RX_VDEVS_TXRX_STATS_PERIODIC_INTERVAL_SET(*msg_word,
(duration >> 3));
HTT_RX_VDEVS_TXRX_STATS_RESET_STATS_BITS_SET(*msg_word, reset);
msg_word++;
*msg_word = 0;
bitmask = (reset_bitmask & HTT_VDEV_TXRX_STATS_RESET_BITMASK_L32_MASK);
*msg_word = bitmask;
msg_word++;
*msg_word = 0;
bitmask =
((reset_bitmask & HTT_VDEV_TXRX_STATS_RESET_BITMASK_U32_MASK) >>
HTT_VDEV_TXRX_STATS_RESET_BITMASK_U32_SHIFT);
*msg_word = bitmask;
pkt = htt_htc_pkt_alloc(soc);
if (!pkt) {
dp_htt_err("%pK: Fail to allocate dp_htt_htc_pkt buffer",
dpsoc);
qdf_assert(0);
qdf_nbuf_free(msg);
return QDF_STATUS_E_NOMEM;
}
pkt->soc_ctxt = NULL; /* not used during send-done callback */
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,
/* tag for no FW response msg */
HTC_TX_PACKET_TAG_RUNTIME_PUT);
SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
status = DP_HTT_SEND_HTC_PKT(soc, pkt,
HTT_H2T_MSG_TYPE_VDEVS_TXRX_STATS_CFG,
htt_logger_bufp);
if (status != QDF_STATUS_SUCCESS) {
qdf_nbuf_free(msg);
htt_htc_pkt_free(soc, pkt);
}
return status;
}
#else
QDF_STATUS dp_h2t_hw_vdev_stats_config_send(struct dp_soc *dpsoc,
uint8_t pdev_id, bool enable,
bool reset, uint64_t reset_bitmask)
{
return QDF_STATUS_SUCCESS;
}
#endif
/**
* dp_h2t_3tuple_config_send(): function to contruct 3 tuple configuration
* HTT message to pass to FW