* [PATCH 0/3] Introduce generic context device bus for IOMMU context isolation
@ 2026-04-14 16:31 Ekansh Gupta via B4 Relay
2026-04-14 16:31 ` [PATCH 1/3] drivers: base: Add generic context device bus Ekansh Gupta via B4 Relay
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Ekansh Gupta via B4 Relay @ 2026-04-14 16:31 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Thierry Reding, Mikko Perttunen, David Airlie, Simona Vetter,
Joerg Roedel, Will Deacon, Robin Murphy, Arnd Bergmann,
Srinivas Kandagatla, Dmitry Baryshkov, Bharath Kumar,
Chenna Kesava Raju
Cc: linux-kernel, driver-core, dri-devel, linux-tegra, iommu,
linux-arm-msm, Ekansh Gupta
This series introduces a generic context device bus to replace driver-specific
implementations and enable proper IOMMU handling of synthetic context bank
devices used by accelerator and GPU drivers.
Background:
-----------
During review of the fastrpc driver changes [1], it was pointed out that using
a platform driver for compute bank (CB) devices was incorrect since these are
synthetic IOMMU context banks, not real platform devices. The platform driver
approach also had a race condition where device nodes were created before
channel resources were initialized, and probe was async, allowing applications
to open devices before sessions were available.
The reviewer suggested following the pattern used in host1x_memory_context_list_init()
and creating devices manually. During review of the QDA driver [2], it was
further suggested to create a generic bus type that could be shared across
multiple drivers rather than having each driver implement its own bus.
This series implements that suggestion by:
1. Creating a generic context_device_bus_type in drivers/base/
2. Migrating the existing host1x driver to use it
3. Converting fastrpc to use it, fixing the race condition in the process
References:
-----------
[1] Fastrpc platform driver review:
https://lore.kernel.org/all/golcrcr6voafr3fqsnihyjyut36sii55vzws4josfhkjjg3nie@ur43qq2kvlsv/
[2] QDA driver review requesting generic bus:
https://lore.kernel.org/all/en5tdgemre7vq5qihe6wnkbrro24vtzwfxwqrpnrrmugxoszs7@x2ox64zeznvd/
Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
---
Ekansh Gupta (3):
drivers: base: Add generic context device bus
gpu: host1x: Migrate to generic context device bus
misc: fastrpc: Use context device bus for compute banks
drivers/base/Kconfig | 3 +
drivers/base/Makefile | 1 +
drivers/base/context_bus.c | 24 ++++++
drivers/gpu/host1x/Kconfig | 5 +-
drivers/gpu/host1x/Makefile | 1 -
drivers/gpu/host1x/context.c | 2 +-
drivers/gpu/host1x/context.h | 3 +-
drivers/gpu/host1x/context_bus.c | 26 ------
drivers/iommu/iommu.c | 6 +-
drivers/misc/Kconfig | 1 +
drivers/misc/fastrpc.c | 180 +++++++++++++++++++++++++++------------
include/linux/context_bus.h | 15 ++++
12 files changed, 174 insertions(+), 93 deletions(-)
---
base-commit: 1c7cc4904160c6fc6377564140062d68a3dc93a0
change-id: 20260414-computebus-e852f994ee25
Best regards,
--
Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/3] drivers: base: Add generic context device bus
2026-04-14 16:31 [PATCH 0/3] Introduce generic context device bus for IOMMU context isolation Ekansh Gupta via B4 Relay
@ 2026-04-14 16:31 ` Ekansh Gupta via B4 Relay
2026-04-14 16:49 ` Greg Kroah-Hartman
` (2 more replies)
2026-04-14 16:31 ` [PATCH 2/3] gpu: host1x: Migrate to " Ekansh Gupta via B4 Relay
2026-04-14 16:31 ` [PATCH 3/3] misc: fastrpc: Use context device bus for compute banks Ekansh Gupta via B4 Relay
2 siblings, 3 replies; 12+ messages in thread
From: Ekansh Gupta via B4 Relay @ 2026-04-14 16:31 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Thierry Reding, Mikko Perttunen, David Airlie, Simona Vetter,
Joerg Roedel, Will Deacon, Robin Murphy, Arnd Bergmann,
Srinivas Kandagatla, Dmitry Baryshkov, Bharath Kumar,
Chenna Kesava Raju
Cc: linux-kernel, driver-core, dri-devel, linux-tegra, iommu,
linux-arm-msm, Ekansh Gupta
From: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
Introduce a new generic bus type for synthetic context bank devices
that require IOMMU context isolation. This bus provides a shared
infrastructure for accelerator and GPU drivers that create virtual
devices representing IOMMU context banks.
Currently, drivers like host1x implement their own bus types for
context devices. This generic implementation allows multiple drivers
to share the same bus infrastructure, simplifying the IOMMU subsystem
integration and reducing code duplication.
Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
---
drivers/base/Kconfig | 3 +++
drivers/base/Makefile | 1 +
drivers/base/context_bus.c | 24 ++++++++++++++++++++++++
include/linux/context_bus.h | 15 +++++++++++++++
4 files changed, 43 insertions(+)
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index f7d385cbd3ba..479bc4bb442b 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -4,6 +4,9 @@ menu "Generic Driver Options"
config AUXILIARY_BUS
bool
+config CONTEXT_DEVICE_BUS
+ bool
+
config UEVENT_HELPER
bool "Support for uevent helper"
help
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 8074a10183dc..ab9a0b2dc73b 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -8,6 +8,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \
topology.o container.o property.o cacheinfo.o \
swnode.o faux.o
obj-$(CONFIG_AUXILIARY_BUS) += auxiliary.o
+obj-$(CONFIG_CONTEXT_DEVICE_BUS) += context_bus.o
obj-$(CONFIG_DEVTMPFS) += devtmpfs.o
obj-y += power/
obj-$(CONFIG_ISA_BUS_API) += isa.o
diff --git a/drivers/base/context_bus.c b/drivers/base/context_bus.c
new file mode 100644
index 000000000000..6ddb6c27bf69
--- /dev/null
+++ b/drivers/base/context_bus.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+
+#include <linux/context_bus.h>
+#include <linux/init.h>
+
+const struct bus_type context_device_bus_type = {
+ .name = "context-device",
+};
+EXPORT_SYMBOL_GPL(context_device_bus_type);
+
+static int __init context_device_bus_init(void)
+{
+ int err;
+
+ err = bus_register(&context_device_bus_type);
+ if (err < 0) {
+ pr_err("context-device bus registration failed: %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+postcore_initcall(context_device_bus_init);
diff --git a/include/linux/context_bus.h b/include/linux/context_bus.h
new file mode 100644
index 000000000000..0cd44cb5b147
--- /dev/null
+++ b/include/linux/context_bus.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef __LINUX_CONTEXT_BUS_H
+#define __LINUX_CONTEXT_BUS_H
+
+#include <linux/device.h>
+
+#ifdef CONFIG_CONTEXT_DEVICE_BUS
+extern const struct bus_type context_device_bus_type;
+#endif
+
+#endif /* __LINUX_CONTEXT_BUS_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/3] gpu: host1x: Migrate to generic context device bus
2026-04-14 16:31 [PATCH 0/3] Introduce generic context device bus for IOMMU context isolation Ekansh Gupta via B4 Relay
2026-04-14 16:31 ` [PATCH 1/3] drivers: base: Add generic context device bus Ekansh Gupta via B4 Relay
@ 2026-04-14 16:31 ` Ekansh Gupta via B4 Relay
2026-04-14 16:31 ` [PATCH 3/3] misc: fastrpc: Use context device bus for compute banks Ekansh Gupta via B4 Relay
2 siblings, 0 replies; 12+ messages in thread
From: Ekansh Gupta via B4 Relay @ 2026-04-14 16:31 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Thierry Reding, Mikko Perttunen, David Airlie, Simona Vetter,
Joerg Roedel, Will Deacon, Robin Murphy, Arnd Bergmann,
Srinivas Kandagatla, Dmitry Baryshkov, Bharath Kumar,
Chenna Kesava Raju
Cc: linux-kernel, driver-core, dri-devel, linux-tegra, iommu,
linux-arm-msm, Ekansh Gupta
From: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
Replace the host1x-specific context device bus with the generic
context_device_bus_type. This eliminates driver-specific bus
infrastructure in favor of shared code in the driver core.
The host1x driver creates synthetic context bank devices to represent
IOMMU contexts for memory isolation. These devices were previously
registered on a host1x-specific bus ("host1x-context"), but this
functionality is now provided by the generic "context-device" bus.
The IOMMU subsystem is updated to recognize the generic bus instead
of the host1x-specific one, allowing proper IOMMU operations on
context devices.
This change maintains functional equivalence - context devices still
work the same way, just on a different bus. The device names remain
"host1x-ctx.N" to preserve any userspace dependencies.
Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
---
drivers/gpu/host1x/Kconfig | 5 +----
drivers/gpu/host1x/Makefile | 1 -
drivers/gpu/host1x/context.c | 2 +-
drivers/gpu/host1x/context.h | 3 +--
drivers/gpu/host1x/context_bus.c | 26 --------------------------
drivers/iommu/iommu.c | 6 +++---
6 files changed, 6 insertions(+), 37 deletions(-)
diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig
index e6c78ae2003a..e3e3896f4d71 100644
--- a/drivers/gpu/host1x/Kconfig
+++ b/drivers/gpu/host1x/Kconfig
@@ -1,13 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
-config TEGRA_HOST1X_CONTEXT_BUS
- bool
-
config TEGRA_HOST1X
tristate "NVIDIA Tegra host1x driver"
depends on ARCH_TEGRA || COMPILE_TEST
select DMA_SHARED_BUFFER
- select TEGRA_HOST1X_CONTEXT_BUS
+ select CONTEXT_DEVICE_BUS
select IOMMU_IOVA
help
Driver for the NVIDIA Tegra host1x hardware.
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index fead483af0b4..2ccd9a5f1c65 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -23,4 +23,3 @@ host1x-$(CONFIG_IOMMU_API) += \
context.o
obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
-obj-$(CONFIG_TEGRA_HOST1X_CONTEXT_BUS) += context_bus.o
diff --git a/drivers/gpu/host1x/context.c b/drivers/gpu/host1x/context.c
index d50d41c20561..6411c17cc060 100644
--- a/drivers/gpu/host1x/context.c
+++ b/drivers/gpu/host1x/context.c
@@ -54,7 +54,7 @@ int host1x_memory_context_list_init(struct host1x *host1x)
ctx->dev.dma_mask = &ctx->dma_mask;
ctx->dev.coherent_dma_mask = ctx->dma_mask;
dev_set_name(&ctx->dev, "host1x-ctx.%d", i);
- ctx->dev.bus = &host1x_context_device_bus_type;
+ ctx->dev.bus = &context_device_bus_type;
ctx->dev.parent = host1x->dev;
ctx->dev.release = host1x_memory_context_release;
diff --git a/drivers/gpu/host1x/context.h b/drivers/gpu/host1x/context.h
index 3e03bc1d3bac..87ae522fafc7 100644
--- a/drivers/gpu/host1x/context.h
+++ b/drivers/gpu/host1x/context.h
@@ -8,13 +8,12 @@
#ifndef __HOST1X_CONTEXT_H
#define __HOST1X_CONTEXT_H
+#include <linux/context_bus.h>
#include <linux/mutex.h>
#include <linux/refcount.h>
struct host1x;
-extern struct bus_type host1x_context_device_bus_type;
-
struct host1x_memory_context_list {
struct mutex lock;
struct host1x_memory_context *devs;
diff --git a/drivers/gpu/host1x/context_bus.c b/drivers/gpu/host1x/context_bus.c
deleted file mode 100644
index 7cd0e1a5edd1..000000000000
--- a/drivers/gpu/host1x/context_bus.c
+++ /dev/null
@@ -1,26 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2021, NVIDIA Corporation.
- */
-
-#include <linux/device.h>
-#include <linux/of.h>
-
-const struct bus_type host1x_context_device_bus_type = {
- .name = "host1x-context",
-};
-EXPORT_SYMBOL_GPL(host1x_context_device_bus_type);
-
-static int __init host1x_context_device_bus_init(void)
-{
- int err;
-
- err = bus_register(&host1x_context_device_bus_type);
- if (err < 0) {
- pr_err("bus type registration failed: %d\n", err);
- return err;
- }
-
- return 0;
-}
-postcore_initcall(host1x_context_device_bus_init);
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 61c12ba78206..f01a13e2e634 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -16,7 +16,7 @@
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/errno.h>
-#include <linux/host1x_context_bus.h>
+#include <linux/context_bus.h>
#include <linux/iommu.h>
#include <linux/iommufd.h>
#include <linux/idr.h>
@@ -173,8 +173,8 @@ static const struct bus_type * const iommu_buses[] = {
#ifdef CONFIG_FSL_MC_BUS
&fsl_mc_bus_type,
#endif
-#ifdef CONFIG_TEGRA_HOST1X_CONTEXT_BUS
- &host1x_context_device_bus_type,
+#ifdef CONFIG_CONTEXT_DEVICE_BUS
+ &context_device_bus_type,
#endif
#ifdef CONFIG_CDX_BUS
&cdx_bus_type,
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/3] misc: fastrpc: Use context device bus for compute banks
2026-04-14 16:31 [PATCH 0/3] Introduce generic context device bus for IOMMU context isolation Ekansh Gupta via B4 Relay
2026-04-14 16:31 ` [PATCH 1/3] drivers: base: Add generic context device bus Ekansh Gupta via B4 Relay
2026-04-14 16:31 ` [PATCH 2/3] gpu: host1x: Migrate to " Ekansh Gupta via B4 Relay
@ 2026-04-14 16:31 ` Ekansh Gupta via B4 Relay
2026-04-14 17:59 ` Dmitry Baryshkov
` (2 more replies)
2 siblings, 3 replies; 12+ messages in thread
From: Ekansh Gupta via B4 Relay @ 2026-04-14 16:31 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Thierry Reding, Mikko Perttunen, David Airlie, Simona Vetter,
Joerg Roedel, Will Deacon, Robin Murphy, Arnd Bergmann,
Srinivas Kandagatla, Dmitry Baryshkov, Bharath Kumar,
Chenna Kesava Raju
Cc: linux-kernel, driver-core, dri-devel, linux-tegra, iommu,
linux-arm-msm, Ekansh Gupta
From: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
Replace the platform driver approach for compute bank (CB) devices
with the generic context_device_bus_type. Compute bank devices are
synthetic IOMMU context banks, not real platform devices, so using
the context device bus provides a more accurate representation in
the device model.
Currently, fastrpc used of_platform_populate() to create platform
devices for each "qcom,fastrpc-compute-cb" DT node, with a platform
driver (fastrpc_cb_driver) to handle probe/remove. This approach
had a race condition: device nodes were created before channel
resources (like spin_lock) were initialized, and probe was async,
so applications could open the device before sessions were available.
This patch addresses the race by manually creating and configuring
CB devices synchronously during fastrpc_rpmsg_probe(), after all
channel resources are initialized. The approach follows the pattern
used in host1x_memory_context_list_init().
Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
---
drivers/misc/Kconfig | 1 +
drivers/misc/fastrpc.c | 180 ++++++++++++++++++++++++++++++++++---------------
2 files changed, 125 insertions(+), 56 deletions(-)
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 00683bf06258..b501462a4548 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -304,6 +304,7 @@ config QCOM_FASTRPC
depends on RPMSG
select DMA_SHARED_BUFFER
select QCOM_SCM
+ select CONTEXT_DEVICE_BUS
help
Provides a communication mechanism that allows for clients to
make remote method invocations across processor boundary to
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 1080f9acf70a..f66fd3eea5fa 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -13,9 +13,9 @@
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of.h>
-#include <linux/platform_device.h>
+#include <linux/of_device.h>
#include <linux/sort.h>
-#include <linux/of_platform.h>
+#include <linux/context_bus.h>
#include <linux/rpmsg.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
@@ -250,6 +250,18 @@ struct fastrpc_invoke_ctx {
struct fastrpc_channel_ctx *cctx;
};
+/**
+ * struct fastrpc_cb_device - Compute bank device wrapper
+ * @dev: Device structure
+ * @sess: Back-pointer to the session context
+ */
+struct fastrpc_cb_device {
+ struct device dev;
+ struct fastrpc_session_ctx *sess;
+};
+
+#define to_fastrpc_cb_device(d) container_of(d, struct fastrpc_cb_device, dev)
+
struct fastrpc_session_ctx {
struct device *dev;
int sid;
@@ -2190,92 +2202,156 @@ static const struct file_operations fastrpc_fops = {
.compat_ioctl = fastrpc_device_ioctl,
};
-static int fastrpc_cb_probe(struct platform_device *pdev)
+static void fastrpc_cb_dev_release(struct device *dev)
+{
+ struct fastrpc_cb_device *cb_dev = to_fastrpc_cb_device(dev);
+
+ of_node_put(dev->of_node);
+ kfree(cb_dev);
+}
+
+static int fastrpc_create_cb_device(struct fastrpc_channel_ctx *cctx,
+ struct device *parent,
+ struct device_node *cb_node)
{
- struct fastrpc_channel_ctx *cctx;
struct fastrpc_session_ctx *sess;
- struct device *dev = &pdev->dev;
- int i, sessions = 0;
+ struct fastrpc_cb_device *cb_dev;
unsigned long flags;
- int rc;
- u32 dma_bits;
-
- cctx = dev_get_drvdata(dev->parent);
- if (!cctx)
- return -EINVAL;
+ int i, sessions = 0, rc;
+ u32 dma_bits, sid = 0;
- of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions);
+ /* Read SID early so it can be used in the device name */
+ of_property_read_u32(cb_node, "reg", &sid);
+ of_property_read_u32(cb_node, "qcom,nsessions", &sessions);
spin_lock_irqsave(&cctx->lock, flags);
if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) {
- dev_err(&pdev->dev, "too many sessions\n");
+ dev_err(parent, "too many sessions\n");
spin_unlock_irqrestore(&cctx->lock, flags);
return -ENOSPC;
}
dma_bits = cctx->soc_data->dma_addr_bits_default;
+ if (cctx->domain_id == CDSP_DOMAIN_ID)
+ dma_bits = cctx->soc_data->dma_addr_bits_cdsp;
+
sess = &cctx->session[cctx->sesscount++];
sess->used = false;
sess->valid = true;
- sess->dev = dev;
- dev_set_drvdata(dev, sess);
+ sess->sid = sid;
+ spin_unlock_irqrestore(&cctx->lock, flags);
- if (cctx->domain_id == CDSP_DOMAIN_ID)
- dma_bits = cctx->soc_data->dma_addr_bits_cdsp;
+ cb_dev = kzalloc_obj(*cb_dev);
+ if (!cb_dev)
+ return -ENOMEM;
- if (of_property_read_u32(dev->of_node, "reg", &sess->sid))
- dev_info(dev, "FastRPC Session ID not specified in DT\n");
+ cb_dev->sess = sess;
- if (sessions > 0) {
- struct fastrpc_session_ctx *dup_sess;
+ device_initialize(&cb_dev->dev);
+ cb_dev->dev.parent = parent;
+ cb_dev->dev.bus = &context_device_bus_type;
+ cb_dev->dev.release = fastrpc_cb_dev_release;
+ cb_dev->dev.of_node = of_node_get(cb_node);
+ cb_dev->dev.dma_mask = &cb_dev->dev.coherent_dma_mask;
+ cb_dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ dev_set_name(&cb_dev->dev, "%s:compute-cb@%u", dev_name(parent), sid);
+ rc = device_add(&cb_dev->dev);
+ if (rc) {
+ dev_err(parent, "failed to add CB device: %d\n", rc);
+ goto err_put;
+ }
+
+ rc = of_dma_configure(&cb_dev->dev, cb_node, true);
+ if (rc) {
+ dev_err(parent, "of_dma_configure failed for CB device: %d\n", rc);
+ goto err_del;
+ }
+
+ rc = dma_set_mask(&cb_dev->dev, DMA_BIT_MASK(dma_bits));
+ if (rc) {
+ dev_err(parent, "%u-bit DMA enable failed\n", dma_bits);
+ goto err_del;
+ }
+
+ sess->dev = &cb_dev->dev;
+
+ if (sessions > 0) {
+ spin_lock_irqsave(&cctx->lock, flags);
for (i = 1; i < sessions; i++) {
+ struct fastrpc_session_ctx *dup_sess;
+
if (cctx->sesscount >= FASTRPC_MAX_SESSIONS)
break;
dup_sess = &cctx->session[cctx->sesscount++];
memcpy(dup_sess, sess, sizeof(*dup_sess));
}
- }
- spin_unlock_irqrestore(&cctx->lock, flags);
- rc = dma_set_mask(dev, DMA_BIT_MASK(dma_bits));
- if (rc) {
- dev_err(dev, "%u-bit DMA enable failed\n", dma_bits);
- return rc;
+ spin_unlock_irqrestore(&cctx->lock, flags);
}
return 0;
+
+err_del:
+ device_del(&cb_dev->dev);
+err_put:
+ of_node_put(cb_dev->dev.of_node);
+ put_device(&cb_dev->dev);
+ return rc;
}
-static void fastrpc_cb_remove(struct platform_device *pdev)
+static void fastrpc_depopulate_cb_devices(struct fastrpc_channel_ctx *cctx)
{
- struct fastrpc_channel_ctx *cctx = dev_get_drvdata(pdev->dev.parent);
- struct fastrpc_session_ctx *sess = dev_get_drvdata(&pdev->dev);
unsigned long flags;
- int i;
+ int i, j;
spin_lock_irqsave(&cctx->lock, flags);
for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) {
- if (cctx->session[i].sid == sess->sid) {
+ if (cctx->session[i].valid) {
cctx->session[i].valid = false;
cctx->sesscount--;
}
}
spin_unlock_irqrestore(&cctx->lock, flags);
+
+ for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) {
+ struct device *dev = cctx->session[i].dev;
+
+ if (!dev)
+ continue;
+
+ /* Unregister the device once */
+ device_unregister(dev);
+
+ /* Clear this dev pointer from all sessions that share it */
+ for (j = i; j < FASTRPC_MAX_SESSIONS; j++) {
+ if (cctx->session[j].dev == dev)
+ cctx->session[j].dev = NULL;
+ }
+ }
}
-static const struct of_device_id fastrpc_match_table[] = {
- { .compatible = "qcom,fastrpc-compute-cb", },
- {}
-};
+static int fastrpc_populate_cb_devices(struct fastrpc_channel_ctx *cctx,
+ struct device *parent,
+ struct device_node *parent_node)
+{
+ struct device_node *child;
+ int ret = 0;
-static struct platform_driver fastrpc_cb_driver = {
- .probe = fastrpc_cb_probe,
- .remove = fastrpc_cb_remove,
- .driver = {
- .name = "qcom,fastrpc-cb",
- .of_match_table = fastrpc_match_table,
- .suppress_bind_attrs = true,
- },
-};
+ for_each_child_of_node(parent_node, child) {
+ if (!of_device_is_compatible(child, "qcom,fastrpc-compute-cb"))
+ continue;
+
+ ret = fastrpc_create_cb_device(cctx, parent, child);
+ if (ret) {
+ dev_err(parent, "failed to create CB device for %s: %d\n",
+ child->name, ret);
+ of_node_put(child);
+ fastrpc_depopulate_cb_devices(cctx);
+ return ret;
+ }
+ }
+
+ return 0;
+}
static int fastrpc_device_register(struct device *dev, struct fastrpc_channel_ctx *cctx,
bool is_secured, const char *domain)
@@ -2441,7 +2517,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
data->domain_id = domain_id;
data->rpdev = rpdev;
- err = of_platform_populate(rdev->of_node, NULL, NULL, rdev);
+ err = fastrpc_populate_cb_devices(data, rdev, rdev->of_node);
if (err)
goto err_deregister_fdev;
@@ -2496,7 +2572,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
if (cctx->remote_heap)
fastrpc_buf_free(cctx->remote_heap);
- of_platform_depopulate(&rpdev->dev);
+ fastrpc_depopulate_cb_devices(cctx);
fastrpc_channel_ctx_put(cctx);
}
@@ -2558,16 +2634,9 @@ static int fastrpc_init(void)
{
int ret;
- ret = platform_driver_register(&fastrpc_cb_driver);
- if (ret < 0) {
- pr_err("fastrpc: failed to register cb driver\n");
- return ret;
- }
-
ret = register_rpmsg_driver(&fastrpc_driver);
if (ret < 0) {
pr_err("fastrpc: failed to register rpmsg driver\n");
- platform_driver_unregister(&fastrpc_cb_driver);
return ret;
}
@@ -2577,7 +2646,6 @@ module_init(fastrpc_init);
static void fastrpc_exit(void)
{
- platform_driver_unregister(&fastrpc_cb_driver);
unregister_rpmsg_driver(&fastrpc_driver);
}
module_exit(fastrpc_exit);
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] drivers: base: Add generic context device bus
2026-04-14 16:31 ` [PATCH 1/3] drivers: base: Add generic context device bus Ekansh Gupta via B4 Relay
@ 2026-04-14 16:49 ` Greg Kroah-Hartman
2026-04-15 17:34 ` Vishnu Reddy
2026-04-15 11:25 ` Srinivas Kandagatla
2026-04-15 17:16 ` Vishnu Reddy
2 siblings, 1 reply; 12+ messages in thread
From: Greg Kroah-Hartman @ 2026-04-14 16:49 UTC (permalink / raw)
To: ekansh.gupta
Cc: Rafael J. Wysocki, Danilo Krummrich, Thierry Reding,
Mikko Perttunen, David Airlie, Simona Vetter, Joerg Roedel,
Will Deacon, Robin Murphy, Arnd Bergmann, Srinivas Kandagatla,
Dmitry Baryshkov, Bharath Kumar, Chenna Kesava Raju, linux-kernel,
driver-core, dri-devel, linux-tegra, iommu, linux-arm-msm
On Tue, Apr 14, 2026 at 10:01:15PM +0530, Ekansh Gupta via B4 Relay wrote:
> From: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
>
> Introduce a new generic bus type for synthetic context bank devices
> that require IOMMU context isolation. This bus provides a shared
> infrastructure for accelerator and GPU drivers that create virtual
> devices representing IOMMU context banks.
>
> Currently, drivers like host1x implement their own bus types for
> context devices. This generic implementation allows multiple drivers
> to share the same bus infrastructure, simplifying the IOMMU subsystem
> integration and reducing code duplication.
>
> Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
> ---
> drivers/base/Kconfig | 3 +++
> drivers/base/Makefile | 1 +
> drivers/base/context_bus.c | 24 ++++++++++++++++++++++++
> include/linux/context_bus.h | 15 +++++++++++++++
> 4 files changed, 43 insertions(+)
>
> diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
> index f7d385cbd3ba..479bc4bb442b 100644
> --- a/drivers/base/Kconfig
> +++ b/drivers/base/Kconfig
> @@ -4,6 +4,9 @@ menu "Generic Driver Options"
> config AUXILIARY_BUS
> bool
>
> +config CONTEXT_DEVICE_BUS
> + bool
So this is a context-free bus? I.e. no documentation?
:)
This feels really odd, this "bus" isn't doing anything at all. So why
do you need it and can't use auxbus or faux?
You say something about an iommu, but yet this has no information about
an iommu at all, so why are they somehow special?
You need to provide a lot more information here, sorry.
greg k-h
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] misc: fastrpc: Use context device bus for compute banks
2026-04-14 16:31 ` [PATCH 3/3] misc: fastrpc: Use context device bus for compute banks Ekansh Gupta via B4 Relay
@ 2026-04-14 17:59 ` Dmitry Baryshkov
2026-04-15 11:36 ` Srinivas Kandagatla
2026-04-15 16:05 ` Vishnu Reddy
2 siblings, 0 replies; 12+ messages in thread
From: Dmitry Baryshkov @ 2026-04-14 17:59 UTC (permalink / raw)
To: ekansh.gupta
Cc: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Thierry Reding, Mikko Perttunen, David Airlie, Simona Vetter,
Joerg Roedel, Will Deacon, Robin Murphy, Arnd Bergmann,
Srinivas Kandagatla, Bharath Kumar, Chenna Kesava Raju,
linux-kernel, driver-core, dri-devel, linux-tegra, iommu,
linux-arm-msm
On Tue, Apr 14, 2026 at 10:01:17PM +0530, Ekansh Gupta via B4 Relay wrote:
> From: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
>
> Replace the platform driver approach for compute bank (CB) devices
> with the generic context_device_bus_type. Compute bank devices are
> synthetic IOMMU context banks, not real platform devices, so using
> the context device bus provides a more accurate representation in
> the device model.
>
> Currently, fastrpc used of_platform_populate() to create platform
> devices for each "qcom,fastrpc-compute-cb" DT node, with a platform
> driver (fastrpc_cb_driver) to handle probe/remove. This approach
> had a race condition: device nodes were created before channel
> resources (like spin_lock) were initialized, and probe was async,
> so applications could open the device before sessions were available.
>
> This patch addresses the race by manually creating and configuring
> CB devices synchronously during fastrpc_rpmsg_probe(), after all
> channel resources are initialized. The approach follows the pattern
> used in host1x_memory_context_list_init().
>
> Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
> ---
> drivers/misc/Kconfig | 1 +
> drivers/misc/fastrpc.c | 180 ++++++++++++++++++++++++++++++++++---------------
> 2 files changed, 125 insertions(+), 56 deletions(-)
>
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index 00683bf06258..b501462a4548 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -304,6 +304,7 @@ config QCOM_FASTRPC
> depends on RPMSG
> select DMA_SHARED_BUFFER
> select QCOM_SCM
> + select CONTEXT_DEVICE_BUS
> help
> Provides a communication mechanism that allows for clients to
> make remote method invocations across processor boundary to
> diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
> index 1080f9acf70a..f66fd3eea5fa 100644
> --- a/drivers/misc/fastrpc.c
> +++ b/drivers/misc/fastrpc.c
> @@ -13,9 +13,9 @@
> #include <linux/module.h>
> #include <linux/of_address.h>
> #include <linux/of.h>
> -#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> #include <linux/sort.h>
> -#include <linux/of_platform.h>
> +#include <linux/context_bus.h>
> #include <linux/rpmsg.h>
> #include <linux/scatterlist.h>
> #include <linux/slab.h>
> @@ -250,6 +250,18 @@ struct fastrpc_invoke_ctx {
> struct fastrpc_channel_ctx *cctx;
> };
>
> +/**
> + * struct fastrpc_cb_device - Compute bank device wrapper
> + * @dev: Device structure
> + * @sess: Back-pointer to the session context
> + */
> +struct fastrpc_cb_device {
> + struct device dev;
> + struct fastrpc_session_ctx *sess;
> +};
> +
> +#define to_fastrpc_cb_device(d) container_of(d, struct fastrpc_cb_device, dev)
> +
> struct fastrpc_session_ctx {
> struct device *dev;
> int sid;
> @@ -2190,92 +2202,156 @@ static const struct file_operations fastrpc_fops = {
> .compat_ioctl = fastrpc_device_ioctl,
> };
>
> -static int fastrpc_cb_probe(struct platform_device *pdev)
> +static void fastrpc_cb_dev_release(struct device *dev)
> +{
> + struct fastrpc_cb_device *cb_dev = to_fastrpc_cb_device(dev);
> +
> + of_node_put(dev->of_node);
> + kfree(cb_dev);
> +}
> +
> +static int fastrpc_create_cb_device(struct fastrpc_channel_ctx *cctx,
> + struct device *parent,
> + struct device_node *cb_node)
> {
> - struct fastrpc_channel_ctx *cctx;
> struct fastrpc_session_ctx *sess;
> - struct device *dev = &pdev->dev;
> - int i, sessions = 0;
> + struct fastrpc_cb_device *cb_dev;
> unsigned long flags;
> - int rc;
> - u32 dma_bits;
> -
> - cctx = dev_get_drvdata(dev->parent);
> - if (!cctx)
> - return -EINVAL;
> + int i, sessions = 0, rc;
> + u32 dma_bits, sid = 0;
>
> - of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions);
> + /* Read SID early so it can be used in the device name */
> + of_property_read_u32(cb_node, "reg", &sid);
> + of_property_read_u32(cb_node, "qcom,nsessions", &sessions);
>
> spin_lock_irqsave(&cctx->lock, flags);
> if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) {
> - dev_err(&pdev->dev, "too many sessions\n");
> + dev_err(parent, "too many sessions\n");
> spin_unlock_irqrestore(&cctx->lock, flags);
> return -ENOSPC;
> }
> dma_bits = cctx->soc_data->dma_addr_bits_default;
> + if (cctx->domain_id == CDSP_DOMAIN_ID)
> + dma_bits = cctx->soc_data->dma_addr_bits_cdsp;
> +
> sess = &cctx->session[cctx->sesscount++];
> sess->used = false;
> sess->valid = true;
> - sess->dev = dev;
> - dev_set_drvdata(dev, sess);
> + sess->sid = sid;
> + spin_unlock_irqrestore(&cctx->lock, flags);
>
> - if (cctx->domain_id == CDSP_DOMAIN_ID)
> - dma_bits = cctx->soc_data->dma_addr_bits_cdsp;
> + cb_dev = kzalloc_obj(*cb_dev);
> + if (!cb_dev)
> + return -ENOMEM;
>
> - if (of_property_read_u32(dev->of_node, "reg", &sess->sid))
> - dev_info(dev, "FastRPC Session ID not specified in DT\n");
> + cb_dev->sess = sess;
>
> - if (sessions > 0) {
> - struct fastrpc_session_ctx *dup_sess;
> + device_initialize(&cb_dev->dev);
> + cb_dev->dev.parent = parent;
> + cb_dev->dev.bus = &context_device_bus_type;
> + cb_dev->dev.release = fastrpc_cb_dev_release;
> + cb_dev->dev.of_node = of_node_get(cb_node);
> + cb_dev->dev.dma_mask = &cb_dev->dev.coherent_dma_mask;
> + cb_dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
> + dev_set_name(&cb_dev->dev, "%s:compute-cb@%u", dev_name(parent), sid);
Please extract this code to a helper function inside the context bus and
use it for both host1x and fastrpc.
>
> + rc = device_add(&cb_dev->dev);
> + if (rc) {
> + dev_err(parent, "failed to add CB device: %d\n", rc);
> + goto err_put;
> + }
> +
> + rc = of_dma_configure(&cb_dev->dev, cb_node, true);
> + if (rc) {
> + dev_err(parent, "of_dma_configure failed for CB device: %d\n", rc);
> + goto err_del;
> + }
> +
> + rc = dma_set_mask(&cb_dev->dev, DMA_BIT_MASK(dma_bits));
> + if (rc) {
> + dev_err(parent, "%u-bit DMA enable failed\n", dma_bits);
> + goto err_del;
> + }
> +
> + sess->dev = &cb_dev->dev;
> +
> + if (sessions > 0) {
> + spin_lock_irqsave(&cctx->lock, flags);
> for (i = 1; i < sessions; i++) {
> + struct fastrpc_session_ctx *dup_sess;
> +
> if (cctx->sesscount >= FASTRPC_MAX_SESSIONS)
> break;
> dup_sess = &cctx->session[cctx->sesscount++];
> memcpy(dup_sess, sess, sizeof(*dup_sess));
> }
> - }
> - spin_unlock_irqrestore(&cctx->lock, flags);
> - rc = dma_set_mask(dev, DMA_BIT_MASK(dma_bits));
> - if (rc) {
> - dev_err(dev, "%u-bit DMA enable failed\n", dma_bits);
> - return rc;
> + spin_unlock_irqrestore(&cctx->lock, flags);
> }
>
> return 0;
> +
> +err_del:
> + device_del(&cb_dev->dev);
> +err_put:
> + of_node_put(cb_dev->dev.of_node);
> + put_device(&cb_dev->dev);
> + return rc;
> }
>
> -static void fastrpc_cb_remove(struct platform_device *pdev)
> +static void fastrpc_depopulate_cb_devices(struct fastrpc_channel_ctx *cctx)
> {
> - struct fastrpc_channel_ctx *cctx = dev_get_drvdata(pdev->dev.parent);
> - struct fastrpc_session_ctx *sess = dev_get_drvdata(&pdev->dev);
> unsigned long flags;
> - int i;
> + int i, j;
>
> spin_lock_irqsave(&cctx->lock, flags);
> for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) {
> - if (cctx->session[i].sid == sess->sid) {
> + if (cctx->session[i].valid) {
> cctx->session[i].valid = false;
> cctx->sesscount--;
> }
> }
> spin_unlock_irqrestore(&cctx->lock, flags);
> +
> + for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) {
> + struct device *dev = cctx->session[i].dev;
> +
> + if (!dev)
> + continue;
> +
> + /* Unregister the device once */
> + device_unregister(dev);
> +
> + /* Clear this dev pointer from all sessions that share it */
> + for (j = i; j < FASTRPC_MAX_SESSIONS; j++) {
> + if (cctx->session[j].dev == dev)
> + cctx->session[j].dev = NULL;
> + }
> + }
> }
>
> -static const struct of_device_id fastrpc_match_table[] = {
> - { .compatible = "qcom,fastrpc-compute-cb", },
> - {}
> -};
> +static int fastrpc_populate_cb_devices(struct fastrpc_channel_ctx *cctx,
> + struct device *parent,
> + struct device_node *parent_node)
> +{
> + struct device_node *child;
> + int ret = 0;
>
> -static struct platform_driver fastrpc_cb_driver = {
> - .probe = fastrpc_cb_probe,
> - .remove = fastrpc_cb_remove,
> - .driver = {
> - .name = "qcom,fastrpc-cb",
> - .of_match_table = fastrpc_match_table,
> - .suppress_bind_attrs = true,
> - },
> -};
> + for_each_child_of_node(parent_node, child) {
> + if (!of_device_is_compatible(child, "qcom,fastrpc-compute-cb"))
> + continue;
> +
> + ret = fastrpc_create_cb_device(cctx, parent, child);
> + if (ret) {
> + dev_err(parent, "failed to create CB device for %s: %d\n",
> + child->name, ret);
> + of_node_put(child);
> + fastrpc_depopulate_cb_devices(cctx);
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
>
> static int fastrpc_device_register(struct device *dev, struct fastrpc_channel_ctx *cctx,
> bool is_secured, const char *domain)
> @@ -2441,7 +2517,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
> data->domain_id = domain_id;
> data->rpdev = rpdev;
>
> - err = of_platform_populate(rdev->of_node, NULL, NULL, rdev);
> + err = fastrpc_populate_cb_devices(data, rdev, rdev->of_node);
> if (err)
> goto err_deregister_fdev;
>
> @@ -2496,7 +2572,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
> if (cctx->remote_heap)
> fastrpc_buf_free(cctx->remote_heap);
>
> - of_platform_depopulate(&rpdev->dev);
> + fastrpc_depopulate_cb_devices(cctx);
>
> fastrpc_channel_ctx_put(cctx);
> }
> @@ -2558,16 +2634,9 @@ static int fastrpc_init(void)
> {
> int ret;
>
> - ret = platform_driver_register(&fastrpc_cb_driver);
> - if (ret < 0) {
> - pr_err("fastrpc: failed to register cb driver\n");
> - return ret;
> - }
> -
> ret = register_rpmsg_driver(&fastrpc_driver);
> if (ret < 0) {
> pr_err("fastrpc: failed to register rpmsg driver\n");
> - platform_driver_unregister(&fastrpc_cb_driver);
> return ret;
> }
>
> @@ -2577,7 +2646,6 @@ module_init(fastrpc_init);
>
> static void fastrpc_exit(void)
> {
> - platform_driver_unregister(&fastrpc_cb_driver);
> unregister_rpmsg_driver(&fastrpc_driver);
> }
> module_exit(fastrpc_exit);
>
> --
> 2.34.1
>
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] drivers: base: Add generic context device bus
2026-04-14 16:31 ` [PATCH 1/3] drivers: base: Add generic context device bus Ekansh Gupta via B4 Relay
2026-04-14 16:49 ` Greg Kroah-Hartman
@ 2026-04-15 11:25 ` Srinivas Kandagatla
2026-04-15 17:16 ` Vishnu Reddy
2 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2026-04-15 11:25 UTC (permalink / raw)
To: ekansh.gupta, Greg Kroah-Hartman, Rafael J. Wysocki,
Danilo Krummrich, Thierry Reding, Mikko Perttunen, David Airlie,
Simona Vetter, Joerg Roedel, Will Deacon, Robin Murphy,
Arnd Bergmann, Srinivas Kandagatla, Dmitry Baryshkov,
Bharath Kumar, Chenna Kesava Raju
Cc: linux-kernel, driver-core, dri-devel, linux-tegra, iommu,
linux-arm-msm
On 4/14/26 4:31 PM, Ekansh Gupta via B4 Relay wrote:
> From: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
>
> Introduce a new generic bus type for synthetic context bank devices
> that require IOMMU context isolation. This bus provides a shared
> infrastructure for accelerator and GPU drivers that create virtual
> devices representing IOMMU context banks.
>
> Currently, drivers like host1x implement their own bus types for
> context devices. This generic implementation allows multiple drivers
> to share the same bus infrastructure, simplifying the IOMMU subsystem
> integration and reducing code duplication.
>
> Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
> ---
> drivers/base/Kconfig | 3 +++
> drivers/base/Makefile | 1 +
> drivers/base/context_bus.c | 24 ++++++++++++++++++++++++
> include/linux/context_bus.h | 15 +++++++++++++++
This patch as it is does not add any details on how the iommu will be
binded to this bus, Please consider adding the iommu changes to this
patch so that its easy to understand and for completeness.
Also naming it as context bus is bit generic, I think the whole purpose
of this is bus is to add this as another supported bus in the iommu.
may be iommu_context bus or something on those lines would be much clear.
> 4 files changed, 43 insertions(+)
>
> diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
> index f7d385cbd3ba..479bc4bb442b 100644
> --- a/drivers/base/Kconfig
> +++ b/drivers/base/Kconfig
> @@ -4,6 +4,9 @@ menu "Generic Driver Options"
> config AUXILIARY_BUS
> bool
>
> +config CONTEXT_DEVICE_BUS
> + bool
> +
> config UEVENT_HELPER
> bool "Support for uevent helper"
> help
> diff --git a/drivers/base/Makefile b/drivers/base/Makefile
> index 8074a10183dc..ab9a0b2dc73b 100644
> --- a/drivers/base/Makefile
> +++ b/drivers/base/Makefile
> @@ -8,6 +8,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \
> topology.o container.o property.o cacheinfo.o \
> swnode.o faux.o
> obj-$(CONFIG_AUXILIARY_BUS) += auxiliary.o
> +obj-$(CONFIG_CONTEXT_DEVICE_BUS) += context_bus.o
> obj-$(CONFIG_DEVTMPFS) += devtmpfs.o
> obj-y += power/
> obj-$(CONFIG_ISA_BUS_API) += isa.o
> diff --git a/drivers/base/context_bus.c b/drivers/base/context_bus.c
> new file mode 100644
> index 000000000000..6ddb6c27bf69
> --- /dev/null
> +++ b/drivers/base/context_bus.c
> @@ -0,0 +1,24 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
Some credits to the inspiring code would be nice.
> +
> +#include <linux/context_bus.h>
> +#include <linux/init.h>
> +
> +const struct bus_type context_device_bus_type = {
> + .name = "context-device",
> +};
> +EXPORT_SYMBOL_GPL(context_device_bus_type);
> +
> +static int __init context_device_bus_init(void)
> +{
> + int err;
> +
> + err = bus_register(&context_device_bus_type);
> + if (err < 0) {
> + pr_err("context-device bus registration failed: %d\n", err);
> + return err;
> + }
> +
> + return 0;
> +}
So is the consumer drivers are expected to do the device management for
this bus, this certainly is not correct and every consumer would be
duplicating it.
Did you consider faux bus?
> +postcore_initcall(context_device_bus_init);
> diff --git a/include/linux/context_bus.h b/include/linux/context_bus.h
> new file mode 100644
> index 000000000000..0cd44cb5b147
> --- /dev/null
> +++ b/include/linux/context_bus.h
> @@ -0,0 +1,15 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#ifndef __LINUX_CONTEXT_BUS_H
> +#define __LINUX_CONTEXT_BUS_H
> +
> +#include <linux/device.h>
> +
> +#ifdef CONFIG_CONTEXT_DEVICE_BUS
> +extern const struct bus_type context_device_bus_type;
> +#endif
> +
> +#endif /* __LINUX_CONTEXT_BUS_H */
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] misc: fastrpc: Use context device bus for compute banks
2026-04-14 16:31 ` [PATCH 3/3] misc: fastrpc: Use context device bus for compute banks Ekansh Gupta via B4 Relay
2026-04-14 17:59 ` Dmitry Baryshkov
@ 2026-04-15 11:36 ` Srinivas Kandagatla
2026-04-15 16:05 ` Vishnu Reddy
2 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2026-04-15 11:36 UTC (permalink / raw)
To: ekansh.gupta, Greg Kroah-Hartman, Rafael J. Wysocki,
Danilo Krummrich, Thierry Reding, Mikko Perttunen, David Airlie,
Simona Vetter, Joerg Roedel, Will Deacon, Robin Murphy,
Arnd Bergmann, Srinivas Kandagatla, Dmitry Baryshkov,
Bharath Kumar, Chenna Kesava Raju
Cc: linux-kernel, driver-core, dri-devel, linux-tegra, iommu,
linux-arm-msm
On 4/14/26 4:31 PM, Ekansh Gupta via B4 Relay wrote:
> From: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
>
> Replace the platform driver approach for compute bank (CB) devices
> with the generic context_device_bus_type. Compute bank devices are
> synthetic IOMMU context banks, not real platform devices, so using
> the context device bus provides a more accurate representation in
> the device model.
>
> Currently, fastrpc used of_platform_populate() to create platform
> devices for each "qcom,fastrpc-compute-cb" DT node, with a platform
> driver (fastrpc_cb_driver) to handle probe/remove. This approach
> had a race condition: device nodes were created before channel
> resources (like spin_lock) were initialized, and probe was async,
> so applications could open the device before sessions were available.
>
> This patch addresses the race by manually creating and configuring
> CB devices synchronously during fastrpc_rpmsg_probe(), after all
> channel resources are initialized. The approach follows the pattern
> used in host1x_memory_context_list_init().
>
> Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
> ---
> drivers/misc/Kconfig | 1 +
> drivers/misc/fastrpc.c | 180 ++++++++++++++++++++++++++++++++++---------------
> 2 files changed, 125 insertions(+), 56 deletions(-)
>
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index 00683bf06258..b501462a4548 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -304,6 +304,7 @@ config QCOM_FASTRPC
> depends on RPMSG
> select DMA_SHARED_BUFFER
> select QCOM_SCM
> + select CONTEXT_DEVICE_BUS
> help
> Provides a communication mechanism that allows for clients to
> make remote method invocations across processor boundary to
> diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
> index 1080f9acf70a..f66fd3eea5fa 100644
> --- a/drivers/misc/fastrpc.c
> +++ b/drivers/misc/fastrpc.c
> @@ -13,9 +13,9 @@
> #include <linux/module.h>
> #include <linux/of_address.h>
> #include <linux/of.h>
> -#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> #include <linux/sort.h>
> -#include <linux/of_platform.h>
> +#include <linux/context_bus.h>
> #include <linux/rpmsg.h>
> #include <linux/scatterlist.h>
> #include <linux/slab.h>
> @@ -250,6 +250,18 @@ struct fastrpc_invoke_ctx {
> struct fastrpc_channel_ctx *cctx;
> };
>
> +/**
> + * struct fastrpc_cb_device - Compute bank device wrapper
> + * @dev: Device structure
> + * @sess: Back-pointer to the session context
> + */
> +struct fastrpc_cb_device {
> + struct device dev;
> + struct fastrpc_session_ctx *sess;
> +};
As part of this migration are we saying that driver and device model
should be done in the consumer driver?
May be the right question is why can not we add other bus types into
iommu supported buses.
There has been some discussion on this in the past
https://www.mail-archive.com/iommu@lists.linux-foundation.org/msg22139.html
This is one of the restrictions that is forcing the fake the context
devices as platform devices.
for me this looks like half baked solution and very much specific to
deal with the iommu driver situation
--srini
> +
> +#define to_fastrpc_cb_device(d) container_of(d, struct fastrpc_cb_device, dev)
> +
> struct fastrpc_session_ctx {
> struct device *dev;
> int sid;
> @@ -2190,92 +2202,156 @@ static const struct file_operations fastrpc_fops = {
> .compat_ioctl = fastrpc_device_ioctl,
> };
>
> -static int fastrpc_cb_probe(struct platform_device *pdev)
> +static void fastrpc_cb_dev_release(struct device *dev)
> +{
> + struct fastrpc_cb_device *cb_dev = to_fastrpc_cb_device(dev);
> +
> + of_node_put(dev->of_node);
> + kfree(cb_dev);
> +}
> +
> +static int fastrpc_create_cb_device(struct fastrpc_channel_ctx *cctx,
> + struct device *parent,
> + struct device_node *cb_node)
> {
> - struct fastrpc_channel_ctx *cctx;
> struct fastrpc_session_ctx *sess;
> - struct device *dev = &pdev->dev;
> - int i, sessions = 0;
> + struct fastrpc_cb_device *cb_dev;
> unsigned long flags;
> - int rc;
> - u32 dma_bits;
> -
> - cctx = dev_get_drvdata(dev->parent);
> - if (!cctx)
> - return -EINVAL;
> + int i, sessions = 0, rc;
> + u32 dma_bits, sid = 0;
>
> - of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions);
> + /* Read SID early so it can be used in the device name */
> + of_property_read_u32(cb_node, "reg", &sid);
> + of_property_read_u32(cb_node, "qcom,nsessions", &sessions);
>
> spin_lock_irqsave(&cctx->lock, flags);
> if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) {
> - dev_err(&pdev->dev, "too many sessions\n");
> + dev_err(parent, "too many sessions\n");
> spin_unlock_irqrestore(&cctx->lock, flags);
> return -ENOSPC;
> }
> dma_bits = cctx->soc_data->dma_addr_bits_default;
> + if (cctx->domain_id == CDSP_DOMAIN_ID)
> + dma_bits = cctx->soc_data->dma_addr_bits_cdsp;
> +
> sess = &cctx->session[cctx->sesscount++];
> sess->used = false;
> sess->valid = true;
> - sess->dev = dev;
> - dev_set_drvdata(dev, sess);
> + sess->sid = sid;
> + spin_unlock_irqrestore(&cctx->lock, flags);
>
> - if (cctx->domain_id == CDSP_DOMAIN_ID)
> - dma_bits = cctx->soc_data->dma_addr_bits_cdsp;
> + cb_dev = kzalloc_obj(*cb_dev);
> + if (!cb_dev)
> + return -ENOMEM;
>
> - if (of_property_read_u32(dev->of_node, "reg", &sess->sid))
> - dev_info(dev, "FastRPC Session ID not specified in DT\n");
> + cb_dev->sess = sess;
>
> - if (sessions > 0) {
> - struct fastrpc_session_ctx *dup_sess;
> + device_initialize(&cb_dev->dev);
> + cb_dev->dev.parent = parent;
> + cb_dev->dev.bus = &context_device_bus_type;
> + cb_dev->dev.release = fastrpc_cb_dev_release;
> + cb_dev->dev.of_node = of_node_get(cb_node);
> + cb_dev->dev.dma_mask = &cb_dev->dev.coherent_dma_mask;
> + cb_dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
> + dev_set_name(&cb_dev->dev, "%s:compute-cb@%u", dev_name(parent), sid);
>
> + rc = device_add(&cb_dev->dev);
> + if (rc) {
> + dev_err(parent, "failed to add CB device: %d\n", rc);
> + goto err_put;
> + }
> +
> + rc = of_dma_configure(&cb_dev->dev, cb_node, true);
> + if (rc) {
> + dev_err(parent, "of_dma_configure failed for CB device: %d\n", rc);
> + goto err_del;
> + }
> +
> + rc = dma_set_mask(&cb_dev->dev, DMA_BIT_MASK(dma_bits));
> + if (rc) {
> + dev_err(parent, "%u-bit DMA enable failed\n", dma_bits);
> + goto err_del;
> + }
> +
> + sess->dev = &cb_dev->dev;
> +
> + if (sessions > 0) {
> + spin_lock_irqsave(&cctx->lock, flags);
> for (i = 1; i < sessions; i++) {
> + struct fastrpc_session_ctx *dup_sess;
> +
> if (cctx->sesscount >= FASTRPC_MAX_SESSIONS)
> break;
> dup_sess = &cctx->session[cctx->sesscount++];
> memcpy(dup_sess, sess, sizeof(*dup_sess));
> }
> - }
> - spin_unlock_irqrestore(&cctx->lock, flags);
> - rc = dma_set_mask(dev, DMA_BIT_MASK(dma_bits));
> - if (rc) {
> - dev_err(dev, "%u-bit DMA enable failed\n", dma_bits);
> - return rc;
> + spin_unlock_irqrestore(&cctx->lock, flags);
> }
>
> return 0;
> +
> +err_del:
> + device_del(&cb_dev->dev);
> +err_put:
> + of_node_put(cb_dev->dev.of_node);
> + put_device(&cb_dev->dev);
> + return rc;
> }
>
> -static void fastrpc_cb_remove(struct platform_device *pdev)
> +static void fastrpc_depopulate_cb_devices(struct fastrpc_channel_ctx *cctx)
> {
> - struct fastrpc_channel_ctx *cctx = dev_get_drvdata(pdev->dev.parent);
> - struct fastrpc_session_ctx *sess = dev_get_drvdata(&pdev->dev);
> unsigned long flags;
> - int i;
> + int i, j;
>
> spin_lock_irqsave(&cctx->lock, flags);
> for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) {
> - if (cctx->session[i].sid == sess->sid) {
> + if (cctx->session[i].valid) {
> cctx->session[i].valid = false;
> cctx->sesscount--;
> }
> }
> spin_unlock_irqrestore(&cctx->lock, flags);
> +
> + for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) {
> + struct device *dev = cctx->session[i].dev;
> +
> + if (!dev)
> + continue;
> +
> + /* Unregister the device once */
> + device_unregister(dev);
> +
> + /* Clear this dev pointer from all sessions that share it */
> + for (j = i; j < FASTRPC_MAX_SESSIONS; j++) {
> + if (cctx->session[j].dev == dev)
> + cctx->session[j].dev = NULL;
> + }
> + }
> }
>
> -static const struct of_device_id fastrpc_match_table[] = {
> - { .compatible = "qcom,fastrpc-compute-cb", },
> - {}
> -};
> +static int fastrpc_populate_cb_devices(struct fastrpc_channel_ctx *cctx,
> + struct device *parent,
> + struct device_node *parent_node)
> +{
> + struct device_node *child;
> + int ret = 0;
>
> -static struct platform_driver fastrpc_cb_driver = {
> - .probe = fastrpc_cb_probe,
> - .remove = fastrpc_cb_remove,
> - .driver = {
> - .name = "qcom,fastrpc-cb",
> - .of_match_table = fastrpc_match_table,
> - .suppress_bind_attrs = true,
> - },
> -};
> + for_each_child_of_node(parent_node, child) {
> + if (!of_device_is_compatible(child, "qcom,fastrpc-compute-cb"))
> + continue;
> +
> + ret = fastrpc_create_cb_device(cctx, parent, child);
> + if (ret) {
> + dev_err(parent, "failed to create CB device for %s: %d\n",
> + child->name, ret);
> + of_node_put(child);
> + fastrpc_depopulate_cb_devices(cctx);
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
>
> static int fastrpc_device_register(struct device *dev, struct fastrpc_channel_ctx *cctx,
> bool is_secured, const char *domain)
> @@ -2441,7 +2517,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
> data->domain_id = domain_id;
> data->rpdev = rpdev;
>
> - err = of_platform_populate(rdev->of_node, NULL, NULL, rdev);
> + err = fastrpc_populate_cb_devices(data, rdev, rdev->of_node);
> if (err)
> goto err_deregister_fdev;
>
> @@ -2496,7 +2572,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
> if (cctx->remote_heap)
> fastrpc_buf_free(cctx->remote_heap);
>
> - of_platform_depopulate(&rpdev->dev);
> + fastrpc_depopulate_cb_devices(cctx);
>
> fastrpc_channel_ctx_put(cctx);
> }
> @@ -2558,16 +2634,9 @@ static int fastrpc_init(void)
> {
> int ret;
>
> - ret = platform_driver_register(&fastrpc_cb_driver);
> - if (ret < 0) {
> - pr_err("fastrpc: failed to register cb driver\n");
> - return ret;
> - }
> -
> ret = register_rpmsg_driver(&fastrpc_driver);
> if (ret < 0) {
> pr_err("fastrpc: failed to register rpmsg driver\n");
> - platform_driver_unregister(&fastrpc_cb_driver);
> return ret;
> }
>
> @@ -2577,7 +2646,6 @@ module_init(fastrpc_init);
>
> static void fastrpc_exit(void)
> {
> - platform_driver_unregister(&fastrpc_cb_driver);
> unregister_rpmsg_driver(&fastrpc_driver);
> }
> module_exit(fastrpc_exit);
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] misc: fastrpc: Use context device bus for compute banks
2026-04-14 16:31 ` [PATCH 3/3] misc: fastrpc: Use context device bus for compute banks Ekansh Gupta via B4 Relay
2026-04-14 17:59 ` Dmitry Baryshkov
2026-04-15 11:36 ` Srinivas Kandagatla
@ 2026-04-15 16:05 ` Vishnu Reddy
2026-04-19 0:16 ` Dmitry Baryshkov
2 siblings, 1 reply; 12+ messages in thread
From: Vishnu Reddy @ 2026-04-15 16:05 UTC (permalink / raw)
To: Ekansh Gupta, Greg Kroah-Hartman, Rafael J. Wysocki,
Danilo Krummrich, Thierry Reding, Mikko Perttunen, David Airlie,
Simona Vetter, Joerg Roedel, Will Deacon, Robin Murphy,
Arnd Bergmann, Srinivas Kandagatla, Dmitry Baryshkov,
Bharath Kumar, Chenna Kesava Raju, Vikash Garodia
Cc: linux-kernel, driver-core, dri-devel, linux-tegra, iommu,
linux-arm-msm
On 4/14/2026 10:01 PM, Ekansh Gupta wrote:
> Replace the platform driver approach for compute bank (CB) devices
> with the generic context_device_bus_type. Compute bank devices are
> synthetic IOMMU context banks, not real platform devices, so using
> the context device bus provides a more accurate representation in
> the device model.
>
> Currently, fastrpc used of_platform_populate() to create platform
> devices for each "qcom,fastrpc-compute-cb" DT node, with a platform
> driver (fastrpc_cb_driver) to handle probe/remove. This approach
> had a race condition: device nodes were created before channel
> resources (like spin_lock) were initialized, and probe was async,
> so applications could open the device before sessions were available.
>
> This patch addresses the race by manually creating and configuring
> CB devices synchronously during fastrpc_rpmsg_probe(), after all
> channel resources are initialized. The approach follows the pattern
> used in host1x_memory_context_list_init().
>
> Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
> ---
> drivers/misc/Kconfig | 1 +
> drivers/misc/fastrpc.c | 180 ++++++++++++++++++++++++++++++++++---------------
> 2 files changed, 125 insertions(+), 56 deletions(-)
>
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index 00683bf06258..b501462a4548 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -304,6 +304,7 @@ config QCOM_FASTRPC
> depends on RPMSG
> select DMA_SHARED_BUFFER
> select QCOM_SCM
> + select CONTEXT_DEVICE_BUS
> help
> Provides a communication mechanism that allows for clients to
> make remote method invocations across processor boundary to
> diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
> index 1080f9acf70a..f66fd3eea5fa 100644
> --- a/drivers/misc/fastrpc.c
> +++ b/drivers/misc/fastrpc.c
> @@ -13,9 +13,9 @@
> #include <linux/module.h>
> #include <linux/of_address.h>
> #include <linux/of.h>
> -#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> #include <linux/sort.h>
> -#include <linux/of_platform.h>
> +#include <linux/context_bus.h>
> #include <linux/rpmsg.h>
> #include <linux/scatterlist.h>
> #include <linux/slab.h>
> @@ -250,6 +250,18 @@ struct fastrpc_invoke_ctx {
> struct fastrpc_channel_ctx *cctx;
> };
>
> +/**
> + * struct fastrpc_cb_device - Compute bank device wrapper
> + * @dev: Device structure
> + * @sess: Back-pointer to the session context
> + */
> +struct fastrpc_cb_device {
> + struct device dev;
> + struct fastrpc_session_ctx *sess;
> +};
> +
> +#define to_fastrpc_cb_device(d) container_of(d, struct fastrpc_cb_device, dev)
> +
> struct fastrpc_session_ctx {
> struct device *dev;
> int sid;
> @@ -2190,92 +2202,156 @@ static const struct file_operations fastrpc_fops = {
> .compat_ioctl = fastrpc_device_ioctl,
> };
>
> -static int fastrpc_cb_probe(struct platform_device *pdev)
> +static void fastrpc_cb_dev_release(struct device *dev)
> +{
> + struct fastrpc_cb_device *cb_dev = to_fastrpc_cb_device(dev);
> +
> + of_node_put(dev->of_node);
> + kfree(cb_dev);
> +}
> +
> +static int fastrpc_create_cb_device(struct fastrpc_channel_ctx *cctx,
> + struct device *parent,
> + struct device_node *cb_node)
> {
> - struct fastrpc_channel_ctx *cctx;
> struct fastrpc_session_ctx *sess;
> - struct device *dev = &pdev->dev;
> - int i, sessions = 0;
> + struct fastrpc_cb_device *cb_dev;
> unsigned long flags;
> - int rc;
> - u32 dma_bits;
> -
> - cctx = dev_get_drvdata(dev->parent);
> - if (!cctx)
> - return -EINVAL;
> + int i, sessions = 0, rc;
> + u32 dma_bits, sid = 0;
>
> - of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions);
> + /* Read SID early so it can be used in the device name */
> + of_property_read_u32(cb_node, "reg", &sid);
> + of_property_read_u32(cb_node, "qcom,nsessions", &sessions);
>
> spin_lock_irqsave(&cctx->lock, flags);
> if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) {
> - dev_err(&pdev->dev, "too many sessions\n");
> + dev_err(parent, "too many sessions\n");
> spin_unlock_irqrestore(&cctx->lock, flags);
> return -ENOSPC;
> }
> dma_bits = cctx->soc_data->dma_addr_bits_default;
> + if (cctx->domain_id == CDSP_DOMAIN_ID)
> + dma_bits = cctx->soc_data->dma_addr_bits_cdsp;
> +
> sess = &cctx->session[cctx->sesscount++];
> sess->used = false;
> sess->valid = true;
> - sess->dev = dev;
> - dev_set_drvdata(dev, sess);
> + sess->sid = sid;
> + spin_unlock_irqrestore(&cctx->lock, flags);
>
> - if (cctx->domain_id == CDSP_DOMAIN_ID)
> - dma_bits = cctx->soc_data->dma_addr_bits_cdsp;
> + cb_dev = kzalloc_obj(*cb_dev);
> + if (!cb_dev)
> + return -ENOMEM;
>
> - if (of_property_read_u32(dev->of_node, "reg", &sess->sid))
> - dev_info(dev, "FastRPC Session ID not specified in DT\n");
> + cb_dev->sess = sess;
>
> - if (sessions > 0) {
> - struct fastrpc_session_ctx *dup_sess;
> + device_initialize(&cb_dev->dev);
> + cb_dev->dev.parent = parent;
> + cb_dev->dev.bus = &context_device_bus_type;
> + cb_dev->dev.release = fastrpc_cb_dev_release;
> + cb_dev->dev.of_node = of_node_get(cb_node);
> + cb_dev->dev.dma_mask = &cb_dev->dev.coherent_dma_mask;
> + cb_dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
> + dev_set_name(&cb_dev->dev, "%s:compute-cb@%u", dev_name(parent), sid);
>
> + rc = device_add(&cb_dev->dev);
device_initialize() and device_add() can be replaced with single
device_register() call. You can refer the below patch,
https://lore.kernel.org/all/20260313-kaanapali-iris-v3-4-9c0d1a67af4b@oss.qualcomm.com/
> + if (rc) {
> + dev_err(parent, "failed to add CB device: %d\n", rc);
> + goto err_put;
> + }
> +
> + rc = of_dma_configure(&cb_dev->dev, cb_node, true);
Specific dma configuration should be done via .dma_configure callback,
as suggested by Robin earlier in the discussion,
https://lore.kernel.org/all/02b3d0f5-f94c-43cd-93af-97cfcf7751b1@arm.com/
> + if (rc) {
> + dev_err(parent, "of_dma_configure failed for CB device: %d\n", rc);
> + goto err_del;
> + }
> +
> + rc = dma_set_mask(&cb_dev->dev, DMA_BIT_MASK(dma_bits));
Can this be set during device configuration and avoid explict
dma_set_mask call?
> + if (rc) {
> + dev_err(parent, "%u-bit DMA enable failed\n", dma_bits);
> + goto err_del;
> + }
> +
> + sess->dev = &cb_dev->dev;
> +
> + if (sessions > 0) {
> + spin_lock_irqsave(&cctx->lock, flags);
> for (i = 1; i < sessions; i++) {
> + struct fastrpc_session_ctx *dup_sess;
> +
> if (cctx->sesscount >= FASTRPC_MAX_SESSIONS)
> break;
> dup_sess = &cctx->session[cctx->sesscount++];
> memcpy(dup_sess, sess, sizeof(*dup_sess));
> }
> - }
> - spin_unlock_irqrestore(&cctx->lock, flags);
> - rc = dma_set_mask(dev, DMA_BIT_MASK(dma_bits));
> - if (rc) {
> - dev_err(dev, "%u-bit DMA enable failed\n", dma_bits);
> - return rc;
> + spin_unlock_irqrestore(&cctx->lock, flags);
> }
>
> return 0;
> +
> +err_del:
> + device_del(&cb_dev->dev);
> +err_put:
> + of_node_put(cb_dev->dev.of_node);
> + put_device(&cb_dev->dev);
> + return rc;
> }
>
> -static void fastrpc_cb_remove(struct platform_device *pdev)
> +static void fastrpc_depopulate_cb_devices(struct fastrpc_channel_ctx *cctx)
> {
> - struct fastrpc_channel_ctx *cctx = dev_get_drvdata(pdev->dev.parent);
> - struct fastrpc_session_ctx *sess = dev_get_drvdata(&pdev->dev);
> unsigned long flags;
> - int i;
> + int i, j;
>
> spin_lock_irqsave(&cctx->lock, flags);
> for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) {
> - if (cctx->session[i].sid == sess->sid) {
> + if (cctx->session[i].valid) {
> cctx->session[i].valid = false;
> cctx->sesscount--;
> }
> }
> spin_unlock_irqrestore(&cctx->lock, flags);
> +
> + for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) {
> + struct device *dev = cctx->session[i].dev;
> +
> + if (!dev)
> + continue;
> +
> + /* Unregister the device once */
> + device_unregister(dev);
> +
> + /* Clear this dev pointer from all sessions that share it */
> + for (j = i; j < FASTRPC_MAX_SESSIONS; j++) {
> + if (cctx->session[j].dev == dev)
> + cctx->session[j].dev = NULL;
> + }
> + }
> }
>
> -static const struct of_device_id fastrpc_match_table[] = {
> - { .compatible = "qcom,fastrpc-compute-cb", },
> - {}
> -};
> +static int fastrpc_populate_cb_devices(struct fastrpc_channel_ctx *cctx,
> + struct device *parent,
> + struct device_node *parent_node)
> +{
> + struct device_node *child;
> + int ret = 0;
>
> -static struct platform_driver fastrpc_cb_driver = {
> - .probe = fastrpc_cb_probe,
> - .remove = fastrpc_cb_remove,
> - .driver = {
> - .name = "qcom,fastrpc-cb",
> - .of_match_table = fastrpc_match_table,
> - .suppress_bind_attrs = true,
> - },
> -};
> + for_each_child_of_node(parent_node, child) {
> + if (!of_device_is_compatible(child, "qcom,fastrpc-compute-cb"))
> + continue;
> +
> + ret = fastrpc_create_cb_device(cctx, parent, child);
> + if (ret) {
> + dev_err(parent, "failed to create CB device for %s: %d\n",
> + child->name, ret);
> + of_node_put(child);
> + fastrpc_depopulate_cb_devices(cctx);
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
>
> static int fastrpc_device_register(struct device *dev, struct fastrpc_channel_ctx *cctx,
> bool is_secured, const char *domain)
> @@ -2441,7 +2517,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
> data->domain_id = domain_id;
> data->rpdev = rpdev;
>
> - err = of_platform_populate(rdev->of_node, NULL, NULL, rdev);
> + err = fastrpc_populate_cb_devices(data, rdev, rdev->of_node);
> if (err)
> goto err_deregister_fdev;
>
> @@ -2496,7 +2572,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
> if (cctx->remote_heap)
> fastrpc_buf_free(cctx->remote_heap);
>
> - of_platform_depopulate(&rpdev->dev);
> + fastrpc_depopulate_cb_devices(cctx);
>
> fastrpc_channel_ctx_put(cctx);
> }
> @@ -2558,16 +2634,9 @@ static int fastrpc_init(void)
> {
> int ret;
>
> - ret = platform_driver_register(&fastrpc_cb_driver);
> - if (ret < 0) {
> - pr_err("fastrpc: failed to register cb driver\n");
> - return ret;
> - }
> -
> ret = register_rpmsg_driver(&fastrpc_driver);
> if (ret < 0) {
> pr_err("fastrpc: failed to register rpmsg driver\n");
> - platform_driver_unregister(&fastrpc_cb_driver);
> return ret;
> }
>
> @@ -2577,7 +2646,6 @@ module_init(fastrpc_init);
>
> static void fastrpc_exit(void)
> {
> - platform_driver_unregister(&fastrpc_cb_driver);
> unregister_rpmsg_driver(&fastrpc_driver);
> }
> module_exit(fastrpc_exit);
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] drivers: base: Add generic context device bus
2026-04-14 16:31 ` [PATCH 1/3] drivers: base: Add generic context device bus Ekansh Gupta via B4 Relay
2026-04-14 16:49 ` Greg Kroah-Hartman
2026-04-15 11:25 ` Srinivas Kandagatla
@ 2026-04-15 17:16 ` Vishnu Reddy
2 siblings, 0 replies; 12+ messages in thread
From: Vishnu Reddy @ 2026-04-15 17:16 UTC (permalink / raw)
To: Ekansh Gupta, Greg Kroah-Hartman, Rafael J. Wysocki,
Danilo Krummrich, Thierry Reding, Mikko Perttunen, David Airlie,
Simona Vetter, Joerg Roedel, Will Deacon, Robin Murphy,
Arnd Bergmann, Srinivas Kandagatla, Dmitry Baryshkov,
Bharath Kumar, Chenna Kesava Raju, Vikash Garodia
Cc: linux-kernel, driver-core, dri-devel, linux-tegra, iommu,
linux-arm-msm
On 4/14/2026 10:01 PM, Ekansh Gupta wrote:
> Introduce a new generic bus type for synthetic context bank devices
> that require IOMMU context isolation. This bus provides a shared
> infrastructure for accelerator and GPU drivers that create virtual
> devices representing IOMMU context banks.
>
> Currently, drivers like host1x implement their own bus types for
> context devices. This generic implementation allows multiple drivers
> to share the same bus infrastructure, simplifying the IOMMU subsystem
> integration and reducing code duplication.
>
> Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
> ---
> drivers/base/Kconfig | 3 +++
> drivers/base/Makefile | 1 +
> drivers/base/context_bus.c | 24 ++++++++++++++++++++++++
> include/linux/context_bus.h | 15 +++++++++++++++
> 4 files changed, 43 insertions(+)
>
> diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
> index f7d385cbd3ba..479bc4bb442b 100644
> --- a/drivers/base/Kconfig
> +++ b/drivers/base/Kconfig
> @@ -4,6 +4,9 @@ menu "Generic Driver Options"
> config AUXILIARY_BUS
> bool
>
> +config CONTEXT_DEVICE_BUS
> + bool
> +
> config UEVENT_HELPER
> bool "Support for uevent helper"
> help
> diff --git a/drivers/base/Makefile b/drivers/base/Makefile
> index 8074a10183dc..ab9a0b2dc73b 100644
> --- a/drivers/base/Makefile
> +++ b/drivers/base/Makefile
> @@ -8,6 +8,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \
> topology.o container.o property.o cacheinfo.o \
> swnode.o faux.o
> obj-$(CONFIG_AUXILIARY_BUS) += auxiliary.o
> +obj-$(CONFIG_CONTEXT_DEVICE_BUS) += context_bus.o
> obj-$(CONFIG_DEVTMPFS) += devtmpfs.o
> obj-y += power/
> obj-$(CONFIG_ISA_BUS_API) += isa.o
> diff --git a/drivers/base/context_bus.c b/drivers/base/context_bus.c
> new file mode 100644
> index 000000000000..6ddb6c27bf69
> --- /dev/null
> +++ b/drivers/base/context_bus.c
> @@ -0,0 +1,24 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> +
> +#include <linux/context_bus.h>
> +#include <linux/init.h>
> +
> +const struct bus_type context_device_bus_type = {
> + .name = "context-device",
add the .dma_configure callback instead of calling from the client driver.
> +};
> +EXPORT_SYMBOL_GPL(context_device_bus_type);
> +
> +static int __init context_device_bus_init(void)
> +{
> + int err;
> +
> + err = bus_register(&context_device_bus_type);
> + if (err < 0) {
> + pr_err("context-device bus registration failed: %d\n", err);
> + return err;
> + }
> +
> + return 0;
> +}
> +postcore_initcall(context_device_bus_init);
> diff --git a/include/linux/context_bus.h b/include/linux/context_bus.h
> new file mode 100644
> index 000000000000..0cd44cb5b147
> --- /dev/null
> +++ b/include/linux/context_bus.h
> @@ -0,0 +1,15 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#ifndef __LINUX_CONTEXT_BUS_H
> +#define __LINUX_CONTEXT_BUS_H
> +
> +#include <linux/device.h>
> +
> +#ifdef CONFIG_CONTEXT_DEVICE_BUS
> +extern const struct bus_type context_device_bus_type;
> +#endif
> +
> +#endif /* __LINUX_CONTEXT_BUS_H */
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] drivers: base: Add generic context device bus
2026-04-14 16:49 ` Greg Kroah-Hartman
@ 2026-04-15 17:34 ` Vishnu Reddy
0 siblings, 0 replies; 12+ messages in thread
From: Vishnu Reddy @ 2026-04-15 17:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, ekansh.gupta
Cc: Rafael J. Wysocki, Danilo Krummrich, Thierry Reding,
Mikko Perttunen, David Airlie, Simona Vetter, Joerg Roedel,
Will Deacon, Robin Murphy, Arnd Bergmann, Srinivas Kandagatla,
Dmitry Baryshkov, Bharath Kumar, Chenna Kesava Raju, linux-kernel,
driver-core, dri-devel, linux-tegra, iommu, linux-arm-msm,
Vikash Garodia
On 4/14/2026 10:19 PM, Greg Kroah-Hartman wrote:
> On Tue, Apr 14, 2026 at 10:01:15PM +0530, Ekansh Gupta via B4 Relay wrote:
>> From: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
>>
>> Introduce a new generic bus type for synthetic context bank devices
>> that require IOMMU context isolation. This bus provides a shared
>> infrastructure for accelerator and GPU drivers that create virtual
>> devices representing IOMMU context banks.
>>
>> Currently, drivers like host1x implement their own bus types for
>> context devices. This generic implementation allows multiple drivers
>> to share the same bus infrastructure, simplifying the IOMMU subsystem
>> integration and reducing code duplication.
>>
>> Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
>> ---
>> drivers/base/Kconfig | 3 +++
>> drivers/base/Makefile | 1 +
>> drivers/base/context_bus.c | 24 ++++++++++++++++++++++++
>> include/linux/context_bus.h | 15 +++++++++++++++
>> 4 files changed, 43 insertions(+)
>>
>> diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
>> index f7d385cbd3ba..479bc4bb442b 100644
>> --- a/drivers/base/Kconfig
>> +++ b/drivers/base/Kconfig
>> @@ -4,6 +4,9 @@ menu "Generic Driver Options"
>> config AUXILIARY_BUS
>> bool
>>
>> +config CONTEXT_DEVICE_BUS
>> + bool
>
> So this is a context-free bus? I.e. no documentation?
>
> :)
>
> This feels really odd, this "bus" isn't doing anything at all. So why
> do you need it and can't use auxbus or faux?
Looks like the device have specific iommu configuration (via
of_dma_configure()), then using the auxbus or faux bus types does not
have the bus notifier calls to iommu_release_device(). Please correct me
if I misunderstood?
>
> You say something about an iommu, but yet this has no information about
> an iommu at all, so why are they somehow special?
>
> You need to provide a lot more information here, sorry.
>
> greg k-h
>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] misc: fastrpc: Use context device bus for compute banks
2026-04-15 16:05 ` Vishnu Reddy
@ 2026-04-19 0:16 ` Dmitry Baryshkov
0 siblings, 0 replies; 12+ messages in thread
From: Dmitry Baryshkov @ 2026-04-19 0:16 UTC (permalink / raw)
To: Vishnu Reddy
Cc: Ekansh Gupta, Greg Kroah-Hartman, Rafael J. Wysocki,
Danilo Krummrich, Thierry Reding, Mikko Perttunen, David Airlie,
Simona Vetter, Joerg Roedel, Will Deacon, Robin Murphy,
Arnd Bergmann, Srinivas Kandagatla, Bharath Kumar,
Chenna Kesava Raju, Vikash Garodia, linux-kernel, driver-core,
dri-devel, linux-tegra, iommu, linux-arm-msm
On Wed, Apr 15, 2026 at 09:35:47PM +0530, Vishnu Reddy wrote:
>
>
> On 4/14/2026 10:01 PM, Ekansh Gupta wrote:
> > Replace the platform driver approach for compute bank (CB) devices
> > with the generic context_device_bus_type. Compute bank devices are
> > synthetic IOMMU context banks, not real platform devices, so using
> > the context device bus provides a more accurate representation in
> > the device model.
> >
> > Currently, fastrpc used of_platform_populate() to create platform
> > devices for each "qcom,fastrpc-compute-cb" DT node, with a platform
> > driver (fastrpc_cb_driver) to handle probe/remove. This approach
> > had a race condition: device nodes were created before channel
> > resources (like spin_lock) were initialized, and probe was async,
> > so applications could open the device before sessions were available.
> >
> > This patch addresses the race by manually creating and configuring
> > CB devices synchronously during fastrpc_rpmsg_probe(), after all
> > channel resources are initialized. The approach follows the pattern
> > used in host1x_memory_context_list_init().
> >
> > Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
> > ---
> > drivers/misc/Kconfig | 1 +
> > drivers/misc/fastrpc.c | 180 ++++++++++++++++++++++++++++++++++---------------
> > 2 files changed, 125 insertions(+), 56 deletions(-)
> >
> > }
> > dma_bits = cctx->soc_data->dma_addr_bits_default;
> > + if (cctx->domain_id == CDSP_DOMAIN_ID)
> > + dma_bits = cctx->soc_data->dma_addr_bits_cdsp;
> > +
> > sess = &cctx->session[cctx->sesscount++];
> > sess->used = false;
> > sess->valid = true;
> > - sess->dev = dev;
> > - dev_set_drvdata(dev, sess);
> > + sess->sid = sid;
> > + spin_unlock_irqrestore(&cctx->lock, flags);
> > - if (cctx->domain_id == CDSP_DOMAIN_ID)
> > - dma_bits = cctx->soc_data->dma_addr_bits_cdsp;
> > + cb_dev = kzalloc_obj(*cb_dev);
> > + if (!cb_dev)
> > + return -ENOMEM;
> > - if (of_property_read_u32(dev->of_node, "reg", &sess->sid))
> > - dev_info(dev, "FastRPC Session ID not specified in DT\n");
> > + cb_dev->sess = sess;
> > - if (sessions > 0) {
> > - struct fastrpc_session_ctx *dup_sess;
> > + device_initialize(&cb_dev->dev);
> > + cb_dev->dev.parent = parent;
> > + cb_dev->dev.bus = &context_device_bus_type;
> > + cb_dev->dev.release = fastrpc_cb_dev_release;
> > + cb_dev->dev.of_node = of_node_get(cb_node);
> > + cb_dev->dev.dma_mask = &cb_dev->dev.coherent_dma_mask;
> > + cb_dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
> > + dev_set_name(&cb_dev->dev, "%s:compute-cb@%u", dev_name(parent), sid);
> > + rc = device_add(&cb_dev->dev);
>
> device_initialize() and device_add() can be replaced with single
> device_register() call. You can refer the below patch,
Keep in mind that for several arches device_initialize() sets the
coherent_dma_mask. So one should set coherent_dma_mask (as it's done
here) after calling device_initialize().
>
> https://lore.kernel.org/all/20260313-kaanapali-iris-v3-4-9c0d1a67af4b@oss.qualcomm.com/
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-04-19 0:16 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-14 16:31 [PATCH 0/3] Introduce generic context device bus for IOMMU context isolation Ekansh Gupta via B4 Relay
2026-04-14 16:31 ` [PATCH 1/3] drivers: base: Add generic context device bus Ekansh Gupta via B4 Relay
2026-04-14 16:49 ` Greg Kroah-Hartman
2026-04-15 17:34 ` Vishnu Reddy
2026-04-15 11:25 ` Srinivas Kandagatla
2026-04-15 17:16 ` Vishnu Reddy
2026-04-14 16:31 ` [PATCH 2/3] gpu: host1x: Migrate to " Ekansh Gupta via B4 Relay
2026-04-14 16:31 ` [PATCH 3/3] misc: fastrpc: Use context device bus for compute banks Ekansh Gupta via B4 Relay
2026-04-14 17:59 ` Dmitry Baryshkov
2026-04-15 11:36 ` Srinivas Kandagatla
2026-04-15 16:05 ` Vishnu Reddy
2026-04-19 0:16 ` Dmitry Baryshkov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox