Skip to content

Commit b8b3f99

Browse files
tamng-amperesmb49
authored andcommitted
i2c: designware: Disable TX_EMPTY irq while waiting for block length byte
BugLink: https://bugs.launchpad.net/bugs/2050038 commit e8183fa upstream. During SMBus block data read process, we have seen high interrupt rate because of TX_EMPTY irq status while waiting for block length byte (the first data byte after the address phase). The interrupt handler does not do anything because the internal state is kept as STATUS_WRITE_IN_PROGRESS. Hence, we should disable TX_EMPTY IRQ until I2C DesignWare receives first data byte from I2C device, then re-enable it to resume SMBus transaction. It takes 0.789 ms for host to receive data length from slave. Without the patch, i2c_dw_isr() is called 99 times by TX_EMPTY interrupt. And it is none after applying the patch. Cc: stable@vger.kernel.org Co-developed-by: Chuong Tran <chuong@os.amperecomputing.com> Signed-off-by: Chuong Tran <chuong@os.amperecomputing.com> Signed-off-by: Tam Nguyen <tamnguyenchi@os.amperecomputing.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Reviewed-by: Serge Semin <fancer.lancer@gmail.com> Signed-off-by: Wolfram Sang <wsa@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Portia Stephens <portia.stephens@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent 9a9ef1c commit b8b3f99

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

drivers/i2c/busses/i2c-designware-master.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,10 +456,16 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
456456

457457
/*
458458
* Because we don't know the buffer length in the
459-
* I2C_FUNC_SMBUS_BLOCK_DATA case, we can't stop
460-
* the transaction here.
459+
* I2C_FUNC_SMBUS_BLOCK_DATA case, we can't stop the
460+
* transaction here. Also disable the TX_EMPTY IRQ
461+
* while waiting for the data length byte to avoid the
462+
* bogus interrupts flood.
461463
*/
462-
if (buf_len > 0 || flags & I2C_M_RECV_LEN) {
464+
if (flags & I2C_M_RECV_LEN) {
465+
dev->status |= STATUS_WRITE_IN_PROGRESS;
466+
intr_mask &= ~DW_IC_INTR_TX_EMPTY;
467+
break;
468+
} else if (buf_len > 0) {
463469
/* more bytes to be written */
464470
dev->status |= STATUS_WRITE_IN_PROGRESS;
465471
break;
@@ -495,6 +501,13 @@ i2c_dw_recv_len(struct dw_i2c_dev *dev, u8 len)
495501
msgs[dev->msg_read_idx].len = len;
496502
msgs[dev->msg_read_idx].flags &= ~I2C_M_RECV_LEN;
497503

504+
/*
505+
* Received buffer length, re-enable TX_EMPTY interrupt
506+
* to resume the SMBUS transaction.
507+
*/
508+
regmap_update_bits(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_TX_EMPTY,
509+
DW_IC_INTR_TX_EMPTY);
510+
498511
return len;
499512
}
500513

0 commit comments

Comments
 (0)