From nobody Tue Jun 23 13:20:34 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1EE72C433EF for ; Fri, 4 Mar 2022 06:47:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238555AbiCDGrv (ORCPT ); Fri, 4 Mar 2022 01:47:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40930 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238533AbiCDGrr (ORCPT ); Fri, 4 Mar 2022 01:47:47 -0500 X-Greylist: delayed 64 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Thu, 03 Mar 2022 22:46:57 PST Received: from esa4.hc1455-7.c3s2.iphmx.com (esa4.hc1455-7.c3s2.iphmx.com [68.232.139.117]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A3A2D18DA95; Thu, 3 Mar 2022 22:46:57 -0800 (PST) IronPort-SDR: yw/kl5ucYqtKfEOU0+STPvlOgazcPv6PxvvuTNQbUT0KAwXEjZT3JlOai2tdh2OkYrDYg/7BjG mh8O+eGxCw7zpv7AnnFvcmM9VY5ccd0VyEat/BaA3LNWjBVUqo7SOcVFSD8TwWZcla2prVP8o3 uu/C4Nut7bK039lVYlXn3ltaYTbMlArWnPo34dj4cJ5PJh5cVNOIOLs95OLBotdJ1TiQuGNWKD KplTjVIdKqK7/7qOHzto9qzLRhMpzSYKf3V/PoCnEim4uzKNe4TqHbHEMA7plMyVL0GE5zWl5O fLhOC+XkcQIzZ82otRrKAEdB X-IronPort-AV: E=McAfee;i="6200,9189,10275"; a="64906697" X-IronPort-AV: E=Sophos;i="5.90,154,1643641200"; d="scan'208";a="64906697" Received: from unknown (HELO yto-r2.gw.nic.fujitsu.com) ([218.44.52.218]) by esa4.hc1455-7.c3s2.iphmx.com with ESMTP; 04 Mar 2022 15:45:50 +0900 Received: from yto-m3.gw.nic.fujitsu.com (yto-nat-yto-m3.gw.nic.fujitsu.com [192.168.83.66]) by yto-r2.gw.nic.fujitsu.com (Postfix) with ESMTP id 47ED8C68A5; Fri, 4 Mar 2022 15:45:49 +0900 (JST) Received: from yto-om2.fujitsu.com (yto-om2.o.css.fujitsu.com [10.128.89.163]) by yto-m3.gw.nic.fujitsu.com (Postfix) with ESMTP id DF1EF1428B; Fri, 4 Mar 2022 15:45:47 +0900 (JST) Received: from cn-r05-10.example.com (n3235113.np.ts.nmh.cs.fujitsu.co.jp [10.123.235.113]) by yto-om2.fujitsu.com (Postfix) with ESMTP id 616B64007DEED; Fri, 4 Mar 2022 15:45:47 +0900 (JST) From: Hitomi Hasegawa To: linux-arm-kernel@lists.infradead.org, soc@kernel.org, linux-serial@vger.kernel.org, sumit.garg@linaro.org Cc: arnd@arndb.de, olof@lixom.net, catalin.marinas@arm.com, will@kernel.org, gregkh@linuxfoundation.org, jirislaby@kernel.org, jason.wessel@windriver.com, daniel.thompson@linaro.org, dianders@chromium.org, linux-kernel@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net, peterz@infradead.org, hasegawa-hitomi@fujitsu.com Subject: [PATCH v2 1/2] tty/sysrq: Make sysrq handler NMI aware Date: Fri, 4 Mar 2022 15:43:23 +0900 Message-Id: <20220304064324.331217-2-hasegawa-hitomi@fujitsu.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220304064324.331217-1-hasegawa-hitomi@fujitsu.com> References: <20220304064324.331217-1-hasegawa-hitomi@fujitsu.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Sumit Garg Allow a magic sysrq to be triggered from an NMI context. This is done via marking some sysrq actions as NMI safe. Safe actions will be allowed to run from NMI context whilst that cannot run from an NMI will be queued as irq_work for later processing. The major use-case is to add NMI debugging capabilities to the kernel in order to debug scenarios such as: - Primary CPU is stuck in deadlock with interrupts disabled and hence doesn't honor serial device interrupt. So having magic sysrq triggered as an NMI is helpful for debugging. - Always enabled NMI based magic sysrq irrespective of whether the serial TTY port is active or not. - Apart from UART interrupts, it allows magic sysrq to be triggered from a diagnostic NMI interrupt on systems such as A64FX. A particular sysrq handler is only marked as NMI safe in case the handler isn't contending for any synchronization primitives as in NMI context they are expected to cause deadlocks. Note that the debug sysrq do not contend for any synchronization primitives. It does call kgdb_breakpoint() to provoke a trap but that trap handler should be NMI safe on architectures that implement an NMI. Signed-off-by: Sumit Garg Signed-off-by: Hitomi Hasegawa --- drivers/tty/sysrq.c | 45 ++++++++++++++++++++++++++++++++++++++- include/linux/sysrq.h | 1 + kernel/debug/debug_core.c | 1 + 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index bbfd004449b5..40cd492fe6ec 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -51,6 +51,7 @@ #include #include #include +#include =20 #include #include @@ -112,6 +113,7 @@ static const struct sysrq_key_op sysrq_loglevel_op =3D { .help_msg =3D "loglevel(0-9)", .action_msg =3D "Changing Loglevel", .enable_mask =3D SYSRQ_ENABLE_LOG, + .nmi_safe =3D true, }; =20 #ifdef CONFIG_VT @@ -159,6 +161,7 @@ static const struct sysrq_key_op sysrq_crash_op =3D { .help_msg =3D "crash(c)", .action_msg =3D "Trigger a crash", .enable_mask =3D SYSRQ_ENABLE_DUMP, + .nmi_safe =3D true, }; =20 static void sysrq_handle_reboot(int key) @@ -172,6 +175,7 @@ static const struct sysrq_key_op sysrq_reboot_op =3D { .help_msg =3D "reboot(b)", .action_msg =3D "Resetting", .enable_mask =3D SYSRQ_ENABLE_BOOT, + .nmi_safe =3D true, }; =20 const struct sysrq_key_op *__sysrq_reboot_op =3D &sysrq_reboot_op; @@ -219,6 +223,7 @@ static const struct sysrq_key_op sysrq_showlocks_op =3D= { .handler =3D sysrq_handle_showlocks, .help_msg =3D "show-all-locks(d)", .action_msg =3D "Show Locks Held", + .nmi_safe =3D true, }; #else #define sysrq_showlocks_op (*(const struct sysrq_key_op *)NULL) @@ -291,6 +296,7 @@ static const struct sysrq_key_op sysrq_showregs_op =3D { .help_msg =3D "show-registers(p)", .action_msg =3D "Show Regs", .enable_mask =3D SYSRQ_ENABLE_DUMP, + .nmi_safe =3D true, }; =20 static void sysrq_handle_showstate(int key) @@ -328,6 +334,7 @@ static const struct sysrq_key_op sysrq_ftrace_dump_op = =3D { .help_msg =3D "dump-ftrace-buffer(z)", .action_msg =3D "Dump ftrace buffer", .enable_mask =3D SYSRQ_ENABLE_DUMP, + .nmi_safe =3D true, }; #else #define sysrq_ftrace_dump_op (*(const struct sysrq_key_op *)NULL) @@ -566,6 +573,32 @@ static void __sysrq_put_key_op(int key, const struct s= ysrq_key_op *op_p) sysrq_key_table[i] =3D op_p; } =20 +static int sysrq_nmi_key =3D -1; + +static void sysrq_do_irq_work(struct irq_work *work) +{ + const struct sysrq_key_op *op_p; + int orig_suppress_printk; + + orig_suppress_printk =3D suppress_printk; + suppress_printk =3D 0; + + rcu_sysrq_start(); + rcu_read_lock(); + + op_p =3D __sysrq_get_key_op(sysrq_nmi_key); + if (op_p) + op_p->handler(sysrq_nmi_key); + + rcu_read_unlock(); + rcu_sysrq_end(); + + suppress_printk =3D orig_suppress_printk; + sysrq_nmi_key =3D -1; +} + +static DEFINE_IRQ_WORK(sysrq_irq_work, sysrq_do_irq_work); + void __handle_sysrq(int key, bool check_mask) { const struct sysrq_key_op *op_p; @@ -573,6 +606,10 @@ void __handle_sysrq(int key, bool check_mask) int orig_suppress_printk; int i; =20 + /* Skip sysrq handling if one already in progress */ + if (sysrq_nmi_key !=3D -1) + return; + orig_suppress_printk =3D suppress_printk; suppress_printk =3D 0; =20 @@ -596,7 +633,13 @@ void __handle_sysrq(int key, bool check_mask) if (!check_mask || sysrq_on_mask(op_p->enable_mask)) { pr_info("%s\n", op_p->action_msg); console_loglevel =3D orig_log_level; - op_p->handler(key); + + if (in_nmi() && !op_p->nmi_safe) { + sysrq_nmi_key =3D key; + irq_work_queue(&sysrq_irq_work); + } else { + op_p->handler(key); + } } else { pr_info("This sysrq operation is disabled.\n"); console_loglevel =3D orig_log_level; diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 3a582ec7a2f1..630b5b9dc225 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -34,6 +34,7 @@ struct sysrq_key_op { const char * const help_msg; const char * const action_msg; const int enable_mask; + const bool nmi_safe; }; =20 #ifdef CONFIG_MAGIC_SYSRQ diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index da06a5553835..53b56114f59b 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -978,6 +978,7 @@ static const struct sysrq_key_op sysrq_dbg_op =3D { .handler =3D sysrq_handle_dbg, .help_msg =3D "debug(g)", .action_msg =3D "DEBUG", + .nmi_safe =3D true, }; #endif =20 --=20 2.27.0 From nobody Tue Jun 23 13:20:34 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BD9EAC433EF for ; Fri, 4 Mar 2022 06:47:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238543AbiCDGr5 (ORCPT ); Fri, 4 Mar 2022 01:47:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40876 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238504AbiCDGrs (ORCPT ); Fri, 4 Mar 2022 01:47:48 -0500 Received: from esa11.hc1455-7.c3s2.iphmx.com (esa11.hc1455-7.c3s2.iphmx.com [207.54.90.137]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E76DA18E3C8; Thu, 3 Mar 2022 22:46:59 -0800 (PST) IronPort-SDR: W5DvWfmPs12IvqWG86ZrLc83rxkCU44ifHFKiA6izxMc8uWLVtj6egUmZfi6M+8JEvEJsBQUa2 nJB9ct7C5KLHOnG58h2YDjPAjNlyV9e1HXP8YpP5amwq72cdj4Zkc2G0woXcCC5tAeLZIDEarL AeQCX7P985Ig7kvw47efaanBS6z68pLTXaUGCBv0DXnHLeJyo+QFq/kU4z8alB8DhWd/wdiCz0 wqqA52Q01EjlIeGhbDblYcGcNnTp9AMmML7BuYS0P64rog77AkDxUxvVMTBwJIOt/PT2+IywIF I1LEJ3H3JHpLwNkf77DhPpBS X-IronPort-AV: E=McAfee;i="6200,9189,10275"; a="44623374" X-IronPort-AV: E=Sophos;i="5.90,154,1643641200"; d="scan'208";a="44623374" Received: from unknown (HELO yto-r2.gw.nic.fujitsu.com) ([218.44.52.218]) by esa11.hc1455-7.c3s2.iphmx.com with ESMTP; 04 Mar 2022 15:45:53 +0900 Received: from yto-m1.gw.nic.fujitsu.com (yto-nat-yto-m1.gw.nic.fujitsu.com [192.168.83.64]) by yto-r2.gw.nic.fujitsu.com (Postfix) with ESMTP id A89D4C68B4; Fri, 4 Mar 2022 15:45:52 +0900 (JST) Received: from yto-om2.fujitsu.com (yto-om2.o.css.fujitsu.com [10.128.89.163]) by yto-m1.gw.nic.fujitsu.com (Postfix) with ESMTP id 09B21D0420; Fri, 4 Mar 2022 15:45:51 +0900 (JST) Received: from cn-r05-10.example.com (n3235113.np.ts.nmh.cs.fujitsu.co.jp [10.123.235.113]) by yto-om2.fujitsu.com (Postfix) with ESMTP id 838674007DEED; Fri, 4 Mar 2022 15:45:50 +0900 (JST) From: Hitomi Hasegawa To: linux-arm-kernel@lists.infradead.org, soc@kernel.org, linux-serial@vger.kernel.org, sumit.garg@linaro.org Cc: arnd@arndb.de, olof@lixom.net, catalin.marinas@arm.com, will@kernel.org, gregkh@linuxfoundation.org, jirislaby@kernel.org, jason.wessel@windriver.com, daniel.thompson@linaro.org, dianders@chromium.org, linux-kernel@vger.kernel.org, kgdb-bugreport@lists.sourceforge.net, peterz@infradead.org, hasegawa-hitomi@fujitsu.com Subject: [PATCH v2 2/2] soc: fujitsu: Add A64FX diagnostic interrupt driver Date: Fri, 4 Mar 2022 15:43:24 +0900 Message-Id: <20220304064324.331217-3-hasegawa-hitomi@fujitsu.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220304064324.331217-1-hasegawa-hitomi@fujitsu.com> References: <20220304064324.331217-1-hasegawa-hitomi@fujitsu.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Enable diagnostic interrupts for the A64FX. This is done using a pseudo-NMI. Signed-off-by: Hitomi Hasegawa --- MAINTAINERS | 5 + drivers/soc/Kconfig | 1 + drivers/soc/Makefile | 1 + drivers/soc/fujitsu/Kconfig | 13 +++ drivers/soc/fujitsu/Makefile | 3 + drivers/soc/fujitsu/a64fx-diag.c | 151 +++++++++++++++++++++++++++++++ 6 files changed, 174 insertions(+) create mode 100644 drivers/soc/fujitsu/Kconfig create mode 100644 drivers/soc/fujitsu/Makefile create mode 100644 drivers/soc/fujitsu/a64fx-diag.c diff --git a/MAINTAINERS b/MAINTAINERS index dd36acc87ce6..e9663fa92a52 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -239,6 +239,11 @@ F: include/trace/events/9p.h F: include/uapi/linux/virtio_9p.h F: net/9p/ =20 +A64FX DIAG DRIVER +M: Hitomi Hasegawa +S: Supported +F: drivers/soc/fujitsu/a64fx-diag.c + A8293 MEDIA DRIVER M: Antti Palosaari L: linux-media@vger.kernel.org diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index e8a30c4c5aec..0405ff0b3be6 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -8,6 +8,7 @@ source "drivers/soc/atmel/Kconfig" source "drivers/soc/bcm/Kconfig" source "drivers/soc/canaan/Kconfig" source "drivers/soc/fsl/Kconfig" +source "drivers/soc/fujitsu/Kconfig" source "drivers/soc/imx/Kconfig" source "drivers/soc/ixp4xx/Kconfig" source "drivers/soc/litex/Kconfig" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index a05e9fbcd3e0..86596405a39c 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_SOC_CANAAN) +=3D canaan/ obj-$(CONFIG_ARCH_DOVE) +=3D dove/ obj-$(CONFIG_MACH_DOVE) +=3D dove/ obj-y +=3D fsl/ +obj-y +=3D fujitsu/ obj-$(CONFIG_ARCH_GEMINI) +=3D gemini/ obj-y +=3D imx/ obj-y +=3D ixp4xx/ diff --git a/drivers/soc/fujitsu/Kconfig b/drivers/soc/fujitsu/Kconfig new file mode 100644 index 000000000000..b41cdac67637 --- /dev/null +++ b/drivers/soc/fujitsu/Kconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only +menu "fujitsu SoC drivers" + +config A64FX_DIAG + bool "A64FX diag driver" + depends on ARM64 + help + Say Y here if you want to enable diag interrupt on A64FX. + This driver uses pseudo-NMI if available. + + If unsure, say N. + +endmenu diff --git a/drivers/soc/fujitsu/Makefile b/drivers/soc/fujitsu/Makefile new file mode 100644 index 000000000000..945bc1c14ad0 --- /dev/null +++ b/drivers/soc/fujitsu/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_A64FX_DIAG) +=3D a64fx-diag.o diff --git a/drivers/soc/fujitsu/a64fx-diag.c b/drivers/soc/fujitsu/a64fx-d= iag.c new file mode 100644 index 000000000000..c6f895cf8912 --- /dev/null +++ b/drivers/soc/fujitsu/a64fx-diag.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * A64FX diag driver. + */ + +#include +#include +#include +#include +#include +#include + +#define A64FX_DIAG_IRQ 1 +#define BMC_DIAG_INTERRUPT_STATUS_OFFSET (0x0044) +#define BMC_INTERRUPT_STATUS_MASK ((1U) << 31) +#define BMC_DIAG_INTERRUPT_ENABLE_OFFSET (0x0040) +#define BMC_INTERRUPT_ENABLE_MASK ((1U) << 31) + +struct a64fx_diag_priv { + int irq; + void __iomem *mmsc_reg_base; + bool has_nmi; +}; + +static irqreturn_t a64fx_diag_handler(int irq, void *dev_id) +{ + handle_sysrq('c'); + + return IRQ_HANDLED; +} + +static void a64fx_diag_interrupt_clear(struct a64fx_diag_priv *priv) +{ + u32 mmsc; + const void __iomem *diag_status_reg_addr; + + diag_status_reg_addr =3D priv->mmsc_reg_base + BMC_DIAG_INTERRUPT_STATUS_= OFFSET; + mmsc =3D readl(diag_status_reg_addr); + if (mmsc & BMC_INTERRUPT_STATUS_MASK) + writel(BMC_INTERRUPT_STATUS_MASK, (void *)diag_status_reg_addr); +} + +static void a64fx_diag_interrupt_enable(struct a64fx_diag_priv *priv) +{ + u32 mmsc; + const void __iomem *diag_enable_reg_addr; + + diag_enable_reg_addr =3D priv->mmsc_reg_base + BMC_DIAG_INTERRUPT_ENABLE_= OFFSET; + mmsc =3D readl(diag_enable_reg_addr); + if (!(mmsc & BMC_INTERRUPT_ENABLE_MASK)) { + mmsc |=3D BMC_INTERRUPT_STATUS_MASK; + writel(mmsc, (void *)diag_enable_reg_addr); + } +} + +static void a64fx_diag_interrupt_disable(struct a64fx_diag_priv *priv) +{ + u32 mmsc; + const void __iomem *diag_enable_reg_addr; + + diag_enable_reg_addr =3D priv->mmsc_reg_base + BMC_DIAG_INTERRUPT_ENABLE_= OFFSET; + mmsc =3D readl(diag_enable_reg_addr); + if (mmsc & BMC_INTERRUPT_ENABLE_MASK) { + mmsc &=3D ~BMC_INTERRUPT_ENABLE_MASK; + writel(mmsc, (void *)diag_enable_reg_addr); + } +} + +static int a64fx_diag_probe(struct platform_device *pdev) +{ + int ret; + unsigned long irq_flags; + struct device *dev =3D &pdev->dev; + struct a64fx_diag_priv *priv; + + priv =3D devm_kzalloc(dev, sizeof(struct a64fx_diag_priv), GFP_KERNEL); + if (priv =3D=3D NULL) + return -ENOMEM; + + priv->mmsc_reg_base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->mmsc_reg_base)) + return PTR_ERR(priv->mmsc_reg_base); + + priv->irq =3D platform_get_irq(pdev, A64FX_DIAG_IRQ); + if (priv->irq < 0) + return priv->irq; + + platform_set_drvdata(pdev, priv); + + a64fx_diag_interrupt_clear(priv); + a64fx_diag_interrupt_enable(priv); + + irq_flags =3D IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_AUTOEN | + IRQF_NO_THREAD; + ret =3D request_nmi(priv->irq, &a64fx_diag_handler, irq_flags, + "a64fx_diag_nmi", NULL); + if (ret) { + ret =3D request_irq(priv->irq, &a64fx_diag_handler, + irq_flags, "a64fx_diag_irq", NULL); + if (ret) { + dev_err(dev, "cannot register IRQ %d\n", ret); + return ret; + } + enable_irq(priv->irq); + priv->has_nmi =3D false; + dev_info(dev, "registered for IRQ %d\n", priv->irq); + } else { + enable_nmi(priv->irq); + priv->has_nmi =3D true; + dev_info(dev, "registered for NMI %d\n", priv->irq); + } + + return 0; +} + +static int __exit a64fx_diag_remove(struct platform_device *pdev) +{ + struct a64fx_diag_priv *priv =3D platform_get_drvdata(pdev); + + a64fx_diag_interrupt_disable(priv); + a64fx_diag_interrupt_clear(priv); + + if (priv->has_nmi) + free_nmi(priv->irq, NULL); + else + free_irq(priv->irq, NULL); + + return 0; +} + +static const struct acpi_device_id a64fx_diag_acpi_match[] =3D { + { "FUJI2007", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, a64fx_diag_acpi_match); + + +static struct platform_driver a64fx_diag_driver =3D { + .driver =3D { + .name =3D "a64fx_diag_driver", + .acpi_match_table =3D ACPI_PTR(a64fx_diag_acpi_match), + }, + .probe =3D a64fx_diag_probe, + .remove =3D a64fx_diag_remove, +}; + +module_platform_driver(a64fx_diag_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Hitomi Hasegawa "); +MODULE_DESCRIPTION("A64FX diag driver"); --=20 2.27.0