* [PATCH 0/2] rpmsg: fix after driver_override patchset
@ 2022-04-29 19:59 Krzysztof Kozlowski
2022-04-29 19:59 ` [PATCH 1/2] rpmsg: Fix calling device_lock() on non-initialized device Krzysztof Kozlowski
2022-04-29 19:59 ` [PATCH 2/2] rpmsg: use local 'dev' variable Krzysztof Kozlowski
0 siblings, 2 replies; 4+ messages in thread
From: Krzysztof Kozlowski @ 2022-04-29 19:59 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Krzysztof Kozlowski,
Greg Kroah-Hartman, linux-remoteproc, linux-kernel
Hi,
Marek reported issue introduced by commit in Greg's tree:
2cd402b8fd4 ("rpmsg: Fix kfree() of static memory on setting driver_override")
Therefore this should go via Greg's tree as well.
Marek,
Could you test if it fixes your issue? It worked for my case which used
different RPMSG driver.
Best regards,
Krzysztof
Krzysztof Kozlowski (2):
rpmsg: Fix calling device_lock() on non-initialized device
rpmsg: use local 'dev' variable
drivers/rpmsg/rpmsg_core.c | 39 ++++++++++++++++++++++++++++------
drivers/rpmsg/rpmsg_internal.h | 14 +-----------
drivers/rpmsg/rpmsg_ns.c | 14 +-----------
include/linux/rpmsg.h | 8 +++++++
4 files changed, 43 insertions(+), 32 deletions(-)
--
2.32.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] rpmsg: Fix calling device_lock() on non-initialized device
2022-04-29 19:59 [PATCH 0/2] rpmsg: fix after driver_override patchset Krzysztof Kozlowski
@ 2022-04-29 19:59 ` Krzysztof Kozlowski
2022-04-29 21:56 ` Marek Szyprowski
2022-04-29 19:59 ` [PATCH 2/2] rpmsg: use local 'dev' variable Krzysztof Kozlowski
1 sibling, 1 reply; 4+ messages in thread
From: Krzysztof Kozlowski @ 2022-04-29 19:59 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Krzysztof Kozlowski,
Greg Kroah-Hartman, linux-remoteproc, linux-kernel
Cc: Marek Szyprowski
driver_set_override() helper uses device_lock() so it should not be
called before rpmsg_register_device() (which calls device_register()).
Effect can be seen with CONFIG_DEBUG_MUTEXES:
DEBUG_LOCKS_WARN_ON(lock->magic != lock)
WARNING: CPU: 3 PID: 57 at kernel/locking/mutex.c:582 __mutex_lock+0x1ec/0x430
...
Call trace:
__mutex_lock+0x1ec/0x430
mutex_lock_nested+0x44/0x50
driver_set_override+0x124/0x150
qcom_glink_native_probe+0x30c/0x3b0
glink_rpm_probe+0x274/0x350
platform_probe+0x6c/0xe0
really_probe+0x17c/0x3d0
__driver_probe_device+0x114/0x190
driver_probe_device+0x3c/0xf0
...
Refactor the rpmsg_register_device() function to use two-step device
registering (initialization + add) and call driver_set_override() in
proper moment.
This moves the code around, so while at it also NULL-ify the
rpdev->driver_override in error path to be sure it won't be kfree()
second time.
Fixes: 42cd402b8fd4 ("rpmsg: Fix kfree() of static memory on setting driver_override")
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
Commit SHA from linux-next - Greg's tree.
---
drivers/rpmsg/rpmsg_core.c | 33 ++++++++++++++++++++++++++++++---
drivers/rpmsg/rpmsg_internal.h | 14 +-------------
drivers/rpmsg/rpmsg_ns.c | 14 +-------------
include/linux/rpmsg.h | 8 ++++++++
4 files changed, 40 insertions(+), 29 deletions(-)
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 95fc283f6af7..4938fc4eff00 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -593,24 +593,51 @@ static struct bus_type rpmsg_bus = {
.remove = rpmsg_dev_remove,
};
-int rpmsg_register_device(struct rpmsg_device *rpdev)
+/*
+ * A helper for registering rpmsg device with driver override and name.
+ * Drivers should not be using it, but instead rpmsg_register_device().
+ */
+int rpmsg_register_device_override(struct rpmsg_device *rpdev,
+ const char *driver_override)
{
struct device *dev = &rpdev->dev;
int ret;
+ if (driver_override)
+ strcpy(rpdev->id.name, driver_override);
+
dev_set_name(&rpdev->dev, "%s.%s.%d.%d", dev_name(dev->parent),
rpdev->id.name, rpdev->src, rpdev->dst);
rpdev->dev.bus = &rpmsg_bus;
- ret = device_register(&rpdev->dev);
+ device_initialize(dev);
+ if (driver_override) {
+ ret = driver_set_override(dev, &rpdev->driver_override,
+ driver_override,
+ strlen(driver_override));
+ if (ret) {
+ dev_err(dev, "device_set_override failed: %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = device_add(dev);
if (ret) {
- dev_err(dev, "device_register failed: %d\n", ret);
+ dev_err(dev, "device_add failed: %d\n", ret);
+ kfree(rpdev->driver_override);
+ rpdev->driver_override = NULL;
put_device(&rpdev->dev);
}
return ret;
}
+EXPORT_SYMBOL(rpmsg_register_device_override);
+
+int rpmsg_register_device(struct rpmsg_device *rpdev)
+{
+ return rpmsg_register_device_override(rpdev, NULL);
+}
EXPORT_SYMBOL(rpmsg_register_device);
/*
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index 3e81642238d2..a22cd4abe7d1 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -94,19 +94,7 @@ int rpmsg_release_channel(struct rpmsg_device *rpdev,
*/
static inline int rpmsg_ctrldev_register_device(struct rpmsg_device *rpdev)
{
- int ret;
-
- strcpy(rpdev->id.name, "rpmsg_ctrl");
- ret = driver_set_override(&rpdev->dev, &rpdev->driver_override,
- rpdev->id.name, strlen(rpdev->id.name));
- if (ret)
- return ret;
-
- ret = rpmsg_register_device(rpdev);
- if (ret)
- kfree(rpdev->driver_override);
-
- return ret;
+ return rpmsg_register_device_override(rpdev, "rpmsg_ctrl");
}
#endif
diff --git a/drivers/rpmsg/rpmsg_ns.c b/drivers/rpmsg/rpmsg_ns.c
index 8eb8f328237e..c70ad03ff2e9 100644
--- a/drivers/rpmsg/rpmsg_ns.c
+++ b/drivers/rpmsg/rpmsg_ns.c
@@ -20,22 +20,10 @@
*/
int rpmsg_ns_register_device(struct rpmsg_device *rpdev)
{
- int ret;
-
- strcpy(rpdev->id.name, "rpmsg_ns");
- ret = driver_set_override(&rpdev->dev, &rpdev->driver_override,
- rpdev->id.name, strlen(rpdev->id.name));
- if (ret)
- return ret;
-
rpdev->src = RPMSG_NS_ADDR;
rpdev->dst = RPMSG_NS_ADDR;
- ret = rpmsg_register_device(rpdev);
- if (ret)
- kfree(rpdev->driver_override);
-
- return ret;
+ return rpmsg_register_device_override(rpdev, "rpmsg_ns");
}
EXPORT_SYMBOL(rpmsg_ns_register_device);
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 20c8cd1cde21..523c98b96cb4 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -165,6 +165,8 @@ static inline __rpmsg64 cpu_to_rpmsg64(struct rpmsg_device *rpdev, u64 val)
#if IS_ENABLED(CONFIG_RPMSG)
+int rpmsg_register_device_override(struct rpmsg_device *rpdev,
+ const char *driver_override);
int rpmsg_register_device(struct rpmsg_device *rpdev);
int rpmsg_unregister_device(struct device *parent,
struct rpmsg_channel_info *chinfo);
@@ -192,6 +194,12 @@ ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept);
#else
+static inline int rpmsg_register_device_override(struct rpmsg_device *rpdev,
+ const char *driver_override)
+{
+ return -ENXIO;
+}
+
static inline int rpmsg_register_device(struct rpmsg_device *rpdev)
{
return -ENXIO;
--
2.32.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] rpmsg: use local 'dev' variable
2022-04-29 19:59 [PATCH 0/2] rpmsg: fix after driver_override patchset Krzysztof Kozlowski
2022-04-29 19:59 ` [PATCH 1/2] rpmsg: Fix calling device_lock() on non-initialized device Krzysztof Kozlowski
@ 2022-04-29 19:59 ` Krzysztof Kozlowski
1 sibling, 0 replies; 4+ messages in thread
From: Krzysztof Kozlowski @ 2022-04-29 19:59 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Krzysztof Kozlowski,
Greg Kroah-Hartman, linux-remoteproc, linux-kernel
'&rpdev->dev' is already cached as local variable, so use it to simplify
the code.
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
drivers/rpmsg/rpmsg_core.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 4938fc4eff00..290c1f02da10 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -606,10 +606,10 @@ int rpmsg_register_device_override(struct rpmsg_device *rpdev,
if (driver_override)
strcpy(rpdev->id.name, driver_override);
- dev_set_name(&rpdev->dev, "%s.%s.%d.%d", dev_name(dev->parent),
+ dev_set_name(dev, "%s.%s.%d.%d", dev_name(dev->parent),
rpdev->id.name, rpdev->src, rpdev->dst);
- rpdev->dev.bus = &rpmsg_bus;
+ dev->bus = &rpmsg_bus;
device_initialize(dev);
if (driver_override) {
@@ -627,7 +627,7 @@ int rpmsg_register_device_override(struct rpmsg_device *rpdev,
dev_err(dev, "device_add failed: %d\n", ret);
kfree(rpdev->driver_override);
rpdev->driver_override = NULL;
- put_device(&rpdev->dev);
+ put_device(dev);
}
return ret;
--
2.32.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] rpmsg: Fix calling device_lock() on non-initialized device
2022-04-29 19:59 ` [PATCH 1/2] rpmsg: Fix calling device_lock() on non-initialized device Krzysztof Kozlowski
@ 2022-04-29 21:56 ` Marek Szyprowski
0 siblings, 0 replies; 4+ messages in thread
From: Marek Szyprowski @ 2022-04-29 21:56 UTC (permalink / raw)
To: Krzysztof Kozlowski, Bjorn Andersson, Mathieu Poirier,
Greg Kroah-Hartman, linux-remoteproc, linux-kernel
On 29.04.2022 21:59, Krzysztof Kozlowski wrote:
> driver_set_override() helper uses device_lock() so it should not be
> called before rpmsg_register_device() (which calls device_register()).
> Effect can be seen with CONFIG_DEBUG_MUTEXES:
>
> DEBUG_LOCKS_WARN_ON(lock->magic != lock)
> WARNING: CPU: 3 PID: 57 at kernel/locking/mutex.c:582 __mutex_lock+0x1ec/0x430
> ...
> Call trace:
> __mutex_lock+0x1ec/0x430
> mutex_lock_nested+0x44/0x50
> driver_set_override+0x124/0x150
> qcom_glink_native_probe+0x30c/0x3b0
> glink_rpm_probe+0x274/0x350
> platform_probe+0x6c/0xe0
> really_probe+0x17c/0x3d0
> __driver_probe_device+0x114/0x190
> driver_probe_device+0x3c/0xf0
> ...
>
> Refactor the rpmsg_register_device() function to use two-step device
> registering (initialization + add) and call driver_set_override() in
> proper moment.
>
> This moves the code around, so while at it also NULL-ify the
> rpdev->driver_override in error path to be sure it won't be kfree()
> second time.
>
> Fixes: 42cd402b8fd4 ("rpmsg: Fix kfree() of static memory on setting driver_override")
> Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>
> Commit SHA from linux-next - Greg's tree.
> ---
> drivers/rpmsg/rpmsg_core.c | 33 ++++++++++++++++++++++++++++++---
> drivers/rpmsg/rpmsg_internal.h | 14 +-------------
> drivers/rpmsg/rpmsg_ns.c | 14 +-------------
> include/linux/rpmsg.h | 8 ++++++++
> 4 files changed, 40 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
> index 95fc283f6af7..4938fc4eff00 100644
> --- a/drivers/rpmsg/rpmsg_core.c
> +++ b/drivers/rpmsg/rpmsg_core.c
> @@ -593,24 +593,51 @@ static struct bus_type rpmsg_bus = {
> .remove = rpmsg_dev_remove,
> };
>
> -int rpmsg_register_device(struct rpmsg_device *rpdev)
> +/*
> + * A helper for registering rpmsg device with driver override and name.
> + * Drivers should not be using it, but instead rpmsg_register_device().
> + */
> +int rpmsg_register_device_override(struct rpmsg_device *rpdev,
> + const char *driver_override)
> {
> struct device *dev = &rpdev->dev;
> int ret;
>
> + if (driver_override)
> + strcpy(rpdev->id.name, driver_override);
> +
> dev_set_name(&rpdev->dev, "%s.%s.%d.%d", dev_name(dev->parent),
> rpdev->id.name, rpdev->src, rpdev->dst);
>
> rpdev->dev.bus = &rpmsg_bus;
>
> - ret = device_register(&rpdev->dev);
> + device_initialize(dev);
> + if (driver_override) {
> + ret = driver_set_override(dev, &rpdev->driver_override,
> + driver_override,
> + strlen(driver_override));
> + if (ret) {
> + dev_err(dev, "device_set_override failed: %d\n", ret);
> + return ret;
> + }
> + }
> +
> + ret = device_add(dev);
> if (ret) {
> - dev_err(dev, "device_register failed: %d\n", ret);
> + dev_err(dev, "device_add failed: %d\n", ret);
> + kfree(rpdev->driver_override);
> + rpdev->driver_override = NULL;
> put_device(&rpdev->dev);
> }
>
> return ret;
> }
> +EXPORT_SYMBOL(rpmsg_register_device_override);
> +
> +int rpmsg_register_device(struct rpmsg_device *rpdev)
> +{
> + return rpmsg_register_device_override(rpdev, NULL);
> +}
> EXPORT_SYMBOL(rpmsg_register_device);
>
> /*
> diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
> index 3e81642238d2..a22cd4abe7d1 100644
> --- a/drivers/rpmsg/rpmsg_internal.h
> +++ b/drivers/rpmsg/rpmsg_internal.h
> @@ -94,19 +94,7 @@ int rpmsg_release_channel(struct rpmsg_device *rpdev,
> */
> static inline int rpmsg_ctrldev_register_device(struct rpmsg_device *rpdev)
> {
> - int ret;
> -
> - strcpy(rpdev->id.name, "rpmsg_ctrl");
> - ret = driver_set_override(&rpdev->dev, &rpdev->driver_override,
> - rpdev->id.name, strlen(rpdev->id.name));
> - if (ret)
> - return ret;
> -
> - ret = rpmsg_register_device(rpdev);
> - if (ret)
> - kfree(rpdev->driver_override);
> -
> - return ret;
> + return rpmsg_register_device_override(rpdev, "rpmsg_ctrl");
> }
>
> #endif
> diff --git a/drivers/rpmsg/rpmsg_ns.c b/drivers/rpmsg/rpmsg_ns.c
> index 8eb8f328237e..c70ad03ff2e9 100644
> --- a/drivers/rpmsg/rpmsg_ns.c
> +++ b/drivers/rpmsg/rpmsg_ns.c
> @@ -20,22 +20,10 @@
> */
> int rpmsg_ns_register_device(struct rpmsg_device *rpdev)
> {
> - int ret;
> -
> - strcpy(rpdev->id.name, "rpmsg_ns");
> - ret = driver_set_override(&rpdev->dev, &rpdev->driver_override,
> - rpdev->id.name, strlen(rpdev->id.name));
> - if (ret)
> - return ret;
> -
> rpdev->src = RPMSG_NS_ADDR;
> rpdev->dst = RPMSG_NS_ADDR;
>
> - ret = rpmsg_register_device(rpdev);
> - if (ret)
> - kfree(rpdev->driver_override);
> -
> - return ret;
> + return rpmsg_register_device_override(rpdev, "rpmsg_ns");
> }
> EXPORT_SYMBOL(rpmsg_ns_register_device);
>
> diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
> index 20c8cd1cde21..523c98b96cb4 100644
> --- a/include/linux/rpmsg.h
> +++ b/include/linux/rpmsg.h
> @@ -165,6 +165,8 @@ static inline __rpmsg64 cpu_to_rpmsg64(struct rpmsg_device *rpdev, u64 val)
>
> #if IS_ENABLED(CONFIG_RPMSG)
>
> +int rpmsg_register_device_override(struct rpmsg_device *rpdev,
> + const char *driver_override);
> int rpmsg_register_device(struct rpmsg_device *rpdev);
> int rpmsg_unregister_device(struct device *parent,
> struct rpmsg_channel_info *chinfo);
> @@ -192,6 +194,12 @@ ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept);
>
> #else
>
> +static inline int rpmsg_register_device_override(struct rpmsg_device *rpdev,
> + const char *driver_override)
> +{
> + return -ENXIO;
> +}
> +
> static inline int rpmsg_register_device(struct rpmsg_device *rpdev)
> {
> return -ENXIO;
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-04-29 21:57 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-29 19:59 [PATCH 0/2] rpmsg: fix after driver_override patchset Krzysztof Kozlowski
2022-04-29 19:59 ` [PATCH 1/2] rpmsg: Fix calling device_lock() on non-initialized device Krzysztof Kozlowski
2022-04-29 21:56 ` Marek Szyprowski
2022-04-29 19:59 ` [PATCH 2/2] rpmsg: use local 'dev' variable Krzysztof Kozlowski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.