get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2008487,
    "url": "http://patchwork.ozlabs.org/api/patches/2008487/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-pci/patch/20241108143600.756224-7-herve.codina@bootlin.com/",
    "project": {
        "id": 28,
        "url": "http://patchwork.ozlabs.org/api/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,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20241108143600.756224-7-herve.codina@bootlin.com>",
    "list_archive_url": null,
    "date": "2024-11-08T14:35:59",
    "name": "[v2,6/6] PCI: of: Create device-tree PCI host bridge node",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "7234caa38c60a8506c7bc442190cb5c91e6376c9",
    "submitter": {
        "id": 81983,
        "url": "http://patchwork.ozlabs.org/api/people/81983/?format=api",
        "name": "Herve Codina",
        "email": "herve.codina@bootlin.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-pci/patch/20241108143600.756224-7-herve.codina@bootlin.com/mbox/",
    "series": [
        {
            "id": 431925,
            "url": "http://patchwork.ozlabs.org/api/series/431925/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-pci/list/?series=431925",
            "date": "2024-11-08T14:35:53",
            "name": "Add support for the PCI host bridge device-tree node creation.",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/431925/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2008487/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2008487/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-pci+bounces-16333-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=bootlin.com header.i=@bootlin.com header.a=rsa-sha256\n header.s=gm1 header.b=FjSSh+c7;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=147.75.199.223; helo=ny.mirrors.kernel.org;\n envelope-from=linux-pci+bounces-16333-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com\n header.b=\"FjSSh+c7\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=217.70.183.200",
            "smtp.subspace.kernel.org;\n dmarc=pass (p=reject dis=none) header.from=bootlin.com",
            "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=bootlin.com"
        ],
        "Received": [
            "from ny.mirrors.kernel.org (ny.mirrors.kernel.org [147.75.199.223])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature ECDSA (secp384r1))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4XlM3b4LcFz1xyM\n\tfor <incoming@patchwork.ozlabs.org>; Sat,  9 Nov 2024 01:37:31 +1100 (AEDT)",
            "from smtp.subspace.kernel.org (wormhole.subspace.kernel.org\n [52.25.139.140])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby ny.mirrors.kernel.org (Postfix) with ESMTPS id 4D0641C236C9\n\tfor <incoming@patchwork.ozlabs.org>; Fri,  8 Nov 2024 14:37:29 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 6F05A1F76A6;\n\tFri,  8 Nov 2024 14:36:14 +0000 (UTC)",
            "from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net\n [217.70.183.200])\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 9B6B51F5825;\n\tFri,  8 Nov 2024 14:36:10 +0000 (UTC)",
            "by mail.gandi.net (Postfix) with ESMTPA id 3C4D72000E;\n\tFri,  8 Nov 2024 14:36:08 +0000 (UTC)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1731076574; cv=none;\n b=JTUOb3w2F2csgcaE4u3M6LWYP2tEZOcO1IWcpm5QcT+5SYKUarnN2ZjS/ICc8M62mKDJQ0BA27L8B7U7oLb8aEgKfaRdrAvZ6Upaz426DOdFaLpV705gI7NfCTqTr6yc5Fs7BC7Uwdvyast89NyCLpm+xeXRF1UTedPrZmxpJ/o=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1731076574; c=relaxed/simple;\n\tbh=3kvlDqV0tXgEzAPAtwg8yui0NrIq88s4pdVp/yxJzfE=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=oWsuVdXlBHh5oLwyUxFZRkh7TStCiA8tSzVzsdROHK0FrHUJjWBc9zFnxsbNRI4szrwkXAdBKtdu52V530VRhBKKWEqaiJma54dKpvyPjs0JXyLoLaMjLXf4qnShyBW7wRU1eJ+VVRgLqx+YO9wiWnhIinEyA/CbDq1Aue6kTFM=",
        "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=reject dis=none) header.from=bootlin.com;\n spf=pass smtp.mailfrom=bootlin.com;\n dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com\n header.b=FjSSh+c7; arc=none smtp.client-ip=217.70.183.200",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1;\n\tt=1731076568;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\t to:to:cc:cc:mime-version:mime-version:\n\t content-transfer-encoding:content-transfer-encoding:\n\t in-reply-to:in-reply-to:references:references;\n\tbh=XOigWkMO2U2ofXPZcVrSkjfciW4tfAlRbP7bVVv6C6w=;\n\tb=FjSSh+c7WVylQYQ7FJsL/nQafsc3e0SiFcQ7GKRpymQbkVTOOZ050LrcDH9bav1s4IgLHN\n\tDUarGQ20f0pKh/x7PXklVUXkfDI93KmXvArPtl8UBGT9q5jNFlGQOk/q6O6jiEcy5zY9Qa\n\tni18uyoML8rqQwhSuauXR3nhWUT9OjANZENHFLJiCbpOKgtsxJd4gy8EEorwQvhMHCMrJp\n\tNyv1vgSvVXnTkEew2XFz5D0MS3V7YW3l7oT4339OqIckqxoFstOaWQAlnyQODLXOVv3bqF\n\tEK74wrOlFHLgYnE+Q0l8zapl7Zgzz7tU1+iku0H2oedtrKEM2pwEgasQdZkYQg==",
        "From": "Herve Codina <herve.codina@bootlin.com>",
        "To": "Greg Kroah-Hartman <gregkh@linuxfoundation.org>,\n\t\"Rafael J. Wysocki\" <rafael@kernel.org>,\n\tRob Herring <robh@kernel.org>,\n\tSaravana Kannan <saravanak@google.com>,\n\tBjorn Helgaas <bhelgaas@google.com>,\n\tLizhi Hou <lizhi.hou@amd.com>",
        "Cc": "linux-kernel@vger.kernel.org,\n\tdevicetree@vger.kernel.org,\n\tlinux-pci@vger.kernel.org,\n\tAllan Nielsen <allan.nielsen@microchip.com>,\n\tHoratiu Vultur <horatiu.vultur@microchip.com>,\n\tSteen Hegelund <steen.hegelund@microchip.com>,\n\tThomas Petazzoni <thomas.petazzoni@bootlin.com>,\n\tHerve Codina <herve.codina@bootlin.com>",
        "Subject": "[PATCH v2 6/6] PCI: of: Create device-tree PCI host bridge node",
        "Date": "Fri,  8 Nov 2024 15:35:59 +0100",
        "Message-ID": "<20241108143600.756224-7-herve.codina@bootlin.com>",
        "X-Mailer": "git-send-email 2.46.2",
        "In-Reply-To": "<20241108143600.756224-1-herve.codina@bootlin.com>",
        "References": "<20241108143600.756224-1-herve.codina@bootlin.com>",
        "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-Transfer-Encoding": "8bit",
        "X-GND-Sasl": "herve.codina@bootlin.com"
    },
    "content": "PCI devices device-tree nodes can be already created. This was\nintroduced by commit 407d1a51921e (\"PCI: Create device tree node for\nbridge\").\n\nIn order to have device-tree nodes related to PCI devices attached on\ntheir PCI root bus (the PCI bus handled by the PCI host bridge), a PCI\nroot bus device-tree node is needed. This root bus node will be used as\nthe parent node of the first level devices scanned on the bus. On\ndevice-tree based systems, this PCI root bus device tree node is set to\nthe node of the related PCI host bridge. The PCI host bridge node is\navailable in the device-tree used to describe the hardware passed at\nboot.\n\nOn non device-tree based system (such as ACPI), a device-tree node for\nthe PCI host bridge or for the root bus do not exist. Indeed, the PCI\nhost bridge is not described in a device-tree used at boot simply\nbecause no device-tree are passed at boot.\n\nThe device-tree PCI host bridge node creation needs to be done at\nruntime. This is done in the same way as for the creation of the PCI\ndevice nodes. I.e. node and properties are created based on computed\ninformation done by the PCI core. Also, as is done on device-tree based\nsystems, this PCI host bridge node is used for the PCI root bus.\n\nSigned-off-by: Herve Codina <herve.codina@bootlin.com>\n---\n drivers/pci/of.c          |  94 ++++++++++++++++++++++++++++++++++-\n drivers/pci/of_property.c | 102 ++++++++++++++++++++++++++++++++++++++\n drivers/pci/pci.h         |   6 +++\n drivers/pci/probe.c       |   2 +\n drivers/pci/remove.c      |   2 +\n 5 files changed, 205 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/drivers/pci/of.c b/drivers/pci/of.c\nindex 141ffbb1b3e6..316c31d13aa8 100644\n--- a/drivers/pci/of.c\n+++ b/drivers/pci/of.c\n@@ -726,7 +726,99 @@ void of_pci_make_dev_node(struct pci_dev *pdev)\n out_free_name:\n \tkfree(name);\n }\n-#endif\n+\n+void of_pci_remove_host_bridge_node(struct pci_host_bridge *bridge)\n+{\n+\tstruct device_node *np;\n+\n+\tnp = pci_bus_to_OF_node(bridge->bus);\n+\tif (!np || !of_node_check_flag(np, OF_DYNAMIC))\n+\t\treturn;\n+\n+\tdevice_remove_of_node(&bridge->bus->dev);\n+\tdevice_remove_of_node(&bridge->dev);\n+\tof_changeset_revert(np->data);\n+\tof_changeset_destroy(np->data);\n+\tof_node_put(np);\n+}\n+\n+void of_pci_make_host_bridge_node(struct pci_host_bridge *bridge)\n+{\n+\tstruct device_node *np = NULL;\n+\tstruct of_changeset *cset;\n+\tconst char *name;\n+\tint ret;\n+\n+\t/*\n+\t * If there is already a device-tree node linked to the PCI bus handled\n+\t * by this bridge (i.e. the PCI root bus), nothing to do.\n+\t */\n+\tif (pci_bus_to_OF_node(bridge->bus))\n+\t\treturn;\n+\n+\t/* The root bus has no node. Check that the host bridge has no node too */\n+\tif (bridge->dev.of_node) {\n+\t\tpr_err(\"PCI host bridge of_node already set\");\n+\t\treturn;\n+\t}\n+\n+\t/* Check if there is a DT root node to attach the created node */\n+\tif (!of_root) {\n+\t\tpr_err(\"of_root node is NULL, cannot create PCI host bridge node\\n\");\n+\t\treturn;\n+\t}\n+\n+\tname = kasprintf(GFP_KERNEL, \"pci@%x,%x\", pci_domain_nr(bridge->bus),\n+\t\t\t bridge->bus->number);\n+\tif (!name)\n+\t\treturn;\n+\n+\tcset = kmalloc(sizeof(*cset), GFP_KERNEL);\n+\tif (!cset)\n+\t\tgoto out_free_name;\n+\tof_changeset_init(cset);\n+\n+\tnp = of_changeset_create_node(cset, of_root, name);\n+\tif (!np)\n+\t\tgoto out_destroy_cset;\n+\n+\tret = of_pci_add_host_bridge_properties(bridge, cset, np);\n+\tif (ret)\n+\t\tgoto out_free_node;\n+\n+\t/*\n+\t * This of_node will be added to an existing device. The of_node parent\n+\t * is the root OF node and so this node will be handled by the platform\n+\t * bus. Avoid any new device creation.\n+\t */\n+\tof_node_set_flag(np, OF_POPULATED);\n+\tnp->fwnode.dev = &bridge->dev;\n+\tfwnode_dev_initialized(&np->fwnode, true);\n+\n+\tret = of_changeset_apply(cset);\n+\tif (ret)\n+\t\tgoto out_free_node;\n+\n+\tnp->data = cset;\n+\n+\t/* Add the of_node to host bridge and the root bus */\n+\tdevice_add_of_node(&bridge->dev, np);\n+\tdevice_add_of_node(&bridge->bus->dev, np);\n+\n+\tkfree(name);\n+\n+\treturn;\n+\n+out_free_node:\n+\tof_node_put(np);\n+out_destroy_cset:\n+\tof_changeset_destroy(cset);\n+\tkfree(cset);\n+out_free_name:\n+\tkfree(name);\n+}\n+\n+#endif /* CONFIG_PCI_DYNAMIC_OF_NODES */\n \n #endif /* CONFIG_PCI */\n \ndiff --git a/drivers/pci/of_property.c b/drivers/pci/of_property.c\nindex e56159cc48e8..e8e2c3ecc255 100644\n--- a/drivers/pci/of_property.c\n+++ b/drivers/pci/of_property.c\n@@ -394,3 +394,105 @@ int of_pci_add_properties(struct pci_dev *pdev, struct of_changeset *ocs,\n \n \treturn 0;\n }\n+\n+static bool of_pci_is_range_resource(const struct resource *res, u32 *flags)\n+{\n+\tif (!(resource_type(res) & IORESOURCE_MEM) &&\n+\t    !(resource_type(res) & IORESOURCE_MEM_64))\n+\t\treturn false;\n+\n+\tif (of_pci_get_addr_flags(res, flags))\n+\t\treturn false;\n+\n+\treturn true;\n+}\n+\n+static int of_pci_host_bridge_prop_ranges(struct pci_host_bridge *bridge,\n+\t\t\t\t\t  struct of_changeset *ocs,\n+\t\t\t\t\t  struct device_node *np)\n+{\n+\tstruct resource_entry *window;\n+\tunsigned int ranges_sz = 0;\n+\tunsigned int n_range = 0;\n+\tstruct resource *res;\n+\tint n_addr_cells;\n+\tu32 *ranges;\n+\tu64 val64;\n+\tu32 flags;\n+\tint ret;\n+\n+\tn_addr_cells = of_n_addr_cells(np);\n+\tif (n_addr_cells <= 0 || n_addr_cells > 2)\n+\t\treturn -EINVAL;\n+\n+\tresource_list_for_each_entry(window, &bridge->windows) {\n+\t\tres = window->res;\n+\t\tif (!of_pci_is_range_resource(res, &flags))\n+\t\t\tcontinue;\n+\t\tn_range++;\n+\t}\n+\n+\tif (!n_range)\n+\t\treturn 0;\n+\n+\tranges = kcalloc(n_range,\n+\t\t\t (OF_PCI_ADDRESS_CELLS + OF_PCI_SIZE_CELLS +\n+\t\t\t  n_addr_cells) * sizeof(*ranges),\n+\t\t\t GFP_KERNEL);\n+\tif (!ranges)\n+\t\treturn -ENOMEM;\n+\n+\tresource_list_for_each_entry(window, &bridge->windows) {\n+\t\tres = window->res;\n+\t\tif (!of_pci_is_range_resource(res, &flags))\n+\t\t\tcontinue;\n+\n+\t\t/* PCI bus address */\n+\t\tval64 = res->start;\n+\t\tof_pci_set_address(NULL, &ranges[ranges_sz], val64 - window->offset,\n+\t\t\t\t   0, flags, false);\n+\t\tranges_sz += OF_PCI_ADDRESS_CELLS;\n+\n+\t\t/* Host bus address */\n+\t\tif (n_addr_cells == 2)\n+\t\t\tranges[ranges_sz++] = upper_32_bits(val64);\n+\t\tranges[ranges_sz++] = lower_32_bits(val64);\n+\n+\t\t/* Size */\n+\t\tval64 = resource_size(res);\n+\t\tranges[ranges_sz] = upper_32_bits(val64);\n+\t\tranges[ranges_sz + 1] = lower_32_bits(val64);\n+\t\tranges_sz += OF_PCI_SIZE_CELLS;\n+\t}\n+\n+\tret = of_changeset_add_prop_u32_array(ocs, np, \"ranges\", ranges, ranges_sz);\n+\tkfree(ranges);\n+\treturn ret;\n+}\n+\n+int of_pci_add_host_bridge_properties(struct pci_host_bridge *bridge,\n+\t\t\t\t      struct of_changeset *ocs,\n+\t\t\t\t      struct device_node *np)\n+{\n+\tint ret;\n+\n+\tret = of_changeset_add_prop_string(ocs, np, \"device_type\", \"pci\");\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = of_changeset_add_prop_u32(ocs, np, \"#address-cells\",\n+\t\t\t\t\tOF_PCI_ADDRESS_CELLS);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = of_changeset_add_prop_u32(ocs, np, \"#size-cells\",\n+\t\t\t\t\tOF_PCI_SIZE_CELLS);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = of_pci_host_bridge_prop_ranges(bridge, ocs, np);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/pci/pci.h b/drivers/pci/pci.h\nindex 14d00ce45bfa..f2092a119f2c 100644\n--- a/drivers/pci/pci.h\n+++ b/drivers/pci/pci.h\n@@ -802,9 +802,15 @@ void of_pci_make_dev_node(struct pci_dev *pdev);\n void of_pci_remove_node(struct pci_dev *pdev);\n int of_pci_add_properties(struct pci_dev *pdev, struct of_changeset *ocs,\n \t\t\t  struct device_node *np);\n+void of_pci_make_host_bridge_node(struct pci_host_bridge *bridge);\n+void of_pci_remove_host_bridge_node(struct pci_host_bridge *bridge);\n+int of_pci_add_host_bridge_properties(struct pci_host_bridge *bridge, struct of_changeset *ocs,\n+\t\t\t\t      struct device_node *np);\n #else\n static inline void of_pci_make_dev_node(struct pci_dev *pdev) { }\n static inline void of_pci_remove_node(struct pci_dev *pdev) { }\n+static inline void of_pci_make_host_bridge_node(struct pci_host_bridge *bridge) { }\n+static inline void of_pci_remove_host_bridge_node(struct pci_host_bridge *bridge) { }\n #endif\n \n #ifdef CONFIG_PCIEAER\ndiff --git a/drivers/pci/probe.c b/drivers/pci/probe.c\nindex 4f68414c3086..bfe89ce8d800 100644\n--- a/drivers/pci/probe.c\n+++ b/drivers/pci/probe.c\n@@ -1049,6 +1049,8 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)\n \t\tdev_info(&bus->dev, \"root bus resource %pR%s\\n\", res, addr);\n \t}\n \n+\tof_pci_make_host_bridge_node(bridge);\n+\n \tdown_write(&pci_bus_sem);\n \tlist_add_tail(&bus->node, &pci_root_buses);\n \tup_write(&pci_bus_sem);\ndiff --git a/drivers/pci/remove.c b/drivers/pci/remove.c\nindex e4ce1145aa3e..2c379c9ab5b4 100644\n--- a/drivers/pci/remove.c\n+++ b/drivers/pci/remove.c\n@@ -160,6 +160,8 @@ void pci_stop_root_bus(struct pci_bus *bus)\n \t\t\t\t\t &bus->devices, bus_list)\n \t\tpci_stop_bus_device(child);\n \n+\tof_pci_remove_host_bridge_node(host_bridge);\n+\n \t/* stop the host bridge */\n \tdevice_release_driver(&host_bridge->dev);\n }\n",
    "prefixes": [
        "v2",
        "6/6"
    ]
}