The i2c interrupt handler was not checking against the length of supplied buffer so if the hardware supplied more data than requested in the i2c transfer it happily copies it right past the end of the buffer! Signed-off-by: Andrew Worsley <amworsley@xxxxxxxxx> --- drivers/i2c/busses/i2c-cadence.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index e39d002a385c..81f924d4adcb 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -429,6 +429,7 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr) if (id->p_recv_buf && ((isr_status & CDNS_I2C_IXR_COMP) || (isr_status & CDNS_I2C_IXR_DATA))) { + unsigned char *p = id->p_recv_buf; /* Read data if receive data valid is set */ while (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_RXDV) { @@ -441,6 +442,12 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr) !id->bus_hold_flag) cdns_i2c_clear_bus_hold(id); + if (id->recv_count == 0) { + pr_notice("%s: i2c receive buffer filled : %u aborting transfer %p - %p\n", + __func__, (id->p_recv_buf - p)); + break; + } + *(id->p_recv_buf)++ = cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET); id->recv_count--; -- 2.11.0