public inbox for linux-i2c@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Microchip CoreI2C driver fixes
@ 2024-12-18 12:07 Conor Dooley
  2024-12-18 12:07 ` [PATCH v2 1/2] i2c: microchip-core: actually use repeated sends Conor Dooley
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Conor Dooley @ 2024-12-18 12:07 UTC (permalink / raw)
  To: linux-i2c
  Cc: conor, Conor Dooley, Daire McNamara, Andi Shyti, Wolfram Sang,
	linux-riscv, linux-kernel

From: Conor Dooley <conor.dooley@microchip.com>

Yo,

Here's a v2 with one of the minor items pointed out by Andi resolved and
a new patch for an issue fixed in the months since v1, plus some minor
checkpatch things that I seem to have missed on v1. On v1 there was
unresolved discussion with Wolfram, but it has been two months without a
response so I am sending this v2 in an attempt to make progress.

Cheers,
Conor.

v2:
- remove extra () Andi pointed out
- fix some {} use that defied the coding style
- new patch for "ghost detections"

v1: https://lore.kernel.org/linux-i2c/20240930-uneasy-dorsal-1acda9227b0d@spud/

CC: Conor Dooley <conor.dooley@microchip.com>
CC: Daire McNamara <daire.mcnamara@microchip.com>
CC: Andi Shyti <andi.shyti@kernel.org>
CC: Wolfram Sang <wsa@kernel.org>
CC: linux-riscv@lists.infradead.org
CC: linux-i2c@vger.kernel.org
CC: linux-kernel@vger.kernel.org

Conor Dooley (2):
  i2c: microchip-core: actually use repeated sends
  i2c: microchip-core: fix "ghost" detections

 drivers/i2c/busses/i2c-microchip-corei2c.c | 126 ++++++++++++++++-----
 1 file changed, 96 insertions(+), 30 deletions(-)

-- 
2.45.2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/2] i2c: microchip-core: actually use repeated sends
  2024-12-18 12:07 [PATCH v2 0/2] Microchip CoreI2C driver fixes Conor Dooley
@ 2024-12-18 12:07 ` Conor Dooley
  2024-12-18 12:07 ` [PATCH v2 2/2] i2c: microchip-core: fix "ghost" detections Conor Dooley
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Conor Dooley @ 2024-12-18 12:07 UTC (permalink / raw)
  To: linux-i2c
  Cc: conor, Conor Dooley, Daire McNamara, Andi Shyti, Wolfram Sang,
	linux-riscv, linux-kernel, stable

From: Conor Dooley <conor.dooley@microchip.com>

At present, where repeated sends are intended to be used, the
i2c-microchip-core driver sends a stop followed by a start. Lots of i2c
devices must not malfunction in the face of this behaviour, because the
driver has operated like this for years! Try to keep track of whether or
not a repeated send is required, and suppress sending a stop in these
cases.

CC: stable@vger.kernel.org
Fixes: 64a6f1c4987e ("i2c: add support for microchip fpga i2c controllers")
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
 drivers/i2c/busses/i2c-microchip-corei2c.c | 124 ++++++++++++++++-----
 1 file changed, 96 insertions(+), 28 deletions(-)

diff --git a/drivers/i2c/busses/i2c-microchip-corei2c.c b/drivers/i2c/busses/i2c-microchip-corei2c.c
index 0b0a1c4d17ca..e5af38dfaa81 100644
--- a/drivers/i2c/busses/i2c-microchip-corei2c.c
+++ b/drivers/i2c/busses/i2c-microchip-corei2c.c
@@ -93,27 +93,35 @@
  * @base:		pointer to register struct
  * @dev:		device reference
  * @i2c_clk:		clock reference for i2c input clock
+ * @msg_queue:		pointer to the messages requiring sending
  * @buf:		pointer to msg buffer for easier use
  * @msg_complete:	xfer completion object
  * @adapter:		core i2c abstraction
  * @msg_err:		error code for completed message
  * @bus_clk_rate:	current i2c bus clock rate
  * @isr_status:		cached copy of local ISR status
+ * @total_num:		total number of messages to be sent/received
+ * @current_num:	index of the current message being sent/received
  * @msg_len:		number of bytes transferred in msg
  * @addr:		address of the current slave
+ * @restart_needed:	whether or not a repeated start is required after current message
  */
 struct mchp_corei2c_dev {
 	void __iomem *base;
 	struct device *dev;
 	struct clk *i2c_clk;
+	struct i2c_msg *msg_queue;
 	u8 *buf;
 	struct completion msg_complete;
 	struct i2c_adapter adapter;
 	int msg_err;
+	int total_num;
+	int current_num;
 	u32 bus_clk_rate;
 	u32 isr_status;
 	u16 msg_len;
 	u8 addr;
+	bool restart_needed;
 };
 
 static void mchp_corei2c_core_disable(struct mchp_corei2c_dev *idev)
@@ -222,6 +230,47 @@ static int mchp_corei2c_fill_tx(struct mchp_corei2c_dev *idev)
 	return 0;
 }
 
+static void mchp_corei2c_next_msg(struct mchp_corei2c_dev *idev)
+{
+	struct i2c_msg *this_msg;
+	u8 ctrl;
+
+	if (idev->current_num >= idev->total_num) {
+		complete(&idev->msg_complete);
+		return;
+	}
+
+	/*
+	 * If there's been an error, the isr needs to return control
+	 * to the "main" part of the driver, so as not to keep sending
+	 * messages once it completes and clears the SI bit.
+	 */
+	if (idev->msg_err) {
+		complete(&idev->msg_complete);
+		return;
+	}
+
+	this_msg = idev->msg_queue++;
+
+	if (idev->current_num < (idev->total_num - 1)) {
+		struct i2c_msg *next_msg = idev->msg_queue;
+
+		idev->restart_needed = next_msg->flags & I2C_M_RD;
+	} else {
+		idev->restart_needed = false;
+	}
+
+	idev->addr = i2c_8bit_addr_from_msg(this_msg);
+	idev->msg_len = this_msg->len;
+	idev->buf = this_msg->buf;
+
+	ctrl = readb(idev->base + CORE_I2C_CTRL);
+	ctrl |= CTRL_STA;
+	writeb(ctrl, idev->base + CORE_I2C_CTRL);
+
+	idev->current_num++;
+}
+
 static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev)
 {
 	u32 status = idev->isr_status;
@@ -247,10 +296,14 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev)
 		break;
 	case STATUS_M_SLAW_ACK:
 	case STATUS_M_TX_DATA_ACK:
-		if (idev->msg_len > 0)
+		if (idev->msg_len > 0) {
 			mchp_corei2c_fill_tx(idev);
-		else
-			last_byte = true;
+		} else {
+			if (idev->restart_needed)
+				finished = true;
+			else
+				last_byte = true;
+		}
 		break;
 	case STATUS_M_TX_DATA_NACK:
 	case STATUS_M_SLAR_NACK:
@@ -287,7 +340,7 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev)
 		mchp_corei2c_stop(idev);
 
 	if (last_byte || finished)
-		complete(&idev->msg_complete);
+		mchp_corei2c_next_msg(idev);
 
 	return IRQ_HANDLED;
 }
@@ -311,21 +364,48 @@ static irqreturn_t mchp_corei2c_isr(int irq, void *_dev)
 	return ret;
 }
 
-static int mchp_corei2c_xfer_msg(struct mchp_corei2c_dev *idev,
-				 struct i2c_msg *msg)
+static int mchp_corei2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+			     int num)
 {
-	u8 ctrl;
+	struct mchp_corei2c_dev *idev = i2c_get_adapdata(adap);
+	struct i2c_msg *this_msg = msgs;
 	unsigned long time_left;
-
-	idev->addr = i2c_8bit_addr_from_msg(msg);
-	idev->msg_len = msg->len;
-	idev->buf = msg->buf;
-	idev->msg_err = 0;
-
-	reinit_completion(&idev->msg_complete);
+	u8 ctrl;
 
 	mchp_corei2c_core_enable(idev);
 
+	/*
+	 * The isr controls the flow of a transfer, this info needs to be saved
+	 * to a location that it can access the queue information from.
+	 */
+	idev->restart_needed = false;
+	idev->msg_queue = msgs;
+	idev->total_num = num;
+	idev->current_num = 0;
+
+	/*
+	 * But the first entry to the isr is triggered by the start in this
+	 * function, so the first message needs to be "dequeued".
+	 */
+	idev->addr = i2c_8bit_addr_from_msg(this_msg);
+	idev->msg_len = this_msg->len;
+	idev->buf = this_msg->buf;
+	idev->msg_err = 0;
+
+	if (idev->total_num > 1) {
+		struct i2c_msg *next_msg = msgs + 1;
+
+		idev->restart_needed = next_msg->flags & I2C_M_RD;
+	}
+
+	idev->current_num++;
+	idev->msg_queue++;
+
+	reinit_completion(&idev->msg_complete);
+
+	/*
+	 * Send the first start to pass control to the isr
+	 */
 	ctrl = readb(idev->base + CORE_I2C_CTRL);
 	ctrl |= CTRL_STA;
 	writeb(ctrl, idev->base + CORE_I2C_CTRL);
@@ -335,20 +415,8 @@ static int mchp_corei2c_xfer_msg(struct mchp_corei2c_dev *idev,
 	if (!time_left)
 		return -ETIMEDOUT;
 
-	return idev->msg_err;
-}
-
-static int mchp_corei2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
-			     int num)
-{
-	struct mchp_corei2c_dev *idev = i2c_get_adapdata(adap);
-	int i, ret;
-
-	for (i = 0; i < num; i++) {
-		ret = mchp_corei2c_xfer_msg(idev, msgs++);
-		if (ret)
-			return ret;
-	}
+	if (idev->msg_err)
+		return idev->msg_err;
 
 	return num;
 }
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/2] i2c: microchip-core: fix "ghost" detections
  2024-12-18 12:07 [PATCH v2 0/2] Microchip CoreI2C driver fixes Conor Dooley
  2024-12-18 12:07 ` [PATCH v2 1/2] i2c: microchip-core: actually use repeated sends Conor Dooley
@ 2024-12-18 12:07 ` Conor Dooley
  2024-12-19 11:50 ` [PATCH v2 0/2] Microchip CoreI2C driver fixes Andi Shyti
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Conor Dooley @ 2024-12-18 12:07 UTC (permalink / raw)
  To: linux-i2c
  Cc: conor, Conor Dooley, Daire McNamara, Andi Shyti, Wolfram Sang,
	linux-riscv, linux-kernel, stable

From: Conor Dooley <conor.dooley@microchip.com>

Running i2c-detect currently produces an output akin to:
    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         08 -- 0a -- 0c -- 0e --
10: 10 -- 12 -- 14 -- 16 -- UU 19 -- 1b -- 1d -- 1f
20: -- 21 -- 23 -- 25 -- 27 -- 29 -- 2b -- 2d -- 2f
30: -- -- -- -- -- -- -- -- 38 -- 3a -- 3c -- 3e --
40: 40 -- 42 -- 44 -- 46 -- 48 -- 4a -- 4c -- 4e --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: 60 -- 62 -- 64 -- 66 -- 68 -- 6a -- 6c -- 6e --
70: 70 -- 72 -- 74 -- 76 --

This happens because for an i2c_msg with a len of 0 the driver will
mark the transmission of the message as a success once the START has
been sent, without waiting for the devices on the bus to respond with an
ACK/NAK. Since i2cdetect seems to run in a tight loop over all addresses
the NAK is treated as part of the next test for the next address.

