get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2175496,
    "url": "http://patchwork.ozlabs.org/api/1.0/patches/2175496/?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-6-eec76cd1d40b@kernel.org>",
    "date": "2025-12-18T10:14:32",
    "name": "[v2,6/7] irqchip/gic-v5: Add ACPI ITS probing",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "e3015fda7cad9d2557bcfae6bb16ddbb39d8a008",
    "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-6-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/2175496/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "\n <linux-pci+bounces-43279-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=Csmto2VZ;\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-43279-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=\"Csmto2VZ\"",
            "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 4dX6C84WBQz1xty\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 18 Dec 2025 21:21:24 +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 CD26630F2BE2\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 18 Dec 2025 10:16:41 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id B991133EB17;\n\tThu, 18 Dec 2025 10:15:34 +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 8973433EB0D;\n\tThu, 18 Dec 2025 10:15:34 +0000 (UTC)",
            "by smtp.kernel.org (Postfix) with ESMTPSA id 25835C116C6;\n\tThu, 18 Dec 2025 10:15:29 +0000 (UTC)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1766052934; cv=none;\n b=CEnY4QR+SCMDXJMWhw+kCmGgDOh6oXaouON/oITWESwFNOdzm6UQ4b7QRpSSYWpBFQHnIgKpJOCX9jBSL90Spryx5YQBgXlOdcYz7N2loveWkp0AN7YOgbu4fmjK0ha4UFfa5IpDdU9ba14Rne/YzO0q3TnP88P+TMp5GbMrERY=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1766052934; c=relaxed/simple;\n\tbh=qddCaPpoKzIS+gMhDfBW/nIlBvoNN/1wgvBirpUnYgs=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=XMYDXu6/l3aeZRgjbqNvY9Tc8jNGoU+AH1+aD6ra0jxQrx7HPpr5m8OSLaPSv9YSbMbOJ9ZZ5gxGK8tlzJ2vTYJ5XW8SkJW3JsBjbME+IO0J+ttBZvMilZZwQHpBtJ6zqgNvET5a54tc3cHxlXV/wSK/zHJo78JfeKnNRtvEB2o=",
        "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=Csmto2VZ; 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=1766052934;\n\tbh=qddCaPpoKzIS+gMhDfBW/nIlBvoNN/1wgvBirpUnYgs=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=Csmto2VZGOBapFbUWNZZqQ9VyHhcxrh9870K5MNaYGpevTKfJA0uII1EUGUiF/153\n\t hbSfNJNpIHWDuNNp9FFeUSYxaViBPikXofqrIFbJh0ff9k95te/zw5uUcw50eOmb8I\n\t z0uA1noZDUofKPZNueqkwWBucN0SOmHaCSM8o0V0yV5snROn0gkPZZtHPIkq1q9mnN\n\t afOdFHc8ImsYtTof5TPrDKLH2TdLHl1LFaV3lebDUKsJAG27JB8KlVOtdcLr2SnmND\n\t oV8Q2TXxxef0396CHbEG5aPOyxkFAXvbybOXumcJvTgpcX2p7bWJE3cl5ulGRtthkj\n\t YMDPolycK8fgA==",
        "From": "Lorenzo Pieralisi <lpieralisi@kernel.org>",
        "Date": "Thu, 18 Dec 2025 11:14:32 +0100",
        "Subject": "[PATCH v2 6/7] irqchip/gic-v5: Add ACPI ITS 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-6-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 ACPI ARM64 systems the GICv5 ITS configuration and translate frames\nare described in the MADT table.\n\nRefactor the current GICv5 ITS driver code to share common functions\nbetween ACPI and OF and implement ACPI probing in the GICv5 ITS driver.\n\nAdd iort_msi_xlate() to map a device ID and retrieve an MSI controller\nfwnode node for ACPI systems and update pci_msi_map_rid_ctlr_node() to\nuse it in its ACPI code path.\n\nAdd the required functions to IORT code for deviceID retrieval and IRQ\ndomain registration and look-up so that the GICv5 ITS driver in an\nACPI based system can be successfully probed.\n\nSigned-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>\nCc: Thomas Gleixner <tglx@linutronix.de>\nCc: Hanjun Guo <guohanjun@huawei.com>\nCc: Sudeep Holla <sudeep.holla@arm.com>\nCc: Marc Zyngier <maz@kernel.org>\n---\n drivers/acpi/arm64/iort.c                |  95 +++++++++++++++++-----\n drivers/irqchip/irq-gic-its-msi-parent.c |  39 ++++-----\n drivers/irqchip/irq-gic-v5-irs.c         |   7 +-\n drivers/irqchip/irq-gic-v5-its.c         | 132 ++++++++++++++++++++++++++++++-\n drivers/pci/msi/irqdomain.c              |   2 +\n include/linux/acpi_iort.h                |  10 ++-\n include/linux/irqchip/arm-gic-v5.h       |   1 +\n 7 files changed, 241 insertions(+), 45 deletions(-)",
    "diff": "diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c\nindex 65f0f56ad753..17dbe66da804 100644\n--- a/drivers/acpi/arm64/iort.c\n+++ b/drivers/acpi/arm64/iort.c\n@@ -595,45 +595,45 @@ u32 iort_msi_map_id(struct device *dev, u32 input_id)\n }\n \n /**\n- * iort_pmsi_get_dev_id() - Get the device id for a device\n+ * iort_msi_xlate() - Map a MSI input ID for a device\n  * @dev: The device for which the mapping is to be done.\n- * @dev_id: The device ID found.\n+ * @input_id: The device input ID.\n+ * @fwnode: Pointer to store the fwnode.\n  *\n- * Returns: 0 for successful find a dev id, -ENODEV on error\n+ * Returns: mapped MSI ID on success, input ID otherwise\n+ *\t    On success, the fwnode pointer is initialized to the MSI\n+ *\t    controller fwnode handle.\n  */\n-int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)\n+u32 iort_msi_xlate(struct device *dev, u32 input_id, struct fwnode_handle **fwnode)\n {\n-\tint i, index;\n+\tstruct acpi_iort_its_group *its;\n \tstruct acpi_iort_node *node;\n+\tu32 dev_id;\n \n \tnode = iort_find_dev_node(dev);\n \tif (!node)\n-\t\treturn -ENODEV;\n+\t\treturn input_id;\n \n-\tindex = iort_get_id_mapping_index(node);\n-\t/* if there is a valid index, go get the dev_id directly */\n-\tif (index >= 0) {\n-\t\tif (iort_node_get_id(node, dev_id, index))\n-\t\t\treturn 0;\n-\t} else {\n-\t\tfor (i = 0; i < node->mapping_count; i++) {\n-\t\t\tif (iort_node_map_platform_id(node, dev_id,\n-\t\t\t\t\t\t      IORT_MSI_TYPE, i))\n-\t\t\t\treturn 0;\n-\t\t}\n-\t}\n+\tnode = iort_node_map_id(node, input_id, &dev_id, IORT_MSI_TYPE);\n+\tif (!node)\n+\t\treturn input_id;\n \n-\treturn -ENODEV;\n+\t/* Move to ITS specific data */\n+\tits = (struct acpi_iort_its_group *)node->node_data;\n+\n+\t*fwnode = iort_find_domain_token(its->identifiers[0]);\n+\n+\treturn dev_id;\n }\n \n-static int __maybe_unused iort_find_its_base(u32 its_id, phys_addr_t *base)\n+int iort_its_translate_pa(struct fwnode_handle *node, phys_addr_t *base)\n {\n \tstruct iort_its_msi_chip *its_msi_chip;\n \tint ret = -ENODEV;\n \n \tspin_lock(&iort_msi_chip_lock);\n \tlist_for_each_entry(its_msi_chip, &iort_msi_chip_list, list) {\n-\t\tif (its_msi_chip->translation_id == its_id) {\n+\t\tif (its_msi_chip->fw_node == node) {\n \t\t\t*base = its_msi_chip->base_addr;\n \t\t\tret = 0;\n \t\t\tbreak;\n@@ -644,6 +644,59 @@ static int __maybe_unused iort_find_its_base(u32 its_id, phys_addr_t *base)\n \treturn ret;\n }\n \n+static int __maybe_unused iort_find_its_base(u32 its_id, phys_addr_t *base)\n+{\n+\tstruct fwnode_handle *fwnode = iort_find_domain_token(its_id);\n+\n+\tif (!fwnode)\n+\t\treturn -ENODEV;\n+\n+\treturn iort_its_translate_pa(fwnode, base);\n+}\n+\n+/**\n+ * iort_pmsi_get_msi_info() - Get the device id and translate frame PA for a device\n+ * @dev: The device for which the mapping is to be done.\n+ * @dev_id: The device ID found.\n+ * @pa: optional pointer to store translate frame address.\n+ *\n+ * Returns: 0 for successful devid and pa retrieval, -ENODEV on error\n+ */\n+int iort_pmsi_get_msi_info(struct device *dev, u32 *dev_id, phys_addr_t *pa)\n+{\n+\tstruct acpi_iort_node *node, *parent = NULL;\n+\tstruct acpi_iort_its_group *its;\n+\tint i, index;\n+\n+\tnode = iort_find_dev_node(dev);\n+\tif (!node)\n+\t\treturn -ENODEV;\n+\n+\tindex = iort_get_id_mapping_index(node);\n+\t/* if there is a valid index, go get the dev_id directly */\n+\tif (index >= 0) {\n+\t\tparent = iort_node_get_id(node, dev_id, index);\n+\t} else {\n+\t\tfor (i = 0; i < node->mapping_count; i++) {\n+\t\t\tparent = iort_node_map_platform_id(node, dev_id,\n+\t\t\t\t\t\t      IORT_MSI_TYPE, i);\n+\t\t\tif (parent)\n+\t\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (parent && pa) {\n+\t\tint ret;\n+\n+\t\tits = (struct acpi_iort_its_group *)node->node_data;\n+\t\tret = iort_find_its_base(its->identifiers[0], pa);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\treturn parent ? 0 : -ENODEV;\n+}\n+\n /**\n  * iort_dev_find_its_id() - Find the ITS identifier for a device\n  * @dev: The device.\ndiff --git a/drivers/irqchip/irq-gic-its-msi-parent.c b/drivers/irqchip/irq-gic-its-msi-parent.c\nindex 4d1ad1ee005d..a832cdb2e697 100644\n--- a/drivers/irqchip/irq-gic-its-msi-parent.c\n+++ b/drivers/irqchip/irq-gic-its-msi-parent.c\n@@ -19,18 +19,24 @@\n \t\t\t\t MSI_FLAG_PCI_MSIX      |\t\\\n \t\t\t\t MSI_FLAG_MULTI_PCI_MSI)\n \n-static int its_translate_frame_address(struct device_node *msi_node, phys_addr_t *pa)\n+static int its_translate_frame_address(struct fwnode_handle *msi_node, phys_addr_t *pa)\n {\n \tstruct resource res;\n \tint ret;\n \n-\tret = of_property_match_string(msi_node, \"reg-names\", \"ns-translate\");\n-\tif (ret < 0)\n-\t\treturn ret;\n+\tif (is_of_node(msi_node)) {\n+\t\tstruct device_node *msi_np = to_of_node(msi_node);\n \n-\tret = of_address_to_resource(msi_node, ret, &res);\n-\tif (ret)\n-\t\treturn ret;\n+\t\tret = of_property_match_string(msi_np, \"reg-names\", \"ns-translate\");\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n+\n+\t\tret = of_address_to_resource(msi_np, ret, &res);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t} else {\n+\t\tret = iort_its_translate_pa(msi_node, &res.start);\n+\t}\n \n \t*pa = res.start;\n \treturn 0;\n@@ -120,7 +126,7 @@ static int its_v5_pci_msi_prepare(struct irq_domain *domain, struct device *dev,\n \tif (!msi_node)\n \t\treturn -ENODEV;\n \n-\tret = its_translate_frame_address(to_of_node(msi_node), &pa);\n+\tret = its_translate_frame_address(msi_node, &pa);\n \tif (ret)\n \t\treturn -ENODEV;\n \n@@ -161,7 +167,7 @@ static int of_pmsi_get_msi_info(struct irq_domain *domain, struct device *dev, u\n \t\t\t\tret = -EINVAL;\n \n \t\t\tif (!ret && pa)\n-\t\t\t\tret = its_translate_frame_address(it.node, pa);\n+\t\t\t\tret = its_translate_frame_address(of_fwnode_handle(it.node), pa);\n \n \t\t\tif (!ret)\n \t\t\t\t*dev_id = args;\n@@ -176,11 +182,6 @@ static int of_pmsi_get_msi_info(struct irq_domain *domain, struct device *dev, u\n \treturn of_map_id(dev->of_node, dev->id, \"msi-map\", \"msi-map-mask\", &msi_ctrl, dev_id);\n }\n \n-int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)\n-{\n-\treturn -1;\n-}\n-\n static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,\n \t\t\t    int nvec, msi_alloc_info_t *info)\n {\n@@ -191,7 +192,7 @@ static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,\n \tif (dev->of_node)\n \t\tret = of_pmsi_get_msi_info(domain->parent, dev, &dev_id, NULL);\n \telse\n-\t\tret = iort_pmsi_get_dev_id(dev, &dev_id);\n+\t\tret = iort_pmsi_get_msi_info(dev, &dev_id, NULL);\n \tif (ret)\n \t\treturn ret;\n \n@@ -214,10 +215,10 @@ static int its_v5_pmsi_prepare(struct irq_domain *domain, struct device *dev,\n \tu32 dev_id;\n \tint ret;\n \n-\tif (!dev->of_node)\n-\t\treturn -ENODEV;\n-\n-\tret = of_pmsi_get_msi_info(domain->parent, dev, &dev_id, &pa);\n+\tif (dev->of_node)\n+\t\tret = of_pmsi_get_msi_info(domain->parent, dev, &dev_id, &pa);\n+\telse\n+\t\tret = iort_pmsi_get_msi_info(dev, &dev_id, &pa);\n \tif (ret)\n \t\treturn ret;\n \ndiff --git a/drivers/irqchip/irq-gic-v5-irs.c b/drivers/irqchip/irq-gic-v5-irs.c\nindex 07c3df5692af..a3a0b270b5be 100644\n--- a/drivers/irqchip/irq-gic-v5-irs.c\n+++ b/drivers/irqchip/irq-gic-v5-irs.c\n@@ -816,8 +816,11 @@ void __init gicv5_irs_its_probe(void)\n {\n \tstruct gicv5_irs_chip_data *irs_data;\n \n-\tlist_for_each_entry(irs_data, &irs_nodes, entry)\n-\t\tgicv5_its_of_probe(to_of_node(irs_data->fwnode));\n+\tif (acpi_disabled)\n+\t\tlist_for_each_entry(irs_data, &irs_nodes, entry)\n+\t\t\tgicv5_its_of_probe(to_of_node(irs_data->fwnode));\n+\telse\n+\t\tgicv5_its_acpi_probe();\n }\n \n int __init gicv5_irs_of_probe(struct device_node *parent)\ndiff --git a/drivers/irqchip/irq-gic-v5-its.c b/drivers/irqchip/irq-gic-v5-its.c\nindex 554485f0be1f..751ccd88549a 100644\n--- a/drivers/irqchip/irq-gic-v5-its.c\n+++ b/drivers/irqchip/irq-gic-v5-its.c\n@@ -5,6 +5,8 @@\n \n #define pr_fmt(fmt)\t\"GICv5 ITS: \" fmt\n \n+#include <linux/acpi.h>\n+#include <linux/acpi_iort.h>\n #include <linux/bitmap.h>\n #include <linux/iommu.h>\n #include <linux/init.h>\n@@ -1115,7 +1117,7 @@ static int gicv5_its_init_domain(struct gicv5_its_chip_data *its, struct irq_dom\n }\n \n static int __init gicv5_its_init_bases(void __iomem *its_base, struct fwnode_handle *handle,\n-\t\t\t\t       struct irq_domain *parent_domain)\n+\t\t\t\t       struct irq_domain *parent_domain, bool noncoherent)\n {\n \tstruct device_node *np = to_of_node(handle);\n \tstruct gicv5_its_chip_data *its_node;\n@@ -1208,7 +1210,8 @@ static int __init gicv5_its_init(struct device_node *node)\n \t}\n \n \tret = gicv5_its_init_bases(its_base, of_fwnode_handle(node),\n-\t\t\t\t   gicv5_global_data.lpi_domain);\n+\t\t\t\t   gicv5_global_data.lpi_domain,\n+\t\t\t\t   of_property_read_bool(node, \"dma-noncoherent\"));\n \tif (ret)\n \t\tgoto out_unmap;\n \n@@ -1231,3 +1234,128 @@ void __init gicv5_its_of_probe(struct device_node *parent)\n \t\t\tpr_err(\"Failed to init ITS %s\\n\", np->full_name);\n \t}\n }\n+\n+#ifdef CONFIG_ACPI\n+\n+#define ACPI_GICV5_ITS_MEM_SIZE (SZ_64K)\n+\n+static struct acpi_madt_gicv5_translator *current_its_entry __initdata;\n+static struct fwnode_handle *current_its_fwnode __initdata;\n+\n+static int __init gic_acpi_parse_madt_its_translate(union acpi_subtable_headers *header,\n+\t\t\t\t\t\t    const unsigned long end)\n+{\n+\tstruct acpi_madt_gicv5_translate_frame *its_frame;\n+\tstruct fwnode_handle *msi_dom_handle;\n+\tstruct resource res = {};\n+\tint err;\n+\n+\tits_frame = (struct acpi_madt_gicv5_translate_frame *)header;\n+\tif (its_frame->linked_translator_id != current_its_entry->translator_id)\n+\t\treturn 0;\n+\n+\tres.start = its_frame->base_address;\n+\tres.end = its_frame->base_address + ACPI_GICV5_ITS_MEM_SIZE - 1;\n+\tres.flags = IORESOURCE_MEM;\n+\n+\tmsi_dom_handle = irq_domain_alloc_fwnode_parent(&res.start, current_its_fwnode);\n+\tif (!msi_dom_handle) {\n+\t\tpr_err(\"ITS@%pa: Unable to allocate GICv5 ITS translate domain token\\n\",\n+\t\t       &res.start);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\terr = iort_register_domain_token(its_frame->translate_frame_id, res.start,\n+\t\t\t\t\t msi_dom_handle);\n+\tif (err) {\n+\t\tpr_err(\"ITS@%pa: Unable to register GICv5 ITS domain token (ITS TRANSLATE FRAME ID %d) to IORT\\n\",\n+\t\t       &res.start, its_frame->translate_frame_id);\n+\t\tirq_domain_free_fwnode(msi_dom_handle);\n+\t\treturn err;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int __init gic_acpi_free_madt_its_translate(union acpi_subtable_headers *header,\n+\t\t\t\t\t\t   const unsigned long end)\n+{\n+\tstruct acpi_madt_gicv5_translate_frame *its_frame;\n+\tstruct fwnode_handle *msi_dom_handle;\n+\n+\tits_frame = (struct acpi_madt_gicv5_translate_frame *)header;\n+\tif (its_frame->linked_translator_id != current_its_entry->translator_id)\n+\t\treturn 0;\n+\n+\tmsi_dom_handle = iort_find_domain_token(its_frame->translate_frame_id);\n+\tif (!msi_dom_handle)\n+\t\treturn 0;\n+\n+\tiort_deregister_domain_token(its_frame->translate_frame_id);\n+\tirq_domain_free_fwnode(msi_dom_handle);\n+\n+\treturn 0;\n+}\n+\n+static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,\n+\t\t\t\t\t  const unsigned long end)\n+{\n+\tstruct acpi_madt_gicv5_translator *its_entry;\n+\tstruct fwnode_handle *dom_handle;\n+\tstruct resource res = {};\n+\tvoid __iomem *its_base;\n+\tint err;\n+\n+\tits_entry = (struct acpi_madt_gicv5_translator *)header;\n+\tres.start = its_entry->base_address;\n+\tres.end = its_entry->base_address + ACPI_GICV5_ITS_MEM_SIZE - 1;\n+\tres.flags = IORESOURCE_MEM;\n+\n+\tif (!request_mem_region(res.start, resource_size(&res), \"GICv5 ITS\"))\n+\t\treturn -EBUSY;\n+\n+\tdom_handle = irq_domain_alloc_fwnode(&res.start);\n+\tif (!dom_handle) {\n+\t\tpr_err(\"ITS@%pa: Unable to allocate GICv5 ITS domain token\\n\",\n+\t\t       &res.start);\n+\t\terr = -ENOMEM;\n+\t\tgoto out_rel_res;\n+\t}\n+\n+\tcurrent_its_entry = its_entry;\n+\tcurrent_its_fwnode = dom_handle;\n+\n+\tacpi_table_parse_madt(ACPI_MADT_TYPE_GICV5_ITS_TRANSLATE,\n+\t\t\t      gic_acpi_parse_madt_its_translate, 0);\n+\n+\tits_base = ioremap(res.start, ACPI_GICV5_ITS_MEM_SIZE);\n+\tif (!its_base) {\n+\t\terr = -ENOMEM;\n+\t\tgoto out_unregister;\n+\t}\n+\n+\terr = gicv5_its_init_bases(its_base, dom_handle, gicv5_global_data.lpi_domain,\n+\t\t\t\t   its_entry->flags & ACPI_MADT_GICV5_ITS_NON_COHERENT);\n+\tif (err)\n+\t\tgoto out_unmap;\n+\n+\treturn 0;\n+\n+out_unmap:\n+\tiounmap(its_base);\n+out_unregister:\n+\tacpi_table_parse_madt(ACPI_MADT_TYPE_GICV5_ITS_TRANSLATE,\n+\t\t\t      gic_acpi_free_madt_its_translate, 0);\n+\tirq_domain_free_fwnode(dom_handle);\n+out_rel_res:\n+\trelease_mem_region(res.start, resource_size(&res));\n+\treturn err;\n+}\n+\n+void __init gicv5_its_acpi_probe(void)\n+{\n+\tacpi_table_parse_madt(ACPI_MADT_TYPE_GICV5_ITS, gic_acpi_parse_madt_its, 0);\n+}\n+#else\n+void __init gicv5_its_acpi_probe(void) { }\n+#endif\ndiff --git a/drivers/pci/msi/irqdomain.c b/drivers/pci/msi/irqdomain.c\nindex 3136341e802c..25fcc2114803 100644\n--- a/drivers/pci/msi/irqdomain.c\n+++ b/drivers/pci/msi/irqdomain.c\n@@ -402,6 +402,8 @@ u32 pci_msi_map_rid_ctlr_node(struct irq_domain *domain, struct pci_dev *pdev,\n \t\trid = of_msi_xlate(&pdev->dev, &msi_ctlr_node, rid);\n \t\tif (msi_ctlr_node)\n \t\t\t*node = of_fwnode_handle(msi_ctlr_node);\n+\t} else {\n+\t\trid = iort_msi_xlate(&pdev->dev, rid, node);\n \t}\n \n \treturn rid;\ndiff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h\nindex d4ed5622cf2b..2d22268677a9 100644\n--- a/include/linux/acpi_iort.h\n+++ b/include/linux/acpi_iort.h\n@@ -27,12 +27,14 @@ int iort_register_domain_token(int trans_id, phys_addr_t base,\n \t\t\t       struct fwnode_handle *fw_node);\n void iort_deregister_domain_token(int trans_id);\n struct fwnode_handle *iort_find_domain_token(int trans_id);\n-int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);\n \n #ifdef CONFIG_ACPI_IORT\n u32 iort_msi_map_id(struct device *dev, u32 id);\n+u32 iort_msi_xlate(struct device *dev, u32 id, struct fwnode_handle **node);\n+int iort_its_translate_pa(struct fwnode_handle *node, phys_addr_t *base);\n struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,\n \t\t\t\t\t  enum irq_domain_bus_token bus_token);\n+int iort_pmsi_get_msi_info(struct device *dev, u32 *dev_id, phys_addr_t *pa);\n void acpi_configure_pmsi_domain(struct device *dev);\n void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode,\n \t\t       struct list_head *head);\n@@ -46,9 +48,15 @@ phys_addr_t acpi_iort_dma_get_max_cpu_address(void);\n #else\n static inline u32 iort_msi_map_id(struct device *dev, u32 id)\n { return id; }\n+static inline u32 iort_msi_xlate(struct device *dev, u32 id, struct fwnode_handle **node)\n+{ return id; }\n+static inline int iort_its_translate_pa(struct fwnode_handle *node, phys_addr_t *base)\n+{ return -ENODEV; }\n static inline struct irq_domain *iort_get_device_domain(\n \tstruct device *dev, u32 id, enum irq_domain_bus_token bus_token)\n { return NULL; }\n+static inline int iort_pmsi_get_msi_info(struct device *dev, u32 *dev_id, phys_addr_t *pa)\n+{ return -ENODEV; }\n static inline void acpi_configure_pmsi_domain(struct device *dev) { }\n static inline\n void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode, struct list_head *head) { }\ndiff --git a/include/linux/irqchip/arm-gic-v5.h b/include/linux/irqchip/arm-gic-v5.h\nindex ff5b1a4931d7..334b6986435c 100644\n--- a/include/linux/irqchip/arm-gic-v5.h\n+++ b/include/linux/irqchip/arm-gic-v5.h\n@@ -392,4 +392,5 @@ int gicv5_alloc_lpi(void);\n void gicv5_free_lpi(u32 lpi);\n \n void __init gicv5_its_of_probe(struct device_node *parent);\n+void __init gicv5_its_acpi_probe(void);\n #endif\n",
    "prefixes": [
        "v2",
        "6/7"
    ]
}