mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [RFC PATCH 0/5] hwtracing: rvtrace: Add ACPI support
@ 2026-09-29  8:55 Sunil V L
  2026-09-29  8:55 ` [RFC PATCH 1/5] of: property: Add in-ports/out-ports support to of_fwnode_graph_get_port_parent() Sunil V L
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Sunil V L @ 2026-09-29  8:55 UTC (permalink / raw)
  To: linux-acpi, linux-riscv, linux-kernel, devicetree
  Cc: Rafael J . Wysocki, Len Brown, Mayuresh Chitale, Anup Patel,
	Alexander Shishkin, Rob Herring, Saravana Kannan, Sunil V L

From: Sunil V L <sunilvl@oss.qualcomm.com>

This is an RFC series to add ACPI support for the RISC-V trace
framework. It is based on Mayuresh's v5 series, "Linux RISC-V trace
framework and drivers" [1].

The RISC-V trace specification is proposed in the RISC-V BRS v1.0.6
document [2], Section 6.5. It uses the Device Graph UUID defined in
Section 3.4 of the DSD Guide [3], similar to the approach used by
other architectures.

When I started looking at ACPI support for the trace graph, the obvious
design was to follow the approach used by other architectures, such as
CoreSight. However, that would mean duplicating the ACPI graph parsing
logic and maintaining separate DT and ACPI paths in the rvtrace driver.

Instead, this series proposes enhancing the existing fwnode_* graph APIs
so that the trace driver can use the same interfaces for both DT and
ACPI. The main idea is to parse the Device Graph UUID defined in _DSD
and create synthetic nodes that match the DT nodes. The ACPI-based
fwnode_* APIs are then enhanced to traverse these synthetic nodes in the
same way as DT. The ACPI fwnode_* APIs already support the
"Hierarchical Data Extension UUID" defined in Section 3.2 of the DSD
Guide [3]. Adding support for another GUID therefore seems natural to
me.

The series adds the ACPI device-graph parsing by creating
synthetic nodes matching the DT nodes, extends the graph parent handling
for in-ports and out-ports, converts the rvtrace platform driver to the
fwnode_* APIs, and adds ACPI matching and CPU binding support. In the
future, other drivers that use the Device Graph UUID, including
CoreSight drivers, can use the same interfaces and avoid duplicating
this logic.

One question that may come up is that the DT schema [5] has not
standardized the in-ports/out-ports. However, the existing OF
interfaces already support in-ports and out-ports. Therefore, I do not
see an issue with providing the same capability through the common
fwnode_* graph APIs.

This is an RFC series, and feedback on the overall design and the API
changes would be very helpful. We have a slot to discuss this in LPC
next week under RISC-V MC track. I hope this series gives better context
before the session and we can have a fruitful discussion next week to
converge on the right approach.

The series was tested on a QEMU virt machine with the required ACPI
namespace changes for the trace graph. These changes are available at
[4].

[1] - https://lore-kernel.gnuweeb.org/linux-riscv/20260810152223.3946743-13-mayuresh.chitale@oss.qualcomm.com/T/
[2] - https://github.com/riscv-non-isa/riscv-brs/releases/download/v1.0.6/brs-v1.0.6-20260928.pdf
[3] - https://github.com/UEFI/DSD-Guide/blob/main/dsd-guide.pdf
[4] - https://github.com/vlsunil/qemu/tree/acpi_trace_rfc_v1
[5] - https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/graph.yaml

Sunil V L (5):
  of: property: Add in-ports/out-ports support to
    of_fwnode_graph_get_port_parent()
  ACPI: property: Add ports/in-ports/out-ports support to
    acpi_fwnode_get_parent()
  ACPI: property: Add device graph support
  hwtracing: rvtrace: Move to fwnode_* APIs
  hwtracing: rvtrace: Add ACPI support

 drivers/acpi/property.c                     | 516 +++++++++++++++++++-
 drivers/hwtracing/gtrace/Kconfig            |   4 +-
 drivers/hwtracing/gtrace/rvtrace-platform.c | 191 ++++++--
 drivers/of/property.c                       |   4 +-
 4 files changed, 657 insertions(+), 58 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC PATCH 1/5] of: property: Add in-ports/out-ports support to of_fwnode_graph_get_port_parent()
  2026-09-29  8:55 [RFC PATCH 0/5] hwtracing: rvtrace: Add ACPI support Sunil V L
@ 2026-09-29  8:55 ` Sunil V L
  2026-09-29  8:55 ` [RFC PATCH 2/5] ACPI: property: Add ports/in-ports/out-ports support to acpi_fwnode_get_parent() Sunil V L
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Sunil V L @ 2026-09-29  8:55 UTC (permalink / raw)
  To: linux-acpi, linux-riscv, linux-kernel, devicetree
  Cc: Rafael J . Wysocki, Len Brown, Mayuresh Chitale, Anup Patel,
	Alexander Shishkin, Rob Herring, Saravana Kannan, Sunil V L

From: Sunil V L <sunilvl@oss.qualcomm.com>

Similar to its OF counterpart, the helper
of_fwnode_graph_get_port_parent() should also treat "in-ports" and
"out-ports" as container nodes. Without this, fwnode_* interfaces may
incorrectly return these nodes as port parents.

Extend the check to skip "in-ports" and "out-ports" so that the
correct parent node is returned. This change helps in using the
fwnode_* interface instead of OF-specific helpers.

This change is similar to commit 8f1e0d791b528 ("of: property: Add
in-ports/out-ports support to of_graph_get_port_parent()"), which
addressed the same issue in the OF specific handler.

Signed-off-by: Sunil V L <sunilvl@oss.qualcomm.com>
---
 drivers/of/property.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/of/property.c b/drivers/of/property.c
index 72cf12907de0..c259ac1f0457 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -1228,7 +1228,9 @@ of_fwnode_graph_get_port_parent(struct fwnode_handle *fwnode)
 		return NULL;
 
 	/* Is this the "ports" node? If not, it's the port parent. */
-	if (!of_node_name_eq(np, "ports"))
+	if (!of_node_name_eq(np, "ports") &&
+	    !of_node_name_eq(np, "in-ports") &&
+	    !of_node_name_eq(np, "out-ports"))
 		return of_fwnode_handle(np);
 
 	return of_fwnode_handle(of_get_next_parent(np));
-- 
2.43.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC PATCH 2/5] ACPI: property: Add ports/in-ports/out-ports support to acpi_fwnode_get_parent()
  2026-09-29  8:55 [RFC PATCH 0/5] hwtracing: rvtrace: Add ACPI support Sunil V L
  2026-09-29  8:55 ` [RFC PATCH 1/5] of: property: Add in-ports/out-ports support to of_fwnode_graph_get_port_parent() Sunil V L
@ 2026-09-29  8:55 ` Sunil V L
  2026-09-29  8:55 ` [RFC PATCH 3/5] ACPI: property: Add device graph support Sunil V L
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Sunil V L @ 2026-09-29  8:55 UTC (permalink / raw)
  To: linux-acpi, linux-riscv, linux-kernel, devicetree
  Cc: Rafael J . Wysocki, Len Brown, Mayuresh Chitale, Anup Patel,
	Alexander Shishkin, Rob Herring, Saravana Kannan, Sunil V L

From: Sunil V L <sunilvl@oss.qualcomm.com>

For collections of ports, the node name may be defined as "ports",
"in-ports", or "out-ports". Currently, acpi_fwnode_get_parent() does
not handle these container nodes, which can lead to incorrect parent
resolution when parsing remote-endpoints via common fwnode_* interfaces.

Extend acpi_fwnode_get_parent() to recognize "ports", "in-ports", and
"out-ports" as container nodes and ensure the correct parent node is
returned.

Signed-off-by: Sunil V L <sunilvl@oss.qualcomm.com>
---
 drivers/acpi/property.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 8ee5a1f0eb48..78400620390b 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -1422,7 +1422,7 @@ static struct fwnode_handle *
 acpi_node_get_parent(const struct fwnode_handle *fwnode)
 {
 	if (is_acpi_data_node(fwnode)) {
-		/* All data nodes have parent pointer so just return that */
+		/* Keep the structural parent for generic fwnode iteration. */
 		return to_acpi_data_node(fwnode)->parent;
 	}
 	if (is_acpi_device_node(fwnode)) {
@@ -1703,7 +1703,19 @@ acpi_fwnode_get_name_prefix(const struct fwnode_handle *fwnode)
 static struct fwnode_handle *
 acpi_fwnode_get_parent(struct fwnode_handle *fwnode)
 {
-	return acpi_node_get_parent(fwnode);
+	struct fwnode_handle *parent;
+	const char *name;
+
+	parent = acpi_node_get_parent(fwnode);
+	if (!is_acpi_data_node(parent))
+		return parent;
+
+	name = to_acpi_data_node(parent)->name;
+	if (!strcmp(name, "ports") || !strcmp(name, "in-ports") ||
+	    !strcmp(name, "out-ports"))
+		return acpi_node_get_parent(parent);
+
+	return parent;
 }
 
 static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
-- 
2.43.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC PATCH 3/5] ACPI: property: Add device graph support
  2026-09-29  8:55 [RFC PATCH 0/5] hwtracing: rvtrace: Add ACPI support Sunil V L
  2026-09-29  8:55 ` [RFC PATCH 1/5] of: property: Add in-ports/out-ports support to of_fwnode_graph_get_port_parent() Sunil V L
  2026-09-29  8:55 ` [RFC PATCH 2/5] ACPI: property: Add ports/in-ports/out-ports support to acpi_fwnode_get_parent() Sunil V L
@ 2026-09-29  8:55 ` Sunil V L
  2026-09-29  8:55 ` [RFC PATCH 4/5] hwtracing: rvtrace: Move to fwnode_* APIs Sunil V L
  2026-09-29  8:55 ` [RFC PATCH 5/5] hwtracing: rvtrace: Add ACPI support Sunil V L
  4 siblings, 0 replies; 6+ messages in thread
From: Sunil V L @ 2026-09-29  8:55 UTC (permalink / raw)
  To: linux-acpi, linux-riscv, linux-kernel, devicetree
  Cc: Rafael J . Wysocki, Len Brown, Mayuresh Chitale, Anup Patel,
	Alexander Shishkin, Rob Herring, Saravana Kannan, Sunil V L

From: Sunil V L <sunilvl@oss.qualcomm.com>

Add support for parsing the UEFI DSD-Guide device-graph UUID
(ab02a46b-74c7-45a2-bd68-f7d344ef2153), allowing firmware to describe
device topology graphs similar to devicetree's of_graph bindings.

Synthetic "port" and "endpoint" data nodes are created from
the graph package contents, with "reg"/"port"/"endpoint" integer
properties and a "remote-endpoint" reference property, so that the
existing fwnode graph API (fwnode_graph_parse_endpoint(),
fwnode_graph_get_remote_endpoint(), etc.) can walk the resulting nodes
the same way it walks devicetree graph nodes.

For certain device graph UUIDs, such as the RISC-V Trace ACPI Graph
UUID, nest the synthesized port nodes one level deeper under a synthetic
"in-ports" or "out-ports" node.

Signed-off-by: Sunil V L <sunilvl@oss.qualcomm.com>
---
 drivers/acpi/property.c | 500 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 490 insertions(+), 10 deletions(-)

diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 78400620390b..49af8eaf79e5 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -68,6 +68,7 @@ static const guid_t buffer_prop_guid =
 	GUID_INIT(0xedb12dd0, 0x363d, 0x4085,
 		  0xa3, 0xd2, 0x49, 0x52, 0x2c, 0xa1, 0x60, 0xc4);
 
+static void acpi_free_device_properties(struct list_head *list);
 static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
 					   union acpi_object *desc,
 					   struct acpi_device_data *data,
@@ -76,6 +77,18 @@ static bool acpi_extract_properties(acpi_handle handle,
 				    union acpi_object *desc,
 				    struct acpi_device_data *data);
 
+/* ACPI _DSD device graph GUID [1]: ab02a46b-74c7-45a2-bd68-f7d344ef2153 */
+static const guid_t graph_prop_guid =
+	GUID_INIT(0xab02a46b, 0x74c7, 0x45a2,
+		  0xbd, 0x68, 0xf7, 0xd3, 0x44, 0xef, 0x21, 0x53);
+/* RISC-V Trace ACPI Graph UUID: 42e66f8f-50fe-4eed-9897-cdeed26ecd77 */
+static const guid_t rvtrace_graph_guid =
+	GUID_INIT(0x42e66f8f, 0x50fe, 0x4eed,
+		  0x98, 0x97, 0xcd, 0xee, 0xd2, 0x6e, 0xcd, 0x77);
+
+#define ACPI_GRAPH_LINK_INPUT	0
+#define ACPI_GRAPH_LINK_OUTPUT	1
+
 static bool acpi_nondev_subnode_extract(union acpi_object *desc,
 					acpi_handle handle,
 					const union acpi_object *link,
@@ -254,14 +267,423 @@ static bool acpi_add_nondev_subnodes(acpi_handle scope,
 	return ret;
 }
 
+static struct acpi_data_node *
+acpi_data_node_create(const char *name, acpi_handle scope,
+		      struct fwnode_handle *parent, struct list_head *list)
+{
+	struct acpi_data_node *dn;
+	union acpi_object *marker;
+
+	/*
+	 * Synthetic nodes have no backing _DSD-equivalent package of their
+	 * own, but data->pointer is used elsewhere as an indication that a
+	 * node's data is valid, so give it a dummy non-NULL object to own
+	 * and free, the same way acpi_nondev_subnode_extract() and
+	 * acpi_extract_apple_properties() do for their allocated buffers.
+	 */
+	marker = ACPI_ALLOCATE_ZEROED(sizeof(*marker));
+	if (!marker)
+		return NULL;
+
+	dn = kzalloc_obj(*dn);
+	if (!dn) {
+		ACPI_FREE(marker);
+		return NULL;
+	}
+
+	dn->name = kstrdup(name, GFP_KERNEL);
+	if (!dn->name) {
+		ACPI_FREE(marker);
+		kfree(dn);
+		return NULL;
+	}
+	dn->handle = scope;
+	dn->parent = parent;
+	dn->data.pointer = marker;
+	fwnode_init(&dn->fwnode, &acpi_data_fwnode_ops);
+	INIT_LIST_HEAD(&dn->data.properties);
+	INIT_LIST_HEAD(&dn->data.subnodes);
+	list_add_tail(&dn->sibling, list);
+
+	return dn;
+}
+
+static void acpi_data_node_delete(struct acpi_data_node *dn)
+{
+	list_del(&dn->sibling);
+	acpi_free_device_properties(&dn->data.properties);
+	ACPI_FREE((void *)dn->data.pointer);
+	kfree(dn->name);
+	kfree(dn);
+}
+
+static struct acpi_data_node *
+acpi_graph_node_create(const char *type, u32 id, acpi_handle scope,
+		       struct fwnode_handle *parent,
+		       struct list_head *list)
+{
+	struct acpi_data_node *dn;
+	char *name;
+
+	name = kasprintf(GFP_KERNEL, "%s@%u", type, id);
+	if (!name)
+		return NULL;
+
+	dn = acpi_data_node_create(name, scope, parent, list);
+	kfree(name);
+	return dn;
+}
+
+static bool acpi_data_prop_add_integer(struct acpi_device_data *data,
+				       const char *name, u64 value)
+{
+	struct acpi_device_properties *props;
+	union acpi_object *obj;
+
+	props = kzalloc(sizeof(*props) + 4 * sizeof(*obj), GFP_KERNEL);
+	if (!props)
+		return false;
+
+	INIT_LIST_HEAD(&props->list);
+	props->guid = &prp_guids[0];
+
+	obj = (union acpi_object *)(props + 1);
+	props->properties = &obj[0];
+	obj[0].type = ACPI_TYPE_PACKAGE;
+	obj[0].package.count = 1;
+	obj[0].package.elements = &obj[1];
+
+	obj[1].type = ACPI_TYPE_PACKAGE;
+	obj[1].package.count = 2;
+	obj[1].package.elements = &obj[2];
+
+	obj[2].type = ACPI_TYPE_STRING;
+	obj[2].string.pointer = (char *)name;
+	obj[2].string.length = strlen(name);
+
+	obj[3].type = ACPI_TYPE_INTEGER;
+	obj[3].integer.value = value;
+
+	list_add_tail(&props->list, &data->properties);
+
+	return true;
+}
+
+static bool acpi_data_prop_add_remote_endpoint(struct acpi_device_data *data,
+					       const union acpi_object *remote,
+					       u32 port, u32 endpoint)
+{
+	struct acpi_device_properties *props;
+	union acpi_object *obj;
+
+	if (remote->type != ACPI_TYPE_LOCAL_REFERENCE &&
+	    remote->type != ACPI_TYPE_STRING)
+		return false;
+
+	props = kzalloc(sizeof(*props) + 7 * sizeof(*obj), GFP_KERNEL);
+	if (!props)
+		return false;
+
+	INIT_LIST_HEAD(&props->list);
+	props->guid = &prp_guids[0];
+
+	obj = (union acpi_object *)(props + 1);
+	props->properties = &obj[0];
+	obj[0].type = ACPI_TYPE_PACKAGE;
+	obj[0].package.count = 1;
+	obj[0].package.elements = &obj[1];
+
+	obj[1].type = ACPI_TYPE_PACKAGE;
+	obj[1].package.count = 2;
+	obj[1].package.elements = &obj[2];
+
+	obj[2].type = ACPI_TYPE_STRING;
+	obj[2].string.pointer = "remote-endpoint";
+	obj[2].string.length = strlen("remote-endpoint");
+
+	obj[3].type = ACPI_TYPE_PACKAGE;
+	obj[3].package.count = 3;
+	obj[3].package.elements = &obj[4];
+
+	obj[4] = *remote;
+
+	obj[5].type = ACPI_TYPE_INTEGER;
+	obj[5].integer.value = port;
+
+	obj[6].type = ACPI_TYPE_INTEGER;
+	obj[6].integer.value = endpoint;
+
+	list_add_tail(&props->list, &data->properties);
+
+	return true;
+}
+
+struct acpi_graph_port_map {
+	struct list_head node;
+	struct acpi_data_node *port;
+	struct fwnode_handle *parent;
+	u32 port_nr;
+	u32 endpoint_id;
+};
+
+struct acpi_graph_root_map {
+	struct list_head node;
+	struct acpi_data_node *root;
+};
+
+static bool acpi_graph_is_directional(const guid_t *graph_guid)
+{
+	return guid_equal(graph_guid, &rvtrace_graph_guid);
+}
+
+static struct acpi_data_node *
+acpi_graph_get_root_node(struct list_head *roots, acpi_handle scope,
+			 struct fwnode_handle *parent, struct list_head *subnodes,
+			 const char *name)
+{
+	struct acpi_graph_root_map *entry;
+
+	list_for_each_entry(entry, roots, node) {
+		if (!strcmp(entry->root->name, name))
+			return entry->root;
+	}
+
+	entry = kzalloc_obj(*entry);
+	if (!entry)
+		return NULL;
+
+	entry->root = acpi_data_node_create(name, scope, parent, subnodes);
+	if (!entry->root) {
+		kfree(entry);
+		return NULL;
+	}
+
+	list_add_tail(&entry->node, roots);
+	return entry->root;
+}
+
+static struct acpi_graph_port_map *
+acpi_graph_get_port_map(struct list_head *ports, acpi_handle scope,
+			struct fwnode_handle *parent, struct list_head *subnodes,
+			u32 port_nr)
+{
+	struct acpi_graph_port_map *entry;
+
+	list_for_each_entry(entry, ports, node) {
+		if (entry->parent == parent && entry->port_nr == port_nr)
+			return entry;
+	}
+
+	entry = kzalloc_obj(*entry);
+	if (!entry)
+		return NULL;
+
+	entry->port = acpi_graph_node_create("port", port_nr, scope, parent,
+					     subnodes);
+	if (!entry->port)
+		goto err_free_entry;
+
+	entry->parent = parent;
+	entry->port_nr = port_nr;
+	if (!acpi_data_prop_add_integer(&entry->port->data, "reg", port_nr) ||
+	    !acpi_data_prop_add_integer(&entry->port->data, "port", port_nr))
+		goto err_drop_port;
+
+	list_add_tail(&entry->node, ports);
+
+	return entry;
+
+err_drop_port:
+	acpi_data_node_delete(entry->port);
+err_free_entry:
+	kfree(entry);
+	return NULL;
+}
+
+static bool acpi_dsd_graph_valid(union acpi_object *graph)
+{
+	u64 nr_graphs;
+	u64 i;
+
+	if (graph->type != ACPI_TYPE_PACKAGE)
+		return false;
+
+	if (graph->package.count < 2)
+		return false;
+
+	if (graph->package.elements[0].type != ACPI_TYPE_INTEGER ||
+	    graph->package.elements[1].type != ACPI_TYPE_INTEGER)
+		return false;
+
+	if (graph->package.elements[0].integer.value != 0)
+		return false;
+
+	nr_graphs = graph->package.elements[1].integer.value;
+	if (nr_graphs > graph->package.count - 2)
+		return false;
+
+	for (i = 0; i < nr_graphs; i++) {
+		union acpi_object *graph_entry;
+		u64 nr_links;
+
+		graph_entry = &graph->package.elements[i + 2];
+		if (graph_entry->type != ACPI_TYPE_PACKAGE ||
+		    graph_entry->package.count < 3)
+			return false;
+
+		if (graph_entry->package.elements[0].type != ACPI_TYPE_INTEGER ||
+		    graph_entry->package.elements[1].type != ACPI_TYPE_BUFFER ||
+		    graph_entry->package.elements[1].buffer.length != 16 ||
+		    graph_entry->package.elements[2].type != ACPI_TYPE_INTEGER)
+			return false;
+
+		nr_links = graph_entry->package.elements[2].integer.value;
+		if (nr_links > graph_entry->package.count - 3)
+			return false;
+	}
+
+	return true;
+}
+
+static bool acpi_add_graph_subnodes(acpi_handle scope, union acpi_object *graph,
+				    struct acpi_device_data *data,
+				    struct fwnode_handle *parent)
+{
+	LIST_HEAD(ports);
+	LIST_HEAD(roots);
+	u64 nr_graphs;
+	bool ret = false;
+	u64 i;
+
+	if (!acpi_dsd_graph_valid(graph))
+		return false;
+
+	nr_graphs = graph->package.elements[1].integer.value;
+
+	for (i = 0; i < nr_graphs; i++) {
+		union acpi_object *graph_entry;
+		struct fwnode_handle *graph_parent = parent;
+		struct list_head *graph_subnodes = &data->subnodes;
+		struct acpi_data_node *graph_root;
+		const guid_t *graph_guid;
+		u64 nr_links;
+		u64 j;
+
+		graph_entry = &graph->package.elements[i + 2];
+		graph_guid = (const guid_t *)graph_entry->package.elements[1].buffer.pointer;
+		if (!acpi_graph_is_directional(graph_guid))
+			continue;
+		nr_links = graph_entry->package.elements[2].integer.value;
+
+		for (j = 0; j < nr_links; j++) {
+			union acpi_object *link;
+			struct acpi_graph_port_map *port_map;
+			struct acpi_data_node *endpoint;
+			union acpi_object *elem;
+			u32 src_port, dst_port, ep_id;
+			u64 dir;
+
+			link = &graph_entry->package.elements[j + 3];
+			if (link->type != ACPI_TYPE_PACKAGE ||
+			    link->package.count < 3)
+				continue;
+
+			elem = link->package.elements;
+			if (elem[0].type != ACPI_TYPE_INTEGER ||
+			    elem[1].type != ACPI_TYPE_INTEGER ||
+			    (elem[2].type != ACPI_TYPE_LOCAL_REFERENCE &&
+			     elem[2].type != ACPI_TYPE_STRING))
+				continue;
+
+			src_port = elem[0].integer.value;
+			dst_port = elem[1].integer.value;
+
+			if (acpi_graph_is_directional(graph_guid)) {
+				if (link->package.count < 4 ||
+				    elem[3].type != ACPI_TYPE_INTEGER)
+					continue;
+
+				dir = elem[3].integer.value;
+				if (dir == ACPI_GRAPH_LINK_OUTPUT)
+					graph_root = acpi_graph_get_root_node(&roots, scope,
+									      parent,
+									      &data->subnodes,
+									      "out-ports");
+				else if (dir == ACPI_GRAPH_LINK_INPUT)
+					graph_root = acpi_graph_get_root_node(&roots, scope,
+									      parent,
+									      &data->subnodes,
+									      "in-ports");
+				else
+					continue;
+
+				if (!graph_root)
+					continue;
+
+				graph_parent = &graph_root->fwnode;
+				graph_subnodes = &graph_root->data.subnodes;
+			}
+
+			port_map = acpi_graph_get_port_map(&ports, scope, graph_parent,
+							   graph_subnodes, src_port);
+			if (!port_map)
+				continue;
+
+			ep_id = port_map->endpoint_id++;
+			endpoint = acpi_graph_node_create("endpoint", ep_id, scope,
+							  &port_map->port->fwnode,
+							  &port_map->port->data.subnodes);
+			if (!endpoint)
+				continue;
+
+			if (!acpi_data_prop_add_integer(&endpoint->data, "reg", ep_id) ||
+			    !acpi_data_prop_add_integer(&endpoint->data, "endpoint", ep_id) ||
+			    !acpi_data_prop_add_remote_endpoint(&endpoint->data, &elem[2],
+							dst_port, 0)) {
+				acpi_data_node_delete(endpoint);
+				continue;
+			}
+
+			ret = true;
+		}
+	}
+
+	while (!list_empty(&ports)) {
+		struct acpi_graph_port_map *port_map;
+
+		port_map = list_first_entry(&ports, struct acpi_graph_port_map, node);
+		list_del(&port_map->node);
+
+		if (!ret || list_empty(&port_map->port->data.subnodes))
+			acpi_data_node_delete(port_map->port);
+
+		kfree(port_map);
+	}
+
+	while (!list_empty(&roots)) {
+		struct acpi_graph_root_map *root;
+
+		root = list_first_entry(&roots, struct acpi_graph_root_map, node);
+		list_del(&root->node);
+
+		if (!ret || list_empty(&root->root->data.subnodes))
+			acpi_data_node_delete(root->root);
+
+		kfree(root);
+	}
+
+	return ret;
+}
+
 static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
 					   union acpi_object *desc,
 					   struct acpi_device_data *data,
 					   struct fwnode_handle *parent)
 {
+	bool ret = false;
 	int i;
 
-	/* Look for the ACPI data subnodes GUID. */
+	/* Look for the ACPI data subnodes and graph UUIDs. */
 	for (i = 0; i < desc->package.count; i += 2) {
 		const union acpi_object *guid;
 		union acpi_object *links;
@@ -278,14 +700,14 @@ static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
 		    links->type != ACPI_TYPE_PACKAGE)
 			break;
 
-		if (!guid_equal((guid_t *)guid->buffer.pointer, &ads_guid))
-			continue;
-
-		return acpi_add_nondev_subnodes(scope, links, &data->subnodes,
-						parent);
+		if (guid_equal((guid_t *)guid->buffer.pointer, &ads_guid))
+			ret |= acpi_add_nondev_subnodes(scope, links,
+						       &data->subnodes, parent);
+		else if (guid_equal((guid_t *)guid->buffer.pointer, &graph_prop_guid))
+			ret |= acpi_add_graph_subnodes(scope, links, data, parent);
 	}
 
-	return false;
+	return ret;
 }
 
 static bool acpi_property_value_ok(const union acpi_object *value)
@@ -1485,7 +1907,8 @@ static struct fwnode_handle *acpi_graph_get_next_endpoint(
 				break;
 		} while (port);
 	} else {
-		port = fwnode_get_parent(prev);
+		/* Use the structural parent: the public parent skips port roots. */
+		port = acpi_node_get_parent(prev);
 	}
 
 	if (!port)
@@ -1544,6 +1967,42 @@ static struct fwnode_handle *acpi_graph_get_child_prop_value(
 	return NULL;
 }
 
+static struct fwnode_handle *
+acpi_graph_get_first_endpoint(struct fwnode_handle *port)
+{
+	struct fwnode_handle *endpoint = NULL;
+
+	do {
+		endpoint = acpi_get_next_subnode(port, endpoint);
+	} while (endpoint && !is_acpi_graph_node(endpoint, "endpoint"));
+
+	return endpoint;
+}
+
+/**
+ * acpi_graph_get_remote_directional_port - Find a port nested under a
+ * synthetic "in-ports"/"out-ports" root node
+ * @fwnode: device fwnode
+ * @port_nr: the desired port number
+ *
+ * Return: the port node on success, NULL otherwise.
+ */
+static struct fwnode_handle *
+acpi_graph_get_remote_directional_port(struct fwnode_handle *fwnode,
+				       unsigned int port_nr,
+				       const char *ports_name)
+{
+	struct fwnode_handle *ports_node, *port;
+
+	if (!ports_name)
+		return NULL;
+
+	ports_node = acpi_fwnode_get_named_child_node(fwnode, ports_name);
+	if (ports_node)
+		return acpi_graph_get_child_prop_value(ports_node, "port", port_nr);
+
+	return NULL;
+}
 
 /**
  * acpi_graph_get_remote_endpoint - Parses and returns remote end of an endpoint
@@ -1555,6 +2014,8 @@ static struct fwnode_handle *
 acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode)
 {
 	struct fwnode_handle *fwnode;
+	struct fwnode_handle *source_port, *source_root;
+	const char *remote_ports = NULL;
 	unsigned int port_nr, endpoint_nr;
 	struct fwnode_reference_args args;
 	int ret;
@@ -1580,9 +2041,28 @@ acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode)
 	port_nr = args.args[0];
 	endpoint_nr = args.args[1];
 
-	fwnode = acpi_graph_get_child_prop_value(fwnode, "port", port_nr);
+	/* A directional source can only be connected to the opposite root. */
+	source_port = acpi_node_get_parent(__fwnode);
+	source_root = acpi_node_get_parent(source_port);
+	if (is_acpi_data_node(source_root)) {
+		if (!strcmp(to_acpi_data_node(source_root)->name, "out-ports"))
+			remote_ports = "in-ports";
+		else if (!strcmp(to_acpi_data_node(source_root)->name, "in-ports"))
+			remote_ports = "out-ports";
+	}
+
+	fwnode = acpi_graph_get_child_prop_value(fwnode, "port", port_nr) ?:
+				 acpi_graph_get_remote_directional_port(fwnode, port_nr,
+									remote_ports);
+	if (!fwnode)
+		return NULL;
 
-	return acpi_graph_get_child_prop_value(fwnode, "endpoint", endpoint_nr);
+	/*
+	 * Device Graph UUID links may not provide endpoint IDs. In that case
+	 * return the first endpoint under the remote port.
+	 */
+	return acpi_graph_get_child_prop_value(fwnode, "endpoint", endpoint_nr) ?:
+	       acpi_graph_get_first_endpoint(fwnode);
 }
 
 static bool acpi_fwnode_device_is_available(const struct fwnode_handle *fwnode)
-- 
2.43.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC PATCH 4/5] hwtracing: rvtrace: Move to fwnode_* APIs
  2026-09-29  8:55 [RFC PATCH 0/5] hwtracing: rvtrace: Add ACPI support Sunil V L
                   ` (2 preceding siblings ...)
  2026-09-29  8:55 ` [RFC PATCH 3/5] ACPI: property: Add device graph support Sunil V L
@ 2026-09-29  8:55 ` Sunil V L
  2026-09-29  8:55 ` [RFC PATCH 5/5] hwtracing: rvtrace: Add ACPI support Sunil V L
  4 siblings, 0 replies; 6+ messages in thread
From: Sunil V L @ 2026-09-29  8:55 UTC (permalink / raw)
  To: linux-acpi, linux-riscv, linux-kernel, devicetree
  Cc: Rafael J . Wysocki, Len Brown, Mayuresh Chitale, Anup Patel,
	Alexander Shishkin, Rob Herring, Saravana Kannan, Sunil V L

From: Sunil V L <sunilvl@oss.qualcomm.com>

so that it works for ACPI as well in future.

Signed-off-by: Sunil V L <sunilvl@oss.qualcomm.com>
---
 drivers/hwtracing/gtrace/Kconfig            |   4 +-
 drivers/hwtracing/gtrace/rvtrace-platform.c | 131 +++++++++++++-------
 2 files changed, 90 insertions(+), 45 deletions(-)

diff --git a/drivers/hwtracing/gtrace/Kconfig b/drivers/hwtracing/gtrace/Kconfig
index e5b62d65e2fd..86322250a6a3 100644
--- a/drivers/hwtracing/gtrace/Kconfig
+++ b/drivers/hwtracing/gtrace/Kconfig
@@ -2,7 +2,7 @@
 
 menuconfig GTRACE
 	tristate "Generic Hardware Trace Support"
-	depends on OF
+	depends on OF || ACPI
 	select PERF_EVENTS
 	help
 	  This framework provides an architecture-neutral kernel interface
@@ -18,7 +18,7 @@ menuconfig GTRACE
 config RVTRACE
 	tristate "RISC-V Trace Support"
 	depends on RISCV
-	depends on OF
+	depends on OF || ACPI
 	depends on GTRACE
 	default RISCV
 	help
diff --git a/drivers/hwtracing/gtrace/rvtrace-platform.c b/drivers/hwtracing/gtrace/rvtrace-platform.c
index f34de9183d9a..12330d9dcddd 100644
--- a/drivers/hwtracing/gtrace/rvtrace-platform.c
+++ b/drivers/hwtracing/gtrace/rvtrace-platform.c
@@ -7,7 +7,6 @@
 #include <linux/gtrace.h>
 #include <linux/io.h>
 #include <linux/of.h>
-#include <linux/of_graph.h>
 #include <linux/platform_device.h>
 #include <linux/property.h>
 #include <linux/types.h>
@@ -61,52 +60,61 @@ const struct gtrace_hw_ops rvtrace_hw_ops = {
 	.reset		= rvtrace_hw_reset,
 };
 
-static int rvtrace_of_parse_outconns(struct gtrace_platform_data *pdata)
+static int rvtrace_parse_outconns(struct gtrace_platform_data *pdata)
 {
-	struct device_node *parent, *ep_node, *rep_node, *rdev_node;
+	struct fwnode_handle *parent, *ep_node, *rep_node, *rdev_node;
+	struct fwnode_endpoint ep = { 0 };
+	struct fwnode_endpoint rep = { 0 };
 	struct gtrace_connection *conn;
-	struct of_endpoint ep, rep;
+	unsigned int nr_outconns;
 	int ret = 0, i = 0;
 
-	parent = of_get_child_by_name(dev_of_node(pdata->dev), "out-ports");
+	parent = fwnode_get_named_child_node(dev_fwnode(pdata->dev), "out-ports");
 	if (!parent)
 		return 0;
 
-	pdata->nr_outconns = of_graph_get_endpoint_count(parent);
-	pdata->outconns = devm_kcalloc(pdata->dev, pdata->nr_outconns,
+	nr_outconns = fwnode_graph_get_endpoint_count(parent, 0);
+	pdata->nr_outconns = nr_outconns;
+	pdata->outconns = devm_kcalloc(pdata->dev, nr_outconns,
 				       sizeof(*pdata->outconns), GFP_KERNEL);
 	if (!pdata->outconns) {
 		ret = -ENOMEM;
 		goto done;
 	}
 
-	for_each_endpoint_of_node(parent, ep_node) {
+	fwnode_graph_for_each_endpoint(parent, ep_node) {
 		conn = devm_kzalloc(pdata->dev, sizeof(*conn), GFP_KERNEL);
 		if (!conn) {
-			of_node_put(ep_node);
+			fwnode_handle_put(ep_node);
 			ret = -ENOMEM;
 			break;
 		}
 
-		ret = of_graph_parse_endpoint(ep_node, &ep);
+		ret = fwnode_graph_parse_endpoint(ep_node, &ep);
 		if (ret) {
-			of_node_put(ep_node);
+			fwnode_handle_put(ep_node);
 			break;
 		}
 
-		rep_node = of_graph_get_remote_endpoint(ep_node);
+		rep_node = fwnode_graph_get_remote_endpoint(ep_node);
 		if (!rep_node) {
 			ret = -ENODEV;
-			of_node_put(ep_node);
+			fwnode_handle_put(ep_node);
+			break;
+		}
+		rdev_node = fwnode_graph_get_port_parent(rep_node);
+		if (!rdev_node) {
+			ret = -ENODEV;
+			fwnode_handle_put(ep_node);
+			fwnode_handle_put(rep_node);
 			break;
 		}
-		rdev_node = of_graph_get_port_parent(rep_node);
 
-		ret = of_graph_parse_endpoint(rep_node, &rep);
+		ret = fwnode_graph_parse_endpoint(rep_node, &rep);
 		if (ret) {
-			of_node_put(ep_node);
-			of_node_put(rep_node);
-			of_node_put(rdev_node);
+			fwnode_handle_put(ep_node);
+			fwnode_handle_put(rep_node);
+			fwnode_handle_put(rdev_node);
 			break;
 		}
 
@@ -115,21 +123,25 @@ static int rvtrace_of_parse_outconns(struct gtrace_platform_data *pdata)
 		/* The 'src_comp' is set by gtrace_register_component() */
 		conn->src_comp = NULL;
 		conn->dest_port = rep.port;
-		conn->dest_fwnode = of_fwnode_handle(rdev_node);
+		conn->dest_fwnode = rdev_node;
 		fwnode_handle_get(conn->dest_fwnode);
 		conn->dest_comp = gtrace_find_by_fwnode(conn->dest_fwnode);
 		if (!conn->dest_comp) {
 			ret = -EPROBE_DEFER;
-			of_node_put(ep_node);
-			of_node_put(rep_node);
-			of_node_put(rdev_node);
+			fwnode_handle_put(ep_node);
+			fwnode_handle_put(rep_node);
+			fwnode_handle_put(rdev_node);
 			break;
 		}
 
-		pdata->outconns[i] = conn;
-		i++;
+		pdata->outconns[i++] = conn;
+		fwnode_handle_put(rep_node);
+		fwnode_handle_put(rdev_node);
 	}
 
+	if (!ret)
+		pdata->nr_outconns = i;
+
 done:
 	if (ret) {
 		for (i = 0; i < pdata->nr_outconns && pdata->outconns; i++) {
@@ -138,29 +150,69 @@ static int rvtrace_of_parse_outconns(struct gtrace_platform_data *pdata)
 				fwnode_handle_put(conn->dest_fwnode);
 		}
 	}
-	of_node_put(parent);
+	fwnode_handle_put(parent);
 	return ret;
 }
 
-static int rvtrace_of_parse_inconns(struct gtrace_platform_data *pdata)
+static int rvtrace_parse_inconns(struct gtrace_platform_data *pdata)
 {
-	struct device_node *parent;
+	struct fwnode_handle *parent;
 	int ret = 0;
 
-	parent = of_get_child_by_name(dev_of_node(pdata->dev), "in-ports");
+	parent = fwnode_get_named_child_node(dev_fwnode(pdata->dev), "in-ports");
 	if (!parent)
 		return 0;
 
-	pdata->nr_inconns = of_graph_get_endpoint_count(parent);
+	pdata->nr_inconns = fwnode_graph_get_endpoint_count(parent,
+							    FWNODE_GRAPH_DEVICE_DISABLED);
 	pdata->inconns = devm_kcalloc(pdata->dev, pdata->nr_inconns,
 				      sizeof(*pdata->inconns), GFP_KERNEL);
 	if (!pdata->inconns)
 		ret = -ENOMEM;
 
-	of_node_put(parent);
+	fwnode_handle_put(parent);
 	return ret;
 }
 
+#ifdef CONFIG_OF
+static int of_rvtrace_get_cpu(struct device *dev)
+{
+	struct device_node *dn;
+	int cpu;
+
+	if (!dev->of_node)
+		return -1;
+
+	dn = of_parse_phandle(dev->of_node, "cpus", 0);
+	if (!dn)
+		return -1;
+
+	cpu = of_cpu_node_to_id(dn);
+	of_node_put(dn);
+
+	return cpu;
+}
+#else
+static int of_rvtrace_get_cpu(struct device *dev)
+{
+	return -1;
+}
+#endif
+
+/*
+ * rvtrace_get_cpu - Find the logical CPU id of the CPU associated
+ * with this rvtrace device.
+ *
+ * Returns the logical CPU id when found.
+ */
+static int rvtrace_get_cpu(struct device *dev)
+{
+	if (is_of_node(dev_fwnode(dev)))
+		return of_rvtrace_get_cpu(dev);
+
+	return -1;
+}
+
 static int rvtrace_platform_probe(struct platform_device *pdev)
 {
 	struct gtrace_platform_data *pdata;
@@ -168,7 +220,6 @@ static int rvtrace_platform_probe(struct platform_device *pdev)
 	struct gtrace_component_id id;
 	struct gtrace_component *comp;
 	u32 impl, type, major, minor;
-	struct device_node *node;
 	struct resource *res;
 	int gtype;
 	int ret;
@@ -189,24 +240,18 @@ static int rvtrace_platform_probe(struct platform_device *pdev)
 	if (!pdata->base)
 		return dev_err_probe(dev, -ENOMEM, "failed to ioremap %pR\n", res);
 
-	pdata->bound_cpu = -1;
-	node = of_parse_phandle(dev_of_node(dev), "cpus", 0);
-	if (node) {
-		ret = of_cpu_node_to_id(node);
-		of_node_put(node);
-		if (ret < 0)
-			return dev_err_probe(dev, ret, "failed to get CPU id for %pOF\n", node);
-		pdata->bound_cpu = ret;
-	}
-
+	pdata->bound_cpu = rvtrace_get_cpu(dev);
+	if (pdata->bound_cpu < 0)
+		return dev_err_probe(dev, pdata->bound_cpu,
+				     "failed to get bound CPU\n");
 	/* Default control poll timeout */
 	pdata->control_poll_timeout_usecs = 10;
 
-	ret = rvtrace_of_parse_outconns(pdata);
+	ret = rvtrace_parse_outconns(pdata);
 	if (ret)
 		return dev_err_probe(dev, ret, "failed to parse output connections\n");
 
-	ret = rvtrace_of_parse_inconns(pdata);
+	ret = rvtrace_parse_inconns(pdata);
 	if (ret)
 		return dev_err_probe(dev, ret, "failed to parse input connections\n");
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC PATCH 5/5] hwtracing: rvtrace: Add ACPI support
  2026-09-29  8:55 [RFC PATCH 0/5] hwtracing: rvtrace: Add ACPI support Sunil V L
                   ` (3 preceding siblings ...)
  2026-09-29  8:55 ` [RFC PATCH 4/5] hwtracing: rvtrace: Move to fwnode_* APIs Sunil V L
@ 2026-09-29  8:55 ` Sunil V L
  4 siblings, 0 replies; 6+ messages in thread
From: Sunil V L @ 2026-09-29  8:55 UTC (permalink / raw)
  To: linux-acpi, linux-riscv, linux-kernel, devicetree
  Cc: Rafael J . Wysocki, Len Brown, Mayuresh Chitale, Anup Patel,
	Alexander Shishkin, Rob Herring, Saravana Kannan, Sunil V L

From: Sunil V L <sunilvl@oss.qualcomm.com>

Add ACPI device IDs and ACPI-based CPU binding lookup for rvtrace
platform devices.

Signed-off-by: Sunil V L <sunilvl@oss.qualcomm.com>
---
 drivers/hwtracing/gtrace/rvtrace-platform.c | 60 +++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/drivers/hwtracing/gtrace/rvtrace-platform.c b/drivers/hwtracing/gtrace/rvtrace-platform.c
index 12330d9dcddd..44422d429ccf 100644
--- a/drivers/hwtracing/gtrace/rvtrace-platform.c
+++ b/drivers/hwtracing/gtrace/rvtrace-platform.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2026 Qualcomm Technologies, Inc.
  */
 
+#include <linux/acpi.h>
 #include <linux/device.h>
 #include <linux/gtrace.h>
 #include <linux/io.h>
@@ -174,6 +175,62 @@ static int rvtrace_parse_inconns(struct gtrace_platform_data *pdata)
 	return ret;
 }
 
+#ifdef CONFIG_ACPI
+#include <acpi/processor.h>
+
+static const struct acpi_device_id rvtrace_platform_acpi_match[] = {
+	{ "RSCV0007", 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(acpi, rvtrace_platform_acpi_match);
+
+/*
+ * acpi_handle_to_logical_cpuid - Map a given acpi_handle to the
+ * logical CPU id of the corresponding CPU device.
+ *
+ * Returns the logical CPU id when found. Otherwise returns >= nr_cpus_id.
+ */
+static int acpi_handle_to_logical_cpuid(acpi_handle handle)
+{
+	struct acpi_processor *pr;
+	int i;
+
+	for_each_possible_cpu(i) {
+		pr = per_cpu(processors, i);
+		if (pr && pr->handle == handle)
+			break;
+	}
+
+	return i;
+}
+
+static int acpi_rvtrace_get_cpu(struct device *dev)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+	acpi_handle cpu_handle;
+	acpi_status status;
+	int cpu;
+
+	if (!adev)
+		return -1;
+
+	status = acpi_get_parent(adev->handle, &cpu_handle);
+	if (ACPI_FAILURE(status))
+		return -1;
+
+	cpu = acpi_handle_to_logical_cpuid(cpu_handle);
+	if (cpu >= nr_cpu_ids)
+		return -1;
+
+	return cpu;
+}
+#else
+static int acpi_rvtrace_get_cpu(struct device *dev)
+{
+	return -1;
+}
+#endif
+
 #ifdef CONFIG_OF
 static int of_rvtrace_get_cpu(struct device *dev)
 {
@@ -209,6 +266,8 @@ static int rvtrace_get_cpu(struct device *dev)
 {
 	if (is_of_node(dev_fwnode(dev)))
 		return of_rvtrace_get_cpu(dev);
+	else if (is_acpi_device_node(dev_fwnode(dev)))
+		return acpi_rvtrace_get_cpu(dev);
 
 	return -1;
 }
@@ -308,6 +367,7 @@ static struct platform_driver rvtrace_platform_driver = {
 	.driver = {
 		.name		= "rvtrace",
 		.of_match_table	= rvtrace_platform_match,
+		.acpi_match_table = ACPI_PTR(rvtrace_platform_acpi_match),
 	},
 	.probe = rvtrace_platform_probe,
 	.remove = rvtrace_platform_remove,
-- 
2.43.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-09-29  8:55 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-29  8:55 [RFC PATCH 0/5] hwtracing: rvtrace: Add ACPI support Sunil V L
2026-09-29  8:55 ` [RFC PATCH 1/5] of: property: Add in-ports/out-ports support to of_fwnode_graph_get_port_parent() Sunil V L
2026-09-29  8:55 ` [RFC PATCH 2/5] ACPI: property: Add ports/in-ports/out-ports support to acpi_fwnode_get_parent() Sunil V L
2026-09-29  8:55 ` [RFC PATCH 3/5] ACPI: property: Add device graph support Sunil V L
2026-09-29  8:55 ` [RFC PATCH 4/5] hwtracing: rvtrace: Move to fwnode_* APIs Sunil V L
2026-09-29  8:55 ` [RFC PATCH 5/5] hwtracing: rvtrace: Add ACPI support Sunil V L

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®