* [PATCH v19 2/7] coresight: tmc: add create/clean functions for etr_buf_list
From: Jie Gan @ 2026-06-25 10:45 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Tingwei Zhang, Jie Gan, Bjorn Andersson,
Konrad Dybcio, Yuanfang Zhang, Mao Jinlong
Cc: coresight, linux-arm-kernel, linux-kernel, linux-arm-msm,
devicetree, Mike Leach
In-Reply-To: <20260625-enable-byte-cntr-for-ctcu-v19-0-8fbbf22e8381@oss.qualcomm.com>
Introduce functions for creating and inserting or removing the
etr_buf_node to/from the etr_buf_list.
The byte-cntr functionality requires two etr_buf to receive trace data.
The active etr_buf collects the trace data from source device, while the
byte-cntr reading function accesses the deactivated etr_buf after is
has been filled and synced, transferring data to the userspace.
Reviewed-by: Mike Leach <mike.leach@linaro.org>
Signed-off-by: Jie Gan <jie.gan@oss.qualcomm.com>
---
drivers/hwtracing/coresight/coresight-tmc-core.c | 1 +
drivers/hwtracing/coresight/coresight-tmc-etr.c | 126 +++++++++++++++++++++++
drivers/hwtracing/coresight/coresight-tmc.h | 17 +++
3 files changed, 144 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index bc5a133ada3e..bc7dd676da47 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -835,6 +835,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
idr_init(&drvdata->idr);
mutex_init(&drvdata->idr_mutex);
dev_list = "tmc_etr";
+ INIT_LIST_HEAD(&drvdata->etr_buf_list);
break;
case TMC_CONFIG_TYPE_ETF:
desc.groups = coresight_etf_groups;
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 361a433e6f0c..9b3ef73e9cf2 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -1918,6 +1918,132 @@ const struct coresight_ops tmc_etr_cs_ops = {
.panic_ops = &tmc_etr_sync_ops,
};
+/**
+ * tmc_clean_etr_buf_list - clean the etr_buf_list.
+ * @drvdata: driver data of the TMC device.
+ *
+ * Remove all nodes from @drvdata->etr_buf_list and free their buffers.
+ * If a node holds the live sysfs_buf and the device is active, the node is
+ * removed but the buffer is not freed; ownership stays with drvdata->sysfs_buf.
+ *
+ * Locking: callers must guarantee exclusive access to @drvdata->etr_buf_list
+ * and must not hold @drvdata->spinlock. The spinlock is taken internally only
+ * to serialise the @drvdata->sysfs_buf accesses against the ETR sink
+ * enable/disable paths. Must be called from process context: buffers are freed
+ * with the lock released.
+ */
+void tmc_clean_etr_buf_list(struct tmc_drvdata *drvdata)
+{
+ struct etr_buf_node *nd, *next;
+ unsigned long flags;
+
+ list_for_each_entry_safe(nd, next, &drvdata->etr_buf_list, link) {
+ raw_spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (nd->sysfs_buf == drvdata->sysfs_buf) {
+ if (coresight_get_mode(drvdata->csdev) != CS_MODE_DISABLED)
+ /*
+ * The device is still active. Keep the live
+ * buffer owned by drvdata->sysfs_buf and only
+ * drop the list's reference to it.
+ */
+ nd->sysfs_buf = NULL;
+ else
+ /* Free the buffer below through nd->sysfs_buf */
+ drvdata->sysfs_buf = NULL;
+ }
+ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ /* Free the buffer (NULL is ignored) and the node out of the lock */
+ tmc_etr_free_sysfs_buf(nd->sysfs_buf);
+ list_del(&nd->link);
+ kfree(nd);
+ }
+}
+EXPORT_SYMBOL_GPL(tmc_clean_etr_buf_list);
+
+/**
+ * tmc_create_etr_buf_list - create a list to manage the etr_buf_node.
+ * @drvdata: driver data of the TMC device.
+ * @num_nodes: number of nodes want to create with the list.
+ *
+ * Locking: callers must guarantee exclusive access to @drvdata->etr_buf_list
+ * and must not hold @drvdata->spinlock. The spinlock is taken internally only
+ * to serialise the @drvdata->sysfs_buf accesses against the ETR sink
+ * enable/disable paths. Must be called from process context: buffers and nodes
+ * are allocated with the lock released.
+ *
+ * Return 0 upon success and return the error number if fail.
+ */
+int tmc_create_etr_buf_list(struct tmc_drvdata *drvdata, int num_nodes)
+{
+ struct etr_buf_node *new_node;
+ struct etr_buf *sysfs_buf;
+ unsigned long flags;
+ int i = 0, ret = 0;
+
+ /* We don't need a list if there is only one node */
+ if (num_nodes < 2)
+ return -EINVAL;
+
+ /*
+ * We expect that sysfs_buf in drvdata has already been allocated.
+ * Wrap the live sysfs_buf into the first node so the captured trace
+ * data is preserved. The list is owned by the caller, so no lock is
+ * needed to read sysfs_buf or to add the node here.
+ */
+ if (drvdata->sysfs_buf) {
+ new_node = kzalloc_obj(*new_node, GFP_KERNEL);
+ if (!new_node)
+ return -ENOMEM;
+
+ new_node->sysfs_buf = drvdata->sysfs_buf;
+ new_node->is_free = false;
+ list_add(&new_node->link, &drvdata->etr_buf_list);
+ i++;
+ }
+
+ while (i < num_nodes) {
+ new_node = kzalloc_obj(*new_node, GFP_KERNEL);
+ if (!new_node) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ /* Allocate the buffer with the lock released */
+ sysfs_buf = tmc_alloc_etr_buf(drvdata, drvdata->size, 0, cpu_to_node(0), NULL);
+ if (IS_ERR(sysfs_buf)) {
+ kfree(new_node);
+ ret = PTR_ERR(sysfs_buf);
+ break;
+ }
+
+ new_node->sysfs_buf = sysfs_buf;
+ /*
+ * Only the drvdata->sysfs_buf write needs the spinlock, to
+ * serialise against the ETR sink enable/disable paths.
+ */
+ raw_spin_lock_irqsave(&drvdata->spinlock, flags);
+ /* We don't have an available sysfs_buf in drvdata, set one up */
+ if (!drvdata->sysfs_buf) {
+ drvdata->sysfs_buf = sysfs_buf;
+ new_node->is_free = false;
+ } else {
+ new_node->is_free = true;
+ }
+ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ list_add_tail(&new_node->link, &drvdata->etr_buf_list);
+ i++;
+ }
+
+ /* Clean the list if there is an error */
+ if (ret)
+ tmc_clean_etr_buf_list(drvdata);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tmc_create_etr_buf_list);
+
int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
{
int ret = 0;
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 319a354ede9f..6e994678f926 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -208,6 +208,19 @@ struct tmc_resrv_buf {
s64 len;
};
+/**
+ * @sysfs_buf: Allocated sysfs_buf.
+ * @is_free: Indicates whether the buffer is free to choose.
+ * @pos: Offset to the start of the buffer.
+ * @link: list_head of the node.
+ */
+struct etr_buf_node {
+ struct etr_buf *sysfs_buf;
+ bool is_free;
+ loff_t pos;
+ struct list_head link;
+};
+
/**
* struct tmc_drvdata - specifics associated to an TMC component
* @atclk: optional clock for the core parts of the TMC.
@@ -245,6 +258,7 @@ struct tmc_resrv_buf {
* (after crash) by default.
* @crash_mdata: Reserved memory for storing tmc crash metadata.
* Used by ETR/ETF.
+ * @etr_buf_list: List that is used to manage allocated etr_buf.
*/
struct tmc_drvdata {
struct clk *atclk;
@@ -275,6 +289,7 @@ struct tmc_drvdata {
struct etr_buf *perf_buf;
struct tmc_resrv_buf resrv_buf;
struct tmc_resrv_buf crash_mdata;
+ struct list_head etr_buf_list;
};
struct etr_buf_operations {
@@ -447,5 +462,7 @@ struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
enum cs_mode mode,
struct coresight_path *path);
extern const struct attribute_group coresight_etr_group;
+void tmc_clean_etr_buf_list(struct tmc_drvdata *drvdata);
+int tmc_create_etr_buf_list(struct tmc_drvdata *drvdata, int num_nodes);
#endif
--
2.34.1
^ permalink raw reply related
* [PATCH v19 1/7] coresight: core: refactor ctcu_get_active_port and make it generic
From: Jie Gan @ 2026-06-25 10:45 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Tingwei Zhang, Jie Gan, Bjorn Andersson,
Konrad Dybcio, Yuanfang Zhang, Mao Jinlong
Cc: coresight, linux-arm-kernel, linux-kernel, linux-arm-msm,
devicetree, Mike Leach
In-Reply-To: <20260625-enable-byte-cntr-for-ctcu-v19-0-8fbbf22e8381@oss.qualcomm.com>
Remove ctcu_get_active_port from CTCU module and add it to the core
framework.
The port number is crucial for the CTCU device to identify which ETR
it serves. With the port number we can correctly get required parameters
of the CTCU device in TMC module.
Reviewed-by: Mike Leach <mike.leach@linaro.org>
Signed-off-by: Jie Gan <jie.gan@oss.qualcomm.com>
---
drivers/hwtracing/coresight/coresight-core.c | 27 +++++++++++++++++++++++
drivers/hwtracing/coresight/coresight-ctcu-core.c | 19 +---------------
drivers/hwtracing/coresight/coresight-priv.h | 2 ++
3 files changed, 30 insertions(+), 18 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 6d65c43d574f..7a7a85acdca0 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -773,6 +773,33 @@ struct coresight_device *coresight_get_sink(struct coresight_path *path)
}
EXPORT_SYMBOL_GPL(coresight_get_sink);
+/**
+ * coresight_get_in_port: Find the input port number at @remote where the @csdev
+ * device is connected to.
+ *
+ * @csdev: csdev of the device.
+ * @remote: csdev of the remote device which is connected to @csdev.
+ *
+ * Return: port number upon success or -EINVAL for fail.
+ */
+int coresight_get_in_port(struct coresight_device *csdev,
+ struct coresight_device *remote)
+{
+ struct coresight_platform_data *pdata = remote->pdata;
+ int i;
+
+ for (i = 0; i < pdata->nr_inconns; ++i) {
+ if (!pdata->in_conns[i])
+ continue;
+
+ if (pdata->in_conns[i]->src_dev == csdev)
+ return pdata->in_conns[i]->dest_port;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(coresight_get_in_port);
+
u32 coresight_get_sink_id(struct coresight_device *csdev)
{
if (!csdev->ea)
diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c
index 9043cad42f01..e8720026c9e3 100644
--- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
+++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
@@ -116,23 +116,6 @@ static int __ctcu_set_etr_traceid(struct coresight_device *csdev, u8 traceid, in
return 0;
}
-/*
- * Searching the sink device from helper's view in case there are multiple helper devices
- * connected to the sink device.
- */
-static int ctcu_get_active_port(struct coresight_device *sink, struct coresight_device *helper)
-{
- struct coresight_platform_data *pdata = helper->pdata;
- int i;
-
- for (i = 0; i < pdata->nr_inconns; ++i) {
- if (pdata->in_conns[i]->src_dev == sink)
- return pdata->in_conns[i]->dest_port;
- }
-
- return -EINVAL;
-}
-
static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight_path *path,
bool enable)
{
@@ -145,7 +128,7 @@ static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight
return -EINVAL;
}
- port_num = ctcu_get_active_port(sink, csdev);
+ port_num = coresight_get_in_port(sink, csdev);
if (port_num < 0)
return -EINVAL;
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index dddac946659f..854c0a3cb080 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -155,6 +155,8 @@ void coresight_remove_links(struct coresight_device *orig,
u32 coresight_get_sink_id(struct coresight_device *csdev);
int coresight_path_assign_trace_id(struct coresight_path *path,
enum cs_mode mode);
+int coresight_get_in_port(struct coresight_device *csdev,
+ struct coresight_device *remote);
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
int etm_readl_cp14(u32 off, unsigned int *val);
--
2.34.1
^ permalink raw reply related
* [PATCH v19 0/7] coresight: ctcu: Enable byte-cntr function for TMC ETR
From: Jie Gan @ 2026-06-25 10:45 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Tingwei Zhang, Jie Gan, Bjorn Andersson,
Konrad Dybcio, Yuanfang Zhang, Mao Jinlong
Cc: coresight, linux-arm-kernel, linux-kernel, linux-arm-msm,
devicetree, Konrad Dybcio, Mike Leach, Krzysztof Kozlowski
The byte-cntr function provided by the CTCU device is used to count the
trace data entering the ETR. An interrupt is triggered if the data size
exceeds the threshold set in the BYTECNTRVAL register. The interrupt
handler counts the number of triggered interruptions.
Based on this concept, the irq_cnt can be used to determine whether
the etr_buf is full. The ETR device will be disabled when the active
etr_buf is nearly full or a timeout occurs. The nearly full buffer will
be switched to background after synced. A new buffer will be picked from
the etr_buf_list, then restart the ETR device.
The byte-cntr reading functions can access data from the synced and
deactivated buffer, transferring trace data from the etr_buf to userspace
without stopping the ETR device.
The byte-cntr read operation has integrated with the file node tmc_etr,
for example:
/dev/tmc_etr0
/dev/tmc_etr1
There are two scenarios for the tmc_etr file node with byte-cntr function:
1. BYTECNTRVAL register is configured and byte-cntr is enabled -> byte-cntr read
2. BYTECNTRVAL register is reset or byte-cntr is disabled -> original behavior
Shell commands to enable byte-cntr reading for etr0:
echo 1 > /sys/bus/coresight/devices/ctcu0/irq_enabled0
echo 1 > /sys/bus/coresight/devices/tmc_etr0/enable_sink
echo 1 > /sys/bus/coresight/devices/etm0/enable_source
cat /dev/tmc_etr0
Reset the BYTECNTR register for etr0:
echo 0 > /sys/bus/coresight/devices/ctcu0/irq_enabled0
---
Changes in v19:
1. coresight: tmc: add create/clean functions for etr_buf_list:
- Simplified the kernel-doc "Locking:" note on tmc_create_etr_buf_list()
and tmc_clean_etr_buf_list() to state only the required contract
(caller must guarantee exclusive access to drvdata->etr_buf_list),
dropping the over-specific call-path details.
- Lock the required code block in create/clean functions.
2. coresight: ctcu: enable byte-cntr for TMC ETR devices:
- Fixed a stale reading-state / double-free when irq_enabled was
cleared between prepare and unprepare: the byte-cntr read_unprepare
would return an error and tmc_read_unprepare_etr() would fall back
to the normal unprepare path, freeing drvdata->sysfs_buf while it
was still owned by the byte-cntr buffer list. irq_enabled_store()
now returns -EBUSY while byte_cntr_data->reading is set, so the flag
can no longer change mid-session, and tmc_read_unprepare_byte_cntr()
additionally guards on byte_cntr_data->reading.
- Moved enable_irq_wake()/disable_irq_wake() out of the
byte_cntr_data->spin_lock critical section in
tmc_read_prepare_byte_cntr()/tmc_read_unprepare_byte_cntr().
irq_set_irq_wake() may sleep on slow-bus irqchips, so it must not
be called under a raw spinlock. The threshold IRQ is already
disabled by the in-lock register write before disable_irq_wake() on
the unprepare path, so no wake event can race in the gap.
- Added a comment on the byte_cntr_sysfs_ops pointer documenting the
single-CTCU-instance-per-system assumption.
- Link to v18: https://lore.kernel.org/r/20260507-enable-byte-cntr-for-ctcu-v18-0-2b2d590463a3@oss.qualcomm.com
Changes in v18:
1. add a NULL check for the in_conns instance in patch 1.
2. fix a bug in patch 2: the tmc_alloc_etr_buf never return NULL and the
previous check for the return value is incorrect.
3. add more kernel_doc description for tmc_clean_etr_buf_list function
in patch 2
- Link to v17: https://lore.kernel.org/r/20260421-enable-byte-cntr-for-ctcu-v17-0-9cf36ff55fc0@oss.qualcomm.com
Changes in v17:
1. fix race issue during allocat buffer.
2. fix user after free issue observed when remove module.
- Link to v16: https://lore.kernel.org/r/20260323-enable-byte-cntr-for-ctcu-v16-0-7a413d211b8d@oss.qualcomm.com
Changes in v16:
1. Remove lock/unlock processes in patch "coresight: tmc: add create/clean
functions for etr_buf_list" because we are allocating/freeing memory.
- Link to v15: https://lore.kernel.org/r/20260313-enable-byte-cntr-for-ctcu-v15-0-1777f14ed319@oss.qualcomm.com
Changes in v15:
1. add lockdep_assert_held in patch "coresight: tmc: add create/clean
functions for etr_buf_list"
2. optimize tmc_clean_etr_buf_list function
3. optimize the patch "enable byte-cntr for TMC ETR devices" according
to Suzuki's comments
- call byte_cntr_sysfs_ops from etr_sysfs_ops
- optimize the lock usage in all functions
- remove the buf_node parameter in etr_drvdata, move it to
byte_cntr_data
- move the tmc_reset_sysfs_buf function to tmc-etr.c
- add a read flag to struct etr_buf_node to allow updating pos while
traversing etr_buf_list during data reads.
Link to v14: https://lore.kernel.org/r/20260309-enable-byte-cntr-for-ctcu-v14-0-c08823e5a8e6@oss.qualcomm.com
Changes in V14:
1. Drop the patch: integrate byte-cntr's sysfs_ops with tmc sysfs file_ops
2. Replace tmc_sysfs_ops with byte_cntr_sysfs_ops in byte_cntr_start
function and restore etr_sysfs_ops in byte_cntr_unprepare function.
3. Remove redundant checks in byte‑cntr functions.
Link to V13: https://lore.kernel.org/all/20260223-enable-byte-cntr-for-ctcu-v13-0-9cb44178b250@oss.qualcomm.com/
Changes in v13:
1. initilize the byte_cntr_data->raw_spin_lock before using.
2. replace kzalloc with kzalloc_obj.
Link to V12: https://lore.kernel.org/all/20260203-enable-byte-cntr-for-ctcu-v12-0-7bf81b86b70e@oss.qualcomm.com/
Changes in v12:
1. Add a new function for retrieving the CTCU's coresight_dev instead of
refactor the existing function.
Link to v11: https://lore.kernel.org/r/20260126-enable-byte-cntr-for-ctcu-v11-0-c0af66ba15cf@oss.qualcomm.com
Changes in v11:
1. Correct the description in patch1 for the function coresight_get_in_port.
2. Renaming the sysfs_ops to tmc_sysfs_ops per Suzuki's suggestion.
Link to v10: https://lore.kernel.org/r/20260122-enable-byte-cntr-for-ctcu-v10-0-22978e3c169f@oss.qualcomm.com
Changes in v10:
1. fix a free memory issue that is reported by robot for patch 2.
Link to v9: https://lore.kernel.org/r/20251224-enable-byte-cntr-for-ctcu-v9-0-886c4496fed4@oss.qualcomm.com
Changes in v9:
1. Drop the patch: add a new API to retrieve the helper device
2. Add a new patch to refactor the tmc_etr_get_catu_device function,
making it generic to support all types of helper devices associated with ETR.
3. Optimizing the code for creating irq_threshold sysfs node.
4. Remove interrupt-name property and obtain the IRQ based on the
in-port number.
Link to v8: https://lore.kernel.org/r/20251211-enable-byte-cntr-for-ctcu-v8-0-3e12ff313191@oss.qualcomm.com
Changes in V8:
1. Optimizing the patch 1 and patch 2 according to Suzuki's comments.
2. Combine the patch 3 and patch 4 together.
3. Rename the interrupt-name to prevent confusion, for example:etr0->etrirq0.
Link to V7 - https://lore.kernel.org/all/20251013-enable-byte-cntr-for-ctcu-v7-0-e1e8f41e15dd@oss.qualcomm.com/
Changes in V7:
1. rebased on tag next-20251010
2. updated info for sysfs node document
Link to V6 - https://lore.kernel.org/all/20250908-enable-byte-cntr-for-tmc-v6-0-1db9e621441a@oss.qualcomm.com/
Changes in V6:
1. rebased on next-20250905.
2. fixed the issue that the dtsi file has re-named from sa8775p.dtsi to
lemans.dtsi.
3. fixed some minor issues about comments.
Link to V5 - https://lore.kernel.org/all/20250812083731.549-1-jie.gan@oss.qualcomm.com/
Changes in V5:
1. Add Mike's reviewed-by tag for patchset 1,2,5.
2. Remove the function pointer added to helper_ops according to Mike's
comment, it also results the patchset has been removed.
3. Optimizing the paired create/clean functions for etr_buf_list.
4. Remove the unneeded parameter "reading" from the etr_buf_node.
Link to V4 - https://lore.kernel.org/all/20250725100806.1157-1-jie.gan@oss.qualcomm.com/
Changes in V4:
1. Rename the function to coresight_get_in_port_dest regarding to Mike's
comment (patch 1/10).
2. Add lock to protect the connections regarding to Mike's comment
(patch 2/10).
3. Move all byte-cntr functions to coresight-ctcu-byte-cntr file.
4. Add tmc_read_ops to wrap all read operations for TMC device.
5. Add a function in helper_ops to check whether the byte-cntr is
enabkled.
6. Call byte-cntr's read_ops if byte-cntr is enabled when reading data
from the sysfs node.
Link to V3 resend - https://lore.kernel.org/all/20250714063109.591-1-jie.gan@oss.qualcomm.com/
Changes in V3 resend:
1. rebased on next-20250711.
Link to V3 - https://lore.kernel.org/all/20250624060438.7469-1-jie.gan@oss.qualcomm.com/
Changes in V3:
1. The previous solution has been deprecated.
2. Add a etr_buf_list to manage allcated etr buffers.
3. Add a logic to switch buffer for ETR.
4. Add read functions to read trace data from synced etr buffer.
Link to V2 - https://lore.kernel.org/all/20250410013330.3609482-1-jie.gan@oss.qualcomm.com/
Changes in V2:
1. Removed the independent file node /dev/byte_cntr.
2. Integrated the byte-cntr's file operations with current ETR file
node.
3. Optimized the driver code of the CTCU that associated with byte-cntr.
4. Add kernel document for the export API tmc_etr_get_rwp_offset.
5. Optimized the way to read the rwp_offset according to Mike's
suggestion.
6. Removed the dependency of the dts patch.
Link to V1 - https://lore.kernel.org/all/20250310090407.2069489-1-quic_jiegan@quicinc.com/
Signed-off-by: Jie Gan <jie.gan@oss.qualcomm.com>
---
Jie Gan (7):
coresight: core: refactor ctcu_get_active_port and make it generic
coresight: tmc: add create/clean functions for etr_buf_list
coresight: tmc: introduce tmc_sysfs_ops to wrap sysfs read operations
coresight: etr: add a new function to retrieve the CTCU device
dt-bindings: arm: add an interrupt property for Coresight CTCU
coresight: ctcu: enable byte-cntr for TMC ETR devices
arm64: dts: qcom: lemans: add interrupts to CTCU device
.../ABI/testing/sysfs-bus-coresight-devices-ctcu | 9 +
.../bindings/arm/qcom,coresight-ctcu.yaml | 10 +
arch/arm64/boot/dts/qcom/lemans.dtsi | 3 +
drivers/hwtracing/coresight/Makefile | 2 +-
drivers/hwtracing/coresight/coresight-core.c | 27 ++
.../hwtracing/coresight/coresight-ctcu-byte-cntr.c | 327 +++++++++++++++++++++
drivers/hwtracing/coresight/coresight-ctcu-core.c | 146 +++++++--
drivers/hwtracing/coresight/coresight-ctcu.h | 81 ++++-
drivers/hwtracing/coresight/coresight-priv.h | 2 +
drivers/hwtracing/coresight/coresight-tmc-core.c | 55 ++--
drivers/hwtracing/coresight/coresight-tmc-etr.c | 265 ++++++++++++++++-
drivers/hwtracing/coresight/coresight-tmc.h | 42 +++
12 files changed, 896 insertions(+), 73 deletions(-)
---
base-commit: 4e5dfb7c84012007c3c7061126491bbc92d71bf1
change-id: 20260309-enable-byte-cntr-for-ctcu-ff86e6198b7f
Best regards,
--
Jie Gan <jie.gan@oss.qualcomm.com>
^ permalink raw reply
* [PATCH v2] arm64: ptrace: use live x0 for seccomp and audit after ptrace
From: Yiqi Sun @ 2026-06-25 10:45 UTC (permalink / raw)
To: catalin.marinas, linux-arm-kernel
Cc: linux-kernel, rmk+kernel, ruanjinjie, will, Yiqi Sun
In-Reply-To: <20260529065444.1336608-1-sunyiqixm@gmail.com>
On arm64, seccomp obtains syscall arguments via
syscall_get_arguments(), where arg0 is currently read from
regs->orig_x0. audit_syscall_entry() in syscall_trace_enter() also
takes arg0 from regs->orig_x0. However, the syscall wrapper consumes
live arguments from regs->regs[0..5].
A ptracer can modify x0 on syscall-enter stop before seccomp and audit
run, but cannot update orig_x0 through the native syscall-stop
interface. This can leave seccomp and audit checking stale arg0 while
the syscall executes with updated live x0.
Make both paths read arg0 from regs->regs[0], matching the actual
dispatch arguments and keeping seccomp and audit aligned after ptrace
updates.
Fixes: f27bb139c387 ("arm64: Miscellaneous library functions")
Signed-off-by: Yiqi Sun <sunyiqixm@gmail.com>
---
Changes in v2:
- Also switch the arm64 audit entry path to use live x0
- Clarify the orig_x0 synchronization comment in syscall_set_arguments()
---
arch/arm64/include/asm/syscall.h | 7 +++----
arch/arm64/kernel/ptrace.c | 2 +-
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 5e4c7fc44f73..0a44db425522 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -81,7 +81,7 @@ static inline void syscall_get_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned long *args)
{
- args[0] = regs->orig_x0;
+ args[0] = regs->regs[0];
args[1] = regs->regs[1];
args[2] = regs->regs[2];
args[3] = regs->regs[3];
@@ -101,9 +101,8 @@ static inline void syscall_set_arguments(struct task_struct *task,
regs->regs[5] = args[5];
/*
- * Also copy the first argument into orig_x0
- * so that syscall_get_arguments() would return it
- * instead of the previous value.
+ * Keep orig_x0 in sync so syscall_rollback() and compat
+ * register views see the updated first argument.
*/
regs->orig_x0 = regs->regs[0];
}
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 4d08598e2891..35dd86f9e87a 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -2426,7 +2426,7 @@ int syscall_trace_enter(struct pt_regs *regs)
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_enter(regs, regs->syscallno);
- audit_syscall_entry(regs->syscallno, regs->orig_x0, regs->regs[1],
+ audit_syscall_entry(regs->syscallno, regs->regs[0], regs->regs[1],
regs->regs[2], regs->regs[3]);
return regs->syscallno;
--
2.34.1
^ permalink raw reply related
* [PATCH v4 2/2] tracing: Remove trace_printk.h from kernel.h
From: Steven Rostedt @ 2026-06-25 10:40 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel
Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Linus Torvalds, Sebastian Andrzej Siewior, John Ogness,
Thomas Gleixner, Peter Zijlstra, Julia Lawall, Yury Norov,
linux-doc, linux-kbuild, linuxppc-dev, dri-devel, linux-stm32,
linux-arm-kernel, linux-rdma, linux-usb, linux-ext4, linux-nfs,
kvm, intel-gfx
In-Reply-To: <20260625104007.041432666@kernel.org>
From: Steven Rostedt <rostedt@goodmis.org>
There have been complaints about trace_printk.h causing more build time
for being in kernel.h if it changes. There is also an effort to clean up
kernel.h to have it not include unneeded header files. Move trace_printk.h
out of kernel.h and place it in the headers and C files that use it.
Link: https://lore.kernel.org/all/CAHk-=wikCBeVFjVXiY4o-oepdbjAoir5+TcAgtL12c4u1TpZLQ@mail.gmail.com/
Suggested-by: Yury Norov <yury.norov@gmail.com>
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
arch/powerpc/kvm/book3s_xics.c | 1 +
drivers/gpu/drm/i915/gt/intel_gtt.h | 1 +
drivers/gpu/drm/i915/i915_gem.h | 1 +
drivers/hwtracing/stm/dummy_stm.c | 1 +
drivers/infiniband/hw/hfi1/trace_dbg.h | 1 +
drivers/usb/early/xhci-dbc.c | 1 +
fs/ext4/inline.c | 1 +
include/linux/ftrace.h | 2 ++
include/linux/kernel.h | 1 -
include/linux/sunrpc/debug.h | 1 +
include/linux/trace_printk.h | 5 +++--
kernel/trace/ring_buffer_benchmark.c | 1 +
samples/fprobe/fprobe_example.c | 1 +
samples/ftrace/ftrace-direct-too.c | 1 -
samples/trace_printk/trace-printk.c | 1 +
15 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
index 74a44fa702b0..ef5eb596a56e 100644
--- a/arch/powerpc/kvm/book3s_xics.c
+++ b/arch/powerpc/kvm/book3s_xics.c
@@ -26,6 +26,7 @@
#if 1
#define XICS_DBG(fmt...) do { } while (0)
#else
+#include <linux/trace_printk.h>
#define XICS_DBG(fmt...) trace_printk(fmt)
#endif
diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h
index b54ee4f25af1..f6f223090760 100644
--- a/drivers/gpu/drm/i915/gt/intel_gtt.h
+++ b/drivers/gpu/drm/i915/gt/intel_gtt.h
@@ -35,6 +35,7 @@
#define I915_GFP_ALLOW_FAIL (GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN)
#if IS_ENABLED(CONFIG_DRM_I915_TRACE_GTT)
+#include <linux/trace_printk.h>
#define GTT_TRACE(...) trace_printk(__VA_ARGS__)
#else
#define GTT_TRACE(...)
diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h
index 1da8fb61c09e..f490052e8964 100644
--- a/drivers/gpu/drm/i915/i915_gem.h
+++ b/drivers/gpu/drm/i915/i915_gem.h
@@ -117,6 +117,7 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file);
#if IS_ENABLED(CONFIG_DRM_I915_TRACE_GEM)
#include <linux/trace_controls.h>
+#include <linux/trace_printk.h>
#define GEM_TRACE(...) trace_printk(__VA_ARGS__)
#define GEM_TRACE_ERR(...) do { \
pr_err(__VA_ARGS__); \
diff --git a/drivers/hwtracing/stm/dummy_stm.c b/drivers/hwtracing/stm/dummy_stm.c
index 38528ffdc0b3..7c5e48ebfb9f 100644
--- a/drivers/hwtracing/stm/dummy_stm.c
+++ b/drivers/hwtracing/stm/dummy_stm.c
@@ -8,6 +8,7 @@
*/
#undef DEBUG
+#include <linux/trace_printk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
diff --git a/drivers/infiniband/hw/hfi1/trace_dbg.h b/drivers/infiniband/hw/hfi1/trace_dbg.h
index 58304b91380f..30df5e246586 100644
--- a/drivers/infiniband/hw/hfi1/trace_dbg.h
+++ b/drivers/infiniband/hw/hfi1/trace_dbg.h
@@ -103,6 +103,7 @@ __hfi1_trace_def(IOCTL);
*/
#ifdef HFI1_EARLY_DBG
+#include <linux/trace_printk.h>
#define hfi1_dbg_early(fmt, ...) \
trace_printk(fmt, ##__VA_ARGS__)
#else
diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c
index 41118bba9197..955c73bd601f 100644
--- a/drivers/usb/early/xhci-dbc.c
+++ b/drivers/usb/early/xhci-dbc.c
@@ -30,6 +30,7 @@ static struct xdbc_state xdbc;
static bool early_console_keep;
#ifdef XDBC_TRACE
+#include <linux/trace_printk.h>
#define xdbc_trace trace_printk
#else
static inline void xdbc_trace(const char *fmt, ...) { }
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index 8045e4ff270c..0eff4a0c6a6c 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -934,6 +934,7 @@ static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,
}
#ifdef INLINE_DIR_DEBUG
+#include <linux/trace_printk.h>
void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh,
void *inline_start, int inline_size)
{
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 02bc5027523a..b5336a81e619 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -8,6 +8,8 @@
#define _LINUX_FTRACE_H
#include <linux/trace_recursion.h>
+#include <linux/trace_controls.h>
+#include <linux/trace_printk.h>
#include <linux/trace_clock.h>
#include <linux/jump_label.h>
#include <linux/kallsyms.h>
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e5570a16cbb1..e87a40fbd152 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -31,7 +31,6 @@
#include <linux/build_bug.h>
#include <linux/sprintf.h>
#include <linux/static_call_types.h>
-#include <linux/trace_printk.h>
#include <linux/util_macros.h>
#include <linux/wordpart.h>
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index ab61bed2f7af..7524f5d82fba 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -29,6 +29,7 @@ extern unsigned int nlm_debug;
# define ifdebug(fac) if (unlikely(rpc_debug & RPCDBG_##fac))
# if IS_ENABLED(CONFIG_SUNRPC_DEBUG_TRACE)
+# include <linux/trace_printk.h>
# define __sunrpc_printk(fmt, ...) trace_printk(fmt, ##__VA_ARGS__)
# else
# define __sunrpc_printk(fmt, ...) printk(KERN_DEFAULT fmt, ##__VA_ARGS__)
diff --git a/include/linux/trace_printk.h b/include/linux/trace_printk.h
index a488ea9e9f85..74ce4f8995c4 100644
--- a/include/linux/trace_printk.h
+++ b/include/linux/trace_printk.h
@@ -1,11 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_TRACE_PRINTK_H
#define _LINUX_TRACE_PRINTK_H
+#if !defined(__ASSEMBLY__) && !defined(__GENKSYMS__) && !defined(BUILD_VDSO)
-#include <linux/compiler_attributes.h>
#include <linux/instruction_pointer.h>
#include <linux/stddef.h>
#include <linux/stringify.h>
+#include <linux/stdarg.h>
#ifdef CONFIG_TRACING
static inline __printf(1, 2)
@@ -147,5 +148,5 @@ ftrace_vprintk(const char *fmt, va_list ap)
return 0;
}
#endif /* CONFIG_TRACING */
-
+#endif /* !defined(__ASSEMBLY__) && !defined(__GENKSYMS__) && !defined(BUILD_VDSO) */
#endif
diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c
index 593e3b59e42e..2bb25caebb75 100644
--- a/kernel/trace/ring_buffer_benchmark.c
+++ b/kernel/trace/ring_buffer_benchmark.c
@@ -5,6 +5,7 @@
* Copyright (C) 2009 Steven Rostedt <srostedt@redhat.com>
*/
#include <linux/ring_buffer.h>
+#include <linux/trace_printk.h>
#include <linux/completion.h>
#include <linux/kthread.h>
#include <uapi/linux/sched/types.h>
diff --git a/samples/fprobe/fprobe_example.c b/samples/fprobe/fprobe_example.c
index bfe98ce826f3..de81b9b4ca7d 100644
--- a/samples/fprobe/fprobe_example.c
+++ b/samples/fprobe/fprobe_example.c
@@ -12,6 +12,7 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
+#include <linux/trace_printk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fprobe.h>
diff --git a/samples/ftrace/ftrace-direct-too.c b/samples/ftrace/ftrace-direct-too.c
index bf2411aa6fd7..159190f4103f 100644
--- a/samples/ftrace/ftrace-direct-too.c
+++ b/samples/ftrace/ftrace-direct-too.c
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/module.h>
-
#include <linux/mm.h> /* for handle_mm_fault() */
#include <linux/ftrace.h>
#if !defined(CONFIG_ARM64) && !defined(CONFIG_PPC32)
diff --git a/samples/trace_printk/trace-printk.c b/samples/trace_printk/trace-printk.c
index cfc159580263..ff37aeb8523e 100644
--- a/samples/trace_printk/trace-printk.c
+++ b/samples/trace_printk/trace-printk.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/trace_printk.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/irq_work.h>
--
2.53.0
^ permalink raw reply related
* [PATCH v4 0/2] tracing: Move non-trace_printk prototypes into trace_controls.h
From: Steven Rostedt @ 2026-06-25 10:40 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel
Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Linus Torvalds, Sebastian Andrzej Siewior, John Ogness,
Thomas Gleixner, Peter Zijlstra, Julia Lawall, Yury Norov,
linux-doc, linux-kbuild, linuxppc-dev, dri-devel, linux-stm32,
linux-arm-kernel, linux-rdma, linux-usb, linux-ext4, linux-nfs,
kvm, intel-gfx
Remove trace_printk.h by creating a trace_controls.h for those places that
need access to tracing prototypes like tracing_off() and for the places that
need trace_printk() directly, to have it included directly.
Changse since v3: https://lore.kernel.org/all/20260624081806.120105649@kernel.org/
- Always include trace_controls.h in rcu.h (kernel test robot)
There are other configs that may include tracing_off() in rcu.h besides
the one that had the include of trace_controls.h. Just always include
it in that header to be safe.
Steven Rostedt (2):
tracing: Move non-trace_printk prototypes into trace_controls.h
tracing: Remove trace_printk.h from kernel.h
----
arch/powerpc/kvm/book3s_xics.c | 1 +
arch/powerpc/xmon/xmon.c | 1 +
arch/s390/kernel/ipl.c | 1 +
arch/s390/kernel/machine_kexec.c | 1 +
drivers/gpu/drm/i915/gt/intel_gtt.h | 1 +
drivers/gpu/drm/i915/i915_gem.h | 2 ++
drivers/hwtracing/stm/dummy_stm.c | 1 +
drivers/infiniband/hw/hfi1/trace_dbg.h | 1 +
drivers/tty/sysrq.c | 1 +
drivers/usb/early/xhci-dbc.c | 1 +
fs/ext4/inline.c | 1 +
include/linux/ftrace.h | 2 ++
include/linux/kernel.h | 1 -
include/linux/sunrpc/debug.h | 1 +
include/linux/trace_controls.h | 54 ++++++++++++++++++++++++++++++++
include/linux/trace_printk.h | 56 ++--------------------------------
kernel/debug/debug_core.c | 1 +
kernel/panic.c | 1 +
kernel/rcu/rcu.h | 1 +
kernel/rcu/rcutorture.c | 1 +
kernel/trace/ring_buffer_benchmark.c | 1 +
kernel/trace/trace.h | 1 +
kernel/trace/trace_benchmark.c | 1 +
lib/sys_info.c | 1 +
samples/fprobe/fprobe_example.c | 1 +
samples/ftrace/ftrace-direct-too.c | 1 -
samples/trace_printk/trace-printk.c | 1 +
27 files changed, 82 insertions(+), 55 deletions(-)
create mode 100644 include/linux/trace_controls.h
^ permalink raw reply
* [PATCH v4 1/2] tracing: Move non-trace_printk prototypes into trace_controls.h
From: Steven Rostedt @ 2026-06-25 10:40 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel
Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Linus Torvalds, Sebastian Andrzej Siewior, John Ogness,
Thomas Gleixner, Peter Zijlstra, Julia Lawall, Yury Norov,
linux-doc, linux-kbuild, linuxppc-dev, dri-devel, linux-stm32,
linux-arm-kernel, linux-rdma, linux-usb, linux-ext4, linux-nfs,
kvm, intel-gfx
In-Reply-To: <20260625104007.041432666@kernel.org>
From: Steven Rostedt <rostedt@goodmis.org>
Remove the prototypes of the code that is not associated with
trace_printk() from trace_printk.h.
These control functions as well as ftrace_dump() and trace_dump_stack()
are used in cases where things go wrong. The main use case is to do a
trace_dump_stack(); tracing_off(); ftrace_dump(); in a place that detected
that something went wrong, whereas, trace_printk() is added to normal code
during debugging and removed before committing upstream. The dump code is
fine to keep in production.
Suggested-by: Yury Norov <yury.norov@gmail.com>
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
Changes since v3: https://patch.msgid.link/20260624081948.147764194@kernel.org
- Move include out of #if statement in rcu.h
kernel test robot found other configs that could require the
control functions in rcu.h. Just always include it in that file.
arch/powerpc/xmon/xmon.c | 1 +
arch/s390/kernel/ipl.c | 1 +
arch/s390/kernel/machine_kexec.c | 1 +
drivers/gpu/drm/i915/i915_gem.h | 1 +
drivers/tty/sysrq.c | 1 +
include/linux/trace_controls.h | 54 ++++++++++++++++++++++++++++++++
include/linux/trace_printk.h | 51 ------------------------------
kernel/debug/debug_core.c | 1 +
kernel/panic.c | 1 +
kernel/rcu/rcu.h | 1 +
kernel/rcu/rcutorture.c | 1 +
kernel/trace/trace.h | 1 +
kernel/trace/trace_benchmark.c | 1 +
lib/sys_info.c | 1 +
14 files changed, 66 insertions(+), 51 deletions(-)
create mode 100644 include/linux/trace_controls.h
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index cb3a3244ae6f..2135f319e0dd 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -27,6 +27,7 @@
#include <linux/highmem.h>
#include <linux/security.h>
#include <linux/debugfs.h>
+#include <linux/trace_controls.h>
#include <asm/ptrace.h>
#include <asm/smp.h>
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 3c346b02ceb9..baac66cc4de4 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -22,6 +22,7 @@
#include <linux/debug_locks.h>
#include <linux/vmalloc.h>
#include <linux/secure_boot.h>
+#include <linux/trace_controls.h>
#include <asm/asm-extable.h>
#include <asm/machine.h>
#include <asm/diag.h>
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index baeb3dcfc1c8..33f9a89eb3ad 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/reboot.h>
#include <linux/ftrace.h>
+#include <linux/trace_controls.h>
#include <linux/debug_locks.h>
#include <linux/cpufeature.h>
#include <asm/guarded_storage.h>
diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h
index 20b3cb29cfff..1da8fb61c09e 100644
--- a/drivers/gpu/drm/i915/i915_gem.h
+++ b/drivers/gpu/drm/i915/i915_gem.h
@@ -116,6 +116,7 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file);
#endif
#if IS_ENABLED(CONFIG_DRM_I915_TRACE_GEM)
+#include <linux/trace_controls.h>
#define GEM_TRACE(...) trace_printk(__VA_ARGS__)
#define GEM_TRACE_ERR(...) do { \
pr_err(__VA_ARGS__); \
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index c2e4b31b699a..d3f72dc430b8 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -324,6 +324,7 @@ static const struct sysrq_key_op sysrq_showstate_blocked_op = {
};
#ifdef CONFIG_TRACING
+#include <linux/trace_controls.h>
#include <linux/ftrace.h>
static void sysrq_ftrace_dump(u8 key)
diff --git a/include/linux/trace_controls.h b/include/linux/trace_controls.h
new file mode 100644
index 000000000000..995b97e963b4
--- /dev/null
+++ b/include/linux/trace_controls.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_TRACE_CONTROLS_H
+#define _LINUX_TRACE_CONTROLS_H
+
+
+/*
+ * General tracing related utility functions - trace_printk(),
+ * tracing_on/tracing_off and tracing_start()/tracing_stop
+ *
+ * Use tracing_on/tracing_off when you want to quickly turn on or off
+ * tracing. It simply enables or disables the recording of the trace events.
+ * This also corresponds to the user space /sys/kernel/tracing/tracing_on
+ * file, which gives a means for the kernel and userspace to interact.
+ * Place a tracing_off() in the kernel where you want tracing to end.
+ * From user space, examine the trace, and then echo 1 > tracing_on
+ * to continue tracing.
+ *
+ * tracing_stop/tracing_start has slightly more overhead. It is used
+ * by things like suspend to ram where disabling the recording of the
+ * trace is not enough, but tracing must actually stop because things
+ * like calling smp_processor_id() may crash the system.
+ *
+ * Most likely, you want to use tracing_on/tracing_off.
+ */
+enum ftrace_dump_mode {
+ DUMP_NONE,
+ DUMP_ALL,
+ DUMP_ORIG,
+ DUMP_PARAM,
+};
+
+#ifdef CONFIG_TRACING
+void tracing_on(void);
+void tracing_off(void);
+int tracing_is_on(void);
+void tracing_snapshot(void);
+void tracing_snapshot_alloc(void);
+void tracing_start(void);
+void tracing_stop(void);
+void trace_dump_stack(int skip);
+void ftrace_dump(enum ftrace_dump_mode oops_dump_mode);
+#else
+static inline void tracing_start(void) { }
+static inline void tracing_stop(void) { }
+static inline void tracing_on(void) { }
+static inline void tracing_off(void) { }
+static inline int tracing_is_on(void) { return 0; }
+static inline void tracing_snapshot(void) { }
+static inline void tracing_snapshot_alloc(void) { }
+static inline void trace_dump_stack(int skip) { }
+static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
+#endif
+
+#endif /* _LINUX_TRACE_CONTROLS_H */
diff --git a/include/linux/trace_printk.h b/include/linux/trace_printk.h
index 3d54f440dccf..a488ea9e9f85 100644
--- a/include/linux/trace_printk.h
+++ b/include/linux/trace_printk.h
@@ -7,43 +7,7 @@
#include <linux/stddef.h>
#include <linux/stringify.h>
-/*
- * General tracing related utility functions - trace_printk(),
- * tracing_on/tracing_off and tracing_start()/tracing_stop
- *
- * Use tracing_on/tracing_off when you want to quickly turn on or off
- * tracing. It simply enables or disables the recording of the trace events.
- * This also corresponds to the user space /sys/kernel/tracing/tracing_on
- * file, which gives a means for the kernel and userspace to interact.
- * Place a tracing_off() in the kernel where you want tracing to end.
- * From user space, examine the trace, and then echo 1 > tracing_on
- * to continue tracing.
- *
- * tracing_stop/tracing_start has slightly more overhead. It is used
- * by things like suspend to ram where disabling the recording of the
- * trace is not enough, but tracing must actually stop because things
- * like calling smp_processor_id() may crash the system.
- *
- * Most likely, you want to use tracing_on/tracing_off.
- */
-
-enum ftrace_dump_mode {
- DUMP_NONE,
- DUMP_ALL,
- DUMP_ORIG,
- DUMP_PARAM,
-};
-
#ifdef CONFIG_TRACING
-void tracing_on(void);
-void tracing_off(void);
-int tracing_is_on(void);
-void tracing_snapshot(void);
-void tracing_snapshot_alloc(void);
-
-extern void tracing_start(void);
-extern void tracing_stop(void);
-
static inline __printf(1, 2)
void ____trace_printk_check_format(const char *fmt, ...)
{
@@ -149,8 +113,6 @@ int __trace_printk(unsigned long ip, const char *fmt, ...);
extern int __trace_bputs(unsigned long ip, const char *str);
extern int __trace_puts(unsigned long ip, const char *str);
-extern void trace_dump_stack(int skip);
-
/*
* The double __builtin_constant_p is because gcc will give us an error
* if we try to allocate the static variable to fmt if it is not a
@@ -173,19 +135,7 @@ __ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap);
extern __printf(2, 0) int
__ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap);
-
-extern void ftrace_dump(enum ftrace_dump_mode oops_dump_mode);
#else
-static inline void tracing_start(void) { }
-static inline void tracing_stop(void) { }
-static inline void trace_dump_stack(int skip) { }
-
-static inline void tracing_on(void) { }
-static inline void tracing_off(void) { }
-static inline int tracing_is_on(void) { return 0; }
-static inline void tracing_snapshot(void) { }
-static inline void tracing_snapshot_alloc(void) { }
-
static inline __printf(1, 2)
int trace_printk(const char *fmt, ...)
{
@@ -196,7 +146,6 @@ ftrace_vprintk(const char *fmt, va_list ap)
{
return 0;
}
-static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
#endif /* CONFIG_TRACING */
#endif
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index b276504c1c6b..f9c83a470c98 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -27,6 +27,7 @@
#define pr_fmt(fmt) "KGDB: " fmt
+#include <linux/trace_controls.h>
#include <linux/pid_namespace.h>
#include <linux/clocksource.h>
#include <linux/serial_core.h>
diff --git a/kernel/panic.c b/kernel/panic.c
index 213725b612aa..1415e910371d 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -9,6 +9,7 @@
* This function is used through-out the kernel (including mm and fs)
* to indicate a major problem.
*/
+#include <linux/trace_controls.h>
#include <linux/debug_locks.h>
#include <linux/sched/debug.h>
#include <linux/interrupt.h>
diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h
index fa6d30ce73d1..735a80df0b30 100644
--- a/kernel/rcu/rcu.h
+++ b/kernel/rcu/rcu.h
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <trace/events/rcu.h>
+#include <linux/trace_controls.h>
/*
* Grace-period counter management.
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 882a158ada7b..76bf0184b267 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -39,6 +39,7 @@
#include <linux/srcu.h>
#include <linux/slab.h>
#include <linux/trace_clock.h>
+#include <linux/trace_controls.h>
#include <asm/byteorder.h>
#include <linux/torture.h>
#include <linux/vmalloc.h>
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 80fe152af1dd..2537c33ddd49 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -22,6 +22,7 @@
#include <linux/ctype.h>
#include <linux/once_lite.h>
#include <linux/ftrace_regs.h>
+#include <linux/trace_controls.h>
#include <linux/llist.h>
#include "pid_list.h"
diff --git a/kernel/trace/trace_benchmark.c b/kernel/trace/trace_benchmark.c
index e19c32f2a938..69cc39008c36 100644
--- a/kernel/trace/trace_benchmark.c
+++ b/kernel/trace/trace_benchmark.c
@@ -3,6 +3,7 @@
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/trace_clock.h>
+#include <linux/trace_controls.h>
#define CREATE_TRACE_POINTS
#include "trace_benchmark.h"
diff --git a/lib/sys_info.c b/lib/sys_info.c
index f32a06ec9ed4..e3c9ca05601b 100644
--- a/lib/sys_info.c
+++ b/lib/sys_info.c
@@ -8,6 +8,7 @@
#include <linux/ftrace.h>
#include <linux/nmi.h>
#include <linux/sched/debug.h>
+#include <linux/trace_controls.h>
#include <linux/string.h>
#include <linux/sysctl.h>
--
2.53.0
^ permalink raw reply related
* [PATCH v5 5/7] drm/verisilicon: add DC8000 (DCUltraLite) display controller support
From: Joey Lu @ 2026-06-25 9:44 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260625094449.708386-1-a0987203069@gmail.com>
The Nuvoton MA35D1 SoC integrates a Verisilicon DCUltraLite display
controller (DC8000 generation) whose register layout differs from
the DC8200 in several important ways:
1. No CONFIG_EX commit path: framebuffer updates use the enable (bit 0)
and reset (bit 4) bits in FB_CONFIG instead of the DC8200 staging
registers (FB_CONFIG_EX, FB_TOP_LEFT, FB_BOTTOM_RIGHT,
FB_BLEND_CONFIG, PANEL_CONFIG_EX).
2. No PANEL_START register: panel output starts when
PANEL_CONFIG.RUNNING is set; there is no multi-display sync start
register.
3. Different IRQ registers: DCUltraLite uses DISP_IRQ_STA (0x147C) /
DISP_IRQ_EN (0x1480) versus DC8200's TOP_IRQ_ACK (0x0010) /
TOP_IRQ_EN (0x0014).
4. Simpler clock topology: only 'core' (bus gate) and 'pix0' (pixel
divider) clocks; no axi or ahb clocks required.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_dc.c | 5 +-
drivers/gpu/drm/verisilicon/vs_dc.h | 1 +
drivers/gpu/drm/verisilicon/vs_dc8000.c | 86 +++++++++++++++++++++++++
4 files changed, 92 insertions(+), 2 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8000.c
diff --git a/drivers/gpu/drm/verisilicon/Makefile b/drivers/gpu/drm/verisilicon/Makefile
index 9d4cd16452fa..d2fd8e4dff24 100644
--- a/drivers/gpu/drm/verisilicon/Makefile
+++ b/drivers/gpu/drm/verisilicon/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
-verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_drm.o vs_hwdb.o \
+verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_dc8000.o vs_drm.o vs_hwdb.o \
vs_plane.o vs_primary_plane.o vs_cursor_plane.o
obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon-dc.o
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c
index fd1f5fe67a68..9499fffbca58 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -134,7 +134,10 @@ static int vs_dc_probe(struct platform_device *pdev)
dev_info(dev, "Found DC%x rev %x customer %x\n", dc->identity.model,
dc->identity.revision, dc->identity.customer_id);
- dc->funcs = &vs_dc8200_funcs;
+ if (dc->identity.generation == VSDC_GEN_DC8200)
+ dc->funcs = &vs_dc8200_funcs;
+ else
+ dc->funcs = &vs_dc8000_funcs;
if (port_count > dc->identity.display_count) {
dev_err(dev, "too many downstream ports than HW capability\n");
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.h b/drivers/gpu/drm/verisilicon/vs_dc.h
index 825f5dd6bf17..ac96ad701199 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.h
+++ b/drivers/gpu/drm/verisilicon/vs_dc.h
@@ -66,5 +66,6 @@ struct vs_dc {
};
extern const struct vs_dc_funcs vs_dc8200_funcs;
+extern const struct vs_dc_funcs vs_dc8000_funcs;
#endif /* _VS_DC_H_ */
diff --git a/drivers/gpu/drm/verisilicon/vs_dc8000.c b/drivers/gpu/drm/verisilicon/vs_dc8000.c
new file mode 100644
index 000000000000..fbe0fa516cac
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dc8000.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 Joey Lu <yclu4@nuvoton.com>
+ */
+
+#include <linux/regmap.h>
+
+#include "vs_crtc_regs.h"
+#include "vs_dc.h"
+#include "vs_drm.h"
+#include "vs_primary_plane_regs.h"
+
+static void vs_dc8000_panel_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_RESET);
+}
+
+static void vs_dc8000_panel_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_RESET);
+}
+
+static void vs_dc8000_crtc_begin(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_VALID);
+}
+
+static void vs_dc8000_crtc_flush(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_VALID);
+}
+
+static void vs_dc8000_crtc_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_ENABLE);
+}
+
+static void vs_dc8000_crtc_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_ENABLE);
+}
+
+static void vs_dc8000_enable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_DISP_IRQ_EN,
+ VSDC_DISP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8000_disable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_DISP_IRQ_EN,
+ VSDC_DISP_IRQ_VSYNC(output));
+}
+
+static u32 vs_dc8000_irq_ack(struct vs_dc *dc)
+{
+ u32 hw_irqs, unified = 0;
+ unsigned int i;
+
+ regmap_read(dc->regs, VSDC_DISP_IRQ_STA, &hw_irqs);
+
+ for (i = 0; i < VSDC_MAX_OUTPUTS; i++) {
+ if (hw_irqs & VSDC_DISP_IRQ_VSYNC(i))
+ unified |= VSDC_IRQ_VSYNC(i);
+ }
+
+ return unified;
+}
+
+const struct vs_dc_funcs vs_dc8000_funcs = {
+ .panel_enable_ex = vs_dc8000_panel_enable_ex,
+ .panel_disable_ex = vs_dc8000_panel_disable_ex,
+ .crtc_begin = vs_dc8000_crtc_begin,
+ .crtc_flush = vs_dc8000_crtc_flush,
+ .crtc_enable_ex = vs_dc8000_crtc_enable_ex,
+ .crtc_disable_ex = vs_dc8000_crtc_disable_ex,
+ .enable_vblank = vs_dc8000_enable_vblank,
+ .disable_vblank = vs_dc8000_disable_vblank,
+ .irq_ack = vs_dc8000_irq_ack,
+};
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] ARM: enable interrupts when arm_notify_die() is handling user mode errors
From: Russell King @ 2026-06-25 10:23 UTC (permalink / raw)
To: Xie Yuanbin
Cc: bigeasy, clrkwllms, rostedt, linusw, arnd, linux-arm-kernel,
linux-kernel, linux-rt-devel, liaohua4, lilinjie8
In-Reply-To: <20260625100031.25088-1-xieyuanbin1@huawei.com>
On Thu, Jun 25, 2026 at 06:00:31PM +0800, Xie Yuanbin wrote:
> On 2026-06-25 10:05:52 [+0100], Russell King wrote:
> > > for this but actual breakpoint handling might be broken or is it
> > > just me? But then your stack trace looks like mine so :/
> >
> > ARM Linux doesn't use BKPT. BKPT was an instruction introduced by Arm
> > Ltd in ARMv5TE. Prior to this, we use a UDF instruction instead (we
> > had to pick something!) and gdb and other tools use that as a
> > breapoint.
> >
> > Moreover, BKPT isn't guaranteed to trap to the kernel, especially when
> > there is a hardware debugger connected. In that case, DDI0100E states
> > that use of BKPT must be according to the instructions provided with
> > the hardware debugger. This makes BKPT unsuitable for use.
>
> When do_DataAbort()/do_PrefetchAbort() run into `inf->fn()`, and the
> hook function return != 0 with interrupts disabled, the WARN may be
> triggered. From the code perspective, there are countless possible
> places, and "bkpt #0" is just one of these.
>
> For example:
> bcm5301x_init_early()->hook_fault_code(bcm5301x_abort_handler).
> if CONFIG_ARCH_BCM_5301X=y, then bcm5301x_abort_handler() may return 1
> without enabling the interrupts.
> if CONFIG_ARCH_BCM_5301X=n, then in the same scenario it will run into
> do_bad(), also return 1 without enabling the interrupts.
>
> So I think maybe:
> 1. enable interrupts in all hook functions, maybe
> multiple points for modification.
> 2. enable interrupts in do_DataAbort()/do_PrefetchAbort() before
> `inf->fn()`, but harden_branch_predictor() may be difficult.
Unfortunately, this breaks the Spectre/Meltdown mitigations. The
page fault handlers must be entered with interrupts disabled.
> 3. enable interrupts in do_DataAbort()/do_PrefetchAbort() after
> `inf->fn()`, this may be ok.
>
> From this perspective, arm_notify_die() also seems to be a good place?
If one is happy with higher latency for preempt cases, then it may
be, but if we want lower latency, then it ought to be earlier.
My preference is (3).
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply
* Re: [PATCH v9 04/12] reset: realtek: Add RTD1625-ISO reset controller driver
From: Philipp Zabel @ 2026-06-25 10:22 UTC (permalink / raw)
To: Yu-Chun Lin [林祐君], mturquette@baylibre.com,
sboyd@kernel.org, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org, Edgar Lee [李承諭],
afaerber@suse.com, Jyan Chou [周芷安],
bmasney@redhat.com
Cc: devicetree@vger.kernel.org, linux-clk@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-realtek-soc@lists.infradead.org,
James Tai [戴志峰],
CY_Huang[黃鉦晏],
Stanley Chang[昌育德]
In-Reply-To: <f3b747e20110424c8a434cbd271edb87@realtek.com>
On Do, 2026-06-25 at 10:05 +0000, Yu-Chun Lin [林祐君] wrote:
> Hi Philipp,
>
> > On Mi, 2026-06-24 at 19:29 +0800, Yu-Chun Lin wrote:
> > > From: Cheng-Yu Lee <cylee12@realtek.com>
> > >
> > > Add support for the ISO (Isolation) domain reset controller on the
> > > Realtek
> > > RTD1625 SoC.
> > >
> > > The reset controller shares the same register space with the ISO clock
> > > controller. To handle this shared register space, the reset driver is
> > > implemented as an auxiliary driver. It will be instantiated and probed
> > > via the auxiliary bus by the RTD1625-ISO clock controller driver.
> > >
> > > Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
> > > Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> > > Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> > > ---
> > > Changes in v9:
> > > - Extract reset-related code from the previous clock driver patch
> > > (formerly patch 9 in v8).
> > > ---
> > > drivers/reset/realtek/Makefile | 2 +-
> > > drivers/reset/realtek/reset-rtd1625-iso.c | 99
> > > +++++++++++++++++++++++
> > > 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644
> > > drivers/reset/realtek/reset-rtd1625-iso.c
> > >
> > > diff --git a/drivers/reset/realtek/Makefile
> > > b/drivers/reset/realtek/Makefile index c3f605ffb11c..9007c9d5683b
> > > 100644
> > > --- a/drivers/reset/realtek/Makefile
> > > +++ b/drivers/reset/realtek/Makefile
> > > @@ -1,3 +1,3 @@
> > > # SPDX-License-Identifier: GPL-2.0-only
> > > obj-$(CONFIG_RESET_RTK_COMMON) += reset-rtk-common.o
> > > -obj-$(CONFIG_RESET_RTD1625) += reset-rtd1625-crt.o
> > > +obj-$(CONFIG_RESET_RTD1625) += reset-rtd1625-crt.o
> > > +reset-rtd1625-iso.o
> >
> > Is there any benefit to these two being separate modules?
> > I suggest you merge them into one: reset-rtd1625.o
> >
>
> If I merge them into a single 'reset-rtd1625' module,
> both the 'crt' and 'iso' clock drivers would trigger the probe
> process for the same reset driver name, which would lead to a
> duplicate driver registration error.
What do you mean by duplicate driver registration error?
There would only be one auxiliary_driver, with support for all three
auxiliary_device_id's.
regards
Philipp
^ permalink raw reply
* Re: [PATCH] ARM: enable interrupts when arm_notify_die() is handling user mode errors
From: Russell King @ 2026-06-25 10:20 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: Xie Yuanbin, clrkwllms, rostedt, linusw, arnd, linux-arm-kernel,
linux-kernel, linux-rt-devel, liaohua4, lilinjie8
In-Reply-To: <20260625093008.e5I4bh-_@linutronix.de>
On Thu, Jun 25, 2026 at 11:30:08AM +0200, Sebastian Andrzej Siewior wrote:
> On 2026-06-25 10:05:52 [+0100], Russell King wrote:
> > > for this but actual breakpoint handling might be broken or is it just
> > > me? But then your stack trace looks like mine so :/
> >
> > ARM Linux doesn't use BKPT. BKPT was an instruction introduced by Arm
> > Ltd in ARMv5TE. Prior to this, we use a UDF instruction instead (we
> > had to pick something!) and gdb and other tools use that as a
> > breapoint.
> >
> > Moreover, BKPT isn't guaranteed to trap to the kernel, especially when
> > there is a hardware debugger connected. In that case, DDI0100E states
> > that use of BKPT must be according to the instructions provided with
> > the hardware debugger. This makes BKPT unsuitable for use.
>
> So you are saying this:
>
> diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
> index e62cc4be5adf6..11ac69113eca2 100644
> --- a/arch/arm/mm/fault.c
> +++ b/arch/arm/mm/fault.c
> @@ -595,6 +595,16 @@ do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
> return 1;
> }
>
> +static int do_debug_event(unsigned long addr, unsigned int fsr,
> + struct pt_regs *regs)
> +{
> + if (!user_mode(regs))
> + return 1;
> + local_irq_enable();
> + ptrace_break(regs);
> + return 0;
> +}
> +
> struct fsr_info {
> int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
> int sig;
> diff --git a/arch/arm/mm/fsr-2level.c b/arch/arm/mm/fsr-2level.c
> index f2be95197265d..bfd718f64020c 100644
> --- a/arch/arm/mm/fsr-2level.c
> +++ b/arch/arm/mm/fsr-2level.c
> @@ -46,7 +46,7 @@ static struct fsr_info fsr_info[] = {
> static struct fsr_info ifsr_info[] = {
> { do_bad, SIGBUS, 0, "unknown 0" },
> { do_bad, SIGBUS, 0, "unknown 1" },
> - { do_bad, SIGBUS, 0, "debug event" },
> + { do_debug_event, SIGBUS, 0, "debug event" },
> { do_bad, SIGSEGV, SEGV_ACCERR, "section access flag fault" },
> { do_bad, SIGBUS, 0, "unknown 4" },
> { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" },
> diff --git a/arch/arm/mm/fsr-3level.c b/arch/arm/mm/fsr-3level.c
> index d0ae2963656a6..96c1d45d20d9e 100644
> --- a/arch/arm/mm/fsr-3level.c
> +++ b/arch/arm/mm/fsr-3level.c
> @@ -34,7 +34,7 @@ static struct fsr_info fsr_info[] = {
> { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" },
> { do_bad, SIGBUS, 0, "unknown 32" },
> { do_bad, SIGBUS, BUS_ADRALN, "alignment fault" },
> - { do_bad, SIGBUS, 0, "debug event" },
> + { do_debug_event, SIGBUS, 0, "debug event" },
> { do_bad, SIGBUS, 0, "unknown 35" },
> { do_bad, SIGBUS, 0, "unknown 36" },
> { do_bad, SIGBUS, 0, "unknown 37" },
>
> is not worth doing it? With this I can my little testcase working.
No, it isn't, because if you enable PERF_EVENTS then BKPT breaks.
hw_breakpoint.c claims this vector.
Moreover, in older architectures, FSR=2 means "Terminal exception"
which is defined as "This indicates that an irrecoverable fault has
occurred. The circumstances under which this can happen (if at all)
are IMPLEMENTATION DEFINED." - from DDI0100E (which includes
ARMv5TE). In DDI0100F, this encoding was changed to "Debug exception".
Hence, the above can not be unconditional.
Then, we also have that FSR=2 is generated for a number of different
reasons (including hardware debug events) which may trigger.
Also a hardware debugger (e.g. connected via JTAG) could decide to
pass a BKPT exception on, and that could happen from the kernel. I
believe LLVM CFI uses BKPT (see LinusW's commit c3f89986fde7 ("ARM:
9391/2: hw_breakpoint: Handle CFI breakpoints")
BKPT is a total mess.
> That would be exc_int3() from arch/x86/kernel/traps.c.
> Besides doing "notify_die(DIE_INT3, "int3", regs, 0, X86_TRAP_BP, SIGTRAP);"
>
> it does cond_local_irq_enable() which enables the interrupts if they
> were enabled by the "caller", sends the signal (SIGTRAP).
I'm happy with that approach as far as interrupts go, but we can't
change the behaviour for FSR=2 again, beyond fixing LinusW's
commit (which has recently been reported as a regression.)
Note that the change which makes this raise a SIGTRAP rather than
SIGBUS when PERF_EVENTS=y could _also_ be reported as a regression
that we would have to fix, and making FSR=2 raise a SIGTRAP now
could very well invite that regression to be reported.
Essentially, I don't think we can "fix" BKPT to always raise SIGTRAP.
The BKPT instruction is something the kernel has never _officially_
supported.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply
* Re: [PATCH] arm64: dts: imx8mp-ab2: Enable MU2 for DSP communication
From: Daniel Baluta @ 2026-06-25 10:13 UTC (permalink / raw)
To: shengjiu.wang, robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel,
festevam, devicetree, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <20260625054709.301209-1-shengjiu.wang@oss.nxp.com>
On 6/25/26 08:47, shengjiu.wang@oss.nxp.com wrote:
> [You don't often get email from shengjiu.wang@oss.nxp.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> From: Shengjiu Wang <shengjiu.wang@nxp.com>
>
> Enable the MU2 (Message Unit 2) node on the i.MX8MP Audio Board v2.
> MU2 is required for inter-processor communication between the
> application CPU and the HiFi4 DSP, allowing DSP firmware to exchange
> control and status messages with the Linux host.
>
> Without this change, the DSP driver cannot establish the message
> channel and DSP audio processing is non-functional.
>
> Fixes: bf68c18150efc ("arm64: dts: imx8mp-ab2: add support for NXP i.MX8MP audio board (version 2)")
> Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
^ permalink raw reply
* Re: [PATCH 1/2] KVM: arm64: Fix sign-extension of MMIO loads
From: Marc Zyngier @ 2026-06-25 10:10 UTC (permalink / raw)
To: Fuad Tabba
Cc: Oliver Upton, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Steffen Eiden, Catalin Marinas, Will Deacon, Shuah Khan,
linux-arm-kernel, kvmarm, linux-kernel
In-Reply-To: <CA+EHjTxn8W=KYqTeqs-ZTw-SBD9tH0zUz_O9rTHsq3M7ELXn_w@mail.gmail.com>
On Tue, 23 Jun 2026 14:51:49 +0100,
Fuad Tabba <fuad.tabba@linux.dev> wrote:
>
> My reading of the ARM ARM is that the byte reversal is keyed on the access
> size there too. It lives in Mem{size}, with the register width handled
> separately by SignExtend(regsize):
>
> data = Mem[address, 2]; // byte-reversed by the access size, BE
> X[t] = SignExtend(data, regsize);
>
> So vcpu_data_host_to_guest(..., len) swapping by len matches the Mem-side
> reversal. Swapping by the register width would reorder bytes that were never
> loaded. An LDRSH into Wt reads 2 bytes but would bswap 4: the halfword
> reaches the helper as 0x0180 host-native, cpu_to_be32 turns it into
> 0x80010000 instead of the 0x8001 cpu_to_be16 gives, and it never sign-extends
> to 0xffff8001.
>
> If that reading holds, none of the helper's ops are individually wrong, and
> the only bug was the order, with the sign-extend running before the swap and
> the width mask then dropping it. But I've gone round in circles on endianness
> before (to say the least), so please say if I've done it again.
That's quite convincing.
And the quoted pseudocode is much easier to reason about than the
current blurb in the commit message. For reference, J1.2.3.111 Mem{}()
is the relevant bit of the M.b spec and clearly shows that the access
is done LE, and only then byteswapped. Can you please repaint the
commit log to describe things in those terms?
Also, can you augment your test to cover for BE accesses from the
guest if the HW supports it?
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* RE: [PATCH v9 04/12] reset: realtek: Add RTD1625-ISO reset controller driver
From: Yu-Chun Lin [林祐君] @ 2026-06-25 10:05 UTC (permalink / raw)
To: Philipp Zabel, mturquette@baylibre.com, sboyd@kernel.org,
robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
Edgar Lee [李承諭], afaerber@suse.com,
Jyan Chou [周芷安], bmasney@redhat.com
Cc: devicetree@vger.kernel.org, linux-clk@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-realtek-soc@lists.infradead.org,
James Tai [戴志峰],
CY_Huang[黃鉦晏],
Stanley Chang[昌育德]
In-Reply-To: <9db83aa615f43ff6eac090626b43915fcd593a25.camel@pengutronix.de>
Hi Philipp,
> On Mi, 2026-06-24 at 19:29 +0800, Yu-Chun Lin wrote:
> > From: Cheng-Yu Lee <cylee12@realtek.com>
> >
> > Add support for the ISO (Isolation) domain reset controller on the
> > Realtek
> > RTD1625 SoC.
> >
> > The reset controller shares the same register space with the ISO clock
> > controller. To handle this shared register space, the reset driver is
> > implemented as an auxiliary driver. It will be instantiated and probed
> > via the auxiliary bus by the RTD1625-ISO clock controller driver.
> >
> > Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
> > Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> > Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> > ---
> > Changes in v9:
> > - Extract reset-related code from the previous clock driver patch
> > (formerly patch 9 in v8).
> > ---
> > drivers/reset/realtek/Makefile | 2 +-
> > drivers/reset/realtek/reset-rtd1625-iso.c | 99
> > +++++++++++++++++++++++
> > 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644
> > drivers/reset/realtek/reset-rtd1625-iso.c
> >
> > diff --git a/drivers/reset/realtek/Makefile
> > b/drivers/reset/realtek/Makefile index c3f605ffb11c..9007c9d5683b
> > 100644
> > --- a/drivers/reset/realtek/Makefile
> > +++ b/drivers/reset/realtek/Makefile
> > @@ -1,3 +1,3 @@
> > # SPDX-License-Identifier: GPL-2.0-only
> > obj-$(CONFIG_RESET_RTK_COMMON) += reset-rtk-common.o
> > -obj-$(CONFIG_RESET_RTD1625) += reset-rtd1625-crt.o
> > +obj-$(CONFIG_RESET_RTD1625) += reset-rtd1625-crt.o
> > +reset-rtd1625-iso.o
>
> Is there any benefit to these two being separate modules?
> I suggest you merge them into one: reset-rtd1625.o
>
If I merge them into a single 'reset-rtd1625' module,
both the 'crt' and 'iso' clock drivers would trigger the probe
process for the same reset driver name, which would lead to a
duplicate driver registration error.
Therefore, I would prefer to keep them separate.
> > diff --git a/drivers/reset/realtek/reset-rtd1625-iso.c
> > b/drivers/reset/realtek/reset-rtd1625-iso.c
> > new file mode 100644
> > index 000000000000..78eaabb408f0
> > --- /dev/null
> > +++ b/drivers/reset/realtek/reset-rtd1625-iso.c
> > @@ -0,0 +1,99 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (C) 2026 Realtek Semiconductor Corporation */
> > +
> > +#include <dt-bindings/reset/realtek,rtd1625.h>
> > +#include <linux/auxiliary_bus.h>
> > +#include <linux/device.h>
> > +#include <linux/errno.h>
> > +#include <linux/of.h>
> > +#include <linux/slab.h>
> > +#include "reset-rtk-common.h"
> > +
> > +#define RTD1625_ISO_RSTN_MAX 29
> > +#define RTD1625_ISO_S_RSTN_MAX 5
>
> These are not necessary, just use ARRAY_SIZE() for nr_resets.
>
Ack.
> > +
[...]
> > +
> > +static int rtd1625_iso_reset_probe(struct auxiliary_device *adev,
> > + const struct auxiliary_device_id *id)
> > +{
> > + struct device *dev = &adev->dev;
> > + struct device *parent = dev->parent;
> > + struct rtk_reset_data *data;
> > +
> > + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> > + if (!data)
> > + return -ENOMEM;
> > +
> > + if (of_device_is_compatible(parent->of_node,
> "realtek,rtd1625-iso-s-clk")) {
> > + data->descs = rtd1625_iso_s_reset_descs;
> > + data->rcdev.nr_resets = RTD1625_ISO_S_RSTN_MAX;
> > + } else {
> > + data->descs = rtd1625_iso_reset_descs;
> > + data->rcdev.nr_resets = RTD1625_ISO_RSTN_MAX;
> > + }
>
> No need to parse OF compatible again. Store these in a struct, point
> auxiliary_device_id::driver_data to it, and use that here.
>
> regards
> Philipp
Agreed, I will do it in v10. Thanks.
Best Regards,
Yu-Chun
^ permalink raw reply
* RE: [PATCH v9 02/12] reset: Add Realtek basic reset support
From: Yu-Chun Lin [林祐君] @ 2026-06-25 10:02 UTC (permalink / raw)
To: Philipp Zabel, mturquette@baylibre.com, sboyd@kernel.org,
robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
Edgar Lee [李承諭], afaerber@suse.com,
Jyan Chou [周芷安], bmasney@redhat.com
Cc: devicetree@vger.kernel.org, linux-clk@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-realtek-soc@lists.infradead.org,
James Tai [戴志峰],
CY_Huang[黃鉦晏],
Stanley Chang[昌育德]
In-Reply-To: <eb03894ae2765a426457238157e474087ea0aaa6.camel@pengutronix.de>
Hi Philipp,
> On Mi, 2026-06-24 at 19:29 +0800, Yu-Chun Lin wrote:
> > Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> > ---
> > +static int rtk_reset_deassert(struct reset_controller_dev *rcdev,
> > + unsigned long idx) {
> > + struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
> > + const struct rtk_reset_desc *desc;
> > + u32 mask, val;
> > +
> > + desc = rtk_reset_get_desc(data, idx);
> > + mask = desc->write_en ? (0x3U << desc->bit) : BIT(desc->bit);
> > + val = mask;
> > +
> > + return regmap_update_bits(data->regmap, desc->ofs, mask, val);
>
> You can use regmap_set_bits() here.
>
Ack.
> > +}
> > +
> > +static int rtk_reset_status(struct reset_controller_dev *rcdev,
> > + unsigned long idx) {
> > + struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
> > + const struct rtk_reset_desc *desc;
> > + u32 val;
>
> unsigned int val;
>
Ack.
> > + int ret;
> > +
> > + desc = rtk_reset_get_desc(data, idx);
> > + ret = regmap_read(data->regmap, desc->ofs, &val);
> > + if (ret)
> > + return ret;
> > +
> > + return !((val >> desc->bit) & 1); }
> > +
> > +static const struct reset_control_ops rtk_reset_ops = {
> > + .assert = rtk_reset_assert,
> > + .deassert = rtk_reset_deassert,
> > + .status = rtk_reset_status,
> > +};
> > +
> > +/* The caller must initialize data->descs, data->rcdev.nr_resets and
> > + * data->rcdev.owner before calling rtk_reset_controller_add().
> > + */
> > +int rtk_reset_controller_add(struct device *dev,
> > + struct rtk_reset_data *data) {
> > + data->regmap = dev_get_platdata(dev);
> > + data->rcdev.ops = &rtk_reset_ops;
> > + data->rcdev.dev = dev;
> > + data->rcdev.of_node = dev->parent->of_node;
>
> This split rcdev initialization is more hassle than it is worth.
> Please just export rtk_reset_ops and duplicate the regmap/ops/dev/of_node
> assignment in the probe functions.
>
> Alternatively, consolidate the probe function and export it from here.
>
Thanks for your suggestion. I will go with your first approach in v10.
Best Regards,
Yu-Chun
> regards
> Philipp
^ permalink raw reply
* Re: [PATCH] ARM: enable interrupts when arm_notify_die() is handling user mode errors
From: Xie Yuanbin @ 2026-06-25 10:00 UTC (permalink / raw)
To: linux, bigeasy, clrkwllms, rostedt, rmk+kernel, linusw, arnd
Cc: linux-arm-kernel, linux-kernel, linux-rt-devel, liaohua4,
lilinjie8, Xie Yuanbin
In-Reply-To: <20260625073522.182503-1-xieyuanbin1@huawei.com>
On 2026-06-25 10:05:52 [+0100], Russell King wrote:
> > for this but actual breakpoint handling might be broken or is it
> > just me? But then your stack trace looks like mine so :/
>
> ARM Linux doesn't use BKPT. BKPT was an instruction introduced by Arm
> Ltd in ARMv5TE. Prior to this, we use a UDF instruction instead (we
> had to pick something!) and gdb and other tools use that as a
> breapoint.
>
> Moreover, BKPT isn't guaranteed to trap to the kernel, especially when
> there is a hardware debugger connected. In that case, DDI0100E states
> that use of BKPT must be according to the instructions provided with
> the hardware debugger. This makes BKPT unsuitable for use.
When do_DataAbort()/do_PrefetchAbort() run into `inf->fn()`, and the
hook function return != 0 with interrupts disabled, the WARN may be
triggered. From the code perspective, there are countless possible
places, and "bkpt #0" is just one of these.
For example:
bcm5301x_init_early()->hook_fault_code(bcm5301x_abort_handler).
if CONFIG_ARCH_BCM_5301X=y, then bcm5301x_abort_handler() may return 1
without enabling the interrupts.
if CONFIG_ARCH_BCM_5301X=n, then in the same scenario it will run into
do_bad(), also return 1 without enabling the interrupts.
So I think maybe:
1. enable interrupts in all hook functions, maybe
multiple points for modification.
2. enable interrupts in do_DataAbort()/do_PrefetchAbort() before
`inf->fn()`, but harden_branch_predictor() may be difficult.
3. enable interrupts in do_DataAbort()/do_PrefetchAbort() after
`inf->fn()`, this may be ok.
From this perspective, arm_notify_die() also seems to be a good place?
^ permalink raw reply
* Re: [PATCH 0/3] KVM: arm64: nv: Shadow ptdump fixes
From: Marc Zyngier @ 2026-06-25 9:54 UTC (permalink / raw)
To: Wei-Lin Chang
Cc: Itaru Kitayama, linux-arm-kernel, kvmarm, linux-kernel,
Oliver Upton, Joey Gouly, Steffen Eiden, Suzuki K Poulose,
Zenghui Yu, Catalin Marinas, Will Deacon
In-Reply-To: <fabkknc7dqpve4oo2hsgcsodq4syfgg5bp54qi6cywzssaue7u@ow3q6tupzwyz>
On Thu, 25 Jun 2026 08:47:04 +0100,
Wei-Lin Chang <weilin.chang@arm.com> wrote:
>
> I don't see a way out with this per-mmu file scheme. The core issue is
> mmus have a different lifetime than the VM's debugfs directory, and
> both's removal can happen in parallel, i.e. the VM debugfs directory
> can be removed anytime we are in mmu notifier release freeing the mmus
> and their shadow ptdump files.
Why isn't that a problem with the existing S2 ptdump code?
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* [PATCH v5 7/7] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms
From: Joey Lu @ 2026-06-25 9:44 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260625094449.708386-1-a0987203069@gmail.com>
Add ARCH_MA35 to the platform dependencies to allow the driver to be
built for Nuvoton MA35D1.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
Reviewed-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
---
drivers/gpu/drm/verisilicon/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/verisilicon/Kconfig b/drivers/gpu/drm/verisilicon/Kconfig
index 7cce86ec8603..295d246eb4b4 100644
--- a/drivers/gpu/drm/verisilicon/Kconfig
+++ b/drivers/gpu/drm/verisilicon/Kconfig
@@ -2,7 +2,7 @@
config DRM_VERISILICON_DC
tristate "DRM Support for Verisilicon DC-series display controllers"
depends on DRM && COMMON_CLK
- depends on RISCV || COMPILE_TEST
+ depends on RISCV || ARCH_MA35 || COMPILE_TEST
select DRM_BRIDGE_CONNECTOR
select DRM_CLIENT_SELECTION
select DRM_DISPLAY_HELPER
--
2.43.0
^ permalink raw reply related
* [PATCH v5 6/7] drm/verisilicon: add DCUltraLite chip identity to HWDB
From: Joey Lu @ 2026-06-25 9:44 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260625094449.708386-1-a0987203069@gmail.com>
The Nuvoton MA35D1 chip contains a DCUltraLite display controller with
model number 0x0 (sic, the model name contains no number either),
revision 0x5560 and customer ID 0x305. It has a similar register map
with DC8000, only one display output and only 32x32 cursor supported.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
drivers/gpu/drm/verisilicon/vs_hwdb.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.c b/drivers/gpu/drm/verisilicon/vs_hwdb.c
index 91524d16f778..7d630a667a3f 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.c
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.c
@@ -129,6 +129,16 @@ static struct vs_chip_identity vs_chip_identities[] = {
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
},
+ {
+ .model = 0x0, /* DCUltraLite */
+ .revision = 0x5560,
+ .customer_id = 0x305,
+
+ .generation = VSDC_GEN_DC8000,
+ .display_count = 1,
+ .max_cursor_size = 32,
+ .formats = &vs_formats_no_yuv444,
+ },
};
int vs_fill_chip_identity(struct regmap *regs,
--
2.43.0
^ permalink raw reply related
* [PATCH v5 3/7] drm/verisilicon: introduce per-variant hardware ops table
From: Joey Lu @ 2026-06-25 9:44 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260625094449.708386-1-a0987203069@gmail.com>
The DC8200 and DCUltraLite share a broadly similar register layout but
differ in how the bridge, CRTC, primary plane and IRQ paths are driven.
Introduce a vs_dc_funcs vtable so each variant can supply its own
implementation without scattering conditionals across multiple files.
Add a generation field to struct vs_chip_identity to distinguish variants.
Extract the DC8200-specific hardware ops into vs_dc8200.c and add unified
IRQ bit definitions so implementations can translate hardware-specific
bits to a common set. Update the shared code to dispatch through
dc->funcs.
No behaviour change for existing DC8200 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_bridge.c | 20 +--
drivers/gpu/drm/verisilicon/vs_crtc.c | 38 +++++-
drivers/gpu/drm/verisilicon/vs_dc.c | 6 +-
drivers/gpu/drm/verisilicon/vs_dc.h | 32 +++++
drivers/gpu/drm/verisilicon/vs_dc8200.c | 115 ++++++++++++++++++
drivers/gpu/drm/verisilicon/vs_drm.c | 5 +-
drivers/gpu/drm/verisilicon/vs_drm.h | 8 ++
drivers/gpu/drm/verisilicon/vs_hwdb.c | 4 +
drivers/gpu/drm/verisilicon/vs_hwdb.h | 6 +
.../gpu/drm/verisilicon/vs_primary_plane.c | 32 +----
11 files changed, 214 insertions(+), 54 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8200.c
diff --git a/drivers/gpu/drm/verisilicon/Makefile b/drivers/gpu/drm/verisilicon/Makefile
index 426f4bcaa834..9d4cd16452fa 100644
--- a/drivers/gpu/drm/verisilicon/Makefile
+++ b/drivers/gpu/drm/verisilicon/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
-verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_drm.o vs_hwdb.o \
+verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_drm.o vs_hwdb.o \
vs_plane.o vs_primary_plane.o vs_cursor_plane.o
obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon-dc.o
diff --git a/drivers/gpu/drm/verisilicon/vs_bridge.c b/drivers/gpu/drm/verisilicon/vs_bridge.c
index dc7c85b07fe3..3fbc8d57f8a1 100644
--- a/drivers/gpu/drm/verisilicon/vs_bridge.c
+++ b/drivers/gpu/drm/verisilicon/vs_bridge.c
@@ -162,15 +162,8 @@ static void vs_bridge_enable_common(struct vs_crtc *crtc,
VSDC_DISP_PANEL_CONFIG_DE_EN |
VSDC_DISP_PANEL_CONFIG_DAT_EN |
VSDC_DISP_PANEL_CONFIG_CLK_EN);
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
- VSDC_DISP_PANEL_CONFIG_RUNNING);
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_MULTI_DISP_SYNC);
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_RUNNING(output));
-
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(crtc->id),
- VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+
+ dc->funcs->panel_enable_ex(dc, output);
}
static void vs_bridge_atomic_enable_dpi(struct drm_bridge *bridge,
@@ -228,14 +221,7 @@ static void vs_bridge_atomic_disable(struct drm_bridge *bridge,
struct vs_dc *dc = crtc->dc;
unsigned int output = crtc->id;
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_MULTI_DISP_SYNC |
- VSDC_DISP_PANEL_START_RUNNING(output));
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
- VSDC_DISP_PANEL_CONFIG_RUNNING);
-
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(crtc->id),
- VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+ dc->funcs->panel_disable_ex(dc, output);
}
static const struct drm_bridge_funcs vs_dpi_bridge_funcs = {
diff --git a/drivers/gpu/drm/verisilicon/vs_crtc.c b/drivers/gpu/drm/verisilicon/vs_crtc.c
index 0b8a35d09cd2..1c4aac708669 100644
--- a/drivers/gpu/drm/verisilicon/vs_crtc.c
+++ b/drivers/gpu/drm/verisilicon/vs_crtc.c
@@ -16,10 +16,33 @@
#include "vs_crtc_regs.h"
#include "vs_crtc.h"
#include "vs_dc.h"
-#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#include "vs_plane.h"
+static void vs_crtc_atomic_begin(struct drm_crtc *crtc,
+ struct drm_atomic_commit *state)
+{
+ struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
+ struct vs_dc *dc = vcrtc->dc;
+ unsigned int output = vcrtc->id;
+
+ if (dc->funcs->crtc_begin)
+ dc->funcs->crtc_begin(dc, output);
+}
+
+static void vs_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_atomic_commit *state)
+{
+ struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
+ struct vs_dc *dc = vcrtc->dc;
+ unsigned int output = vcrtc->id;
+
+ if (dc->funcs->crtc_flush)
+ dc->funcs->crtc_flush(dc, output);
+
+ drm_crtc_vblank_atomic_flush(crtc, state);
+}
+
static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_atomic_commit *state)
{
@@ -30,6 +53,9 @@ static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
drm_crtc_vblank_off(crtc);
clk_disable_unprepare(dc->pix_clk[output]);
+
+ if (dc->funcs->crtc_disable_ex)
+ dc->funcs->crtc_disable_ex(dc, output);
}
static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
@@ -42,6 +68,9 @@ static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
drm_WARN_ON(&dc->drm_dev->base,
clk_prepare_enable(dc->pix_clk[output]));
+ if (dc->funcs->crtc_enable_ex)
+ dc->funcs->crtc_enable_ex(dc, output);
+
drm_crtc_vblank_on(crtc);
}
@@ -119,7 +148,8 @@ static bool vs_crtc_mode_fixup(struct drm_crtc *crtc,
}
static const struct drm_crtc_helper_funcs vs_crtc_helper_funcs = {
- .atomic_flush = drm_crtc_vblank_atomic_flush,
+ .atomic_begin = vs_crtc_atomic_begin,
+ .atomic_flush = vs_crtc_atomic_flush,
.atomic_enable = vs_crtc_atomic_enable,
.atomic_disable = vs_crtc_atomic_disable,
.mode_set_nofb = vs_crtc_mode_set_nofb,
@@ -132,7 +162,7 @@ static int vs_crtc_enable_vblank(struct drm_crtc *crtc)
struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_TOP_IRQ_EN, VSDC_TOP_IRQ_VSYNC(vcrtc->id));
+ dc->funcs->enable_vblank(dc, vcrtc->id);
return 0;
}
@@ -142,7 +172,7 @@ static void vs_crtc_disable_vblank(struct drm_crtc *crtc)
struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
struct vs_dc *dc = vcrtc->dc;
- regmap_clear_bits(dc->regs, VSDC_TOP_IRQ_EN, VSDC_TOP_IRQ_VSYNC(vcrtc->id));
+ dc->funcs->disable_vblank(dc, vcrtc->id);
}
static const struct drm_crtc_funcs vs_crtc_funcs = {
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c
index dad9967bc10b..9729b693d360 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -8,9 +8,7 @@
#include <linux/of.h>
#include <linux/of_graph.h>
-#include "vs_crtc.h"
#include "vs_dc.h"
-#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#include "vs_hwdb.h"
@@ -33,7 +31,7 @@ static irqreturn_t vs_dc_irq_handler(int irq, void *private)
struct vs_dc *dc = private;
u32 irqs;
- regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &irqs);
+ irqs = dc->funcs->irq_ack(dc);
vs_drm_handle_irq(dc, irqs);
@@ -136,6 +134,8 @@ static int vs_dc_probe(struct platform_device *pdev)
dev_info(dev, "Found DC%x rev %x customer %x\n", dc->identity.model,
dc->identity.revision, dc->identity.customer_id);
+ dc->funcs = &vs_dc8200_funcs;
+
if (port_count > dc->identity.display_count) {
dev_err(dev, "too many downstream ports than HW capability\n");
ret = -EINVAL;
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.h b/drivers/gpu/drm/verisilicon/vs_dc.h
index ed1016f18758..825f5dd6bf17 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.h
+++ b/drivers/gpu/drm/verisilicon/vs_dc.h
@@ -14,6 +14,7 @@
#include <linux/reset.h>
#include <drm/drm_device.h>
+#include <drm/drm_plane.h>
#include "vs_hwdb.h"
@@ -22,6 +23,34 @@
struct vs_drm_dev;
struct vs_crtc;
+struct vs_dc;
+
+struct vs_dc_funcs {
+ /* Bridge: atomic_enable, atomic_disable */
+ void (*panel_enable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*panel_disable_ex)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: atomic_begin, atomic_flush */
+ void (*crtc_begin)(struct vs_dc *dc, unsigned int output);
+ void (*crtc_flush)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: atomic_enable, atomic_disable */
+ void (*crtc_enable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*crtc_disable_ex)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: enable_vblank, disable_vblank */
+ void (*enable_vblank)(struct vs_dc *dc, unsigned int output);
+ void (*disable_vblank)(struct vs_dc *dc, unsigned int output);
+
+ /* Primary plane: atomic_enable, atomic_disable, atomic_update */
+ void (*primary_plane_enable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*primary_plane_disable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*primary_plane_update_ex)(struct vs_dc *dc, unsigned int output,
+ struct drm_plane_state *state);
+
+ /* IRQ acknowledge */
+ u32 (*irq_ack)(struct vs_dc *dc);
+};
struct vs_dc {
struct regmap *regs;
@@ -33,6 +62,9 @@ struct vs_dc {
struct vs_drm_dev *drm_dev;
struct vs_chip_identity identity;
+ const struct vs_dc_funcs *funcs;
};
+extern const struct vs_dc_funcs vs_dc8200_funcs;
+
#endif /* _VS_DC_H_ */
diff --git a/drivers/gpu/drm/verisilicon/vs_dc8200.c b/drivers/gpu/drm/verisilicon/vs_dc8200.c
new file mode 100644
index 000000000000..17378f4ef96d
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dc8200.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 Icenowy Zheng <uwu@icenowy.me>
+ */
+
+#include <linux/regmap.h>
+
+#include "vs_bridge_regs.h"
+#include "vs_dc.h"
+#include "vs_dc_top_regs.h"
+#include "vs_drm.h"
+#include "vs_plane.h"
+#include "vs_primary_plane_regs.h"
+
+static void vs_dc8200_panel_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
+ VSDC_DISP_PANEL_CONFIG_RUNNING);
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_MULTI_DISP_SYNC);
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_RUNNING(output));
+
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(output),
+ VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_panel_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
+ VSDC_DISP_PANEL_CONFIG_RUNNING);
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_MULTI_DISP_SYNC |
+ VSDC_DISP_PANEL_START_RUNNING(output));
+
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(output),
+ VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_enable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_TOP_IRQ_EN,
+ VSDC_TOP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8200_disable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_TOP_IRQ_EN,
+ VSDC_TOP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8200_plane_commit(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_primary_plane_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_FB_EN);
+ regmap_update_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_DISPLAY_ID_MASK,
+ VSDC_FB_CONFIG_EX_DISPLAY_ID(output));
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static void vs_dc8200_primary_plane_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_FB_EN);
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static void vs_dc8200_primary_plane_update_ex(struct vs_dc *dc, unsigned int output,
+ struct drm_plane_state *state)
+{
+ regmap_write(dc->regs, VSDC_FB_TOP_LEFT(output),
+ VSDC_MAKE_PLANE_POS(state->crtc_x, state->crtc_y));
+ regmap_write(dc->regs, VSDC_FB_BOTTOM_RIGHT(output),
+ VSDC_MAKE_PLANE_POS(state->crtc_x + state->crtc_w,
+ state->crtc_y + state->crtc_h));
+ regmap_write(dc->regs, VSDC_FB_BLEND_CONFIG(output),
+ VSDC_FB_BLEND_CONFIG_BLEND_DISABLE);
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static u32 vs_dc8200_irq_ack(struct vs_dc *dc)
+{
+ u32 hw_irqs, unified = 0;
+ unsigned int i;
+
+ regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &hw_irqs);
+
+ for (i = 0; i < VSDC_MAX_OUTPUTS; i++) {
+ if (hw_irqs & VSDC_TOP_IRQ_VSYNC(i))
+ unified |= VSDC_IRQ_VSYNC(i);
+ }
+
+ return unified;
+}
+
+const struct vs_dc_funcs vs_dc8200_funcs = {
+ .panel_enable_ex = vs_dc8200_panel_enable_ex,
+ .panel_disable_ex = vs_dc8200_panel_disable_ex,
+ .enable_vblank = vs_dc8200_enable_vblank,
+ .disable_vblank = vs_dc8200_disable_vblank,
+ .primary_plane_enable_ex = vs_dc8200_primary_plane_enable_ex,
+ .primary_plane_disable_ex = vs_dc8200_primary_plane_disable_ex,
+ .primary_plane_update_ex = vs_dc8200_primary_plane_update_ex,
+ .irq_ack = vs_dc8200_irq_ack,
+};
diff --git a/drivers/gpu/drm/verisilicon/vs_drm.c b/drivers/gpu/drm/verisilicon/vs_drm.c
index fd259d53f49f..24e9d0b008f3 100644
--- a/drivers/gpu/drm/verisilicon/vs_drm.c
+++ b/drivers/gpu/drm/verisilicon/vs_drm.c
@@ -25,7 +25,6 @@
#include "vs_bridge.h"
#include "vs_crtc.h"
#include "vs_dc.h"
-#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#define DRIVER_NAME "verisilicon"
@@ -168,8 +167,8 @@ void vs_drm_handle_irq(struct vs_dc *dc, u32 irqs)
unsigned int i;
for (i = 0; i < dc->identity.display_count; i++) {
- if (irqs & VSDC_TOP_IRQ_VSYNC(i)) {
- irqs &= ~VSDC_TOP_IRQ_VSYNC(i);
+ if (irqs & VSDC_IRQ_VSYNC(i)) {
+ irqs &= ~VSDC_IRQ_VSYNC(i);
if (dc->drm_dev->crtcs[i])
drm_crtc_handle_vblank(&dc->drm_dev->crtcs[i]->base);
}
diff --git a/drivers/gpu/drm/verisilicon/vs_drm.h b/drivers/gpu/drm/verisilicon/vs_drm.h
index 606338206a42..6a89c20879df 100644
--- a/drivers/gpu/drm/verisilicon/vs_drm.h
+++ b/drivers/gpu/drm/verisilicon/vs_drm.h
@@ -6,6 +6,7 @@
#ifndef _VS_DRM_H_
#define _VS_DRM_H_
+#include <linux/bits.h>
#include <linux/platform_device.h>
#include <linux/types.h>
@@ -13,6 +14,13 @@
struct vs_dc;
+/*
+ * DC variants use different interrupt registers with diverging bit
+ * assignments; each irq_ack() implementation must translate its
+ * hardware-specific bits into these definitions.
+ */
+#define VSDC_IRQ_VSYNC(n) BIT(n)
+
struct vs_drm_dev {
struct drm_device base;
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.c b/drivers/gpu/drm/verisilicon/vs_hwdb.c
index 2a0f7c59afa3..91524d16f778 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.c
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.c
@@ -94,6 +94,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5720,
.customer_id = ~0U,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
@@ -103,6 +104,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5721,
.customer_id = 0x30B,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
@@ -112,6 +114,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5720,
.customer_id = 0x310,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_with_yuv444,
@@ -121,6 +124,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5720,
.customer_id = 0x311,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.h b/drivers/gpu/drm/verisilicon/vs_hwdb.h
index 2065ecb73043..a15c8b565604 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.h
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.h
@@ -9,6 +9,11 @@
#include <linux/regmap.h>
#include <linux/types.h>
+enum vs_dc_generation {
+ VSDC_GEN_DC8000,
+ VSDC_GEN_DC8200,
+};
+
struct vs_formats {
const u32 *array;
unsigned int num;
@@ -19,6 +24,7 @@ struct vs_chip_identity {
u32 revision;
u32 customer_id;
+ enum vs_dc_generation generation;
u32 display_count;
/*
* The hardware only supports square cursor planes, so this field
diff --git a/drivers/gpu/drm/verisilicon/vs_primary_plane.c b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
index 1f2be41ae496..f992cb277f61 100644
--- a/drivers/gpu/drm/verisilicon/vs_primary_plane.c
+++ b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
@@ -53,12 +53,6 @@ static int vs_primary_plane_atomic_check(struct drm_plane *plane,
return 0;
}
-static void vs_primary_plane_commit(struct vs_dc *dc, unsigned int output)
-{
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_COMMIT);
-}
-
static void vs_primary_plane_atomic_enable(struct drm_plane *plane,
struct drm_atomic_commit *atomic_state)
{
@@ -69,13 +63,8 @@ static void vs_primary_plane_atomic_enable(struct drm_plane *plane,
unsigned int output = vcrtc->id;
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_FB_EN);
- regmap_update_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_DISPLAY_ID_MASK,
- VSDC_FB_CONFIG_EX_DISPLAY_ID(output));
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->primary_plane_enable_ex)
+ dc->funcs->primary_plane_enable_ex(dc, output);
}
static void vs_primary_plane_atomic_disable(struct drm_plane *plane,
@@ -88,10 +77,8 @@ static void vs_primary_plane_atomic_disable(struct drm_plane *plane,
unsigned int output = vcrtc->id;
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_FB_EN);
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->primary_plane_disable_ex)
+ dc->funcs->primary_plane_disable_ex(dc, output);
}
static void vs_primary_plane_atomic_update(struct drm_plane *plane,
@@ -133,18 +120,11 @@ static void vs_primary_plane_atomic_update(struct drm_plane *plane,
regmap_write(dc->regs, VSDC_FB_STRIDE(output),
fb->pitches[0]);
- regmap_write(dc->regs, VSDC_FB_TOP_LEFT(output),
- VSDC_MAKE_PLANE_POS(state->crtc_x, state->crtc_y));
- regmap_write(dc->regs, VSDC_FB_BOTTOM_RIGHT(output),
- VSDC_MAKE_PLANE_POS(state->crtc_x + state->crtc_w,
- state->crtc_y + state->crtc_h));
regmap_write(dc->regs, VSDC_FB_SIZE(output),
VSDC_MAKE_PLANE_SIZE(state->crtc_w, state->crtc_h));
- regmap_write(dc->regs, VSDC_FB_BLEND_CONFIG(output),
- VSDC_FB_BLEND_CONFIG_BLEND_DISABLE);
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->primary_plane_update_ex)
+ dc->funcs->primary_plane_update_ex(dc, output, state);
}
static const struct drm_plane_helper_funcs vs_primary_plane_helper_funcs = {
--
2.43.0
^ permalink raw reply related
* [PATCH v5 4/7] drm/verisilicon: make axi and ahb clocks optional
From: Joey Lu @ 2026-06-25 9:44 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260625094449.708386-1-a0987203069@gmail.com>
The Nuvoton MA35D1 SoC integrates a DCUltraLite display controller whose
AXI and AHB bus clocks share a single gate enable bit with the display
core clock, so the clock driver does not expose them separately. This
patch makes the axi and ahb clocks optional in the probe.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/vs_dc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c
index 9729b693d360..fd1f5fe67a68 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -90,13 +90,13 @@ static int vs_dc_probe(struct platform_device *pdev)
return PTR_ERR(dc->core_clk);
}
- dc->axi_clk = devm_clk_get_enabled(dev, "axi");
+ dc->axi_clk = devm_clk_get_optional_enabled(dev, "axi");
if (IS_ERR(dc->axi_clk)) {
dev_err(dev, "can't get axi clock\n");
return PTR_ERR(dc->axi_clk);
}
- dc->ahb_clk = devm_clk_get_enabled(dev, "ahb");
+ dc->ahb_clk = devm_clk_get_optional_enabled(dev, "ahb");
if (IS_ERR(dc->ahb_clk)) {
dev_err(dev, "can't get ahb clock\n");
return PTR_ERR(dc->ahb_clk);
--
2.43.0
^ permalink raw reply related
* [PATCH v5 2/7] drm/verisilicon: add register-level macros for DC8000
From: Joey Lu @ 2026-06-25 9:44 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260625094449.708386-1-a0987203069@gmail.com>
Add register-level constants needed by the forthcoming DC8000 (DCUltraLite)
hardware ops:
VSDC_DISP_IRQ_VSYNC(n) in vs_crtc_regs.h: bit mask for per-output
VSYNC interrupt bits in DISP_IRQ_STA (0x147C) / DISP_IRQ_EN (0x1480),
which are the IRQ registers used by DCUltraLite in place of the DC8200
TOP_IRQ_ACK / TOP_IRQ_EN registers.
VSDC_FB_CONFIG_ENABLE (bit 0), VSDC_FB_CONFIG_VALID (bit 3) and
VSDC_FB_CONFIG_RESET (bit 4) in vs_primary_plane_regs.h: control bits
in the FB_CONFIG register used by DCUltraLite for framebuffer enable
and per-frame commit handshake.
No behaviour change for existing DC8200 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
Reviewed-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
---
drivers/gpu/drm/verisilicon/vs_crtc_regs.h | 1 +
drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h | 3 +++
2 files changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/verisilicon/vs_crtc_regs.h b/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
index c7930e817635..d4da22b08cd5 100644
--- a/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
+++ b/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
@@ -54,6 +54,7 @@
#define VSDC_DISP_GAMMA_DATA(n) (0x1460 + 0x4 * (n))
#define VSDC_DISP_IRQ_STA 0x147C
+#define VSDC_DISP_IRQ_VSYNC(n) BIT(n)
#define VSDC_DISP_IRQ_EN 0x1480
diff --git a/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h b/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
index cbb125c46b39..67d4b00f294e 100644
--- a/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
+++ b/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
@@ -16,6 +16,9 @@
#define VSDC_FB_STRIDE(n) (0x1408 + 0x4 * (n))
#define VSDC_FB_CONFIG(n) (0x1518 + 0x4 * (n))
+#define VSDC_FB_CONFIG_ENABLE BIT(0)
+#define VSDC_FB_CONFIG_VALID BIT(3)
+#define VSDC_FB_CONFIG_RESET BIT(4)
#define VSDC_FB_CONFIG_CLEAR_EN BIT(8)
#define VSDC_FB_CONFIG_ROT_MASK GENMASK(13, 11)
#define VSDC_FB_CONFIG_ROT(v) ((v) << 11)
--
2.43.0
^ permalink raw reply related
* [PATCH v5 1/7] dt-bindings: display: verisilicon,dc: generalize for single-output variants
From: Joey Lu @ 2026-06-25 9:44 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260625094449.708386-1-a0987203069@gmail.com>
The verisilicon,dc binding was originally written for the T-Head TH1520
SoC carrying a DC8200, and hard-codes five clocks, three resets and two
output ports.
Add the Nuvoton MA35D1 DCUltraLite (nuvoton,ma35d1-dcu) to the binding.
The DCUltraLite uses only two clocks (core, pix0) and one reset (core),
with a single output port.
Use allOf/if blocks to express per-variant constraints rather than
hard-coding the DC8200 topology at the top level. Each compatible's
block constrains the clock and reset item counts; the nuvoton block
additionally overrides clock-names to the two names it actually uses.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
.../bindings/display/verisilicon,dc.yaml | 57 +++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
index 9dc35ab973f2..1e751f3c7ce8 100644
--- a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
+++ b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
@@ -17,6 +17,7 @@ properties:
items:
- enum:
- thead,th1520-dc8200
+ - nuvoton,ma35d1-dcu
- const: verisilicon,dc # DC IPs have discoverable ID/revision registers
reg:
@@ -77,6 +78,62 @@ required:
- clock-names
- ports
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: thead,th1520-dc8200
+ then:
+ properties:
+ clocks:
+ minItems: 5
+ maxItems: 5
+
+ clock-names:
+ minItems: 5
+ maxItems: 5
+
+ resets:
+ minItems: 3
+ maxItems: 3
+
+ reset-names:
+ minItems: 3
+ maxItems: 3
+
+ required:
+ - resets
+ - reset-names
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: nuvoton,ma35d1-dcu
+ then:
+ properties:
+ clocks:
+ minItems: 2
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: core
+ - const: pix0
+
+ resets:
+ minItems: 1
+ maxItems: 1
+
+ reset-names:
+ items:
+ - const: core
+
+ required:
+ - resets
+ - reset-names
+
additionalProperties: false
examples:
--
2.43.0
^ permalink raw reply related
* [PATCH v5 0/7] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support
From: Joey Lu @ 2026-06-25 9:44 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
This series adds support for the Verisilicon DCUltraLite display
controller as integrated in the Nuvoton MA35D1 SoC.
The Verisilicon DC driver and its DT binding were originally written by
Icenowy Zheng <zhengxingda@iscas.ac.cn> for the T-Head TH1520 SoC, which
carries a DC8200 IP block. The present series builds on that foundation
with gratitude to Icenowy for the original work.
The DCUltraLite is a different variant in the DC IP family. While the two
IPs share a broadly similar register layout, a number of differences
prevent the existing driver from working on the MA35D1 without
modification:
- No CONFIG_EX commit path: the DC8200 staging registers
(FB_CONFIG_EX, FB_TOP_LEFT, FB_BOTTOM_RIGHT, FB_BLEND_CONFIG,
PANEL_CONFIG_EX) are absent. The DCUltraLite uses enable (bit 0) and
reset (bit 4) bits in FB_CONFIG for direct framebuffer updates, and
requires a per-frame VALID bit toggle (FB_CONFIG bit 3) to latch
configuration changes.
- No PANEL_START register: panel output begins when
PANEL_CONFIG.RUNNING is set; the DC8200 multi-display sync start
register at 0x1CCC does not exist.
- Different IRQ registers: DISP_IRQ_STA at 0x147C / DISP_IRQ_EN at
0x1480, versus the DC8200's TOP_IRQ_ACK at 0x0010 / TOP_IRQ_EN at
0x0014.
- Simpler clock topology: two clocks ("core" bus gate and "pix0" pixel
divider); no axi or ahb clocks required.
- Single display output: no per-output indexing beyond index 0 is
needed.
- Hardware-discoverable identity: the DCUltraLite exposes chip identity
registers whose model field reads 0x0 (revision 0x5560,
customer_id 0x305), allowing the existing vs_fill_chip_identity()
path to identify the variant purely through register reads.
Patch 1 generalises the verisilicon,dc DT binding to accommodate the
Nuvoton MA35D1 SoC-specific compatible and the variant's two-clock,
one-reset, single-port topology.
Patch 2 adds the register-level macros needed by the DC8000 ops.
Patches 3-5 introduce the driver changes in three logical steps: the
vs_dc_funcs hardware ops vtable with DC8200 ops extracted into
vs_dc8200.c; making axi/ahb clocks optional as a separate atomic change;
and the DC8000 ops in vs_dc8000.c. Patch 6 adds the DCUltraLite HWDB
entry that gates hardware recognition once all support is in place.
Patch 7 adds the Kconfig dependency on ARCH_MA35, placed last because it
is only meaningful after the HWDB entry is added.
All patches have been tested on Nuvoton MA35D1 hardware.
Changes from v4:
- [dt-bindings] Kept clock and reset item descriptions in the global
clocks:/resets: properties; per-compatible sections only constrain
minItems/maxItems and override clock-names items for nuvoton,ma35d1-dcu.
- [dt-bindings] Dropped redundant global minItems/maxItems on clocks:
and clock-names:.
- [dt-bindings] Dropped the extra-space typo fix in port@0 description
to keep the patch atomic; left for a separate patch later.
- [ops] Renamed crtc_enable/crtc_disable hooks to crtc_enable_ex/
crtc_disable_ex.
- [ops] Added unified IRQ bit definitions; each irq_ack() implementation
now translates hardware-specific bits before returning.
- [clocks] Split the axi/ahb optional-clock change into its own patch
for atomicity.
- [hwdb] Simplified the commit message for patch 6.
- [kconfig] Simplified the commit message for patch 7.
Joey Lu (7):
dt-bindings: display: verisilicon,dc: generalize for single-output
variants
drm/verisilicon: add register-level macros for DC8000
drm/verisilicon: introduce per-variant hardware ops table
drm/verisilicon: make axi and ahb clocks optional
drm/verisilicon: add DC8000 (DCUltraLite) display controller support
drm/verisilicon: add DCUltraLite chip identity to HWDB
drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms
.../bindings/display/verisilicon,dc.yaml | 57 +++++++++
drivers/gpu/drm/verisilicon/Kconfig | 2 +-
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_bridge.c | 20 +--
drivers/gpu/drm/verisilicon/vs_crtc.c | 38 +++++-
drivers/gpu/drm/verisilicon/vs_crtc_regs.h | 1 +
drivers/gpu/drm/verisilicon/vs_dc.c | 13 +-
drivers/gpu/drm/verisilicon/vs_dc.h | 33 +++++
drivers/gpu/drm/verisilicon/vs_dc8000.c | 86 +++++++++++++
drivers/gpu/drm/verisilicon/vs_dc8200.c | 115 ++++++++++++++++++
drivers/gpu/drm/verisilicon/vs_drm.c | 5 +-
drivers/gpu/drm/verisilicon/vs_drm.h | 8 ++
drivers/gpu/drm/verisilicon/vs_hwdb.c | 14 +++
drivers/gpu/drm/verisilicon/vs_hwdb.h | 6 +
.../gpu/drm/verisilicon/vs_primary_plane.c | 32 +----
.../drm/verisilicon/vs_primary_plane_regs.h | 3 +
16 files changed, 378 insertions(+), 57 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8000.c
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8200.c
--
2.43.0
^ permalink raw reply
* [PATCH net] net: airoha: dma map xmit frags with skb_frag_dma_map()
From: Lorenzo Bianconi @ 2026-06-25 9:42 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: linux-arm-kernel, linux-mediatek, netdev, Lorenzo Bianconi
Map xmit skb fragments using skb_frag_dma_map() instead of
dma_map_single(skb_frag_address()). skb_frag_address() relies on
page_address() to obtain a kernel virtual address, which is not
guaranteed to work for all page types (e.g. highmem pages or
user-pinned pages from MSG_ZEROCOPY).
skb_frag_dma_map() maps the fragment directly via its struct page and
offset through dma_map_page(), avoiding the need for a kernel virtual
address entirely.
Introduce an enum airoha_dma_map_type to track how each queue entry was
mapped (single vs page), so that the matching unmap function is called
on completion and in error paths.
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 61 ++++++++++++++++++++------------
drivers/net/ethernet/airoha/airoha_eth.h | 7 ++++
2 files changed, 45 insertions(+), 23 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 932b3a3df2e5..1caf6766f2c0 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -944,6 +944,25 @@ static void airoha_qdma_wake_netdev_txqs(struct airoha_queue *q)
q->txq_stopped = false;
}
+static void airoha_unmap_xmit_buf(struct airoha_eth *eth,
+ struct airoha_queue_entry *e)
+{
+ switch (e->dma_type) {
+ case AIROHA_DMA_MAP_PAGE:
+ dma_unmap_page(eth->dev, e->dma_addr, e->dma_len,
+ DMA_TO_DEVICE);
+ break;
+ case AIROHA_DMA_MAP_SINGLE:
+ dma_unmap_single(eth->dev, e->dma_addr, e->dma_len,
+ DMA_TO_DEVICE);
+ break;
+ case AIROHA_DMA_UNMAPPED:
+ default:
+ break;
+ }
+ e->dma_type = AIROHA_DMA_UNMAPPED;
+}
+
static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget)
{
struct airoha_tx_irq_queue *irq_q;
@@ -1006,9 +1025,7 @@ static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget)
skb = e->skb;
e->skb = NULL;
- dma_unmap_single(eth->dev, e->dma_addr, e->dma_len,
- DMA_TO_DEVICE);
- e->dma_addr = 0;
+ airoha_unmap_xmit_buf(eth, e);
list_add_tail(&e->list, &q->tx_list);
WRITE_ONCE(desc->msg0, 0);
@@ -1177,12 +1194,10 @@ static void airoha_qdma_tx_cleanup(struct airoha_qdma *qdma)
struct airoha_qdma_desc *desc = &q->desc[j];
struct sk_buff *skb = e->skb;
- if (!e->dma_addr)
+ if (e->dma_type == AIROHA_DMA_UNMAPPED)
continue;
- dma_unmap_single(qdma->eth->dev, e->dma_addr,
- e->dma_len, DMA_TO_DEVICE);
- e->dma_addr = 0;
+ airoha_unmap_xmit_buf(qdma->eth, e);
list_add_tail(&e->list, &q->tx_list);
WRITE_ONCE(desc->ctrl, 0);
@@ -2193,8 +2208,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
struct netdev_queue *txq;
struct airoha_queue *q;
LIST_HEAD(tx_list);
+ dma_addr_t addr;
int i = 0, qid;
- void *data;
u16 index;
u8 fport;
@@ -2250,24 +2265,22 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
- len = skb_headlen(skb);
- data = skb->data;
-
e = list_first_entry(&q->tx_list, struct airoha_queue_entry,
list);
+ len = skb_headlen(skb);
+ addr = dma_map_single(netdev->dev.parent, skb->data, len,
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(netdev->dev.parent, addr)))
+ goto error_unlock;
+
+ e->dma_type = AIROHA_DMA_MAP_SINGLE;
index = e - q->entry;
while (true) {
struct airoha_qdma_desc *desc = &q->desc[index];
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- dma_addr_t addr;
u32 val;
- addr = dma_map_single(netdev->dev.parent, data, len,
- DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(netdev->dev.parent, addr)))
- goto error_unmap;
-
list_move_tail(&e->list, &tx_list);
e->skb = i == nr_frags - 1 ? skb : NULL;
e->dma_addr = addr;
@@ -2291,8 +2304,13 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
if (++i == nr_frags)
break;
- data = skb_frag_address(frag);
len = skb_frag_size(frag);
+ addr = skb_frag_dma_map(netdev->dev.parent, frag, 0, len,
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(netdev->dev.parent, addr)))
+ goto error_unmap;
+
+ e->dma_type = AIROHA_DMA_MAP_PAGE;
}
q->queued += i;
@@ -2313,11 +2331,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
error_unmap:
- list_for_each_entry(e, &tx_list, list) {
- dma_unmap_single(netdev->dev.parent, e->dma_addr, e->dma_len,
- DMA_TO_DEVICE);
- e->dma_addr = 0;
- }
+ list_for_each_entry(e, &tx_list, list)
+ airoha_unmap_xmit_buf(dev->eth, e);
list_splice(&tx_list, &q->tx_list);
error_unlock:
spin_unlock_bh(&q->lock);
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index d7ff8c5200e2..2765244d937c 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -170,12 +170,19 @@ enum trtcm_param {
#define TRTCM_TOKEN_RATE_MASK GENMASK(23, 6)
#define TRTCM_TOKEN_RATE_FRACTION_MASK GENMASK(5, 0)
+enum airoha_dma_map_type {
+ AIROHA_DMA_UNMAPPED,
+ AIROHA_DMA_MAP_SINGLE,
+ AIROHA_DMA_MAP_PAGE,
+};
+
struct airoha_queue_entry {
union {
void *buf;
struct {
struct list_head list;
struct sk_buff *skb;
+ enum airoha_dma_map_type dma_type;
};
};
dma_addr_t dma_addr;
---
base-commit: 232c4ca2343d1181cbfc061f9856d9591e397579
change-id: 20260625-airoha-eth-skb_frag_dma_map-bcccd5d6e4b1
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox