From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: David Zheng <david.zheng@intel.com>,
Jarkko Nikula <jarkko.nikula@linux.intel.com>,
Wolfram Sang <wsa@kernel.org>, Sasha Levin <sashal@kernel.org>,
andi.shyti@kernel.org, linux-i2c@vger.kernel.org
Subject: [PATCH AUTOSEL 6.3 20/30] i2c: designware: fix idx_write_cnt in read loop
Date: Fri, 16 Jun 2023 06:25:08 -0400 [thread overview]
Message-ID: <20230616102521.673087-20-sashal@kernel.org> (raw)
In-Reply-To: <20230616102521.673087-1-sashal@kernel.org>
From: David Zheng <david.zheng@intel.com>
[ Upstream commit 1acfc6e753ed978b36d722f54e57fe4d1e8a6ffa ]
With IC_INTR_RX_FULL slave interrupt handler reads data in a loop until
RX FIFO is empty. When testing with the slave-eeprom, each transaction
has 2 bytes for address/index and 1 byte for value, the address byte
can be written as data byte due to dropping STOP condition.
In the test below, the master continuously writes to the slave, first 2
bytes are index, 3rd byte is value and follow by a STOP condition.
i2c_write: i2c-3 #0 a=04b f=0000 l=3 [00-D1-D1]
i2c_write: i2c-3 #0 a=04b f=0000 l=3 [00-D2-D2]
i2c_write: i2c-3 #0 a=04b f=0000 l=3 [00-D3-D3]
Upon receiving STOP condition slave eeprom would reset `idx_write_cnt` so
next 2 bytes can be treated as buffer index for upcoming transaction.
Supposedly the slave eeprom buffer would be written as
EEPROM[0x00D1] = 0xD1
EEPROM[0x00D2] = 0xD2
EEPROM[0x00D3] = 0xD3
When CPU load is high the slave irq handler may not read fast enough,
the interrupt status can be seen as 0x204 with both DW_IC_INTR_STOP_DET
(0x200) and DW_IC_INTR_RX_FULL (0x4) bits. The slave device may see
the transactions below.
0x1 STATUS SLAVE_ACTIVITY=0x1 : RAW_INTR_STAT=0x1594 : INTR_STAT=0x4
0x1 STATUS SLAVE_ACTIVITY=0x1 : RAW_INTR_STAT=0x1594 : INTR_STAT=0x4
0x1 STATUS SLAVE_ACTIVITY=0x1 : RAW_INTR_STAT=0x1594 : INTR_STAT=0x4
0x1 STATUS SLAVE_ACTIVITY=0x1 : RAW_INTR_STAT=0x1794 : INTR_STAT=0x204
0x1 STATUS SLAVE_ACTIVITY=0x0 : RAW_INTR_STAT=0x1790 : INTR_STAT=0x200
0x1 STATUS SLAVE_ACTIVITY=0x1 : RAW_INTR_STAT=0x1594 : INTR_STAT=0x4
0x1 STATUS SLAVE_ACTIVITY=0x1 : RAW_INTR_STAT=0x1594 : INTR_STAT=0x4
0x1 STATUS SLAVE_ACTIVITY=0x1 : RAW_INTR_STAT=0x1594 : INTR_STAT=0x4
After `D1` is received, read loop continues to read `00` which is the
first bype of next index. Since STOP condition is ignored by the loop,
eeprom buffer index increased to `D2` and `00` is written as value.
So the slave eeprom buffer becomes
EEPROM[0x00D1] = 0xD1
EEPROM[0x00D2] = 0x00
EEPROM[0x00D3] = 0xD3
The fix is to use `FIRST_DATA_BYTE` (bit 11) in `IC_DATA_CMD` to split
the transactions. The first index byte in this case would have bit 11
set. Check this indication to inject I2C_SLAVE_WRITE_REQUESTED event
which will reset `idx_write_cnt` in slave eeprom.
Signed-off-by: David Zheng <david.zheng@intel.com>
Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/i2c/busses/i2c-designware-core.h | 1 +
drivers/i2c/busses/i2c-designware-slave.c | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 050d8c63ad3c5..0164d92163308 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -40,6 +40,7 @@
#define DW_IC_CON_BUS_CLEAR_CTRL BIT(11)
#define DW_IC_DATA_CMD_DAT GENMASK(7, 0)
+#define DW_IC_DATA_CMD_FIRST_DATA_BYTE BIT(11)
/*
* Registers offset
diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c
index cec25054bb244..2e079cf20bb5b 100644
--- a/drivers/i2c/busses/i2c-designware-slave.c
+++ b/drivers/i2c/busses/i2c-designware-slave.c
@@ -176,6 +176,10 @@ static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)
do {
regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
+ if (tmp & DW_IC_DATA_CMD_FIRST_DATA_BYTE)
+ i2c_slave_event(dev->slave,
+ I2C_SLAVE_WRITE_REQUESTED,
+ &val);
val = tmp;
i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED,
&val);
--
2.39.2
next prev parent reply other threads:[~2023-06-16 10:28 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-16 10:24 [PATCH AUTOSEL 6.3 01/30] Input: soc_button_array - add invalid acpi_index DMI quirk handling Sasha Levin
2023-06-16 10:24 ` [PATCH AUTOSEL 6.3 02/30] arm64: dts: qcom: sc7280-idp: drop incorrect dai-cells from WCD938x SDW Sasha Levin
2023-06-16 10:24 ` [PATCH AUTOSEL 6.3 03/30] arm64: dts: qcom: sc7280-qcard: " Sasha Levin
2023-06-16 10:24 ` [PATCH AUTOSEL 6.3 04/30] s390/cio: unregister device when the only path is gone Sasha Levin
2023-06-16 10:24 ` [PATCH AUTOSEL 6.3 05/30] spi: lpspi: disable lpspi module irq in DMA mode Sasha Levin
2023-06-16 10:24 ` [PATCH AUTOSEL 6.3 06/30] ASoC: codecs: wcd938x-sdw: do not set can_multi_write flag Sasha Levin
2023-06-16 10:24 ` [PATCH AUTOSEL 6.3 07/30] ASoC: simple-card: Add missing of_node_put() in case of error Sasha Levin
2023-06-16 10:24 ` [PATCH AUTOSEL 6.3 08/30] soundwire: dmi-quirks: add new mapping for HP Spectre x360 Sasha Levin
2023-06-16 10:24 ` [PATCH AUTOSEL 6.3 09/30] soundwire: qcom: add proper error paths in qcom_swrm_startup() Sasha Levin
2023-06-16 10:24 ` [PATCH AUTOSEL 6.3 10/30] platform/x86: int3472: Avoid crash in unregistering regulator gpio Sasha Levin
2023-06-16 10:24 ` [PATCH AUTOSEL 6.3 11/30] ASoC: nau8824: Add quirk to active-high jack-detect Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 12/30] ASoC: amd: yc: Add Thinkpad Neo14 to quirks list for acp6x Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 13/30] drm/ast: Fix modeset failed on DisplayPort Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 14/30] gfs2: Don't get stuck writing page onto itself under direct I/O Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 15/30] s390/purgatory: disable branch profiling Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 16/30] ASoC: fsl_sai: Enable BCI bit if SAI works on synchronous mode with BYP asserted Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 17/30] net: sched: wrap tc_skip_wrapper with CONFIG_RETPOLINE Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 18/30] ALSA: hda/realtek: Add "Intel Reference board" and "NUC 13" SSID in the ALC256 Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 19/30] i2c: mchp-pci1xxxx: Avoid cast to incompatible function type Sasha Levin
2023-06-16 10:25 ` Sasha Levin [this message]
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 21/30] ARM: dts: Fix erroneous ADS touchscreen polarities Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 22/30] null_blk: Fix: memory release when memory_backed=1 Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 23/30] drm/exynos: vidi: fix a wrong error return Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 24/30] drm/exynos: fix race condition UAF in exynos_g2d_exec_ioctl Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 25/30] drm/radeon: fix race condition UAF in radeon_gem_set_domain_ioctl Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 26/30] Revert "ext4: don't clear SB_RDONLY when remounting r/w until quota is re-enabled" Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 27/30] ext4: only check dquot_initialize_needed() when debugging Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 28/30] tools/virtio: Fix arm64 ringtest compilation error Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 29/30] vhost_vdpa: tell vqs about the negotiated Sasha Levin
2023-06-16 10:25 ` [PATCH AUTOSEL 6.3 30/30] vhost_net: revert upend_idx only on retriable error Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230616102521.673087-20-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=andi.shyti@kernel.org \
--cc=david.zheng@intel.com \
--cc=jarkko.nikula@linux.intel.com \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=wsa@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox