From e7b87de822f42110ae8419f2c178d951cd94d39e Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Apr 20 2023 11:01:08 +0000 Subject: i2c: ocores: generate stop condition after timeout in polling mode (bsc#1012628). --- diff --git a/patches.kernel.org/6.2.12-132-i2c-ocores-generate-stop-condition-after-timeo.patch b/patches.kernel.org/6.2.12-132-i2c-ocores-generate-stop-condition-after-timeo.patch new file mode 100644 index 0000000..bd55f46 --- /dev/null +++ b/patches.kernel.org/6.2.12-132-i2c-ocores-generate-stop-condition-after-timeo.patch @@ -0,0 +1,108 @@ +From: Gregor Herburger +Date: Thu, 13 Apr 2023 11:37:37 +0200 +Subject: [PATCH] i2c: ocores: generate stop condition after timeout in polling + mode +References: bsc#1012628 +Patch-mainline: 6.2.12 +Git-commit: f8160d3b35fc94491bb0cb974dbda310ef96c0e2 + +[ Upstream commit f8160d3b35fc94491bb0cb974dbda310ef96c0e2 ] + +In polling mode, no stop condition is generated after a timeout. This +causes SCL to remain low and thereby block the bus. If this happens +during a transfer it can cause slaves to misinterpret the subsequent +transfer and return wrong values. + +To solve this, pass the ETIMEDOUT error up from ocores_process_polling() +instead of setting STATE_ERROR directly. The caller is adjusted to call +ocores_process_timeout() on error both in polling and in IRQ mode, which +will set STATE_ERROR and generate a stop condition. + +Fixes: 69c8c0c0efa8 ("i2c: ocores: add polling interface") +Signed-off-by: Gregor Herburger +Signed-off-by: Matthias Schiffer +Acked-by: Peter Korsgaard +Reviewed-by: Andrew Lunn +Reviewed-by: Federico Vaga +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +Signed-off-by: Jiri Slaby +--- + drivers/i2c/busses/i2c-ocores.c | 35 ++++++++++++++++++--------------- + 1 file changed, 19 insertions(+), 16 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c +index a0af027d..2e575856 100644 +--- a/drivers/i2c/busses/i2c-ocores.c ++++ b/drivers/i2c/busses/i2c-ocores.c +@@ -342,18 +342,18 @@ static int ocores_poll_wait(struct ocores_i2c *i2c) + * ocores_isr(), we just add our polling code around it. + * + * It can run in atomic context ++ * ++ * Return: 0 on success, -ETIMEDOUT on timeout + */ +-static void ocores_process_polling(struct ocores_i2c *i2c) ++static int ocores_process_polling(struct ocores_i2c *i2c) + { +- while (1) { +- irqreturn_t ret; +- int err; ++ irqreturn_t ret; ++ int err = 0; + ++ while (1) { + err = ocores_poll_wait(i2c); +- if (err) { +- i2c->state = STATE_ERROR; ++ if (err) + break; /* timeout */ +- } + + ret = ocores_isr(-1, i2c); + if (ret == IRQ_NONE) +@@ -364,13 +364,15 @@ static void ocores_process_polling(struct ocores_i2c *i2c) + break; + } + } ++ ++ return err; + } + + static int ocores_xfer_core(struct ocores_i2c *i2c, + struct i2c_msg *msgs, int num, + bool polling) + { +- int ret; ++ int ret = 0; + u8 ctrl; + + ctrl = oc_getreg(i2c, OCI2C_CONTROL); +@@ -388,15 +390,16 @@ static int ocores_xfer_core(struct ocores_i2c *i2c, + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + + if (polling) { +- ocores_process_polling(i2c); ++ ret = ocores_process_polling(i2c); + } else { +- ret = wait_event_timeout(i2c->wait, +- (i2c->state == STATE_ERROR) || +- (i2c->state == STATE_DONE), HZ); +- if (ret == 0) { +- ocores_process_timeout(i2c); +- return -ETIMEDOUT; +- } ++ if (wait_event_timeout(i2c->wait, ++ (i2c->state == STATE_ERROR) || ++ (i2c->state == STATE_DONE), HZ) == 0) ++ ret = -ETIMEDOUT; ++ } ++ if (ret) { ++ ocores_process_timeout(i2c); ++ return ret; + } + + return (i2c->state == STATE_DONE) ? num : -EIO; +-- +2.35.3 + diff --git a/series.conf b/series.conf index 28bbc59..dd1b368 100644 --- a/series.conf +++ b/series.conf @@ -2359,6 +2359,7 @@ patches.kernel.org/6.2.12-129-powerpc-papr_scm-Update-the-NUMA-distance-tabl.patch patches.kernel.org/6.2.12-130-sched-fair-Fix-imbalance-overflow.patch patches.kernel.org/6.2.12-131-x86-rtc-Remove-__init-for-runtime-functions.patch + patches.kernel.org/6.2.12-132-i2c-ocores-generate-stop-condition-after-timeo.patch ######################################################## # Build fixes that apply to the vanilla kernel too.