qcacmn: Add support to log ce hang event info

Add hif APIs to support logging of ce hang event
data.

Change-Id: I9b930d5f983d57a7359ba9f97ea65050c4f54a8a
CRs-Fixed: 2649148
This commit is contained in:
Yeshwanth Sriram Guntuka
2020-03-25 23:15:13 +05:30
committed by nshrivas
parent f5067f066b
commit d3db10ec5b
6 changed files with 198 additions and 2 deletions

View File

@@ -1351,4 +1351,23 @@ void hif_srng_init_phase(struct hif_opaque_softc *hif_ctx,
{ {
} }
#endif /* FORCE_WAKE */ #endif /* FORCE_WAKE */
#ifdef HIF_CE_LOG_INFO
/**
* hif_log_ce_info() - API to log ce info
* @hif_ctx: hif opaque handle
* @data: hang event data buffer
* @offset: offset at which data needs to be written
*
* Return: None
*/
void hif_log_ce_info(struct hif_opaque_softc *hif_ctx, uint8_t *data,
unsigned int *offset);
#else
static inline
void hif_log_ce_info(struct hif_opaque_softc *hif_ctx, uint8_t *data,
unsigned int *offset)
{
}
#endif
#endif /* _HIF_H_ */ #endif /* _HIF_H_ */

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -546,6 +546,8 @@ struct ce_ops {
void (*ce_prepare_shadow_register_v2_cfg)(struct hif_softc *scn, void (*ce_prepare_shadow_register_v2_cfg)(struct hif_softc *scn,
struct pld_shadow_reg_v2_cfg **shadow_config, struct pld_shadow_reg_v2_cfg **shadow_config,
int *num_shadow_registers_configured); int *num_shadow_registers_configured);
int (*ce_get_index_info)(struct hif_softc *scn, void *ce_state,
struct ce_index *info);
}; };
int hif_ce_bus_early_suspend(struct hif_softc *scn); int hif_ce_bus_early_suspend(struct hif_softc *scn);

View File

@@ -48,6 +48,9 @@
#define PCIE_ACCESS_DUMP 4 #define PCIE_ACCESS_DUMP 4
#endif #endif
#include "mp_dev.h" #include "mp_dev.h"
#ifdef HIF_CE_LOG_INFO
#include "qdf_hang_event_notifier.h"
#endif
#if (defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6290) || \ #if (defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6290) || \
defined(QCA_WIFI_QCA6018) || defined(QCA_WIFI_QCA5018)) && \ defined(QCA_WIFI_QCA6018) || defined(QCA_WIFI_QCA5018)) && \
@@ -4197,3 +4200,59 @@ int hif_get_wake_ce_id(struct hif_softc *scn, uint8_t *ce_id)
return 0; return 0;
} }
#ifdef HIF_CE_LOG_INFO
/**
* ce_get_index_info(): Get CE index info
* @scn: HIF Context
* @ce_state: CE opaque handle
* @info: CE info
*
* Return: 0 for success and non zero for failure
*/
static
int ce_get_index_info(struct hif_softc *scn, void *ce_state,
struct ce_index *info)
{
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
return hif_state->ce_services->ce_get_index_info(scn, ce_state, info);
}
void hif_log_ce_info(struct hif_opaque_softc *hif_ctx, uint8_t *data,
unsigned int *offset)
{
struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
struct hang_event_info info = {0};
static uint32_t tracked_ce = BIT(CE_ID_1) | BIT(CE_ID_2) |
BIT(CE_ID_3) | BIT(CE_ID_4) | BIT(CE_ID_9) | BIT(CE_ID_10);
uint8_t curr_index = 0;
uint8_t i;
uint16_t size;
info.active_tasklet_count = qdf_atomic_read(&scn->active_tasklet_cnt);
info.active_grp_tasklet_cnt =
qdf_atomic_read(&scn->active_grp_tasklet_cnt);
for (i = 0; i < scn->ce_count; i++) {
if (!(tracked_ce & BIT(i)) || !scn->ce_id_to_state[i])
continue;
if (ce_get_index_info(scn, scn->ce_id_to_state[i],
&info.ce_info[curr_index]))
continue;
curr_index++;
}
info.ce_count = curr_index;
size = sizeof(info) -
(CE_COUNT_MAX - info.ce_count) * sizeof(struct ce_index);
QDF_HANG_EVT_SET_HDR(&info.tlv_header, HANG_EVT_TAG_CE_INFO,
size - QDF_HANG_EVENT_TLV_HDR_SIZE);
qdf_mem_copy(data + *offset, &info, size);
*offset = *offset + size;
}
#endif

View File

@@ -265,6 +265,49 @@ struct ce_info {
#endif #endif
#endif #endif
/**
* struct ce_index
*
* @id: CE id
* @sw_index: sw index
* @write_index: write index
* @hp: ring head pointer
* @tp: ring tail pointer
* @status_hp: status ring head pointer
* @status_tp: status ring tail pointer
*/
struct ce_index {
uint8_t id;
union {
struct {
uint16_t sw_index;
uint16_t write_index;
} legacy_info;
struct {
uint16_t hp;
uint16_t tp;
uint16_t status_hp;
uint16_t status_tp;
} srng_info;
} u;
} qdf_packed;
/**
* struct hang_event_info
*
* @tlv_header: tlv header
* @active_tasklet_count: active tasklet count
* @active_grp_tasklet_cnt: active grp tasklet count
* @ce_info: CE info
*/
struct hang_event_info {
uint32_t tlv_header;
uint8_t active_tasklet_count;
uint8_t active_grp_tasklet_cnt;
uint8_t ce_count;
struct ce_index ce_info[CE_COUNT_MAX];
} qdf_packed;
void hif_ce_stop(struct hif_softc *scn); void hif_ce_stop(struct hif_softc *scn);
int hif_dump_ce_registers(struct hif_softc *scn); int hif_dump_ce_registers(struct hif_softc *scn);
void void

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -1266,6 +1266,34 @@ static bool ce_check_int_watermark(struct CE_state *CE_state,
return false; return false;
} }
#ifdef HIF_CE_LOG_INFO
/**
* ce_get_index_info_legacy(): Get CE index info
* @scn: HIF Context
* @ce_state: CE opaque handle
* @info: CE info
*
* Return: 0 for success and non zero for failure
*/
static
int ce_get_index_info_legacy(struct hif_softc *scn, void *ce_state,
struct ce_index *info)
{
struct CE_state *state = (struct CE_state *)ce_state;
info->id = state->id;
if (state->src_ring) {
info->u.legacy_info.sw_index = state->src_ring->sw_index;
info->u.legacy_info.write_index = state->src_ring->write_index;
} else if (state->dest_ring) {
info->u.legacy_info.sw_index = state->dest_ring->sw_index;
info->u.legacy_info.write_index = state->dest_ring->write_index;
}
return 0;
}
#endif
struct ce_ops ce_service_legacy = { struct ce_ops ce_service_legacy = {
.ce_get_desc_size = ce_get_desc_size_legacy, .ce_get_desc_size = ce_get_desc_size_legacy,
.ce_ring_setup = ce_ring_setup_legacy, .ce_ring_setup = ce_ring_setup_legacy,
@@ -1282,6 +1310,10 @@ struct ce_ops ce_service_legacy = {
.ce_send_entries_done_nolock = ce_send_entries_done_nolock_legacy, .ce_send_entries_done_nolock = ce_send_entries_done_nolock_legacy,
.ce_prepare_shadow_register_v2_cfg = .ce_prepare_shadow_register_v2_cfg =
ce_prepare_shadow_register_v2_cfg_legacy, ce_prepare_shadow_register_v2_cfg_legacy,
#ifdef HIF_CE_LOG_INFO
.ce_get_index_info =
ce_get_index_info_legacy,
#endif
}; };
struct ce_ops *ce_services_legacy() struct ce_ops *ce_services_legacy()

View File

@@ -941,6 +941,43 @@ static void ce_prepare_shadow_register_v2_cfg_srng(struct hif_softc *scn,
num_shadow_registers_configured); num_shadow_registers_configured);
} }
#ifdef HIF_CE_LOG_INFO
/**
* ce_get_index_info_srng(): Get CE index info
* @scn: HIF Context
* @ce_state: CE opaque handle
* @info: CE info
*
* Return: 0 for success and non zero for failure
*/
static
int ce_get_index_info_srng(struct hif_softc *scn, void *ce_state,
struct ce_index *info)
{
struct CE_state *CE_state = (struct CE_state *)ce_state;
uint32_t tp, hp;
info->id = CE_state->id;
if (CE_state->src_ring) {
hal_get_sw_hptp(scn->hal_soc, CE_state->src_ring->srng_ctx,
&tp, &hp);
info->u.srng_info.tp = tp;
info->u.srng_info.hp = hp;
} else if (CE_state->dest_ring && CE_state->status_ring) {
hal_get_sw_hptp(scn->hal_soc, CE_state->status_ring->srng_ctx,
&tp, &hp);
info->u.srng_info.status_tp = tp;
info->u.srng_info.status_hp = hp;
hal_get_sw_hptp(scn->hal_soc, CE_state->dest_ring->srng_ctx,
&tp, &hp);
info->u.srng_info.tp = tp;
info->u.srng_info.hp = hp;
}
return 0;
}
#endif
static struct ce_ops ce_service_srng = { static struct ce_ops ce_service_srng = {
.ce_get_desc_size = ce_get_desc_size_srng, .ce_get_desc_size = ce_get_desc_size_srng,
.ce_ring_setup = ce_ring_setup_srng, .ce_ring_setup = ce_ring_setup_srng,
@@ -957,6 +994,10 @@ static struct ce_ops ce_service_srng = {
.ce_send_entries_done_nolock = ce_send_entries_done_nolock_srng, .ce_send_entries_done_nolock = ce_send_entries_done_nolock_srng,
.ce_prepare_shadow_register_v2_cfg = .ce_prepare_shadow_register_v2_cfg =
ce_prepare_shadow_register_v2_cfg_srng, ce_prepare_shadow_register_v2_cfg_srng,
#ifdef HIF_CE_LOG_INFO
.ce_get_index_info =
ce_get_index_info_srng,
#endif
}; };
struct ce_ops *ce_services_srng() struct ce_ops *ce_services_srng()