diff mbox series

[v2,29/35] acpi: Support ordering SSDT data by device

Message ID 20200510143320.v2.29.I91d8e58921d27a54f6ecb58ecd5b72d141238f63@changeid
State Superseded
Delegated to: Bin Meng
Headers show
Series dm: Add programmatic generation of ACPI tables (part B) | expand

Commit Message

Simon Glass May 10, 2020, 8:34 p.m. UTC
Add a /chosen property to control the order in which the data appears
in the SSDT. This allows matching up U-Boot's output from a dump of the
known-good data obtained from within Linux.

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

Changes in v2: None
Changes in v1:
- Generalise the ACPI function recursion with acpi_recurse_method()

 arch/sandbox/dts/test.dts           |  5 ++-
 doc/device-tree-bindings/chosen.txt |  9 +++++
 drivers/core/acpi.c                 | 62 +++++++++++++++++++++++++++++
 test/dm/acpi.c                      | 15 ++++---
 4 files changed, 83 insertions(+), 8 deletions(-)

Comments

Wolfgang Wallner June 4, 2020, 11:52 a.m. UTC | #1
Hi Simon,

-----"Simon Glass" <sjg@chromium.org> schrieb: -----
> Betreff: [PATCH v2 29/35] acpi: Support ordering SSDT data by device
> 
> Add a /chosen property to control the order in which the data appears
> in the SSDT. This allows matching up U-Boot's output from a dump of the
> known-good data obtained from within Linux.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v1:
> - Generalise the ACPI function recursion with acpi_recurse_method()
> 
>  arch/sandbox/dts/test.dts           |  5 ++-
>  doc/device-tree-bindings/chosen.txt |  9 +++++
>  drivers/core/acpi.c                 | 62 +++++++++++++++++++++++++++++
>  test/dm/acpi.c                      | 15 ++++---
>  4 files changed, 83 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index f6520a54e8..30eb749671 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -252,7 +252,7 @@
>  		compatible = "denx,u-boot-devres-test";
>  	};
>  
> -	acpi-test {
> +	acpi_test1: acpi-test {
>  		compatible = "denx,u-boot-acpi-test";
>  		acpi-ssdt-test-data = "ab";
>  		child {
> @@ -260,7 +260,7 @@
>  		};
>  	};
>  
> -	acpi-test2 {
> +	acpi_test2: acpi-test2 {
>  		compatible = "denx,u-boot-acpi-test";
>  		acpi-ssdt-test-data = "cd";
>  	};
> @@ -893,6 +893,7 @@
>  		setting = "sunrise ohoka";
>  		other-node = "/some-bus/c-test@5";
>  		int-values = <0x1937 72993>;
> +		u-boot,acpi-ssdt-order = <&acpi_test2 &acpi_test1>;
>  		chosen-test {
>  			compatible = "denx,u-boot-fdt-test";
>  			reg = <9 1>;
> diff --git a/doc/device-tree-bindings/chosen.txt b/doc/device-tree-bindings/chosen.txt
> index 395c9501e3..d4dfc05847 100644
> --- a/doc/device-tree-bindings/chosen.txt
> +++ b/doc/device-tree-bindings/chosen.txt
> @@ -134,3 +134,12 @@ Example
>  		phandlepart = <&mmc 1>;
>  	};
>  };
> +
> +u-boot,acpi-ssdt-order
> +----------------------
> +
> +This provides the ordering to use when writing device data to the ACPI SSDT
> +(Secondary System Descriptor Table). Each cell is a phandle pointer to a device
> +node to add. The ACPI information is written in this order.
> +
> +If the ordering does not include all nodes, an error is generated.
> diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c
> index fa16be8154..a0b598b66b 100644
> --- a/drivers/core/acpi.c
> +++ b/drivers/core/acpi.c
> @@ -108,6 +108,63 @@ static int acpi_add_item(struct acpi_ctx *ctx, struct udevice *dev,
>  	return 0;
>  }
>  
> +struct acpi_item *find_item(const char *devname)

1) Shouldn't this function be static?
2) The name is very generic. How about find_acpi_item?

> +{
> +	int i;
> +
> +	for (i = 0; i < item_count; i++) {
> +		struct acpi_item *item = &acpi_item[i];
> +
> +		if (!strcmp(devname, item->dev->name))
> +			return item;
> +	}
> +
> +	return NULL;
> +}
> +
> +static int build_type(struct acpi_ctx *ctx, void *start, enum gen_type_t type)

1) I find the name "build_type" confusing. It is actually sorting items of a
given type from acpi_items and copies them to a given location. How about
sort_acpi_item_type?

2) What the function does is not immediatly obvious. A function description
would be nice.

> +{
> +	const u32 *order;
> +	int size;
> +	int count;
> +	void *ptr;
> +	void *end = ctx->current;
> +
> +	ptr = start;
> +	order = ofnode_read_chosen_prop("u-boot,acpi-ssdt-order", &size);
> +	if (!order) {
> +		log_warning("Failed to find ordering, leaving as is\n");
> +		return 0;
> +	}
> +
> +	count = size / sizeof(u32);
> +	while (count--) {
> +		struct acpi_item *item;
> +		const char *name;
> +		ofnode node;
> +
> +		node = ofnode_get_by_phandle(fdt32_to_cpu(*order++));
> +		name = ofnode_get_name(node);
> +		item = find_item(name);
> +		if (!item) {
> +			log_err("Failed to find item '%s'\n", name);
> +			return log_msg_ret("find", -ENOENT);
> +		}
> +		if (item->type == type) {
> +			log_debug("   - add %s\n", item->dev->name);
> +			memcpy(ptr, item->buf, item->size);
> +			ptr += item->size;
> +		}
> +	}
> +
> +	if (ptr != end) {
> +		log_warning("*** Missing bytes: ptr=%p, end=%p\n", ptr, end);
> +		return -ENXIO;
> +	}
> +
> +	return 0;
> +}
> +
>  acpi_method acpi_get_method(struct udevice *dev, enum method_t method)
>  {
>  	struct acpi_ops *aops;
> @@ -163,11 +220,16 @@ int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent,
>  
>  int acpi_fill_ssdt(struct acpi_ctx *ctx)
>  {
> +	void *start = ctx->current;
>  	int ret;
>  
>  	log_debug("Writing SSDT tables\n");
> +	item_count = 0;
>  	ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_SSDT, TYPE_SSDT);
>  	log_debug("Writing SSDT finished, err=%d\n", ret);
> +	ret = build_type(ctx, start, TYPE_SSDT);
> +	if (ret)
> +		return log_msg_ret("build", ret);
>  
>  	return ret;
>  }
> diff --git a/test/dm/acpi.c b/test/dm/acpi.c
> index d1bd108223..8df128706d 100644
> --- a/test/dm/acpi.c
> +++ b/test/dm/acpi.c
> @@ -425,13 +425,16 @@ static int dm_test_acpi_fill_ssdt(struct unit_test_state *uts)
>  	buf[4] = 'z';	/* sentinel */
>  	ut_assertok(acpi_fill_ssdt(&ctx));
>  
> -	/* These values come from acpi-test's acpi-ssdt-test-data property */
> -	ut_asserteq('a', buf[0]);
> -	ut_asserteq('b', buf[1]);
> +	/*
> +	 * These values come from acpi-test2's acpi-ssdt-test-data property.
> +	 * This device comes first because of u-boot,acpi-ssdt-order
> +	 */
> +	ut_asserteq('c', buf[0]);
> +	ut_asserteq('d', buf[1]);
>  
> -	/* These values come from acpi-test2's acpi-ssdt-test-data property */
> -	ut_asserteq('c', buf[2]);
> -	ut_asserteq('d', buf[3]);
> +	/* These values come from acpi-test's acpi-ssdt-test-data property */
> +	ut_asserteq('a', buf[2]);
> +	ut_asserteq('b', buf[3]);
>  
>  	ut_asserteq('z', buf[4]);
>  
> -- 
> 2.26.2.645.ge9eca65c58-goog
> 

regards, Wolfgang
diff mbox series

Patch

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index f6520a54e8..30eb749671 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -252,7 +252,7 @@ 
 		compatible = "denx,u-boot-devres-test";
 	};
 
-	acpi-test {
+	acpi_test1: acpi-test {
 		compatible = "denx,u-boot-acpi-test";
 		acpi-ssdt-test-data = "ab";
 		child {
@@ -260,7 +260,7 @@ 
 		};
 	};
 
-	acpi-test2 {
+	acpi_test2: acpi-test2 {
 		compatible = "denx,u-boot-acpi-test";
 		acpi-ssdt-test-data = "cd";
 	};
@@ -893,6 +893,7 @@ 
 		setting = "sunrise ohoka";
 		other-node = "/some-bus/c-test@5";
 		int-values = <0x1937 72993>;
+		u-boot,acpi-ssdt-order = <&acpi_test2 &acpi_test1>;
 		chosen-test {
 			compatible = "denx,u-boot-fdt-test";
 			reg = <9 1>;
diff --git a/doc/device-tree-bindings/chosen.txt b/doc/device-tree-bindings/chosen.txt
index 395c9501e3..d4dfc05847 100644
--- a/doc/device-tree-bindings/chosen.txt
+++ b/doc/device-tree-bindings/chosen.txt
@@ -134,3 +134,12 @@  Example
 		phandlepart = <&mmc 1>;
 	};
 };
+
+u-boot,acpi-ssdt-order
+----------------------
+
+This provides the ordering to use when writing device data to the ACPI SSDT
+(Secondary System Descriptor Table). Each cell is a phandle pointer to a device
+node to add. The ACPI information is written in this order.
+
+If the ordering does not include all nodes, an error is generated.
diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c
index fa16be8154..a0b598b66b 100644
--- a/drivers/core/acpi.c
+++ b/drivers/core/acpi.c
@@ -108,6 +108,63 @@  static int acpi_add_item(struct acpi_ctx *ctx, struct udevice *dev,
 	return 0;
 }
 
+struct acpi_item *find_item(const char *devname)
+{
+	int i;
+
+	for (i = 0; i < item_count; i++) {
+		struct acpi_item *item = &acpi_item[i];
+
+		if (!strcmp(devname, item->dev->name))
+			return item;
+	}
+
+	return NULL;
+}
+
+static int build_type(struct acpi_ctx *ctx, void *start, enum gen_type_t type)
+{
+	const u32 *order;
+	int size;
+	int count;
+	void *ptr;
+	void *end = ctx->current;
+
+	ptr = start;
+	order = ofnode_read_chosen_prop("u-boot,acpi-ssdt-order", &size);
+	if (!order) {
+		log_warning("Failed to find ordering, leaving as is\n");
+		return 0;
+	}
+
+	count = size / sizeof(u32);
+	while (count--) {
+		struct acpi_item *item;
+		const char *name;
+		ofnode node;
+
+		node = ofnode_get_by_phandle(fdt32_to_cpu(*order++));
+		name = ofnode_get_name(node);
+		item = find_item(name);
+		if (!item) {
+			log_err("Failed to find item '%s'\n", name);
+			return log_msg_ret("find", -ENOENT);
+		}
+		if (item->type == type) {
+			log_debug("   - add %s\n", item->dev->name);
+			memcpy(ptr, item->buf, item->size);
+			ptr += item->size;
+		}
+	}
+
+	if (ptr != end) {
+		log_warning("*** Missing bytes: ptr=%p, end=%p\n", ptr, end);
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
 acpi_method acpi_get_method(struct udevice *dev, enum method_t method)
 {
 	struct acpi_ops *aops;
@@ -163,11 +220,16 @@  int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent,
 
 int acpi_fill_ssdt(struct acpi_ctx *ctx)
 {
+	void *start = ctx->current;
 	int ret;
 
 	log_debug("Writing SSDT tables\n");
+	item_count = 0;
 	ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_SSDT, TYPE_SSDT);
 	log_debug("Writing SSDT finished, err=%d\n", ret);
+	ret = build_type(ctx, start, TYPE_SSDT);
+	if (ret)
+		return log_msg_ret("build", ret);
 
 	return ret;
 }
diff --git a/test/dm/acpi.c b/test/dm/acpi.c
index d1bd108223..8df128706d 100644
--- a/test/dm/acpi.c
+++ b/test/dm/acpi.c
@@ -425,13 +425,16 @@  static int dm_test_acpi_fill_ssdt(struct unit_test_state *uts)
 	buf[4] = 'z';	/* sentinel */
 	ut_assertok(acpi_fill_ssdt(&ctx));
 
-	/* These values come from acpi-test's acpi-ssdt-test-data property */
-	ut_asserteq('a', buf[0]);
-	ut_asserteq('b', buf[1]);
+	/*
+	 * These values come from acpi-test2's acpi-ssdt-test-data property.
+	 * This device comes first because of u-boot,acpi-ssdt-order
+	 */
+	ut_asserteq('c', buf[0]);
+	ut_asserteq('d', buf[1]);
 
-	/* These values come from acpi-test2's acpi-ssdt-test-data property */
-	ut_asserteq('c', buf[2]);
-	ut_asserteq('d', buf[3]);
+	/* These values come from acpi-test's acpi-ssdt-test-data property */
+	ut_asserteq('a', buf[2]);
+	ut_asserteq('b', buf[3]);
 
 	ut_asserteq('z', buf[4]);