linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] ACPI: Arm Generic Diagnostic Dump and Reset device
@ 2021-12-03  2:43 Ilkka Koskinen
  2021-12-03  2:43 ` [PATCH 1/2] ACPI: AGDI: Add AGDI tables to drivers/acpi Ilkka Koskinen
  2021-12-03  2:43 ` [PATCH 2/2] ACPI: AGDI: Add driver for Arm Generic Diagnostic Dump and Reset device Ilkka Koskinen
  0 siblings, 2 replies; 5+ messages in thread
From: Ilkka Koskinen @ 2021-12-03  2:43 UTC (permalink / raw)
  To: lorenzo.pieralisi, guohanjun, sudeep.holla
  Cc: rafael, lenb, robert.moore, linux-acpi, linux-arm-kernel,
	linux-kernel, devel, patches, scott, darren

Arm Generic Diagnostic Dump and Reset device enables a maintainer to
request OS to perform a diagnostic dump and reset a system via SDEI
event or an interrupt. This patchset adds support for the SDEI path.

I do have a patch to enable the interrupt path as well but I'm holding
it back since AGDI table is missing interrupt configuration fields
(trigger type etc.).

The recently published specification is available at
https://developer.arm.com/documentation/den0093/latest

The patchset was tested on Ampere Altra/Mt. Jade.

The patchset applies on top of
  git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm master
  git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core


What's the process with new ACPI tables? Should I submit a patch to
ACPICA at first or is this fine?


Ilkka Koskinen (2):
  ACPI: AGDI: Add AGDI tables to drivers/acpi
  ACPI: AGDI: Add driver for Arm Generic Diagnostic Dump and Reset
    device

 drivers/acpi/arm64/Kconfig  |   8 +++
 drivers/acpi/arm64/Makefile |   1 +
 drivers/acpi/arm64/agdi.c   | 133 ++++++++++++++++++++++++++++++++++++
 drivers/acpi/tables.c       |   2 +-
 include/acpi/actbl2.h       |  20 ++++++
 5 files changed, 163 insertions(+), 1 deletion(-)
 create mode 100644 drivers/acpi/arm64/agdi.c

-- 
2.17.1


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

* [PATCH 1/2] ACPI: AGDI: Add AGDI tables to drivers/acpi
  2021-12-03  2:43 [PATCH 0/2] ACPI: Arm Generic Diagnostic Dump and Reset device Ilkka Koskinen
@ 2021-12-03  2:43 ` Ilkka Koskinen
  2021-12-03  2:43 ` [PATCH 2/2] ACPI: AGDI: Add driver for Arm Generic Diagnostic Dump and Reset device Ilkka Koskinen
  1 sibling, 0 replies; 5+ messages in thread
From: Ilkka Koskinen @ 2021-12-03  2:43 UTC (permalink / raw)
  To: lorenzo.pieralisi, guohanjun, sudeep.holla
  Cc: rafael, lenb, robert.moore, linux-acpi, linux-arm-kernel,
	linux-kernel, devel, patches, scott, darren

ACPI for Arm Components 1.1 Platform Design Document v1.1 [0] specifices
Arm Generic Diagnostic Device Interface (AGDI). It allows an admin to
issue diagnostic dump and reset via an SDEI event or an interrupt. This
patch adds support to ACPI/AGDI tables.

[0] https://developer.arm.com/documentation/den0093/latest/

Signed-off-by: Ilkka Koskinen <ilkka@os.amperecomputing.com>
---
 drivers/acpi/tables.c |  2 +-
 include/acpi/actbl2.h | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 71419eb16e09..5e3169bcb9fb 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -500,7 +500,7 @@ static const char table_sigs[][ACPI_NAMESEG_SIZE] __initconst = {
 	ACPI_SIG_WDDT, ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT,
 	ACPI_SIG_PSDT, ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT,
 	ACPI_SIG_IORT, ACPI_SIG_NFIT, ACPI_SIG_HMAT, ACPI_SIG_PPTT,
-	ACPI_SIG_NHLT };
+	ACPI_SIG_NHLT, ACPI_SIG_AGDI };
 
 #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
 
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index 71ca090fd61b..66ca85b9f5fe 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -24,6 +24,7 @@
  * file. Useful because they make it more difficult to inadvertently type in
  * the wrong signature.
  */
+#define ACPI_SIG_AGDI           "AGDI"	/* ARM Generic Diagnostic Dump and Reset Device Interface */
 #define ACPI_SIG_BDAT           "BDAT"	/* BIOS Data ACPI Table */
 #define ACPI_SIG_IORT           "IORT"	/* IO Remapping Table */
 #define ACPI_SIG_IVRS           "IVRS"	/* I/O Virtualization Reporting Structure */
@@ -237,6 +238,25 @@ typedef struct acpi_aest_node_interrupt {
 #define ACPI_AEST_NODE_ERROR_RECOVERY       1
 #define ACPI_AEST_XRUPT_RESERVED            2	/* 2 and above are reserved */
 
+/*******************************************************************************
+ * AGDI - Generic Diagnostic Dump and Reset Device Interface
+ *
+ * Document number: ARM DEN0093
+ *
+ *******************************************************************************/
+
+struct acpi_table_agdi {
+	struct acpi_table_header header;
+	u8 flags;
+	u8 reserved[3];
+	u32 sdei_event;
+	u32 gsiv;
+};
+
+/* Masks for Flags field above for AGDI table */
+
+#define ACPI_AGDI_SIGNALING_MODE (1)
+
 /*******************************************************************************
  *
  * BDAT - BIOS Data ACPI Table
-- 
2.17.1


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

* [PATCH 2/2] ACPI: AGDI: Add driver for Arm Generic Diagnostic Dump and Reset device
  2021-12-03  2:43 [PATCH 0/2] ACPI: Arm Generic Diagnostic Dump and Reset device Ilkka Koskinen
  2021-12-03  2:43 ` [PATCH 1/2] ACPI: AGDI: Add AGDI tables to drivers/acpi Ilkka Koskinen
@ 2021-12-03  2:43 ` Ilkka Koskinen
  2021-12-09 16:36   ` Russell King (Oracle)
  1 sibling, 1 reply; 5+ messages in thread
From: Ilkka Koskinen @ 2021-12-03  2:43 UTC (permalink / raw)
  To: lorenzo.pieralisi, guohanjun, sudeep.holla
  Cc: rafael, lenb, robert.moore, linux-acpi, linux-arm-kernel,
	linux-kernel, devel, patches, scott, darren

ACPI for Arm Components 1.1 Platform Design Document v1.1 [0] specifices
Arm Generic Diagnostic Device Interface (AGDI). It allows an admin to
issue diagnostic dump and reset via an SDEI event or an interrupt.
This patch implements SDEI path.

[0] https://developer.arm.com/documentation/den0093/latest/

Signed-off-by: Ilkka Koskinen <ilkka@os.amperecomputing.com>
---
 drivers/acpi/arm64/Kconfig  |   8 +++
 drivers/acpi/arm64/Makefile |   1 +
 drivers/acpi/arm64/agdi.c   | 133 ++++++++++++++++++++++++++++++++++++
 3 files changed, 142 insertions(+)
 create mode 100644 drivers/acpi/arm64/agdi.c

diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
index 6dba187f4f2e..24869ba5b365 100644
--- a/drivers/acpi/arm64/Kconfig
+++ b/drivers/acpi/arm64/Kconfig
@@ -8,3 +8,11 @@ config ACPI_IORT
 
 config ACPI_GTDT
 	bool
+
+config ACPI_AGDI
+	bool "Arm Generic Diagnostic Dump and Reset Device Interface"
+	depends on ARM_SDE_INTERFACE
+	help
+	  Arm Generic Diagnostic Dump and Reset Device Interface (AGDI) is
+	  a standard that enables issuing a non-maskable diagnostic dump and
+	  reset command.
diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 66acbe77f46e..7b9e4045659d 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_ACPI_AGDI) 	+= agdi.o
 obj-$(CONFIG_ACPI_IORT) 	+= iort.o
 obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
 obj-y				+= dma.o
diff --git a/drivers/acpi/arm64/agdi.c b/drivers/acpi/arm64/agdi.c
new file mode 100644
index 000000000000..cdd8811df3d5
--- /dev/null
+++ b/drivers/acpi/arm64/agdi.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * This file implements handling of
+ * Arm Generic Diagnostic Dump and Reset Interface table (AGDI)
+ *
+ * Copyright (c) 2021, Ampere Computing LLC
+ */
+
+#define pr_fmt(fmt) "ACPI: AGDI: " fmt
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/acpi.h>
+#include <linux/arm_sdei.h>
+#include <linux/io.h>
+
+struct agdi_data {
+	int sdei_event;
+};
+
+static int agdi_sdei_handler(u32 sdei_event, struct pt_regs *regs, void *arg)
+{
+	nmi_panic(regs, "Arm Generic Diagnostic Dump and Reset SDEI event issued");
+	return 0;
+}
+
+static int agdi_sdei_probe(struct platform_device *pdev,
+			   struct agdi_data *adata)
+{
+	int err;
+
+	err = sdei_event_register(adata->sdei_event, agdi_sdei_handler, pdev);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to register for SDEI event %d",
+			adata->sdei_event);
+		return err;
+	}
+
+	err = sdei_event_enable(adata->sdei_event);
+	if (err)  {
+		sdei_event_unregister(adata->sdei_event);
+		dev_err(&pdev->dev, "Failed to enable event %d\n",
+			adata->sdei_event);
+		return err;
+	}
+
+	return 0;
+}
+
+static int agdi_probe(struct platform_device *pdev)
+{
+	struct agdi_data *adata;
+
+	adata = dev_get_platdata(&pdev->dev);
+	if (!adata)
+		return -EINVAL;
+
+	return agdi_sdei_probe(pdev, adata);
+}
+
+static int agdi_remove(struct platform_device *pdev)
+{
+	struct agdi_data *adata = platform_get_drvdata(pdev);
+
+	sdei_event_disable(adata->sdei_event);
+	sdei_event_unregister(adata->sdei_event);
+
+	return 0;
+}
+
+static struct platform_driver agdi_driver = {
+	.driver = {
+		.name = "agdi",
+	},
+	.probe = agdi_probe,
+	.remove = agdi_remove,
+};
+
+static int __init agdi_init(void)
+{
+	int ret;
+	acpi_status status;
+	struct acpi_table_agdi *agdi_table;
+	struct agdi_data *pdata;
+	struct platform_device *pdev;
+
+	if (acpi_disabled)
+		return 0;
+
+	status = acpi_get_table(ACPI_SIG_AGDI, 0,
+				(struct acpi_table_header **) &agdi_table);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	pdata = kzalloc(sizeof(*pdata), GFP_ATOMIC);
+	if (!pdata) {
+		ret = -ENOMEM;
+		goto err_put_table;
+	}
+
+	if (agdi_table->flags & ACPI_AGDI_SIGNALING_MODE) {
+		pr_warn("Interrupt signaling is not supported");
+		ret = -ENODEV;
+		goto err_free_pdata;
+	}
+
+	pdata->sdei_event = agdi_table->sdei_event;
+
+	pdev = platform_device_register_data(NULL, "agdi", 0, pdata, sizeof(*pdata));
+	if (IS_ERR(pdev)) {
+		ret = PTR_ERR(pdev);
+		goto err_free_pdata;
+	}
+
+	ret = platform_driver_register(&agdi_driver);
+	if (ret)
+		goto err_device_unregister;
+
+	acpi_put_table((struct acpi_table_header *)agdi_table);
+	return 0;
+
+err_device_unregister:
+	platform_device_unregister(pdev);
+err_free_pdata:
+	kfree(pdata);
+err_put_table:
+	acpi_put_table((struct acpi_table_header *)agdi_table);
+	return ret;
+}
+device_initcall(agdi_init);
-- 
2.17.1


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

* Re: [PATCH 2/2] ACPI: AGDI: Add driver for Arm Generic Diagnostic Dump and Reset device
  2021-12-03  2:43 ` [PATCH 2/2] ACPI: AGDI: Add driver for Arm Generic Diagnostic Dump and Reset device Ilkka Koskinen
@ 2021-12-09 16:36   ` Russell King (Oracle)
  2021-12-10  8:32     ` ilkka
  0 siblings, 1 reply; 5+ messages in thread
From: Russell King (Oracle) @ 2021-12-09 16:36 UTC (permalink / raw)
  To: Ilkka Koskinen
  Cc: lorenzo.pieralisi, guohanjun, sudeep.holla, rafael, lenb,
	robert.moore, linux-acpi, linux-arm-kernel, linux-kernel, devel,
	patches, scott, darren

Hi,

On Thu, Dec 02, 2021 at 06:43:11PM -0800, Ilkka Koskinen wrote:
> +static int __init agdi_init(void)
> +{
> +	int ret;
> +	acpi_status status;
> +	struct acpi_table_agdi *agdi_table;
> +	struct agdi_data *pdata;
> +	struct platform_device *pdev;
> +
> +	if (acpi_disabled)
> +		return 0;
> +
> +	status = acpi_get_table(ACPI_SIG_AGDI, 0,
> +				(struct acpi_table_header **) &agdi_table);
> +	if (ACPI_FAILURE(status))
> +		return -ENODEV;
> +
> +	pdata = kzalloc(sizeof(*pdata), GFP_ATOMIC);

Why does this need to be GFP_ATOMIC? Also, struct agdi_data is a single
int in size, why do you need to kzalloc() it?

> +	if (!pdata) {
> +		ret = -ENOMEM;
> +		goto err_put_table;
> +	}
> +
> +	if (agdi_table->flags & ACPI_AGDI_SIGNALING_MODE) {
> +		pr_warn("Interrupt signaling is not supported");
> +		ret = -ENODEV;
> +		goto err_free_pdata;
> +	}
> +
> +	pdata->sdei_event = agdi_table->sdei_event;
> +
> +	pdev = platform_device_register_data(NULL, "agdi", 0, pdata, sizeof(*pdata));

platform_device_register_data() uses kmemdup() internally with the
platform data, meaning it takes a copy of the platform data. There is
no need for the pdata allocation to persist past this point. Hence,
given that it is a single int in size, you may as well put
"struct agdi_data" on the stack.

Thanks.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

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

* Re: [PATCH 2/2] ACPI: AGDI: Add driver for Arm Generic Diagnostic Dump and Reset device
  2021-12-09 16:36   ` Russell King (Oracle)
@ 2021-12-10  8:32     ` ilkka
  0 siblings, 0 replies; 5+ messages in thread
From: ilkka @ 2021-12-10  8:32 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Ilkka Koskinen, lorenzo.pieralisi, guohanjun, sudeep.holla,
	rafael, lenb, robert.moore, linux-acpi, linux-arm-kernel,
	linux-kernel, devel, patches, scott, darren


Hi,

Thanks for reviewing the patch

On Thu, 9 Dec 2021, Russell King (Oracle) wrote:
> Hi,
>
> On Thu, Dec 02, 2021 at 06:43:11PM -0800, Ilkka Koskinen wrote:
>> +static int __init agdi_init(void)
>> +{
>> +	int ret;
>> +	acpi_status status;
>> +	struct acpi_table_agdi *agdi_table;
>> +	struct agdi_data *pdata;
>> +	struct platform_device *pdev;
>> +
>> +	if (acpi_disabled)
>> +		return 0;
>> +
>> +	status = acpi_get_table(ACPI_SIG_AGDI, 0,
>> +				(struct acpi_table_header **) &agdi_table);
>> +	if (ACPI_FAILURE(status))
>> +		return -ENODEV;
>> +
>> +	pdata = kzalloc(sizeof(*pdata), GFP_ATOMIC);
>
> Why does this need to be GFP_ATOMIC? Also, struct agdi_data is a single
> int in size, why do you need to kzalloc() it?

There's no reason for that. It should obviously be GFP_KERNEL

>
>> +	if (!pdata) {
>> +		ret = -ENOMEM;
>> +		goto err_put_table;
>> +	}
>> +
>> +	if (agdi_table->flags & ACPI_AGDI_SIGNALING_MODE) {
>> +		pr_warn("Interrupt signaling is not supported");
>> +		ret = -ENODEV;
>> +		goto err_free_pdata;
>> +	}
>> +
>> +	pdata->sdei_event = agdi_table->sdei_event;
>> +
>> +	pdev = platform_device_register_data(NULL, "agdi", 0, pdata, sizeof(*pdata));
>
> platform_device_register_data() uses kmemdup() internally with the
> platform data, meaning it takes a copy of the platform data. There is
> no need for the pdata allocation to persist past this point. Hence,
> given that it is a single int in size, you may as well put
> "struct agdi_data" on the stack.

I somehow missed kmemdup() part. I remove the allocation and move pdata to 
the stack instead.

Thanks,
Ilkka


>
> Thanks.
>
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
>

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

end of thread, other threads:[~2021-12-10  8:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-03  2:43 [PATCH 0/2] ACPI: Arm Generic Diagnostic Dump and Reset device Ilkka Koskinen
2021-12-03  2:43 ` [PATCH 1/2] ACPI: AGDI: Add AGDI tables to drivers/acpi Ilkka Koskinen
2021-12-03  2:43 ` [PATCH 2/2] ACPI: AGDI: Add driver for Arm Generic Diagnostic Dump and Reset device Ilkka Koskinen
2021-12-09 16:36   ` Russell King (Oracle)
2021-12-10  8:32     ` ilkka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).