From: Chalapathi V <chalapath...@linux.ibm.com> There is a possibility that SPI controller can get into loop due to indefinite RDR match failures. Hence put a limit to failures and stop the sequencer.
Signed-off-by: Chalapathi V <chalapath...@linux.ibm.com> Reviewed-by: Nicholas Piggin <npig...@gmail.com> Message-ID: <20250303141328.23991-5-chalapath...@linux.ibm.com> Signed-off-by: Nicholas Piggin <npig...@gmail.com> --- hw/ssi/pnv_spi.c | 10 ++++++++++ include/hw/ssi/pnv_spi.h | 1 + 2 files changed, 11 insertions(+) diff --git a/hw/ssi/pnv_spi.c b/hw/ssi/pnv_spi.c index 83221607c9..126070393e 100644 --- a/hw/ssi/pnv_spi.c +++ b/hw/ssi/pnv_spi.c @@ -20,6 +20,7 @@ #define PNV_SPI_OPCODE_LO_NIBBLE(x) (x & 0x0F) #define PNV_SPI_MASKED_OPCODE(x) (x & 0xF0) #define PNV_SPI_FIFO_SIZE 16 +#define RDR_MATCH_FAILURE_LIMIT 16 /* * Macro from include/hw/ppc/fdt.h @@ -872,18 +873,27 @@ static void operation_sequencer(PnvSpi *s) rdr_matched = does_rdr_match(s); if (rdr_matched) { trace_pnv_spi_RDR_match("success"); + s->fail_count = 0; /* A match occurred, increment the sequencer index. */ seq_index++; s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status, SEQ_STATE_INDEX_INCREMENT); } else { trace_pnv_spi_RDR_match("failed"); + s->fail_count++; /* * Branch the sequencer to the index coded into the op * code. */ seq_index = PNV_SPI_OPCODE_LO_NIBBLE(opcode); } + if (s->fail_count >= RDR_MATCH_FAILURE_LIMIT) { + qemu_log_mask(LOG_GUEST_ERROR, "pnv_spi: RDR match failure" + " limit crossed %d times hence requesting " + "sequencer to stop.\n", + RDR_MATCH_FAILURE_LIMIT); + stop = true; + } /* * Regardless of where the branch ended up we want the * sequencer to continue shifting so we have to clear diff --git a/include/hw/ssi/pnv_spi.h b/include/hw/ssi/pnv_spi.h index 6adb72dbb2..c591a0663d 100644 --- a/include/hw/ssi/pnv_spi.h +++ b/include/hw/ssi/pnv_spi.h @@ -40,6 +40,7 @@ typedef struct PnvSpi { MemoryRegion xscom_spic_regs; Fifo8 tx_fifo; Fifo8 rx_fifo; + uint8_t fail_count; /* RDR Match failure counter */ /* SPI object number */ uint32_t spic_num; uint32_t chip_id; -- 2.47.1