msm: gsi: cache last 20 gsi interrupt for interrupt storm debug

GSI interrupt storm can happen due to un-clocked gsi isr.
If we enable clock and assert, there is a chance the gsi isr will
be already handled.
To debug it further, the change is to cache last 20 gsi isr with
timestamp.

Change-Id: I30be03a20df9f11be7f5d8c06b049591305940bb
Signed-off-by: Bojun Pan <bojunp@codeaurora.org>
This commit is contained in:
Bojun Pan 2020-02-07 14:00:06 -08:00
commit a2f95e6aab
2 changed files with 27 additions and 0 deletions

View file

@ -15,6 +15,13 @@
#include "gsi_reg.h"
#include "gsi_emulation.h"
#include <asm/arch_timer.h>
#include <linux/sched/clock.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/delay.h>
#define GSI_CMD_TIMEOUT (5*HZ)
#define GSI_START_CMD_TIMEOUT_MS 1000
#define GSI_CMD_POLL_CNT 5
@ -776,6 +783,7 @@ static void gsi_handle_irq(void)
uint32_t type;
int ee = gsi_ctx->per.ee;
unsigned long cnt = 0;
int index;
while (1) {
if (!gsi_ctx->per.clk_status_cb())
@ -787,6 +795,15 @@ static void gsi_handle_irq(void)
break;
GSIDBG_LOW("type 0x%x\n", type);
index = gsi_ctx->gsi_isr_cache_index;
gsi_ctx->gsi_isr_cache[index].timestamp =
sched_clock();
gsi_ctx->gsi_isr_cache[index].qtimer =
__arch_counter_get_cntvct();
gsi_ctx->gsi_isr_cache[index].interrupt_type = type;
gsi_ctx->gsi_isr_cache_index++;
if (gsi_ctx->gsi_isr_cache_index == GSI_ISR_CACHE_MAX)
gsi_ctx->gsi_isr_cache_index = 0;
if (type & GSI_EE_n_CNTXT_TYPE_IRQ_CH_CTRL_BMSK)
gsi_handle_ch_ctrl(ee);
@ -1348,6 +1365,7 @@ int gsi_register_device(struct gsi_per_props *props, unsigned long *dev_hdl)
}
*dev_hdl = (uintptr_t)gsi_ctx;
gsi_ctx->gsi_isr_cache_index = 0;
return GSI_STATUS_SUCCESS;
}

View file

@ -28,6 +28,7 @@
#define GSI_CHAN_MAX 31
#define GSI_EVT_RING_MAX 24
#define GSI_NO_EVT_ERINDEX 31
#define GSI_ISR_CACHE_MAX 20
#define gsi_readl(c) (readl_relaxed(c))
#define gsi_writel(v, c) ({ __iowmb(); writel_relaxed((v), (c)); })
@ -206,6 +207,12 @@ struct gsi_coal_chan_info {
uint8_t evchid;
};
struct gsi_log_ts {
u64 timestamp;
u64 qtimer;
u32 interrupt_type;
};
struct gsi_ctx {
void __iomem *base;
struct device *dev;
@ -237,6 +244,8 @@ struct gsi_ctx {
u32 intcntrlr_mem_size;
irq_handler_t intcntrlr_gsi_isr;
irq_handler_t intcntrlr_client_isr;
struct gsi_log_ts gsi_isr_cache[GSI_ISR_CACHE_MAX];
int gsi_isr_cache_index;
atomic_t num_unclock_irq;
};