get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.0/patches/2175494/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2175494,
    "url": "http://patchwork.ozlabs.org/api/1.0/patches/2175494/?format=api",
    "project": {
        "id": 28,
        "url": "http://patchwork.ozlabs.org/api/1.0/projects/28/?format=api",
        "name": "Linux PCI development",
        "link_name": "linux-pci",
        "list_id": "linux-pci.vger.kernel.org",
        "list_email": "linux-pci@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null
    },
    "msgid": "<20251218-gicv5-host-acpi-v2-5-eec76cd1d40b@kernel.org>",
    "date": "2025-12-18T10:14:31",
    "name": "[v2,5/7] irqchip/gic-v5: Add ACPI IRS probing",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "f7a8bda8f5fd853dd87df04d32ec40e6ec80ad07",
    "submitter": {
        "id": 84664,
        "url": "http://patchwork.ozlabs.org/api/1.0/people/84664/?format=api",
        "name": "Lorenzo Pieralisi",
        "email": "lpieralisi@kernel.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-pci/patch/20251218-gicv5-host-acpi-v2-5-eec76cd1d40b@kernel.org/mbox/",
    "series": [
        {
            "id": 485814,
            "url": "http://patchwork.ozlabs.org/api/1.0/series/485814/?format=api",
            "date": "2025-12-18T10:14:26",
            "name": "irqchip/gic-v5: Code first ACPI boot support",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/485814/mbox/"
        }
    ],
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2175494/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "\n <linux-pci+bounces-43278-incoming=patchwork.ozlabs.org@vger.kernel.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "linux-pci@vger.kernel.org"
        ],
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=usY576Hj;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-pci+bounces-43278-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=\"usY576Hj\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"
        ],
        "Received": [
            "from sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4dX6BS6HjHz1xty\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 18 Dec 2025 21:20:48 +1100 (AEDT)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 2BDBF30EEB89\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 18 Dec 2025 10:16:36 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 2F93033E377;\n\tThu, 18 Dec 2025 10:15:30 +0000 (UTC)",
            "from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org\n [10.30.226.201])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id F2D5E33E371;\n\tThu, 18 Dec 2025 10:15:29 +0000 (UTC)",
            "by smtp.kernel.org (Postfix) with ESMTPSA id AC401C116D0;\n\tThu, 18 Dec 2025 10:15:24 +0000 (UTC)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1766052930; cv=none;\n b=CYTWExtJ7P9C5pnkIp2z+l/jmsXLOmiuVgmy4HdBTJausXMDiTCiDIbgN712Z4qMS/aV4DGEaaM2v1Zd8gmBmNvQKD20XGYoTEqI1u8Imlzj3yyqUNdnY03JTJxkXKvq8DHkp81L8B8Pp/WgX43IGK0//7snhipDLS7ofgJcS74=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1766052930; c=relaxed/simple;\n\tbh=11REyH6T/zi9pofxE8viB/8eRKLpOXtocQ0cKQzSEV4=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=UfUBkqtZB5sHpTTIs6m7RwfS3KOu0F4UVdVDNRKJ/RkN0A/V/0V7Lcx+DXUbRM4SVKAExICB+aKYXSftZMJrZobWgS9SW34YnCKLRR0q/Dbfp0QG1bYPxLsB6cMmlwKi32cB4R4bHGRCxjNUdUFBLaAQ08iJ3ve2LXP8RMfJKaY=",
        "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=usY576Hj; arc=none smtp.client-ip=10.30.226.201",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1766052929;\n\tbh=11REyH6T/zi9pofxE8viB/8eRKLpOXtocQ0cKQzSEV4=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=usY576HjQPHAk75AVH55Aa9sTD+W+zb5gKRe+tRH8z7P6gW6NyeHxG+hz9YNsoPwq\n\t J0NLswXurq35zu14nXlijle0JqpSWHYgsrpu1ak7mWGmhnuOQiYSJwixTYLXIMcDoL\n\t TAd3834zRrcOi7w/GgEtGPMpYYF8NnPlv6wqN73VhDgEKk47yk3pYRzGrzxKUpYER4\n\t N/tnERwnIvquT43G7osqPOneCvaswbgpMhHXA07O6UFVS9+jfHaCEp4Ge3aHffbys3\n\t CZJeX5gfKqGQqxeTs2HLezpZfYLeNEDCM5OGFSeYc5qy3O+XtPg8HHyMjYf6O8aYjh\n\t yrsM0riC5CRWg==",
        "From": "Lorenzo Pieralisi <lpieralisi@kernel.org>",
        "Date": "Thu, 18 Dec 2025 11:14:31 +0100",
        "Subject": "[PATCH v2 5/7] irqchip/gic-v5: Add ACPI IRS probing",
        "Precedence": "bulk",
        "X-Mailing-List": "linux-pci@vger.kernel.org",
        "List-Id": "<linux-pci.vger.kernel.org>",
        "List-Subscribe": "<mailto:linux-pci+subscribe@vger.kernel.org>",
        "List-Unsubscribe": "<mailto:linux-pci+unsubscribe@vger.kernel.org>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "<20251218-gicv5-host-acpi-v2-5-eec76cd1d40b@kernel.org>",
        "References": "<20251218-gicv5-host-acpi-v2-0-eec76cd1d40b@kernel.org>",
        "In-Reply-To": "<20251218-gicv5-host-acpi-v2-0-eec76cd1d40b@kernel.org>",
        "To": "\"Rafael J. Wysocki\" <rafael@kernel.org>, Len Brown <lenb@kernel.org>,\n Robert Moore <robert.moore@intel.com>, Thomas Gleixner <tglx@linutronix.de>,\n Hanjun Guo <guohanjun@huawei.com>, Sudeep Holla <sudeep.holla@arm.com>,\n Marc Zyngier <maz@kernel.org>, Bjorn Helgaas <bhelgaas@google.com>",
        "Cc": "linux-acpi@vger.kernel.org, acpica-devel@lists.linux.dev,\n linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org,\n linux-pci@vger.kernel.org, Lorenzo Pieralisi <lpieralisi@kernel.org>",
        "X-Mailer": "b4 0.14.3"
    },
    "content": "On ARM64 ACPI systems GICv5 IRSes are described in MADT sub-entries.\n\nAdd the required plumbing to parse MADT IRS firmware table entries and\nprobe the IRS components in ACPI.\n\nRefactor the OF based probe so that common code paths can be reused for\nACPI as well in the process.\n\nAugment the irqdomain_ops.translate() for PPI and SPI IRQs in order to\nprovide support for their ACPI based firmware translation.\n\nImplement an irqchip ACPI based callback to initialize the global GSI\ndomain upon an MADT IRS detection.\n\nThe IRQCHIP_ACPI_DECLARE() entry in the top level GICv5 driver is only used\nto trigger the IRS probing (ie the global GSI domain is initialized once on\nthe first call on multi-IRS systems); IRS probing takes place by calling\nacpi_table_parse_madt() in the IRS sub-driver, that probes all IRSes\nin sequence.\n\nAdd a new ACPI interrupt model so that it can be detected at runtime and\ndistinguished from previous GIC architecture models.\n\nSigned-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>\nCc: Thomas Gleixner <tglx@linutronix.de>\nCc: \"Rafael J. Wysocki\" <rafael@kernel.org>\nCc: Marc Zyngier <maz@kernel.org>\n---\n drivers/acpi/bus.c                 |   3 +\n drivers/irqchip/irq-gic-v5-irs.c   | 239 +++++++++++++++++++++++++++++--------\n drivers/irqchip/irq-gic-v5.c       | 134 ++++++++++++++++++---\n include/linux/acpi.h               |   1 +\n include/linux/irqchip/arm-gic-v5.h |   1 +\n 5 files changed, 308 insertions(+), 70 deletions(-)",
    "diff": "diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c\nindex a984ccd4a2a0..e4f4059c4f1d 100644\n--- a/drivers/acpi/bus.c\n+++ b/drivers/acpi/bus.c\n@@ -1197,6 +1197,9 @@ static int __init acpi_bus_init_irq(void)\n \tcase ACPI_IRQ_MODEL_GIC:\n \t\tmessage = \"GIC\";\n \t\tbreak;\n+\tcase ACPI_IRQ_MODEL_GIC_V5:\n+\t\tmessage = \"GICv5\";\n+\t\tbreak;\n \tcase ACPI_IRQ_MODEL_PLATFORM:\n \t\tmessage = \"platform specific model\";\n \t\tbreak;\ndiff --git a/drivers/irqchip/irq-gic-v5-irs.c b/drivers/irqchip/irq-gic-v5-irs.c\nindex ce2732d649a3..07c3df5692af 100644\n--- a/drivers/irqchip/irq-gic-v5-irs.c\n+++ b/drivers/irqchip/irq-gic-v5-irs.c\n@@ -5,6 +5,7 @@\n \n #define pr_fmt(fmt)\t\"GICv5 IRS: \" fmt\n \n+#include <linux/acpi.h>\n #include <linux/kmemleak.h>\n #include <linux/log2.h>\n #include <linux/of.h>\n@@ -545,15 +546,15 @@ int gicv5_irs_register_cpu(int cpuid)\n \n static void __init gicv5_irs_init_bases(struct gicv5_irs_chip_data *irs_data,\n \t\t\t\t\tvoid __iomem *irs_base,\n-\t\t\t\t\tstruct fwnode_handle *handle)\n+\t\t\t\t\tstruct fwnode_handle *handle,\n+\t\t\t\t\tbool noncoherent)\n {\n-\tstruct device_node *np = to_of_node(handle);\n \tu32 cr0, cr1;\n \n \tirs_data->fwnode = handle;\n \tirs_data->irs_base = irs_base;\n \n-\tif (of_property_read_bool(np, \"dma-noncoherent\")) {\n+\tif (noncoherent) {\n \t\t/*\n \t\t * A non-coherent IRS implies that some cache levels cannot be\n \t\t * used coherently by the cores and GIC. Our only option is to mark\n@@ -678,49 +679,13 @@ static void irs_setup_pri_bits(u32 idr1)\n \t}\n }\n \n-static int __init gicv5_irs_init(struct device_node *node)\n+static int __init gicv5_irs_init(struct gicv5_irs_chip_data *irs_data)\n {\n-\tstruct gicv5_irs_chip_data *irs_data;\n-\tvoid __iomem *irs_base;\n-\tu32 idr, spi_count;\n-\tu8 iaffid_bits;\n-\tint ret;\n+\tu32 spi_count, idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR2);\n \n-\tirs_data = kzalloc(sizeof(*irs_data), GFP_KERNEL);\n-\tif (!irs_data)\n-\t\treturn -ENOMEM;\n-\n-\traw_spin_lock_init(&irs_data->spi_config_lock);\n-\n-\tret = of_property_match_string(node, \"reg-names\", \"ns-config\");\n-\tif (ret < 0) {\n-\t\tpr_err(\"%pOF: ns-config reg-name not present\\n\", node);\n-\t\tgoto out_err;\n-\t}\n-\n-\tirs_base = of_io_request_and_map(node, ret, of_node_full_name(node));\n-\tif (IS_ERR(irs_base)) {\n-\t\tpr_err(\"%pOF: unable to map GICv5 IRS registers\\n\", node);\n-\t\tret = PTR_ERR(irs_base);\n-\t\tgoto out_err;\n-\t}\n-\n-\tgicv5_irs_init_bases(irs_data, irs_base, &node->fwnode);\n-\n-\tidr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR1);\n-\tiaffid_bits = FIELD_GET(GICV5_IRS_IDR1_IAFFID_BITS, idr) + 1;\n-\n-\tret = gicv5_irs_of_init_affinity(node, irs_data, iaffid_bits);\n-\tif (ret) {\n-\t\tpr_err(\"Failed to parse CPU IAFFIDs from the device tree!\\n\");\n-\t\tgoto out_iomem;\n-\t}\n-\n-\tidr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR2);\n \tif (WARN(!FIELD_GET(GICV5_IRS_IDR2_LPI, idr),\n \t\t \"LPI support not available - no IPIs, can't proceed\\n\")) {\n-\t\tret = -ENODEV;\n-\t\tgoto out_iomem;\n+\t\treturn -ENODEV;\n \t}\n \n \tidr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR7);\n@@ -729,14 +694,6 @@ static int __init gicv5_irs_init(struct device_node *node)\n \tidr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR6);\n \tirs_data->spi_range = FIELD_GET(GICV5_IRS_IDR6_SPI_IRS_RANGE, idr);\n \n-\tif (irs_data->spi_range) {\n-\t\tpr_info(\"%s detected SPI range [%u-%u]\\n\",\n-\t\t\t\t\t\tof_node_full_name(node),\n-\t\t\t\t\t\tirs_data->spi_min,\n-\t\t\t\t\t\tirs_data->spi_min +\n-\t\t\t\t\t\tirs_data->spi_range - 1);\n-\t}\n-\n \t/*\n \t * Do the global setting only on the first IRS.\n \t * Global properties (iaffid_bits, global spi count) are guaranteed to\n@@ -760,6 +717,60 @@ static int __init gicv5_irs_init(struct device_node *node)\n \tlist_add_tail(&irs_data->entry, &irs_nodes);\n \n \treturn 0;\n+}\n+\n+static int __init gicv5_irs_of_init(struct device_node *node)\n+{\n+\tstruct gicv5_irs_chip_data *irs_data;\n+\tvoid __iomem *irs_base;\n+\tu8 iaffid_bits;\n+\tu32 idr;\n+\tint ret;\n+\n+\tirs_data = kzalloc(sizeof(*irs_data), GFP_KERNEL);\n+\tif (!irs_data)\n+\t\treturn -ENOMEM;\n+\n+\traw_spin_lock_init(&irs_data->spi_config_lock);\n+\n+\tret = of_property_match_string(node, \"reg-names\", \"ns-config\");\n+\tif (ret < 0) {\n+\t\tpr_err(\"%pOF: ns-config reg-name not present\\n\", node);\n+\t\tgoto out_err;\n+\t}\n+\n+\tirs_base = of_io_request_and_map(node, ret, of_node_full_name(node));\n+\tif (IS_ERR(irs_base)) {\n+\t\tpr_err(\"%pOF: unable to map GICv5 IRS registers\\n\", node);\n+\t\tret = PTR_ERR(irs_base);\n+\t\tgoto out_err;\n+\t}\n+\n+\tgicv5_irs_init_bases(irs_data, irs_base, &node->fwnode,\n+\t\t\t     of_property_read_bool(node, \"dma-noncoherent\"));\n+\n+\tidr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR1);\n+\tiaffid_bits = FIELD_GET(GICV5_IRS_IDR1_IAFFID_BITS, idr) + 1;\n+\n+\tret = gicv5_irs_of_init_affinity(node, irs_data, iaffid_bits);\n+\tif (ret) {\n+\t\tpr_err(\"Failed to parse CPU IAFFIDs from the device tree!\\n\");\n+\t\tgoto out_iomem;\n+\t}\n+\n+\tret = gicv5_irs_init(irs_data);\n+\tif (ret)\n+\t\tgoto out_iomem;\n+\n+\tif (irs_data->spi_range) {\n+\t\tpr_info(\"%s detected SPI range [%u-%u]\\n\",\n+\t\t\t\t\t\tof_node_full_name(node),\n+\t\t\t\t\t\tirs_data->spi_min,\n+\t\t\t\t\t\tirs_data->spi_min +\n+\t\t\t\t\t\tirs_data->spi_range - 1);\n+\t}\n+\n+\treturn ret;\n \n out_iomem:\n \tiounmap(irs_base);\n@@ -818,10 +829,136 @@ int __init gicv5_irs_of_probe(struct device_node *parent)\n \t\tif (!of_device_is_compatible(np, \"arm,gic-v5-irs\"))\n \t\t\tcontinue;\n \n-\t\tret = gicv5_irs_init(np);\n+\t\tret = gicv5_irs_of_init(np);\n \t\tif (ret)\n \t\t\tpr_err(\"Failed to init IRS %s\\n\", np->full_name);\n \t}\n \n \treturn list_empty(&irs_nodes) ? -ENODEV : 0;\n }\n+\n+#ifdef CONFIG_ACPI\n+\n+#define ACPI_GICV5_IRS_MEM_SIZE (SZ_64K)\n+static struct gicv5_irs_chip_data *current_irs_data __initdata;\n+static int current_irsid __initdata = -1;\n+static u8 current_iaffid_bits __initdata;\n+\n+static int __init gic_acpi_parse_iaffid(union acpi_subtable_headers *header,\n+\t\t\t\t\tconst unsigned long end)\n+{\n+\tstruct acpi_madt_generic_interrupt *gicc = (struct acpi_madt_generic_interrupt *)header;\n+\tint cpu;\n+\n+\tif (!(gicc->flags & (ACPI_MADT_ENABLED | ACPI_MADT_GICC_ONLINE_CAPABLE)))\n+\t\treturn 0;\n+\n+\tif (gicc->irs_id == current_irsid) {\n+\t\tcpu = get_logical_index(gicc->arm_mpidr);\n+\n+\t\tif (gicc->iaffid & ~GENMASK(current_iaffid_bits - 1, 0)) {\n+\t\t\tpr_warn(\"CPU %d iaffid 0x%x exceeds IRS iaffid bits\\n\", cpu, gicc->iaffid);\n+\t\t\treturn 0;\n+\t\t}\n+\n+\t\t// Bind the IAFFID and the CPU\n+\t\tper_cpu(cpu_iaffid, cpu).iaffid = gicc->iaffid;\n+\t\tper_cpu(cpu_iaffid, cpu).valid = true;\n+\t\tpr_debug(\"Processed IAFFID %u for CPU%d\", per_cpu(cpu_iaffid, cpu).iaffid, cpu);\n+\n+\t\t// We also know that the CPU is connected to this IRS\n+\t\tper_cpu(per_cpu_irs_data, cpu) = current_irs_data;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int __init gicv5_irs_acpi_init_affinity(u32 irsid, struct gicv5_irs_chip_data *irs_data)\n+{\n+\tu32 idr;\n+\n+\tcurrent_irsid = irsid;\n+\tcurrent_irs_data = irs_data;\n+\n+\tidr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR1);\n+\tcurrent_iaffid_bits = FIELD_GET(GICV5_IRS_IDR1_IAFFID_BITS, idr) + 1;\n+\n+\tacpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, gic_acpi_parse_iaffid, 0);\n+\n+\treturn 0;\n+}\n+\n+static struct resource * __init gic_request_region(resource_size_t base, resource_size_t size,\n+\t\t\t\t\t\t   const char *name)\n+{\n+\tstruct resource *r = request_mem_region(base, size, name);\n+\n+\tif (!r)\n+\t\tpr_warn_once(FW_BUG \"%s region %pa has overlapping address\\n\", name, &base);\n+\n+\treturn r;\n+}\n+\n+static int __init gic_acpi_parse_madt_irs(union acpi_subtable_headers *header,\n+\t\t\t\t\t  const unsigned long end)\n+{\n+\tstruct acpi_madt_gicv5_irs *irs = (struct acpi_madt_gicv5_irs *)header;\n+\tstruct gicv5_irs_chip_data *irs_data;\n+\tvoid __iomem *irs_base;\n+\tstruct resource *r;\n+\tint ret;\n+\n+\t// Per-IRS data structure\n+\tirs_data = kzalloc(sizeof(*irs_data), GFP_KERNEL);\n+\tif (!irs_data)\n+\t\treturn -ENOMEM;\n+\n+\t// This spinlock is used for SPI config changes\n+\traw_spin_lock_init(&irs_data->spi_config_lock);\n+\n+\tirs_base = ioremap(irs->config_base_address, ACPI_GICV5_IRS_MEM_SIZE);\n+\tif (!irs_base) {\n+\t\tpr_err(\"Unable to map GIC IRS registers\\n\");\n+\t\tret = -ENOMEM;\n+\t\tgoto out_free;\n+\t}\n+\n+\tr = gic_request_region(irs->config_base_address, ACPI_GICV5_IRS_MEM_SIZE, \"GICv5 IRS\");\n+\tif (!r) {\n+\t\tret = -EBUSY;\n+\t\tgoto out_map;\n+\t}\n+\n+\tgicv5_irs_init_bases(irs_data, irs_base, NULL, irs->flags & ACPI_MADT_IRS_NON_COHERENT);\n+\n+\tgicv5_irs_acpi_init_affinity(irs->irs_id, irs_data);\n+\n+\tret = gicv5_irs_init(irs_data);\n+\tif (ret)\n+\t\tgoto out_release;\n+\n+\tif (irs_data->spi_range) {\n+\t\tpr_info(\"%s @%llx detected SPI range [%u-%u]\\n\", \"IRS\", irs->config_base_address,\n+\t\t\t\t\t\t\t\t\tirs_data->spi_min,\n+\t\t\t\t\t\t\t\t\tirs_data->spi_min +\n+\t\t\t\t\t\t\t\t\tirs_data->spi_range - 1);\n+\t}\n+\n+\treturn 0;\n+\n+out_release:\n+\trelease_mem_region(r->start, resource_size(r));\n+out_map:\n+\tiounmap(irs_base);\n+out_free:\n+\tkfree(irs_data);\n+\treturn ret;\n+}\n+\n+int __init gicv5_irs_acpi_probe(void)\n+{\n+\tacpi_table_parse_madt(ACPI_MADT_TYPE_GICV5_IRS, gic_acpi_parse_madt_irs, 0);\n+\n+\treturn list_empty(&irs_nodes) ? -ENODEV : 0;\n+}\n+#endif\ndiff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c\nindex 41ef286c4d78..23fd551c4347 100644\n--- a/drivers/irqchip/irq-gic-v5.c\n+++ b/drivers/irqchip/irq-gic-v5.c\n@@ -579,16 +579,36 @@ static __always_inline int gicv5_irq_domain_translate(struct irq_domain *d,\n \t\t\t\t\t\t      unsigned int *type,\n \t\t\t\t\t\t      const u8 hwirq_type)\n {\n-\tif (!is_of_node(fwspec->fwnode))\n-\t\treturn -EINVAL;\n+\tunsigned int hwirq_trigger;\n+\tu8 fwspec_irq_type;\n \n-\tif (fwspec->param_count < 3)\n-\t\treturn -EINVAL;\n+\tif (is_of_node(fwspec->fwnode)) {\n \n-\tif (fwspec->param[0] != hwirq_type)\n-\t\treturn -EINVAL;\n+\t\tif (fwspec->param_count < 3)\n+\t\t\treturn -EINVAL;\n \n-\t*hwirq = fwspec->param[1];\n+\t\tfwspec_irq_type = fwspec->param[0];\n+\n+\t\tif (fwspec->param[0] != hwirq_type)\n+\t\t\treturn -EINVAL;\n+\n+\t\t*hwirq = fwspec->param[1];\n+\t\thwirq_trigger = fwspec->param[2];\n+\t}\n+\n+\tif (is_fwnode_irqchip(fwspec->fwnode)) {\n+\n+\t\tif (fwspec->param_count != 2)\n+\t\t\treturn -EINVAL;\n+\n+\t\tfwspec_irq_type = FIELD_GET(GICV5_HWIRQ_TYPE, fwspec->param[0]);\n+\n+\t\tif (fwspec_irq_type != hwirq_type)\n+\t\t\treturn -EINVAL;\n+\n+\t\t*hwirq = FIELD_GET(GICV5_HWIRQ_ID, fwspec->param[0]);\n+\t\thwirq_trigger = fwspec->param[1];\n+\t}\n \n \tswitch (hwirq_type) {\n \tcase GICV5_HWIRQ_TYPE_PPI:\n@@ -600,7 +620,7 @@ static __always_inline int gicv5_irq_domain_translate(struct irq_domain *d,\n \t\t\t\t\t\t\t IRQ_TYPE_EDGE_RISING;\n \t\tbreak;\n \tcase GICV5_HWIRQ_TYPE_SPI:\n-\t\t*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;\n+\t\t*type = hwirq_trigger & IRQ_TYPE_SENSE_MASK;\n \t\tbreak;\n \tdefault:\n \t\tBUILD_BUG_ON(1);\n@@ -660,10 +680,18 @@ static void gicv5_irq_domain_free(struct irq_domain *domain, unsigned int virq,\n static int gicv5_irq_ppi_domain_select(struct irq_domain *d, struct irq_fwspec *fwspec,\n \t\t\t\t       enum irq_domain_bus_token bus_token)\n {\n+\tu32 hwirq_type;\n+\n \tif (fwspec->fwnode != d->fwnode)\n \t\treturn 0;\n \n-\tif (fwspec->param[0] != GICV5_HWIRQ_TYPE_PPI)\n+\tif (is_of_node(fwspec->fwnode))\n+\t\thwirq_type = fwspec->param[0];\n+\n+\tif (is_fwnode_irqchip(fwspec->fwnode))\n+\t\thwirq_type = FIELD_GET(GICV5_HWIRQ_TYPE, fwspec->param[0]);\n+\n+\tif (hwirq_type != GICV5_HWIRQ_TYPE_PPI)\n \t\treturn 0;\n \n \treturn (d == gicv5_global_data.ppi_domain);\n@@ -718,10 +746,18 @@ static int gicv5_irq_spi_domain_alloc(struct irq_domain *domain, unsigned int vi\n static int gicv5_irq_spi_domain_select(struct irq_domain *d, struct irq_fwspec *fwspec,\n \t\t\t\t       enum irq_domain_bus_token bus_token)\n {\n+\tu32 hwirq_type;\n+\n \tif (fwspec->fwnode != d->fwnode)\n \t\treturn 0;\n \n-\tif (fwspec->param[0] != GICV5_HWIRQ_TYPE_SPI)\n+\tif (is_of_node(fwspec->fwnode))\n+\t\thwirq_type = fwspec->param[0];\n+\n+\tif (is_fwnode_irqchip(fwspec->fwnode))\n+\t\thwirq_type = FIELD_GET(GICV5_HWIRQ_TYPE, fwspec->param[0]);\n+\n+\tif (hwirq_type != GICV5_HWIRQ_TYPE_SPI)\n \t\treturn 0;\n \n \treturn (d == gicv5_global_data.spi_domain);\n@@ -1082,16 +1118,12 @@ static inline void __init gic_of_setup_kvm_info(struct device_node *node)\n }\n #endif // CONFIG_KVM\n \n-static int __init gicv5_of_init(struct device_node *node, struct device_node *parent)\n+static int __init gicv5_init_common(struct fwnode_handle *parent_domain)\n {\n-\tint ret = gicv5_irs_of_probe(node);\n+\tint ret = gicv5_init_domains(parent_domain);\n \tif (ret)\n \t\treturn ret;\n \n-\tret = gicv5_init_domains(of_fwnode_handle(node));\n-\tif (ret)\n-\t\tgoto out_irs;\n-\n \tgicv5_set_cpuif_pribits();\n \tgicv5_set_cpuif_idbits();\n \n@@ -1113,18 +1145,82 @@ static int __init gicv5_of_init(struct device_node *node, struct device_node *pa\n \tgicv5_smp_init();\n \n \tgicv5_irs_its_probe();\n-\n-\tgic_of_setup_kvm_info(node);\n-\n \treturn 0;\n \n out_int:\n \tgicv5_cpu_disable_interrupts();\n out_dom:\n \tgicv5_free_domains();\n+\treturn ret;\n+}\n+\n+static int __init gicv5_of_init(struct device_node *node, struct device_node *parent)\n+{\n+\tint ret = gicv5_irs_of_probe(node);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = gicv5_init_common(of_fwnode_handle(node));\n+\tif (ret)\n+\t\tgoto out_irs;\n+\n+\tgic_of_setup_kvm_info(node);\n+\n+\treturn 0;\n out_irs:\n \tgicv5_irs_remove();\n \n \treturn ret;\n }\n IRQCHIP_DECLARE(gic_v5, \"arm,gic-v5\", gicv5_of_init);\n+\n+#ifdef CONFIG_ACPI\n+static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,\n+\t\t\t\t\t   struct acpi_probe_entry *ape)\n+{\n+\tstruct acpi_madt_gicv5_irs *irs = (struct acpi_madt_gicv5_irs *)header;\n+\n+\treturn (irs->version == ape->driver_data);\n+}\n+\n+static struct fwnode_handle *gsi_domain_handle;\n+\n+static struct fwnode_handle *gic_v5_get_gsi_domain_id(u32 gsi)\n+{\n+\treturn gsi_domain_handle;\n+}\n+\n+static int __init gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end)\n+{\n+\tstruct acpi_madt_gicv5_irs *irs = (struct acpi_madt_gicv5_irs *)header;\n+\tint ret;\n+\n+\tif (gsi_domain_handle)\n+\t\treturn 0;\n+\n+\tgsi_domain_handle = irq_domain_alloc_fwnode(&irs->config_base_address);\n+\tif (!gsi_domain_handle)\n+\t\treturn -ENOMEM;\n+\n+\tret = gicv5_irs_acpi_probe();\n+\tif (ret)\n+\t\tgoto out_fwnode;\n+\n+\tret = gicv5_init_common(gsi_domain_handle);\n+\tif (ret)\n+\t\tgoto out_irs;\n+\n+\tacpi_set_irq_model(ACPI_IRQ_MODEL_GIC_V5, gic_v5_get_gsi_domain_id);\n+\n+\treturn 0;\n+\n+out_irs:\n+\tgicv5_irs_remove();\n+out_fwnode:\n+\tirq_domain_free_fwnode(gsi_domain_handle);\n+\treturn ret;\n+}\n+IRQCHIP_ACPI_DECLARE(gic_v5, ACPI_MADT_TYPE_GICV5_IRS,\n+\t\t     acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V5,\n+\t\t     gic_acpi_init);\n+#endif\ndiff --git a/include/linux/acpi.h b/include/linux/acpi.h\nindex fbf0c3a65f59..3a412dcebc29 100644\n--- a/include/linux/acpi.h\n+++ b/include/linux/acpi.h\n@@ -107,6 +107,7 @@ enum acpi_irq_model_id {\n \tACPI_IRQ_MODEL_IOSAPIC,\n \tACPI_IRQ_MODEL_PLATFORM,\n \tACPI_IRQ_MODEL_GIC,\n+\tACPI_IRQ_MODEL_GIC_V5,\n \tACPI_IRQ_MODEL_LPIC,\n \tACPI_IRQ_MODEL_RINTC,\n \tACPI_IRQ_MODEL_COUNT\ndiff --git a/include/linux/irqchip/arm-gic-v5.h b/include/linux/irqchip/arm-gic-v5.h\nindex 68ddcdb1cec5..ff5b1a4931d7 100644\n--- a/include/linux/irqchip/arm-gic-v5.h\n+++ b/include/linux/irqchip/arm-gic-v5.h\n@@ -344,6 +344,7 @@ void __init gicv5_init_lpi_domain(void);\n void __init gicv5_free_lpi_domain(void);\n \n int gicv5_irs_of_probe(struct device_node *parent);\n+int gicv5_irs_acpi_probe(void);\n void gicv5_irs_remove(void);\n int gicv5_irs_enable(void);\n void gicv5_irs_its_probe(void);\n",
    "prefixes": [
        "v2",
        "5/7"
    ]
}