From: sashiko-bot@kernel.org
To: "Marek Vasut" <marek.vasut+renesas@mailbox.org>,
linux-pci@vger.kernel.org
Cc: wsa+renesas@sang-engineering.com
Subject: Re: [PATCH 1/2] PCI: dwc: rcar-gen4: Replace pe_rst GPIO PERST with GPIO reset aux driver
Date: Wed, 28 Oct 2026 17:35:47 +0000 [thread overview]
Message-ID: <sashiko-outbox-188239@kernel.org> (raw)
In-Reply-To: <20261028172133.20903-1-marek.vasut+renesas@mailbox.org>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] PCI: dwc: rcar-gen4: broken error handling in rcar_gen4_pcie_host_perst_get()
- [High] PCI: dwc: rcar-gen4: rcar->perst UAF across suspend/resume in host_deinit()
- [Medium] PCI: dwc: Kconfig: PCIE_RCAR_GEN4_HOST selects RESET_GPIO without dependencies
--
commit 5d439d30a4d77a2c89c803394ba82b6874d3a0c5
Author: Marek Vasut <marek.vasut+renesas@mailbox.org>
PCI: dwc: rcar-gen4: Replace pe_rst GPIO PERST with GPIO reset aux driver
This commit removes the pe_rst GPIO descriptor from the DesignWare PCIe core
and switches the R-Car Gen4 PCIe host driver to acquire PERST# as a reset
control via the reset-gpio auxiliary driver or from a root port subnode in
rcar_gen4_pcie_host_init().
> diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
> index 0a0d56fcf0ac9..d65cf1e9d842b 100644
> --- a/drivers/pci/controller/dwc/Kconfig
> +++ b/drivers/pci/controller/dwc/Kconfig
> @@ -350,6 +350,7 @@ config PCIE_RCAR_GEN4_HOST
> depends on PCI_MSI
> select PCIE_DW_HOST
> select PCIE_RCAR_GEN4
> + select RESET_GPIO
[Severity: Medium]
In drivers/reset/Kconfig, RESET_GPIO is guarded by if RESET_CONTROLLER and
has depends on GPIOLIB:
drivers/reset/Kconfig:
if RESET_CONTROLLER
...
config RESET_GPIO
tristate "GPIO reset controller"
depends on GPIOLIB
select AUXILIARY_BUS
Since PCIE_RCAR_GEN4_HOST only depends on ARM64 && (ARCH_RENESAS ||
COMPILE_TEST) and PCI_MSI, can selecting RESET_GPIO here trigger Kconfig
unmet direct dependency warnings and build failures when RESET_CONTROLLER=n
or GPIOLIB=n (for example with COMPILE_TEST=y)?
> diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> index fceecbd16355c..d3bf01485e11d 100644
> --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
[ ... ]
> @@ -594,19 +583,84 @@ static int rcar_gen4_pcie_enable_device(struct pci_host_bridge *bridge,
> return 0;
> }
>
> +static int rcar_gen4_pcie_host_perst_get(struct dw_pcie *dw)
> +{
> + struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
> + struct device_node *root_port;
> + struct device *dev = dw->dev;
> + struct reset_control *perst;
> + int index;
[ ... ]
> + index = reset_control_get_count(dev);
> + if (index < 0)
> + return index;
> +
> + /* Attempt to request GPIO PERST# in PCIe controller node. */
> + perst = of_reset_control_get_exclusive_by_index(dev->of_node, index);
> + if (!IS_ERR(perst))
> + goto exit;
> +
> + /* No GPIO reset, test for root port subnode. */
> + root_port = of_get_next_available_child(dev->of_node, NULL);
> + if (!root_port)
> + return dev_err_probe(dev, -EINVAL, "Failed to get PERST# in root port\n");
> +
> + /* Attempt to request reset controller PERST# in root port subnode. */
> + perst = of_reset_control_get_optional_exclusive(root_port, "perst");
> + of_node_put(root_port);
> + if (IS_ERR(perst))
> + return dev_err_probe(dev, PTR_ERR(perst), "Failed to get PERST#\n");
[Severity: High]
What happens in rcar_gen4_pcie_host_perst_get() when reset-gpios is present
in dev->of_node, but of_reset_control_get_exclusive_by_index() returns
ERR_PTR(-EPROBE_DEFER) because the GPIO provider or the reset-gpio auxiliary
driver has not bound yet?
In drivers/reset/core.c:__fwnode_reset_control_get(), if reset-gpios is
present in the node, __reset_add_reset_gpio_device() or __reset_find_rcdev()
returns -EPROBE_DEFER until the GPIO device and the reset.gpio auxiliary
device are ready.
Because rcar_gen4_pcie_host_perst_get() does not check whether PTR_ERR(perst)
is something other than -ENOENT before falling through to the root_port
lookup:
1. On R-Car V4H boards (such as r8a779g0.dtsi with White Hawk or Sparrow
Hawk), the controller node has a pci@0,0 child node without a "perst" reset
property while reset-gpios is in the controller node. Falling through on
-EPROBE_DEFER causes of_reset_control_get_optional_exclusive(root_port,
"perst") to return NULL, so rcar->perst is set to NULL and probe succeeds
without acquiring or deasserting the GPIO PERST#.
2. On R-Car S4 and V4M boards (such as r8a779f0.dtsi Spider and r8a779h0.dtsi
Gray Hawk), there is no root port child node, so falling through on
-EPROBE_DEFER hits if (!root_port) and fails probe permanently with -EINVAL
instead of deferring.
3. Since reset-gpios is optional according to the binding and commit
description, if a controller node has neither reset-gpios nor a root port
child node, of_reset_control_get_exclusive_by_index() returns ERR_PTR(-ENOENT)
and if (!root_port) now fails probe with -EINVAL instead of treating PERST# as
optional.
Should this check for PTR_ERR(perst) != -ENOENT after
of_reset_control_get_exclusive_by_index(), and allow a missing root_port when
PTR_ERR(perst) == -ENOENT?
[ ... ]
> @@ -616,6 +670,10 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
> struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
> int ret;
>
> + ret = rcar_gen4_pcie_host_perst_get(dw);
> + if (ret)
> + return ret;
> +
> if (pp->bridge)
> pp->bridge->enable_device = rcar_gen4_pcie_enable_device;
>
> @@ -623,7 +681,7 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
>
> ret = rcar->drvdata->init(rcar);
> if (ret)
> - return ret;
> + goto err_init;
>
> /*
> * According to the section 3.5.7.2 "RC Mode" in DWC PCIe Dual Mode
> @@ -646,6 +704,8 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
>
> err:
> rcar->drvdata->deinit(rcar);
> +err_init:
> + reset_control_put(rcar->perst);
> return ret;
> }
>
> @@ -656,6 +716,7 @@ static void rcar_gen4_pcie_host_deinit(struct dw_pcie_rp *pp)
>
> rcar_gen4_pcie_host_perst_assert(pp, true);
> rcar->drvdata->deinit(rcar);
> + reset_control_put(rcar->perst);
> }
[Severity: High]
Can moving rcar_gen4_pcie_host_perst_get() and reset_control_put(rcar->perst)
into the dw_pcie_host_ops .init and .deinit callbacks cause a use-after-free
and double-free of rcar->perst across system suspend/resume followed by
driver removal?
In drivers/pci/controller/dwc/pcie-designware-host.c, the .deinit and .init
callbacks are also invoked during noirq suspend and resume:
dw_pcie_suspend_noirq()
pci->pp.ops->deinit(&pci->pp)
rcar_gen4_pcie_host_deinit()
reset_control_put(rcar->perst);
dw_pcie_resume_noirq()
pci->pp.ops->init(&pci->pp)
rcar_gen4_pcie_host_init()
...
err_deinit:
pci->pp.ops->deinit(&pci->pp)
rcar_gen4_pcie_host_deinit()
reset_control_put(rcar->perst);
When dw_pcie_suspend_noirq() runs, rcar_gen4_pcie_host_deinit() frees
rcar->perst via reset_control_put() while leaving the dangling pointer in
rcar->perst.
If the device is later unbound while suspended, or if dw_pcie_resume_noirq()
fails (either inside rcar_gen4_pcie_host_init() or at err_deinit: when link
training times out in dw_pcie_wait_for_link()), a subsequent
rcar_gen4_pcie_remove() -> dw_pcie_host_deinit() ->
rcar_gen4_pcie_host_deinit() will call reset_control_assert(rcar->perst) and
reset_control_put(rcar->perst) on the already-freed rcar->perst pointer.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261028172133.20903-1-marek.vasut+renesas@mailbox.org?part=1
prev parent reply other threads:[~2026-10-28 17:35 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-28 17:21 [PATCH 1/2] PCI: dwc: rcar-gen4: Replace pe_rst GPIO PERST with GPIO reset aux driver Marek Vasut
2026-10-28 17:21 ` [PATCH 2/2] PCI: rcar-gen4: Inline rcar_gen4_pcie_host_perst_assert() again Marek Vasut
2026-10-28 17:32 ` sashiko-bot
2026-10-28 17:27 ` [PATCH 1/2] PCI: dwc: rcar-gen4: Replace pe_rst GPIO PERST with GPIO reset aux driver Marek Vasut
2026-10-28 17:35 ` sashiko-bot [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-188239@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=marek.vasut+renesas@mailbox.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=wsa+renesas@sang-engineering.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox