* FAILED: patch "[PATCH] nvmem: rockchip-otp: Serialize reads" failed to apply to 5.15-stable tree
@ 2026-11-07 11:03 Sasha Levin
2026-11-11 2:19 ` [PATCH 5.15.y 1/3] nvmem: rockchip-otp: Add clks and reg_read to rockchip_data Sasha Levin
0 siblings, 1 reply; 4+ messages in thread
From: Sasha Levin @ 2026-11-07 11:03 UTC (permalink / raw)
To: alchark, miquel.raynal, srini, gregkh; +Cc: stable
The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 9fc6a1592d844c0397f115ee8cbd935169b9a71e
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '20261107060352-failed-5.15-9fc6a1592d84@kernel.org' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 9fc6a1592d844c0397f115ee8cbd935169b9a71e Mon Sep 17 00:00:00 2001
From: Alexey Charkov <alchark@flipper.net>
Date: Fri, 2 Oct 2026 11:13:26 +0100
Subject: [PATCH] nvmem: rockchip-otp: Serialize reads
The OTP controller is driven through a single set of registers holding a
state machine which has to be stepped through for every word read, yet
nothing keeps two readers out of each other's way. Concurrent reads
interleave, and the outcome is either a reader bailing out:
rockchip-otp 2a580000.otp: timeout during read setup
or, worse, one of them silently taking delivery of the other's data.
Reading two cells in parallel from userspace on RK3576 reproduces both
within 150 iterations - 53 read errors and 9 corrupted results, the latter
either losing their first word or, in one case, ending in the two bytes
which belong to the other reader's cell - whereas the same reads issued
sequentially never fail. Concurrency is not hypothetical here, as six
thermal sensors source their trim values from the OTP and reach the driver
straight from asynchronous driver probing.
Guard the read path with a mutex. Reads are the only way into the hardware,
as the driver registers no write callback, and they always run in process
context, so a plain mutex spanning the whole clock-enable, read,
clock-disable sequence is enough.
Fixes: 755864feb729 ("nvmem: add Rockchip OTP driver")
Cc: stable@vger.kernel.org
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Alexey Charkov <alchark@flipper.net>
Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
Link: https://patch.msgid.link/20261002101329.1084348-2-srini@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/rockchip-otp.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
index 2c0feb036f3fd..f8a8c7cece98d 100644
--- a/drivers/nvmem/rockchip-otp.c
+++ b/drivers/nvmem/rockchip-otp.c
@@ -12,6 +12,7 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/nvmem-provider.h>
#include <linux/reset.h>
#include <linux/slab.h>
@@ -80,6 +81,8 @@ struct rockchip_otp {
void __iomem *base;
struct reset_control *rst;
const struct rockchip_data *data;
+ /* Serializes access to the OTP controller state machine */
+ struct mutex mutex;
struct clk_bulk_data clks[];
};
@@ -272,10 +275,12 @@ static int rockchip_otp_read(void *context, unsigned int offset,
if (!otp->data || !otp->data->reg_read)
return -EINVAL;
+ mutex_lock(&otp->mutex);
+
ret = clk_bulk_prepare_enable(otp->data->num_clks, otp->clks);
if (ret < 0) {
dev_err(otp->dev, "failed to prepare/enable clks\n");
- return ret;
+ goto unlock;
}
offset += otp->data->read_offset;
@@ -308,6 +313,9 @@ static int rockchip_otp_read(void *context, unsigned int offset,
err:
clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks);
+unlock:
+ mutex_unlock(&otp->mutex);
+
return ret;
}
@@ -431,6 +439,11 @@ static int rockchip_otp_probe(struct platform_device *pdev)
otp->data = data;
otp->dev = dev;
+
+ ret = devm_mutex_init(dev, &otp->mutex);
+ if (ret)
+ return ret;
+
otp->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(otp->base))
return dev_err_probe(dev, PTR_ERR(otp->base),
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 5.15.y 1/3] nvmem: rockchip-otp: Add clks and reg_read to rockchip_data
2026-11-07 11:03 FAILED: patch "[PATCH] nvmem: rockchip-otp: Serialize reads" failed to apply to 5.15-stable tree Sasha Levin
@ 2026-11-11 2:19 ` Sasha Levin
2026-11-11 2:19 ` [PATCH 5.15.y 2/3] nvmem: rockchip-otp: alloc clks with main struct Sasha Levin
2026-11-11 2:19 ` [PATCH 5.15.y 3/3] nvmem: rockchip-otp: Serialize reads Sasha Levin
0 siblings, 2 replies; 4+ messages in thread
From: Sasha Levin @ 2026-11-11 2:19 UTC (permalink / raw)
To: stable
Cc: Cristian Ciocaltea, Vincent Legoll, Heiko Stuebner,
Srinivas Kandagatla, Greg Kroah-Hartman, Sasha Levin
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
[ Upstream commit 8dc61364164e79e44c07fa2ac0a7b6939f00d5db ]
In preparation to support new Rockchip OTP memory devices with different
clock configurations and register layout, extend rockchip_data struct
with the related members: clks, num_clks, reg_read.
Additionally, to avoid managing redundant driver data, drop num_clks
member from rockchip_otp struct and update all references to point to
the equivalent member in rockchip_data.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Tested-by: Vincent Legoll <vincent.legoll@gmail.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Message-ID: <20230611140330.154222-10-srinivas.kandagatla@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: 9fc6a1592d84 ("nvmem: rockchip-otp: Serialize reads")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/nvmem/rockchip-otp.c | 79 ++++++++++++++++++++++--------------
1 file changed, 49 insertions(+), 30 deletions(-)
diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
index 9f53bcce2f877..b5a84b379da40 100644
--- a/drivers/nvmem/rockchip-otp.c
+++ b/drivers/nvmem/rockchip-otp.c
@@ -54,21 +54,19 @@
#define OTPC_TIMEOUT 10000
+struct rockchip_data {
+ int size;
+ const char * const *clks;
+ int num_clks;
+ nvmem_reg_read_t reg_read;
+};
+
struct rockchip_otp {
struct device *dev;
void __iomem *base;
- struct clk_bulk_data *clks;
- int num_clks;
+ struct clk_bulk_data *clks;
struct reset_control *rst;
-};
-
-/* list of required clocks */
-static const char * const rockchip_otp_clocks[] = {
- "otp", "apb_pclk", "phy",
-};
-
-struct rockchip_data {
- int size;
+ const struct rockchip_data *data;
};
static int rockchip_otp_reset(struct rockchip_otp *otp)
@@ -132,29 +130,23 @@ static int rockchip_otp_ecc_enable(struct rockchip_otp *otp, bool enable)
return ret;
}
-static int rockchip_otp_read(void *context, unsigned int offset,
- void *val, size_t bytes)
+static int px30_otp_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
{
struct rockchip_otp *otp = context;
u8 *buf = val;
- int ret = 0;
-
- ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks);
- if (ret < 0) {
- dev_err(otp->dev, "failed to prepare/enable clks\n");
- return ret;
- }
+ int ret;
ret = rockchip_otp_reset(otp);
if (ret) {
dev_err(otp->dev, "failed to reset otp phy\n");
- goto disable_clks;
+ return ret;
}
ret = rockchip_otp_ecc_enable(otp, false);
if (ret < 0) {
dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
- goto disable_clks;
+ return ret;
}
writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
@@ -174,8 +166,28 @@ static int rockchip_otp_read(void *context, unsigned int offset,
read_end:
writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
-disable_clks:
- clk_bulk_disable_unprepare(otp->num_clks, otp->clks);
+
+ return ret;
+}
+
+static int rockchip_otp_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+ struct rockchip_otp *otp = context;
+ int ret;
+
+ if (!otp->data || !otp->data->reg_read)
+ return -EINVAL;
+
+ ret = clk_bulk_prepare_enable(otp->data->num_clks, otp->clks);
+ if (ret < 0) {
+ dev_err(otp->dev, "failed to prepare/enable clks\n");
+ return ret;
+ }
+
+ ret = otp->data->reg_read(context, offset, val, bytes);
+
+ clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks);
return ret;
}
@@ -189,8 +201,15 @@ static struct nvmem_config otp_config = {
.reg_read = rockchip_otp_read,
};
+static const char * const px30_otp_clocks[] = {
+ "otp", "apb_pclk", "phy",
+};
+
static const struct rockchip_data px30_data = {
.size = 0x40,
+ .clks = px30_otp_clocks,
+ .num_clks = ARRAY_SIZE(px30_otp_clocks),
+ .reg_read = px30_otp_read,
};
static const struct of_device_id rockchip_otp_match[] = {
@@ -225,21 +244,21 @@ static int rockchip_otp_probe(struct platform_device *pdev)
if (!otp)
return -ENOMEM;
+ otp->data = data;
otp->dev = dev;
otp->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(otp->base))
return PTR_ERR(otp->base);
- otp->num_clks = ARRAY_SIZE(rockchip_otp_clocks);
- otp->clks = devm_kcalloc(dev, otp->num_clks,
- sizeof(*otp->clks), GFP_KERNEL);
+ otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks),
+ GFP_KERNEL);
if (!otp->clks)
return -ENOMEM;
- for (i = 0; i < otp->num_clks; ++i)
- otp->clks[i].id = rockchip_otp_clocks[i];
+ for (i = 0; i < data->num_clks; ++i)
+ otp->clks[i].id = data->clks[i];
- ret = devm_clk_bulk_get(dev, otp->num_clks, otp->clks);
+ ret = devm_clk_bulk_get(dev, data->num_clks, otp->clks);
if (ret)
return ret;
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 5.15.y 2/3] nvmem: rockchip-otp: alloc clks with main struct
2026-11-11 2:19 ` [PATCH 5.15.y 1/3] nvmem: rockchip-otp: Add clks and reg_read to rockchip_data Sasha Levin
@ 2026-11-11 2:19 ` Sasha Levin
2026-11-11 2:19 ` [PATCH 5.15.y 3/3] nvmem: rockchip-otp: Serialize reads Sasha Levin
1 sibling, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2026-11-11 2:19 UTC (permalink / raw)
To: stable; +Cc: Rosen Penev, Srinivas Kandagatla, Greg Kroah-Hartman, Sasha Levin
From: Rosen Penev <rosenp@gmail.com>
[ Upstream commit 9f99bb979f930e52e6861114fe03535d4bc2f374 ]
Use a flexible array member to simplify allocation slightly. No need for
a separate calloc.
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
Link: https://patch.msgid.link/20260530205333.117458-3-srini@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: 9fc6a1592d84 ("nvmem: rockchip-otp: Serialize reads")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/nvmem/rockchip-otp.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
index b5a84b379da40..aaa044bb231b8 100644
--- a/drivers/nvmem/rockchip-otp.c
+++ b/drivers/nvmem/rockchip-otp.c
@@ -64,9 +64,9 @@ struct rockchip_data {
struct rockchip_otp {
struct device *dev;
void __iomem *base;
- struct clk_bulk_data *clks;
struct reset_control *rst;
const struct rockchip_data *data;
+ struct clk_bulk_data clks[];
};
static int rockchip_otp_reset(struct rockchip_otp *otp)
@@ -239,7 +239,7 @@ static int rockchip_otp_probe(struct platform_device *pdev)
return -EINVAL;
}
- otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp),
+ otp = devm_kzalloc(&pdev->dev, struct_size(otp, clks, data->num_clks),
GFP_KERNEL);
if (!otp)
return -ENOMEM;
@@ -250,11 +250,6 @@ static int rockchip_otp_probe(struct platform_device *pdev)
if (IS_ERR(otp->base))
return PTR_ERR(otp->base);
- otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks),
- GFP_KERNEL);
- if (!otp->clks)
- return -ENOMEM;
-
for (i = 0; i < data->num_clks; ++i)
otp->clks[i].id = data->clks[i];
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 5.15.y 3/3] nvmem: rockchip-otp: Serialize reads
2026-11-11 2:19 ` [PATCH 5.15.y 1/3] nvmem: rockchip-otp: Add clks and reg_read to rockchip_data Sasha Levin
2026-11-11 2:19 ` [PATCH 5.15.y 2/3] nvmem: rockchip-otp: alloc clks with main struct Sasha Levin
@ 2026-11-11 2:19 ` Sasha Levin
1 sibling, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2026-11-11 2:19 UTC (permalink / raw)
To: stable
Cc: Alexey Charkov, Miquel Raynal, Srinivas Kandagatla,
Greg Kroah-Hartman, Sasha Levin
From: Alexey Charkov <alchark@flipper.net>
[ Upstream commit 9fc6a1592d844c0397f115ee8cbd935169b9a71e ]
The OTP controller is driven through a single set of registers holding a
state machine which has to be stepped through for every word read, yet
nothing keeps two readers out of each other's way. Concurrent reads
interleave, and the outcome is either a reader bailing out:
rockchip-otp 2a580000.otp: timeout during read setup
or, worse, one of them silently taking delivery of the other's data.
Reading two cells in parallel from userspace on RK3576 reproduces both
within 150 iterations - 53 read errors and 9 corrupted results, the latter
either losing their first word or, in one case, ending in the two bytes
which belong to the other reader's cell - whereas the same reads issued
sequentially never fail. Concurrency is not hypothetical here, as six
thermal sensors source their trim values from the OTP and reach the driver
straight from asynchronous driver probing.
Guard the read path with a mutex. Reads are the only way into the hardware,
as the driver registers no write callback, and they always run in process
context, so a plain mutex spanning the whole clock-enable, read,
clock-disable sequence is enough.
Fixes: 755864feb729 ("nvmem: add Rockchip OTP driver")
Cc: stable@vger.kernel.org
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Alexey Charkov <alchark@flipper.net>
Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
Link: https://patch.msgid.link/20261002101329.1084348-2-srini@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/nvmem/rockchip-otp.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
index aaa044bb231b8..0fb8d6d800bbe 100644
--- a/drivers/nvmem/rockchip-otp.c
+++ b/drivers/nvmem/rockchip-otp.c
@@ -12,6 +12,7 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/nvmem-provider.h>
#include <linux/reset.h>
#include <linux/slab.h>
@@ -66,6 +67,8 @@ struct rockchip_otp {
void __iomem *base;
struct reset_control *rst;
const struct rockchip_data *data;
+ /* Serializes access to the OTP controller state machine */
+ struct mutex mutex;
struct clk_bulk_data clks[];
};
@@ -179,16 +182,21 @@ static int rockchip_otp_read(void *context, unsigned int offset,
if (!otp->data || !otp->data->reg_read)
return -EINVAL;
+ mutex_lock(&otp->mutex);
+
ret = clk_bulk_prepare_enable(otp->data->num_clks, otp->clks);
if (ret < 0) {
dev_err(otp->dev, "failed to prepare/enable clks\n");
- return ret;
+ goto unlock;
}
ret = otp->data->reg_read(context, offset, val, bytes);
clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks);
+unlock:
+ mutex_unlock(&otp->mutex);
+
return ret;
}
@@ -246,6 +254,11 @@ static int rockchip_otp_probe(struct platform_device *pdev)
otp->data = data;
otp->dev = dev;
+
+ ret = devm_mutex_init(dev, &otp->mutex);
+ if (ret)
+ return ret;
+
otp->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(otp->base))
return PTR_ERR(otp->base);
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-11 2:19 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-07 11:03 FAILED: patch "[PATCH] nvmem: rockchip-otp: Serialize reads" failed to apply to 5.15-stable tree Sasha Levin
2026-11-11 2:19 ` [PATCH 5.15.y 1/3] nvmem: rockchip-otp: Add clks and reg_read to rockchip_data Sasha Levin
2026-11-11 2:19 ` [PATCH 5.15.y 2/3] nvmem: rockchip-otp: alloc clks with main struct Sasha Levin
2026-11-11 2:19 ` [PATCH 5.15.y 3/3] nvmem: rockchip-otp: Serialize reads Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).