Delete the fast path that marks a message as complete when idev->msg_len
is zero after sending a START/RESTART since this isn't a valid scenario.

CC: stable@vger.kernel.org
Fixes: 64a6f1c4987e ("i2c: add support for microchip fpga i2c controllers")
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
My original tests with KASAN/UBSAN/PREEMPT_RT enabled saw far fewer of
these "ghost" detections and the skip caused by the occupied address at
0x18 on this bus is part of my attribution of the problem. Unless I'm
mistaken there's no scenario that you consider a message complete after
sending a START/RESTART without waiting for the ACK/NAK and this code
path I deleted is useless? Looking out of tree, it predates my involvement
with the code so I don't know where it came from, nor is there anything
like it in the bare-metal driver the linux one was based on.
---
 drivers/i2c/busses/i2c-microchip-corei2c.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-microchip-corei2c.c b/drivers/i2c/busses/i2c-microchip-corei2c.c
index e5af38dfaa81..b0a51695138a 100644
--- a/drivers/i2c/busses/i2c-microchip-corei2c.c
+++ b/drivers/i2c/busses/i2c-microchip-corei2c.c
@@ -287,8 +287,6 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev)
 		ctrl &= ~CTRL_STA;
 		writeb(idev->addr, idev->base + CORE_I2C_DATA);
 		writeb(ctrl, idev->base + CORE_I2C_CTRL);
-		if (idev->msg_len == 0)
-			finished = true;
 		break;
 	case STATUS_M_ARB_LOST:
 		idev->msg_err = -EAGAIN;
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 0/2] Microchip CoreI2C driver fixes
  2024-12-18 12:07 [PATCH v2 0/2] Microchip CoreI2C driver fixes Conor Dooley
  2024-12-18 12:07 ` [PATCH v2 1/2] i2c: microchip-core: actually use repeated sends Conor Dooley
  2024-12-18 12:07 ` [PATCH v2 2/2] i2c: microchip-core: fix "ghost" detections Conor Dooley
@ 2024-12-19 11:50 ` Andi Shyti
  2024-12-26  0:59 ` Andi Shyti
  2025-02-03 19:16 ` patchwork-bot+linux-riscv
  4 siblings, 0 replies; 6+ messages in thread
From: Andi Shyti @ 2024-12-19 11:50 UTC (permalink / raw)
  To: Conor Dooley
  Cc: linux-i2c, Conor Dooley, Daire McNamara, Wolfram Sang,
	linux-riscv, linux-kernel

Hi Conor,

On Wed, Dec 18, 2024 at 12:07:39PM +0000, Conor Dooley wrote:
> From: Conor Dooley <conor.dooley@microchip.com>
> 
> Yo,
> 
> Here's a v2 with one of the minor items pointed out by Andi resolved and
> a new patch for an issue fixed in the months since v1, plus some minor
> checkpatch things that I seem to have missed on v1. On v1 there was
> unresolved discussion with Wolfram, but it has been two months without a
> response so I am sending this v2 in an attempt to make progress.
> 
> Cheers,
> Conor.
> 
> v2:
> - remove extra () Andi pointed out
> - fix some {} use that defied the coding style
> - new patch for "ghost detections"
> 
> v1: https://lore.kernel.org/linux-i2c/20240930-uneasy-dorsal-1acda9227b0d@spud/
> 
> CC: Conor Dooley <conor.dooley@microchip.com>
> CC: Daire McNamara <daire.mcnamara@microchip.com>
> CC: Andi Shyti <andi.shyti@kernel.org>
> CC: Wolfram Sang <wsa@kernel.org>
> CC: linux-riscv@lists.infradead.org
> CC: linux-i2c@vger.kernel.org
> CC: linux-kernel@vger.kernel.org
> 
> Conor Dooley (2):
>   i2c: microchip-core: actually use repeated sends
>   i2c: microchip-core: fix "ghost" detections

Thanks for your patches, they look fine to me. For self reference
I'm going to add

Reviewed-by: Andi Shyti <andi.shyti@kernel.org>

to both of them. If you don't mind, I'm going to queue them up
for next week, as I'm not accepting anymore Fixes for this week
(unless they are trivial).

Thank you,
Andi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 0/2] Microchip CoreI2C driver fixes
  2024-12-18 12:07 [PATCH v2 0/2] Microchip CoreI2C driver fixes Conor Dooley
                   ` (2 preceding siblings ...)
  2024-12-19 11:50 ` [PATCH v2 0/2] Microchip CoreI2C driver fixes Andi Shyti
@ 2024-12-26  0:59 ` Andi Shyti
  2025-02-03 19:16 ` patchwork-bot+linux-riscv
  4 siblings, 0 replies; 6+ messages in thread
From: Andi Shyti @ 2024-12-26  0:59 UTC (permalink / raw)
  To: Conor Dooley
  Cc: linux-i2c, Conor Dooley, Daire McNamara, Wolfram Sang,
	linux-riscv, linux-kernel

Hi Conor,

> Conor Dooley (2):
>   i2c: microchip-core: actually use repeated sends
>   i2c: microchip-core: fix "ghost" detections

merged to i2c/i2c-host-fixes.

Thanks,
Andi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 0/2] Microchip CoreI2C driver fixes
  2024-12-18 12:07 [PATCH v2 0/2] Microchip CoreI2C driver fixes Conor Dooley
                   ` (3 preceding siblings ...)
  2024-12-26  0:59 ` Andi Shyti
@ 2025-02-03 19:16 ` patchwork-bot+linux-riscv
  4 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+linux-riscv @ 2025-02-03 19:16 UTC (permalink / raw)
  To: Conor Dooley
  Cc: linux-riscv, linux-i2c, conor.dooley, daire.mcnamara, andi.shyti,
	wsa, linux-kernel

Hello:

This series was applied to riscv/linux.git (fixes)
by Andi Shyti <andi.shyti@kernel.org>:

On Wed, 18 Dec 2024 12:07:39 +0000 you wrote:
> From: Conor Dooley <conor.dooley@microchip.com>
> 
> Yo,
> 
> Here's a v2 with one of the minor items pointed out by Andi resolved and
> a new patch for an issue fixed in the months since v1, plus some minor
> checkpatch things that I seem to have missed on v1. On v1 there was
> unresolved discussion with Wolfram, but it has been two months without a
> response so I am sending this v2 in an attempt to make progress.
> 
> [...]

Here is the summary with links:
  - [v2,1/2] i2c: microchip-core: actually use repeated sends
    https://git.kernel.org/riscv/c/9a8f9320d67b
  - [v2,2/2] i2c: microchip-core: fix "ghost" detections
    https://git.kernel.org/riscv/c/49e1f0fd0d4c

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-02-03 19:15 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-18 12:07 [PATCH v2 0/2] Microchip CoreI2C driver fixes Conor Dooley
2024-12-18 12:07 ` [PATCH v2 1/2] i2c: microchip-core: actually use repeated sends Conor Dooley
2024-12-18 12:07 ` [PATCH v2 2/2] i2c: microchip-core: fix "ghost" detections Conor Dooley
2024-12-19 11:50 ` [PATCH v2 0/2] Microchip CoreI2C driver fixes Andi Shyti
2024-12-26  0:59 ` Andi Shyti
2025-02-03 19:16 ` patchwork-bot+linux-riscv

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox