All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: u-boot@lists.denx.de
Subject: [PATCH v1 02/35] acpi: Add a function to get a device path and scope
Date: Tue, 28 Apr 2020 20:21:26 -0600	[thread overview]
Message-ID: <20200429022159.254271-2-sjg@chromium.org> (raw)
In-Reply-To: <20200429022159.254271-1-sjg@chromium.org>

Add a function to build up the ACPI path for a device and another for its
scope.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v1:
- Split into more patches for review
- Add tests

 arch/sandbox/dts/test.dts  |  3 ++
 include/acpi/acpi_device.h | 44 ++++++++++++++++++
 lib/acpi/Makefile          |  1 +
 lib/acpi/acpi_device.c     | 82 ++++++++++++++++++++++++++++++++
 test/dm/acpi.c             | 95 ++++++++++++++++++++++++++++++++------
 5 files changed, 212 insertions(+), 13 deletions(-)
 create mode 100644 include/acpi/acpi_device.h
 create mode 100644 lib/acpi/acpi_device.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 4bccfbe6e1..cc4a0a5e72 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -224,6 +224,9 @@
 
 	acpi-test {
 		compatible = "denx,u-boot-acpi-test";
+		child {
+			compatible = "denx,u-boot-acpi-test";
+		};
 	};
 
 	acpi-test2 {
diff --git a/include/acpi/acpi_device.h b/include/acpi/acpi_device.h
new file mode 100644
index 0000000000..37a675f101
--- /dev/null
+++ b/include/acpi/acpi_device.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Generation of tables for particular device types
+ *
+ * Copyright 2019 Google LLC
+ * Mostly taken from coreboot file of the same name
+ */
+
+#ifndef __ACPI_DEVICE_H
+#define __ACPI_DEVICE_H
+
+struct udevice;
+
+/* Length of a full path to an ACPI device */
+#define ACPI_PATH_MAX		30
+
+/**
+ * acpi_device_path() - Get the full path to an ACPI device
+ *
+ * This gets the full path in the form XXXX.YYYY.ZZZZ where XXXX is the root
+ * and ZZZZ is the device. All parent devices are added to the path.
+ *
+ * @dev: Device to check
+ * @buf: Buffer to place the path in (should be ACPI_PATH_MAX long)
+ * @maxlen: Size of buffer (typically ACPI_PATH_MAX)
+ * @return 0 if OK, -ve on error
+ */
+int acpi_device_path(const struct udevice *dev, char *buf, int maxlen);
+
+/**
+ * acpi_device_scope() - Get the scope of an ACPI device
+ *
+ * This gets the scope which is the full path of the parent device, as per
+ * acpi_device_path().
+ *
+ * @dev: Device to check
+ * @buf: Buffer to place the path in (should be ACPI_PATH_MAX long)
+ * @maxlen: Size of buffer (typically ACPI_PATH_MAX)
+ * @return 0 if OK, -EINVAL if the device has no parent, other -ve on other
+ *	error
+ */
+int acpi_device_scope(const struct udevice *dev, char *scope, int maxlen);
+
+#endif
diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile
index 660491ef71..caae6c01bd 100644
--- a/lib/acpi/Makefile
+++ b/lib/acpi/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 
+obj-y += acpi_device.o
 obj-y += acpi_table.o
diff --git a/lib/acpi/acpi_device.c b/lib/acpi/acpi_device.c
new file mode 100644
index 0000000000..d4f7245b6c
--- /dev/null
+++ b/lib/acpi/acpi_device.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generation of tables for particular device types
+ *
+ * Copyright 2019 Google LLC
+ * Mostly taken from coreboot file of the same name
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <acpi/acpi_device.h>
+#include <dm/acpi.h>
+
+/**
+ * acpi_device_path_fill() - Find the root device and build a path from there
+ *
+ * This recursively reaches back to the root device and progressively adds path
+ * elements until the device is reached.
+ *
+ * @dev: Device to return path of
+ * @buf: Buffer to hold the path
+ * @buf_len: Length of buffer
+ * @cur: Current position in the buffer
+ * @return new position in buffer after adding @dev, or -ve on error
+ */
+static int acpi_device_path_fill(const struct udevice *dev, char *buf,
+				 size_t buf_len, int cur)
+{
+	char name[ACPI_NAME_MAX];
+	int next = 0;
+	int ret;
+
+	ret = acpi_get_name(dev, name);
+	if (ret)
+		return ret;
+
+	/*
+	 * Make sure this name segment will fit, including the path segment
+	 * separator and possible NUL terminator, if this is the last segment.
+	 */
+	if (cur + strlen(name) + 2 > buf_len)
+		return -ENOSPC;
+
+	/* Walk up the tree to the root device */
+	if (dev_get_parent(dev)) {
+		next = acpi_device_path_fill(dev_get_parent(dev), buf, buf_len,
+					     cur);
+		if (next < 0)
+			return next;
+	}
+
+	/* Fill in the path from the root device */
+	next += snprintf(buf + next, buf_len - next, "%s%s",
+			 dev_get_parent(dev) && *name ? "." : "", name);
+
+	return next;
+}
+
+int acpi_device_path(const struct udevice *dev, char *buf, int maxlen)
+{
+	int ret;
+
+	ret = acpi_device_path_fill(dev, buf, maxlen, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int acpi_device_scope(const struct udevice *dev, char *scope, int maxlen)
+{
+	int ret;
+
+	if (!dev_get_parent(dev))
+		return log_msg_ret("noparent", -EINVAL);
+
+	ret = acpi_device_path_fill(dev_get_parent(dev), scope, maxlen, 0);
+	if (ret < 0)
+		return log_msg_ret("fill", ret);
+
+	return 0;
+}
diff --git a/test/dm/acpi.c b/test/dm/acpi.c
index 176d207a55..c25fe805c4 100644
--- a/test/dm/acpi.c
+++ b/test/dm/acpi.c
@@ -14,14 +14,27 @@
 #include <version.h>
 #include <tables_csum.h>
 #include <version.h>
+#include <acpi/acpi_device.h>
 #include <acpi/acpi_table.h>
 #include <dm/acpi.h>
 #include <dm/test.h>
 #include <test/ut.h>
 
 #define ACPI_TEST_DEV_NAME	"ABCD"
+#define ACPI_TEST_CHILD_NAME	"EFGH"
 #define BUF_SIZE		4096
 
+/**
+ * struct testacpi_platdata - Platform data for the test ACPI device
+ *
+ * @no_name: true to emit an empty ACPI name from testacpi_get_name()
+ * @return_error: true to return an error instead of a name
+ */
+struct testacpi_platdata {
+	bool return_error;
+	bool no_name;
+};
+
 static int testacpi_write_tables(const struct udevice *dev,
 				 struct acpi_ctx *ctx)
 {
@@ -40,7 +53,18 @@ static int testacpi_write_tables(const struct udevice *dev,
 
 static int testacpi_get_name(const struct udevice *dev, char *out_name)
 {
-	return acpi_copy_name(out_name, ACPI_TEST_DEV_NAME);
+	struct testacpi_platdata *plat = dev_get_platdata(dev);
+
+	if (plat->return_error)
+		return -EINVAL;
+	if (plat->no_name) {
+		*out_name = '\0';
+		return 0;
+	}
+	if (device_get_uclass_id(dev->parent) == UCLASS_TEST_ACPI)
+		return acpi_copy_name(out_name, ACPI_TEST_CHILD_NAME);
+	else
+		return acpi_copy_name(out_name, ACPI_TEST_DEV_NAME);
 }
 
 struct acpi_ops testacpi_ops = {
@@ -57,6 +81,8 @@ U_BOOT_DRIVER(testacpi_drv) = {
 	.name	= "testacpi_drv",
 	.of_match	= testacpi_ids,
 	.id	= UCLASS_TEST_ACPI,
+	.bind	= dm_scan_fdt_dev,
+	.platdata_auto_alloc_size	= sizeof(struct testacpi_platdata),
 	ACPI_OPS_PTR(&testacpi_ops)
 };
 
@@ -138,6 +164,7 @@ static int dm_test_acpi_write_tables(struct unit_test_state *uts)
 	struct acpi_dmar *dmar;
 	struct acpi_ctx ctx;
 	void *buf;
+	int i;
 
 	buf = malloc(BUF_SIZE);
 	ut_assertnonnull(buf);
@@ -147,24 +174,26 @@ static int dm_test_acpi_write_tables(struct unit_test_state *uts)
 	ut_assertok(acpi_write_dev_tables(&ctx));
 
 	/*
-	 * We should have two dmar tables, one for each "denx,u-boot-acpi-test"
-	 * device
+	 * We should have three dmar tables, one for each
+	 * "denx,u-boot-acpi-test" device
 	 */
-	ut_asserteq_ptr(dmar + 2, ctx.current);
+	ut_asserteq_ptr(dmar + 3, ctx.current);
 	ut_asserteq(DMAR_INTR_REMAP, dmar->flags);
 	ut_asserteq(32 - 1, dmar->host_address_width);
 
 	ut_asserteq(DMAR_INTR_REMAP, dmar[1].flags);
 	ut_asserteq(32 - 1, dmar[1].host_address_width);
 
-	/* Check that the pointers were added correctly */
-	ut_asserteq(map_to_sysmem(dmar), ctx.rsdt->entry[0]);
-	ut_asserteq(map_to_sysmem(dmar + 1), ctx.rsdt->entry[1]);
-	ut_asserteq(0, ctx.rsdt->entry[2]);
+	ut_asserteq(DMAR_INTR_REMAP, dmar[2].flags);
+	ut_asserteq(32 - 1, dmar[2].host_address_width);
 
-	ut_asserteq(map_to_sysmem(dmar), ctx.xsdt->entry[0]);
-	ut_asserteq(map_to_sysmem(dmar + 1), ctx.xsdt->entry[1]);
-	ut_asserteq(0, ctx.xsdt->entry[2]);
+	/* Check that the pointers were added correctly */
+	for (i = 0; i < 3; i++) {
+		ut_asserteq(map_to_sysmem(dmar + i), ctx.rsdt->entry[i]);
+		ut_asserteq(map_to_sysmem(dmar + i), ctx.xsdt->entry[i]);
+	}
+	ut_asserteq(0, ctx.rsdt->entry[3]);
+	ut_asserteq(0, ctx.xsdt->entry[3]);
 
 	return 0;
 }
@@ -268,15 +297,18 @@ static int dm_test_acpi_cmd_list(struct unit_test_state *uts)
 	addr = ALIGN(addr + sizeof(struct acpi_rsdp), 16);
 	ut_assert_nextline("RSDT %08lx %06lx (v01 U-BOOT U-BOOTBL %u INTL 0)",
 			   addr, sizeof(struct acpi_table_header) +
-			   2 * sizeof(u32), U_BOOT_BUILD_DATE);
+			   3 * sizeof(u32), U_BOOT_BUILD_DATE);
 	addr = ALIGN(addr + sizeof(struct acpi_rsdt), 16);
 	ut_assert_nextline("XSDT %08lx %06lx (v01 U-BOOT U-BOOTBL %u INTL 0)",
 			   addr, sizeof(struct acpi_table_header) +
-			   2 * sizeof(u64), U_BOOT_BUILD_DATE);
+			   3 * sizeof(u64), U_BOOT_BUILD_DATE);
 	addr = ALIGN(addr + sizeof(struct acpi_xsdt), 64);
 	ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %u INTL 0)",
 			   addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
 	addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
+	ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %u INTL 0)",
+			   addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
+	addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
 	ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %u INTL 0)",
 			   addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
 	ut_assert_console_end();
@@ -315,3 +347,40 @@ static int dm_test_acpi_cmd_dump(struct unit_test_state *uts)
 	return 0;
 }
 DM_TEST(dm_test_acpi_cmd_dump, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test acpi_device_path() */
+static int dm_test_acpi_device_path(struct unit_test_state *uts)
+{
+	struct testacpi_platdata *plat;
+	char buf[ACPI_PATH_MAX];
+	struct udevice *dev, *child;
+
+	ut_assertok(uclass_first_device_err(UCLASS_TEST_ACPI, &dev));
+	ut_assertok(acpi_device_path(dev, buf, sizeof(buf)));
+	ut_asserteq_str("\\_SB." ACPI_TEST_DEV_NAME, buf);
+
+	/* Test running out of space */
+	buf[5] = '\0';
+	ut_asserteq(-ENOSPC, acpi_device_path(dev, buf, 5));
+	ut_asserteq('\0', buf[5]);
+
+	/* Test a three-component name */
+	ut_assertok(device_first_child_err(dev, &child));
+	ut_assertok(acpi_device_path(child, buf, sizeof(buf)));
+	ut_asserteq_str("\\_SB." ACPI_TEST_DEV_NAME "." ACPI_TEST_CHILD_NAME,
+			buf);
+
+	/* Test handling of a device which doesn't produce a name */
+	plat = dev_get_platdata(dev);
+	plat->no_name = true;
+	ut_assertok(acpi_device_path(child, buf, sizeof(buf)));
+	ut_asserteq_str("\\_SB." ACPI_TEST_CHILD_NAME, buf);
+
+	/* Test handling of a device which returns an error */
+	plat = dev_get_platdata(dev);
+	plat->return_error = true;
+	ut_asserteq(-EINVAL, acpi_device_path(child, buf, sizeof(buf)));
+
+	return 0;
+}
+DM_TEST(dm_test_acpi_device_path, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.26.2.303.gf8c07b1a785-goog

  parent reply	other threads:[~2020-04-29  2:21 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-29  2:21 [PATCH v1 00/35] dm: Add programmatic generation of ACPI tables (part B) Simon Glass
2020-04-29  2:21 ` [PATCH v1 01/35] dm: core: Add an ACPI name for the root node Simon Glass
2020-04-30 12:44   ` Antwort: " Wolfgang Wallner
2020-04-29  2:21 ` Simon Glass [this message]
2020-04-29  2:21 ` [PATCH v1 03/35] acpi: Add a way to check device status Simon Glass
2020-04-29  2:21 ` [PATCH v1 04/35] irq: Add a method to convert an interrupt to ACPI Simon Glass
2020-04-29  2:21 ` [PATCH v1 05/35] acpi: Support generation of ACPI code Simon Glass
2020-04-29  2:21 ` [PATCH v1 06/35] acpi: Support generation of interrupt descriptor Simon Glass
2020-04-29  2:21 ` [PATCH v1 07/35] gpio: Add a method to convert a GPIO to ACPI Simon Glass
2020-04-29  2:21 ` [PATCH v1 08/35] acpi: Support string output Simon Glass
2020-04-29  2:21 ` [PATCH v1 09/35] acpi: Support generation of GPIO descriptor Simon Glass
2020-04-29  2:21 ` [PATCH v1 10/35] acpi: Support generation of a GPIO/irq for a device Simon Glass
2020-04-29  2:21 ` [PATCH v1 11/35] acpi: Support generation of I2C descriptor Simon Glass
2020-04-29  2:21 ` [PATCH v1 12/35] acpi: Support generation of SPI descriptor Simon Glass
2020-04-29  2:21 ` [PATCH v1 13/35] acpigen: Support writing a length Simon Glass
2020-04-29  2:21 ` [PATCH v1 14/35] acpigen: Support writing a package Simon Glass
2020-04-29  2:21 ` [PATCH v1 15/35] acpi: Support writing an integer Simon Glass
2020-04-29  2:21 ` [PATCH v1 16/35] acpi: Support writing a string Simon Glass
2020-04-29  2:21 ` [PATCH v1 17/35] acpi: Support writing a name Simon Glass
2020-04-29  2:21 ` [PATCH v1 18/35] acpi: Support writing a UUID Simon Glass
2020-04-29  2:21 ` [PATCH v1 19/35] acpi: Support writing Device Properties objects via _DSD Simon Glass
2020-04-29  2:21 ` [PATCH v1 20/35] acpi: Support writing a GPIO Simon Glass
2020-04-29  2:21 ` [PATCH v1 21/35] acpi: Support copying properties from device tree to ACPI Simon Glass
2020-04-29  2:21 ` [PATCH v1 22/35] acpi: Add support for various misc ACPI opcodes Simon Glass
2020-04-29  2:21 ` [PATCH v1 23/35] acpi: Add support for writing a Power Resource Simon Glass
2020-04-29  2:21 ` [PATCH v1 24/35] acpi: Add support for writing a GPIO power sequence Simon Glass
2020-04-29  2:21 ` [PATCH v1 25/35] acpi: Add support for a generic " Simon Glass
2020-04-29  2:21 ` [PATCH v1 26/35] acpi: Add support for SSDT generation Simon Glass
2020-04-29  2:21 ` [PATCH v1 27/35] x86: acpi: Move MADT down a bit Simon Glass
2020-04-29  2:21 ` [PATCH v1 28/35] acpi: Record the items added to SSDT Simon Glass
2020-04-29  2:21 ` [PATCH v1 29/35] acpi: Support ordering SSDT data by device Simon Glass
2020-04-29  2:21 ` [PATCH v1 30/35] x86: Allow devices to write an SSDT Simon Glass
2020-04-29  2:21 ` [PATCH v1 31/35] acpi: Add support for DSDT generation Simon Glass
2020-04-29  2:21 ` [PATCH v1 32/35] x86: Allow devices to write to DSDT Simon Glass
2020-04-29  2:21 ` [PATCH v1 33/35] pci: Avoid a crash in device_is_on_pci_bus() Simon Glass
2020-04-29  2:21 ` [PATCH v1 34/35] dm: acpi: Enhance acpi_get_name() Simon Glass
2020-04-29  2:21 ` [PATCH v1 35/35] acpi: Add an acpi split command Simon Glass
2020-04-30 13:52 ` Antwort: [PATCH v1 02/35] acpi: Add a function to get a device path and scope Wolfgang Wallner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200429022159.254271-2-sjg@chromium.org \
    --to=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.