msm: ipa: Add NTN3 debug stats support

Add debugfs support for NTN3 stats.
Collect stats from uC add print from debugfs.

Change-Id: Iaf31beedb7403ee924a170f3b6c45ce0b78b7680
Signed-off-by: Amir Levy <alevy@codeaurora.org>
This commit is contained in:
Amir Levy
2021-02-25 10:53:19 +02:00
vanhempi 9115a93389
commit 4d4a72f1da
9 muutettua tiedostoa jossa 236 lisäystä ja 74 poistoa

Näytä tiedosto

@@ -4928,25 +4928,81 @@ int gsi_get_refetch_reg(unsigned long chan_hdl, bool is_rp)
}
EXPORT_SYMBOL(gsi_get_refetch_reg);
int gsi_get_drop_stats(unsigned long ep_id, int scratch_id)
int gsi_get_drop_stats(unsigned long ep_id, int scratch_id,
unsigned long chan_hdl)
{
/* RTK use scratch 5 */
if (scratch_id == 5) {
/*
* each channel context is 6 lines of 8 bytes, but n in SHRAM_n
* is in 4 bytes offsets, so multiplying ep_id by 6*2=12 will
* give the beginning of the required channel context, and then
* need to add 7 since the channel context layout has the ring
* rbase (8 bytes) + channel scratch 0-4 (20 bytes) so adding
* additional 28/4 = 7 to get to scratch 5 of the required
* channel.
*/
gsihal_read_reg_n(GSI_GSI_SHRAM_n, ep_id * 12 + 7);
#define GSI_RTK_ERR_STATS_MASK 0xFFFF
#define GSI_NTN_ERR_STATS_MASK 0xFFFFFFFF
#define GSI_AQC_RX_STATUS_MASK 0x1FFF
#define GSI_AQC_RX_STATUS_SHIFT 0
#define GSI_AQC_RDM_ERR_MASK 0x1FFF0000
#define GSI_AQC_RDM_ERR_SHIFT 16
uint16_t rx_status;
uint16_t rdm_err;
uint32_t val;
/* on newer versions we can read the ch scratch directly from reg */
if (gsi_ctx->per.ver >= GSI_VER_3_0) {
switch (scratch_id) {
case 5:
return gsihal_read_reg_nk(
GSI_EE_n_GSI_CH_k_SCRATCH_5,
gsi_ctx->per.ee,
chan_hdl) & GSI_RTK_ERR_STATS_MASK;
break;
case 6:
return gsihal_read_reg_nk(
GSI_EE_n_GSI_CH_k_SCRATCH_6,
gsi_ctx->per.ee,
chan_hdl) & GSI_NTN_ERR_STATS_MASK;
break;
case 7:
val = gsihal_read_reg_nk(
GSI_EE_n_GSI_CH_k_SCRATCH_7,
gsi_ctx->per.ee,
chan_hdl);
rx_status = (val & GSI_AQC_RX_STATUS_MASK)
>> GSI_AQC_RX_STATUS_SHIFT;
rdm_err = (val & GSI_AQC_RDM_ERR_MASK)
>> (GSI_AQC_RDM_ERR_SHIFT);
return rx_status + rdm_err;
break;
default:
GSIERR("invalid scratch id %d\n", scratch_id);
return 0;
}
/* on older versions we need to read the scratch from SHRAM */
} else {
/* RTK use scratch 5 */
if (scratch_id == 5) {
/*
* each channel context is 6 lines of 8 bytes, but n in
* SHRAM_n is in 4 bytes offsets, so multiplying ep_id
* by 6*2=12 will give the beginning of the required
* channel context, and then need to add 7 since the
* channel context layout has the ring rbase (8 bytes)
* + channel scratch 0-4 (20 bytes) so adding
* additional 28/4 = 7 to get to scratch 5 of the
* required channel.
*/
return gsihal_read_reg_n(
GSI_GSI_SHRAM_n,
ep_id * 12 + 7) & GSI_RTK_ERR_STATS_MASK;
}
}
return 0;
}
EXPORT_SYMBOL(gsi_get_drop_stats);
int gsi_get_wp(unsigned long chan_hdl)
{
return gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_CNTXT_6, gsi_ctx->per.ee,
chan_hdl);
}
EXPORT_SYMBOL(gsi_get_wp);
void gsi_wdi3_dump_register(unsigned long chan_hdl)
{
uint32_t val;

Näytä tiedosto

@@ -2233,8 +2233,17 @@ int gsi_get_refetch_reg(unsigned long chan_hdl, bool is_rp);
*
* @ep_id: ep index
* @scratch_id: drop stats on which scratch register
* @chan_hdl: gsi channel handle
*/
int gsi_get_drop_stats(unsigned long ep_id, int scratch_id);
int gsi_get_drop_stats(unsigned long ep_id, int scratch_id,
unsigned long chan_hdl);
/**
* gsi_get_wp - get channel write pointer for stats
*
* @chan_hdl: gsi channel handle
*/
int gsi_get_wp(unsigned long chan_hdl);
/**
* gsi_wdi3_dump_register - dump wdi3 related gsi registers

Näytä tiedosto

@@ -2014,6 +2014,32 @@ int ipa3_clear_endpoint_delay(u32 clnt_hdl)
return 0;
}
static void ipa3_get_gsi_ring_stats(struct IpaHwRingStats_t *ring,
struct ipa3_uc_dbg_stats *ctx_stats, int idx)
{
ring->ringFull = ioread32(
ctx_stats->uc_dbg_stats_mmio
+ idx * IPA3_UC_DEBUG_STATS_OFF +
IPA3_UC_DEBUG_STATS_RINGFULL_OFF);
ring->ringEmpty = ioread32(
ctx_stats->uc_dbg_stats_mmio
+ idx * IPA3_UC_DEBUG_STATS_OFF +
IPA3_UC_DEBUG_STATS_RINGEMPTY_OFF);
ring->ringUsageHigh = ioread32(
ctx_stats->uc_dbg_stats_mmio
+ idx * IPA3_UC_DEBUG_STATS_OFF +
IPA3_UC_DEBUG_STATS_RINGUSAGEHIGH_OFF);
ring->ringUsageLow = ioread32(
ctx_stats->uc_dbg_stats_mmio
+ idx * IPA3_UC_DEBUG_STATS_OFF +
IPA3_UC_DEBUG_STATS_RINGUSAGELOW_OFF);
ring->RingUtilCount = ioread32(
ctx_stats->uc_dbg_stats_mmio
+ idx * IPA3_UC_DEBUG_STATS_OFF +
IPA3_UC_DEBUG_STATS_RINGUTILCOUNT_OFF);
}
/**
* ipa3_get_aqc_gsi_stats() - Query AQC gsi stats from uc
* @stats: [inout] stats blob from client populated by driver
@@ -2033,32 +2059,43 @@ int ipa3_get_aqc_gsi_stats(struct ipa_uc_dbg_ring_stats *stats)
}
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
for (i = 0; i < MAX_AQC_CHANNELS; i++) {
stats->u.ring[i].ringFull = ioread32(
ipa3_ctx->aqc_ctx.dbg_stats.uc_dbg_stats_mmio
+ i * IPA3_UC_DEBUG_STATS_OFF +
IPA3_UC_DEBUG_STATS_RINGFULL_OFF);
stats->u.ring[i].ringEmpty = ioread32(
ipa3_ctx->aqc_ctx.dbg_stats.uc_dbg_stats_mmio
+ i * IPA3_UC_DEBUG_STATS_OFF +
IPA3_UC_DEBUG_STATS_RINGEMPTY_OFF);
stats->u.ring[i].ringUsageHigh = ioread32(
ipa3_ctx->aqc_ctx.dbg_stats.uc_dbg_stats_mmio
+ i * IPA3_UC_DEBUG_STATS_OFF +
IPA3_UC_DEBUG_STATS_RINGUSAGEHIGH_OFF);
stats->u.ring[i].ringUsageLow = ioread32(
ipa3_ctx->aqc_ctx.dbg_stats.uc_dbg_stats_mmio
+ i * IPA3_UC_DEBUG_STATS_OFF +
IPA3_UC_DEBUG_STATS_RINGUSAGELOW_OFF);
stats->u.ring[i].RingUtilCount = ioread32(
ipa3_ctx->aqc_ctx.dbg_stats.uc_dbg_stats_mmio
+ i * IPA3_UC_DEBUG_STATS_OFF +
IPA3_UC_DEBUG_STATS_RINGUTILCOUNT_OFF);
ipa3_get_gsi_ring_stats(stats->u.ring + i,
&ipa3_ctx->aqc_ctx.dbg_stats, i);
}
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
return 0;
}
/**
* ipa3_get_ntn_gsi_stats() - Query NTN gsi stats from uc
* @stats: [inout] stats blob from client populated by driver
*
* Returns: 0 on success, negative on failure
*
* @note Cannot be called from atomic context
*
*/
int ipa3_get_ntn_gsi_stats(struct ipa_uc_dbg_ring_stats *stats)
{
int i;
if (!ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_mmio) {
IPAERR("bad parms NULL ntn_gsi_stats_mmio\n");
return -EINVAL;
}
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
for (i = 0; i < MAX_NTN_CHANNELS; i++) {
ipa3_get_gsi_ring_stats(stats->u.ring + i,
&ipa3_ctx->ntn_ctx.dbg_stats, i);
}
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
return 0;
}
/**
* ipa3_get_rtk_gsi_stats() - Query RTK gsi stats from uc
* @stats: [inout] stats blob from client populated by driver
@@ -2079,26 +2116,8 @@ int ipa3_get_rtk_gsi_stats(struct ipa_uc_dbg_ring_stats *stats)
}
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
for (i = 0; i < MAX_RTK_CHANNELS; i++) {
stats->u.rtk[i].commStats.ringFull = ioread32(
ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio
+ i * IPA3_UC_DEBUG_STATS_RTK_OFF +
IPA3_UC_DEBUG_STATS_RINGFULL_OFF);
stats->u.rtk[i].commStats.ringEmpty = ioread32(
ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio
+ i * IPA3_UC_DEBUG_STATS_RTK_OFF +
IPA3_UC_DEBUG_STATS_RINGEMPTY_OFF);
stats->u.rtk[i].commStats.ringUsageHigh = ioread32(
ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio
+ i * IPA3_UC_DEBUG_STATS_RTK_OFF +
IPA3_UC_DEBUG_STATS_RINGUSAGEHIGH_OFF);
stats->u.rtk[i].commStats.ringUsageLow = ioread32(
ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio
+ i * IPA3_UC_DEBUG_STATS_RTK_OFF +
IPA3_UC_DEBUG_STATS_RINGUSAGELOW_OFF);
stats->u.rtk[i].commStats.RingUtilCount = ioread32(
ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio
+ i * IPA3_UC_DEBUG_STATS_RTK_OFF +
IPA3_UC_DEBUG_STATS_RINGUTILCOUNT_OFF);
ipa3_get_gsi_ring_stats(&stats->u.rtk[i].commStats,
&ipa3_ctx->rtk_ctx.dbg_stats, i);
stats->u.rtk[i].trCount = ioread32(
ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio
+ i * IPA3_UC_DEBUG_STATS_RTK_OFF +

Näytä tiedosto

@@ -3216,9 +3216,16 @@ static ssize_t ipa3_eth_read_perf_status(struct file *file,
switch (client->client_type) {
case IPA_ETH_CLIENT_AQC107:
case IPA_ETH_CLIENT_AQC113:
ret = ipa3_get_aqc_gsi_stats(&stats);
tx_ep = IPA_CLIENT_AQC_ETHERNET_CONS;
rx_ep = IPA_CLIENT_AQC_ETHERNET_PROD;
case IPA_ETH_CLIENT_NTN:
if (client->client_type == IPA_ETH_CLIENT_NTN) {
ret = ipa3_get_ntn_gsi_stats(&stats);
tx_ep = IPA_CLIENT_ETHERNET_CONS;
rx_ep = IPA_CLIENT_ETHERNET_PROD;
} else {
ret = ipa3_get_aqc_gsi_stats(&stats);
tx_ep = IPA_CLIENT_AQC_ETHERNET_CONS;
rx_ep = IPA_CLIENT_AQC_ETHERNET_PROD;
}
if (!ret) {
nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
"%s_ringFull=%u\n"
@@ -3258,7 +3265,9 @@ static ssize_t ipa3_eth_read_perf_status(struct file *file,
} else {
nbytes = scnprintf(dbg_buff,
IPA_MAX_MSG_LEN,
"Fail to read AQC GSI stats\n");
"Fail to read [%s][%s] GSI stats\n",
ipa_clients_strings[rx_ep],
ipa_clients_strings[tx_ep]);
cnt += nbytes;
}
break;
@@ -3329,7 +3338,7 @@ static ssize_t ipa3_eth_read_perf_status(struct file *file,
cnt += nbytes;
} else {
nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
"Fail to read AQC GSI stats\n");
"Fail to read RTK GSI stats\n");
cnt += nbytes;
}
break;
@@ -3350,6 +3359,7 @@ static ssize_t ipa3_eth_read_err_status(struct file *file,
int tx_ep, rx_ep;
struct ipa3_eth_error_stats tx_stats;
struct ipa3_eth_error_stats rx_stats;
int scratch_num;
memset(&tx_stats, 0, sizeof(struct ipa3_eth_error_stats));
memset(&rx_stats, 0, sizeof(struct ipa3_eth_error_stats));
@@ -3368,42 +3378,45 @@ static ssize_t ipa3_eth_read_err_status(struct file *file,
case IPA_ETH_CLIENT_AQC113:
tx_ep = IPA_CLIENT_AQC_ETHERNET_CONS;
rx_ep = IPA_CLIENT_AQC_ETHERNET_PROD;
break;
scratch_num = 7;
case IPA_ETH_CLIENT_RTK8111K:
case IPA_ETH_CLIENT_RTK8125B:
tx_ep = IPA_CLIENT_RTK_ETHERNET_CONS;
rx_ep = IPA_CLIENT_RTK_ETHERNET_PROD;
ipa3_eth_get_status(tx_ep, 5, &tx_stats);
ipa3_eth_get_status(rx_ep, 5, &rx_stats);
scratch_num = 5;
break;
case IPA_ETH_CLIENT_NTN:
tx_ep = IPA_CLIENT_ETHERNET_CONS;
rx_ep = IPA_CLIENT_ETHERNET_PROD;
scratch_num = 6;
default:
IPAERR("Not supported\n");
return 0;
}
ipa3_eth_get_status(tx_ep, scratch_num, &tx_stats);
ipa3_eth_get_status(rx_ep, scratch_num, &rx_stats);
nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
"%s_RP=0x%x\n"
"%s_WP=0x%x\n"
"%s_SCRATCH5=0x%x\n",
"%s_err:%u (scratch %d)\n",
ipa_clients_strings[tx_ep],
tx_stats.rp,
ipa_clients_strings[tx_ep],
tx_stats.wp,
ipa_clients_strings[tx_ep],
tx_stats.err);
tx_stats.err, scratch_num);
cnt += nbytes;
nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN - cnt,
"%s_RP=0x%x\n"
"%s_WP=0x%x\n"
"%s_SCRATCH5=0x%x\n"
"%s_err:%u\n",
"%s_err:%u (scratch %d)\n",
ipa_clients_strings[rx_ep],
rx_stats.rp,
ipa_clients_strings[rx_ep],
rx_stats.wp,
ipa_clients_strings[rx_ep],
rx_stats.err,
ipa_clients_strings[rx_ep],
rx_stats.err & 0xff);
rx_stats.err, scratch_num);
cnt += nbytes;
done:
return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);

Näytä tiedosto

@@ -915,7 +915,7 @@ int ipa3_eth_connect(
return -EINVAL;
}
if ((pipe->client_info->client_type == IPA_ETH_CLIENT_NTN)) {
if (pipe->client_info->client_type == IPA_ETH_CLIENT_NTN) {
if (pipe->info.fix_buffer_size != NTN_BUFFER_SIZE) {
IPAERR("fix buffer size %u not valid for NTN, use 2K\n"
, pipe->info.fix_buffer_size);

Näytä tiedosto

@@ -1710,6 +1710,13 @@ struct ipa3_rtk_ctx {
struct ipa3_uc_dbg_stats dbg_stats;
};
/**
* struct ipa3_ntn_ctx - IPA ntn context
*/
struct ipa3_ntn_ctx {
struct ipa3_uc_dbg_stats dbg_stats;
};
/**
* struct ipa3_transport_pm - transport power management related members
* @transport_pm_mutex: Mutex to protect the transport_pm functionality.
@@ -2180,6 +2187,7 @@ struct ipa3_context {
struct ipa3_mhip_ctx mhip_ctx;
struct ipa3_aqc_ctx aqc_ctx;
struct ipa3_rtk_ctx rtk_ctx;
struct ipa3_ntn_ctx ntn_ctx;
atomic_t ipa_clk_vote;
int (*client_lock_unlock[IPA_MAX_CLNT])(bool is_lock);
@@ -2789,6 +2797,7 @@ int ipa3_get_wdi3_gsi_stats(struct ipa_uc_dbg_ring_stats *stats);
int ipa3_get_usb_gsi_stats(struct ipa_uc_dbg_ring_stats *stats);
int ipa3_get_aqc_gsi_stats(struct ipa_uc_dbg_ring_stats *stats);
int ipa3_get_rtk_gsi_stats(struct ipa_uc_dbg_ring_stats *stats);
int ipa3_get_ntn_gsi_stats(struct ipa_uc_dbg_ring_stats *stats);
int ipa3_get_wdi_stats(struct IpaHwStatsWDIInfoData_t *stats);
u16 ipa3_get_smem_restr_bytes(void);
int ipa3_broadcast_wdi_quota_reach_ind(uint32_t fid, uint64_t num_bytes);

Näytä tiedosto

@@ -440,6 +440,17 @@ static void ipa3_uc_save_dbg_stats(u32 size)
} else
goto unmap;
break;
case IPA_HW_PROTOCOL_NTN3:
if (!ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_mmio) {
ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_size =
size;
ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_ofst =
addr_offset;
ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_mmio =
mmio;
} else
goto unmap;
break;
case IPA_HW_PROTOCOL_WDI:
if (!ipa3_ctx->wdi2_ctx.dbg_stats.uc_dbg_stats_mmio) {
ipa3_ctx->wdi2_ctx.dbg_stats.uc_dbg_stats_size =
@@ -1627,6 +1638,10 @@ int ipa3_uc_debug_stats_dealloc(uint32_t prot_id)
iounmap(ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio);
ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio = NULL;
break;
case IPA_HW_PROTOCOL_NTN3:
iounmap(ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_mmio);
ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_mmio = NULL;
break;
case IPA_HW_PROTOCOL_WDI:
iounmap(ipa3_ctx->wdi2_ctx.dbg_stats.uc_dbg_stats_mmio);
ipa3_ctx->wdi2_ctx.dbg_stats.uc_dbg_stats_mmio = NULL;

Näytä tiedosto

@@ -25,6 +25,7 @@
#define MAX_AQC_CHANNELS 2
#define MAX_RTK_CHANNELS 2
#define MAX_NTN_CHANNELS 2
#define MAX_11AD_CHANNELS 5
#define MAX_WDI2_CHANNELS 2
#define MAX_WDI3_CHANNELS 3

Näytä tiedosto

@@ -11640,7 +11640,9 @@ void ipa3_get_gsi_stats(int prot_id,
stats->num_ch = MAX_WDI3_CHANNELS;
ipa3_get_wdi3_gsi_stats(stats);
break;
case IPA_HW_PROTOCOL_ETH:
case IPA_HW_PROTOCOL_NTN3:
stats->num_ch = MAX_NTN_CHANNELS;
ipa3_get_ntn_gsi_stats(stats);
break;
case IPA_HW_PROTOCOL_MHIP:
stats->num_ch = MAX_MHIP_CHANNELS;
@@ -11796,6 +11798,10 @@ int ipa3_get_prot_id(enum ipa_client_type client)
void ipa3_eth_get_status(u32 client, int scratch_id,
struct ipa3_eth_error_stats *stats)
{
#define RTK_GSI_SCRATCH_ID 5
#define AQC_GSI_SCRATCH_ID 7
#define NTN_GSI_SCRATCH_ID 6
int ch_id;
int ipa_ep_idx;
@@ -11804,9 +11810,43 @@ void ipa3_eth_get_status(u32 client, int scratch_id,
if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED)
return;
ch_id = ipa3_ctx->ep[ipa_ep_idx].gsi_chan_hdl;
stats->rp = gsi_get_refetch_reg(ch_id, true);
stats->wp = gsi_get_refetch_reg(ch_id, false);
stats->err = gsi_get_drop_stats(ipa_ep_idx, scratch_id);
/*
* drop stats sometimes exist for RX and sometimes for Tx,
* wp sometimes acquired from ch_cntxt_6 and sometimes from refetch,
* depending on protocol.
*/
stats->err = 0;
switch (client) {
case IPA_CLIENT_RTK_ETHERNET_PROD:
stats->err = gsi_get_drop_stats(ipa_ep_idx, RTK_GSI_SCRATCH_ID,
ch_id);
case IPA_CLIENT_RTK_ETHERNET_CONS:
stats->wp = gsi_get_refetch_reg(ch_id, false);
stats->rp = gsi_get_refetch_reg(ch_id, true);
break;
case IPA_CLIENT_AQC_ETHERNET_PROD:
stats->err = gsi_get_drop_stats(ipa_ep_idx, AQC_GSI_SCRATCH_ID,
ch_id);
stats->wp = gsi_get_wp(ch_id);
stats->rp = gsi_get_refetch_reg(ch_id, true);
break;
case IPA_CLIENT_AQC_ETHERNET_CONS:
stats->wp = gsi_get_refetch_reg(ch_id, false);
stats->rp = gsi_get_refetch_reg(ch_id, true);
break;
case IPA_CLIENT_ETHERNET_PROD:
stats->wp = gsi_get_wp(ch_id);
stats->rp = gsi_get_refetch_reg(ch_id, true);
break;
case IPA_CLIENT_ETHERNET_CONS:
stats->err = gsi_get_drop_stats(ipa_ep_idx, NTN_GSI_SCRATCH_ID,
ch_id);
stats->wp = gsi_get_refetch_reg(ch_id, false);
stats->rp = gsi_get_refetch_reg(ch_id, true);
break;
}
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
}