b/drivers/irqchip/irq-gic-v3-its.c
@@ -111,6 +111,9 @@ struct its_node {
u32 pre_its_base; /* for Socionext Synquacer */
bool is_v4;
int vlpi_redist_offset;
+ int last_rd;
+ u64 cmd_wrapped_cnt;
+ u64 rd_wrapped_cnt;
};
#define ITS_ITT_ALIGN SZ_256
@@ -662,6 +665,7 @@ static int its_queue_full(struct its_node *its)
static struct its_cmd_block *its_allocate_entry(struct its_node *its)
{
+ u32 rd;
struct its_cmd_block *cmd;
u32 count = 1000000; /* 1s! */
@@ -675,11 +679,24 @@ static struct its_cmd_block
*its_allocate_entry(struct its_node *its)
udelay(1);
}
+ /*
+ * Here is protected by its->lock and driver cannot allocate
+ * ITS commands, if ITS command queue is full, so the read
+ * won't wrap twice between this rd_idx and last rd_idx.
+ * Count rd wrapped times here is safe.
+ */
+ rd = readl_relaxed(its->base + GITS_CREADR);
+ if (rd < its->last_rd)
+ its->rd_wrapped_cnt++;
+ its->last_rd = rd;
+
cmd = its->cmd_write++;
/* Handle queue wrapping */
- if (its->cmd_write == (its->cmd_base + ITS_CMD_QUEUE_NR_ENTRIES))
+ if (its->cmd_write == (its->cmd_base + ITS_CMD_QUEUE_NR_ENTRIES)) {
its->cmd_write = its->cmd_base;
+ its->cmd_wrapped_cnt++;
+ }
/* Clear command */