All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: u-boot@lists.denx.de
Subject: [PATCH v3 02/35] acpi: Add a function to get a device path and scope
Date: Sat, 13 Jun 2020 20:54:50 -0600	[thread overview]
Message-ID: <20200613205459.v3.2.Ia1c0ba090f86174165e99209155eb4d8352fbf72@changeid> (raw)
In-Reply-To: <20200614025523.40183-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>
Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---

Changes in v3:
- s/NUL/NULL/ for the NUL character, since that is in more common use

Changes in v1:
- Split into more patches for review
- Add tests
- Rebase on top of common.h series

 arch/sandbox/dts/test.dts  |  3 ++
 include/acpi/acpi_device.h | 44 ++++++++++++++++++
 lib/acpi/Makefile          |  1 +
 lib/acpi/acpi_device.c     | 83 +++++++++++++++++++++++++++++++++
 test/dm/acpi.c             | 95 ++++++++++++++++++++++++++++++++------
 5 files changed, 213 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 5ce5e28476..bad0b4f1a8 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -255,6 +255,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..3a9424e7ee
--- /dev/null
+++ b/lib/acpi/acpi_device.c
@@ -0,0 +1,83 @@
+// 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 <log.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 NULL 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 4c46dd83a6..5b8459311c 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.27.0.290.gba653c62da-goog

  parent reply	other threads:[~2020-06-14  2:54 UTC|newest]

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

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=20200613205459.v3.2.Ia1c0ba090f86174165e99209155eb4d8352fbf72@changeid \
    --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.