From: sashiko-bot@kernel.org
To: "Vidya Sagar" <vidyas@nvidia.com>
Cc: linux-pci@vger.kernel.org
Subject: Re: [PATCH] PCI: Save/restore Device 3 control and clear stale 14-bit Tag enables
Date: Wed, 13 May 2026 23:41:02 +0000 [thread overview]
Message-ID: <20260513234103.0F362C19425@smtp.kernel.org> (raw)
In-Reply-To: <20260512163012.2336191-1-vidyas@nvidia.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Premature downstream config accesses before child device readiness causes child fixups to be silently skipped.
- [High] Incomplete bus hierarchy traversal leaves endpoints behind switches with stale 14-bit tag enables.
- [High] Unsynchronized C bitfield assignments cause data races that corrupt device and bus state.
- [High] Incorrect bus flit_mode assignment for downstream ports corrupts primary bus state.
--
commit cfcee5167fd2cdd929f8d6d46c5515889aa39e42
Author: Vidya Sagar <vidyas@nvidia.com>
Subject: PCI: Save/restore Device 3 control and clear stale 14-bit Tag enables
This patch saves and restores DEV3_CTL across pci_save_state() and
pci_restore_state(). It also clears stale 14-bit Tag enables when the link
mode changes to non-flit.
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 8f7cfcc000901..a146db4ca358c 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
[ ... ]
> @@ -1695,6 +1695,199 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
[ ... ]
> +static void pci_restore_dev3_state(struct pci_dev *dev)
> +{
[ ... ]
> + pci_read_config_dword(dev, pos + PCI_DEV3_STA, &dev3_sta);
> + dev->fm_enabled = !!(dev3_sta & PCI_DEV3_STA_SEGMENT);
Is this bitfield assignment safe against concurrent modifications?
Compilers implement bitfield assignments as non-atomic read-modify-write
operations on the entire containing integer word.
If this runs concurrently with sibling resumes, or asynchronously during
probe or suspend (which modify adjacent bitfields like is_managed or
state_saved), could this clobber those other states and cause a data race?
> +
> + pcie_capability_read_word(dev, PCI_EXP_LNKSTA2, &lnksta2);
> + flit_now = !!(lnksta2 & PCI_EXP_LNKSTA2_FLIT);
> + if (dev->bus)
> + dev->bus->flit_mode = flit_now;
For a downstream port or root port, LNKSTA2 reflects the status of its
downstream link.
Would assigning this to dev->bus incorrectly update the port's upstream
primary bus instead of the secondary bus (dev->subordinate)?
[ ... ]
> +static void __pci_dev_clear_stale_14bit_tag(struct pci_dev *dev, bool flit_now)
> +{
[ ... ]
> + pci_read_config_dword(dev, pos + PCI_DEV3_STA, &dev3_sta);
> + dev->fm_enabled = !!(dev3_sta & PCI_DEV3_STA_SEGMENT);
This is another C bitfield assignment that might race if triggered
asynchronously.
Since pci_bridge_refresh_14bit_tag() holds only down_read(&pci_bus_sem)
during bandwidth notification events, could this also result in data
corruption?
[ ... ]
> +void pci_bridge_refresh_14bit_tag(struct pci_dev *bridge)
> +{
[ ... ]
> + /*
> + * Walk the secondary bus. pci_restore_dev3_state() only fires on
> + * paths that go through pci_dev_restore(); DPC release, hotplug
> + * link status updates, and similar paths do not. Fix those too.
> + */
> + down_read(&pci_bus_sem);
> + list_for_each_entry(child, &bus->devices, bus_list)
> + __pci_dev_clear_stale_14bit_tag(child, flit_now);
> + up_read(&pci_bus_sem);
> +}
Does this iterate deeply enough to catch endpoints behind PCIe switches?
If the bridge is a root port connected to a PCIe switch,
list_for_each_entry() will only visit the immediate child (the switch
upstream port).
Should this use pci_walk_bus() instead to recursively visit all downstream
devices, ensuring endpoints beneath a switch do not retain stale enables?
[ ... ]
> @@ -4758,6 +4956,14 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
> pci_dbg(dev, "waiting %d ms for downstream link\n", delay);
> msleep(delay);
>
> + /*
> + * The link has had a chance to come back; refresh the
> + * bridge's (and subtree's) DEV3_CTL 14-Bit Tag enables
> + * against the live LNKSTA2.Flit_Mode before we issue the
> + * first config TLP to the child.
> + */
> + pci_bridge_refresh_14bit_tag(dev);
> +
> if (!pci_dev_wait(child, reset_type, PCI_RESET_WAIT - delay))
> return 0;
Will calling pci_bridge_refresh_14bit_tag() here cause child devices to be
silently skipped if they are not yet ready?
pci_bridge_refresh_14bit_tag() walks the secondary bus and issues downstream
config reads via pci_find_ext_capability(). Since this occurs before
pci_dev_wait() verifies child recovery, the child may respond with CRS.
If it responds with CRS, pci_find_ext_capability() fails and skips the child.
When the child finally becomes ready, it will retain its stale 14-bit tag
enables.
Could the child traversal be deferred until after pci_dev_wait() guarantees
the devices are accessible?
> @@ -4785,6 +4991,13 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
> return -ENOTTY;
> }
>
> + /*
> + * Link is up. Refresh the bridge's (and subtree's) DEV3_CTL
> + * 14-Bit Tag enables against the live LNKSTA2.Flit_Mode before
> + * we issue the first config TLP to the child below.
> + */
> + pci_bridge_refresh_14bit_tag(dev);
> +
> return pci_dev_wait(child, reset_type,
> PCIE_RESET_READY_POLL_MS - delay);
> }
Similarly, could the child devices be missed here since pci_dev_wait() has
not yet completed?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260512163012.2336191-1-vidyas@nvidia.com?part=1
prev parent reply other threads:[~2026-05-13 23:41 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-12 16:30 [PATCH] PCI: Save/restore Device 3 control and clear stale 14-bit Tag enables Vidya Sagar
2026-05-12 22:49 ` Bjorn Helgaas
2026-05-13 23:41 ` 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=20260513234103.0F362C19425@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=vidyas@nvidia.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