From: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
To: "JC Chen[陳饒靜]" <jc_chen@diodes.com>
Cc: Bjorn Helgaas <helgaas@kernel.org>,
Nirmoy Das <nirmoyd@nvidia.com>,
Bjorn Helgaas <bhelgaas@google.com>,
"linux-pci@vger.kernel.org" <linux-pci@vger.kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: RE: [RFC PATCH] PCI: Work around Pericom PI7C9X3G606GPC Port 4 BAR erratum
Date: Wed, 26 Aug 2026 17:28:11 +0300 (EEST) [thread overview]
Message-ID: <b4d8e820-4cd5-7225-5078-678c4f191297@linux.intel.com> (raw)
In-Reply-To: <TYQPR02MB90041221BDD960DDD05CF63DF3CF2@TYQPR02MB9004.apcprd02.prod.outlook.com>
[-- Attachment #1: Type: text/plain, Size: 9788 bytes --]
On Fri, 24 Jul 2026, JC Chen[陳饒靜] wrote:
>
> Hi,
>
>
>
> Attached are kernel log "dmesg.log" and lspci "lspci.log" output.
>
>
>
> I guess without this patch, MSI-X from the downstream port doesn't work correctly?
>
> => YES
>
>
>
> By "mirror", I guess you mean you want the same value in BAR 0 of both the switch
> upstream port and the downstream port?
>
> => Yes, please use the same value in BAR 0 of both the switch upstream and downstream
> ports.
>
> I don't know what that even means, because the upstream port BAR 0 can't be inside
> its memory window, so reads should never reach the downstream port.
>
> => Yes, you are correct that the upstream port BAR 0 can't be inside its memory
> window, so reads should never reach the downstream port. When CDEP function is
> disabled, BAR0 of P4 is read as all zeros. If root complex send out memory address
> 0x7F000 or 0x7F080 to P4, it will hit P4’s MSI-X Table or PBA address range, switch
> will response UR and then cause SOC reports timeout. To avoid this issue, the patch
> write P0’s BAR0 to P4’s BAR0.
Hi,
I have problem of understanding why touching that downstream BAR helps
because the bridge windows on 0000:17:00.0 are disabled.
--
i.
>
>
>
> Thanks,
>
> JC
>
>
>
> -----Original Message-----
> From: Bjorn Helgaas <helgaas@kernel.org>
> Sent: Friday, July 24, 2026 4:54 AM
> To: Nirmoy Das <nirmoyd@nvidia.com>
> Cc: Bjorn Helgaas <bhelgaas@google.com>; linux-pci@vger.kernel.org;
> linux-kernel@vger.kernel.org; JC Chen[陳饒靜] <jc_chen@diodes.com>; Ilpo Järvinen
> <ilpo.jarvinen@linux.intel.com>
> Subject: Re: [RFC PATCH] PCI: Work around Pericom PI7C9X3G606GPC Port 4 BAR erratum
>
>
>
> [You don't often get email from helgaas@kernel.org. Learn why this is important at
> https://aka.ms/LearnAboutSenderIdentification ]
>
>
>
> [+cc Ilpo, this sounds really weird from a resource perspective]
>
>
>
> On Thu, Jul 23, 2026 at 09:10:00AM -0700, Nirmoy Das wrote:
>
> > The Pericom PI7C9X3G606GPC PCIe switch has an erratum where downstream
>
> > Port 4 retains a default MSI-X table and PBA decode when BAR 0 is zero.
>
> > Memory reads that match this window are dropped with an Unsupported
>
> > Request completion, which may cause the SoC to report a timeout.
>
>
>
> Help me understand what's going on here. Can you share the dmesg log of enumeration
> and resource assignment and the "lspci -v" output for the whole switch (both upstream
> and downstream ports) without this patch?
>
>
>
> I guess without this patch, MSI-X from the downstream port doesn't work correctly?
>
>
>
> > The workaround is to make Port 4 BAR 0 mirror BAR 0 of the immediate
>
> > upstream port. Firmware may establish this at boot, but PCI resource
>
> > assignment can move upstream BAR 0 without updating Port 4.
>
>
>
> By "mirror", I guess you mean you want the same value in BAR 0 of both the switch
> upstream port and the downstream port? I don't know what that even means, because
> the upstream port BAR 0 can't be inside its memory window, so reads should never
> reach the downstream port.
>
>
>
> > For a 64-bit BAR, also mirror BAR 1 while memory decoding is disabled,
>
> > matching the PCI core update sequence. Port 4 BAR 0 may read back as
>
> > zero after a successful write, so do not use readback to validate the update.
>
> >
>
> > Signed-off-by: Nirmoy Das <nirmoyd@nvidia.com>
>
> > ---
>
> > drivers/pci/quirks.c | 92
>
> > ++++++++++++++++++++++++++++++++++++++++++++
>
> > 1 file changed, 92 insertions(+)
>
> >
>
> > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index
>
> > b09f27f7846fc..fa8098d77adb5 100644
>
> > --- a/drivers/pci/quirks.c
>
> > +++ b/drivers/pci/quirks.c
>
> > @@ -6264,6 +6264,98 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_PERICOM,
>
> > 0xb404, DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_PERICOM, 0xb404,
>
> > pci_fixup_pericom_acs_store_forward);
>
> >
>
> > +#define PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC 0xc008
>
> > +
>
> > +/*
>
> > + * Pericom PI7C9X3G606GPC switch erratum E15 -
>
> > + * Downstream Port 4 BAR 0 must mirror the immediate upstream port
>
> > +BAR 0
>
> > + *
>
> > + * Port 4 uses BAR 0 for its MSI-X table and PBA. Firmware may
>
> > +program this
>
> > + * mirror at boot, but Linux resource assignment can move the
>
> > +upstream BAR
>
> > + * and leave Port 4 with a stale mirror.
>
> > + *
>
> > + * Diodes confirmed Tile0/P4 appears to Linux as device 4, function 0
>
> > +on the
>
> > + * bus below the upstream port. Match that downstream function and
>
> > +re-apply
>
> > + * the mirror after resource assignment and early resume.
>
> > + */
>
> > +static void pci_fixup_pericom_pi7c9x3g606gpc_bar0_mirror(struct
>
> > +pci_dev *pdev) {
>
> > + struct pci_dev *upstream;
>
> > + bool bar0_64, disable_mem;
>
> > + u16 cmd = 0;
>
> > + u32 bar = 0, bar1 = 0, upstream_bar = 0, upstream_bar1 = 0;
>
> > +
>
> > + if (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)
>
> > + return;
>
> > +
>
> > + if (PCI_SLOT(pdev->devfn) != 4 || PCI_FUNC(pdev->devfn))
>
> > + return;
>
> > +
>
> > + upstream = pci_upstream_bridge(pdev);
>
> > + if (!upstream || upstream->vendor != PCI_VENDOR_ID_PERICOM ||
>
> > + upstream->device != PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC ||
>
> > + pci_pcie_type(upstream) != PCI_EXP_TYPE_UPSTREAM)
>
> > + return;
>
> > +
>
> > + pci_read_config_dword(upstream, PCI_BASE_ADDRESS_0, &upstream_bar);
>
> > + if (upstream_bar & PCI_BASE_ADDRESS_SPACE_IO)
>
> > + return;
>
> > +
>
> > + bar0_64 = (upstream_bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
>
> > + PCI_BASE_ADDRESS_MEM_TYPE_64;
>
> > + if (bar0_64)
>
> > + pci_read_config_dword(upstream, PCI_BASE_ADDRESS_1,
>
> > + &upstream_bar1);
>
> > +
>
> > + if (!(upstream_bar & PCI_BASE_ADDRESS_MEM_MASK) &&
>
> > + (!bar0_64 || !upstream_bar1)) {
>
> > + pci_warn(pdev, "skipping PI7C9X3G606GPC BAR 0 mirror workaround
> because upstream BAR 0 is unassigned\n");
>
> > + return;
>
> > + }
>
> > +
>
> > + pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &bar);
>
> > + if (bar0_64) {
>
> > + pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, &bar1);
>
> > + if (bar == upstream_bar && bar1 == upstream_bar1)
>
> > + return;
>
> > + } else {
>
> > + if (bar == upstream_bar)
>
> > + return;
>
> > + }
>
> > +
>
> > + /*
>
> > + * Port 4 BAR 0 may read back as zero even after a successful write.
>
> > + * If BAR 0 is configured as 64-bit, BAR 1 is the upper half.
>
> > + * Disable memory decoding while updating both dwords, matching PCI
>
> > + * core's 64-bit BAR update sequence.
>
> > + */
>
> > + disable_mem = bar0_64 && !pdev->mmio_always_on;
>
> > + if (disable_mem) {
>
> > + pci_read_config_word(pdev, PCI_COMMAND, &cmd);
>
> > + pci_write_config_word(pdev, PCI_COMMAND,
>
> > + cmd & ~PCI_COMMAND_MEMORY);
>
> > + }
>
> > +
>
> > + pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, upstream_bar);
>
> > + if (bar0_64)
>
> > + pci_write_config_dword(pdev, PCI_BASE_ADDRESS_1, upstream_bar1);
>
> > + if (disable_mem)
>
> > + pci_write_config_word(pdev, PCI_COMMAND, cmd);
>
> > +
>
> > + if (bar0_64)
>
> > + pci_info(pdev, "wrote upstream BAR 0/1 %#x/%#x to Port 4 BAR 0/1 for
> PI7C9X3G606GPC BAR 0 mirror workaround\n",
>
> > + upstream_bar, upstream_bar1);
>
> > + else
>
> > + pci_info(pdev, "wrote upstream BAR 0 %#x to Port 4 BAR 0 for
> PI7C9X3G606GPC BAR 0 mirror workaround\n",
>
> > + upstream_bar);
>
> > +}
>
> > +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_PERICOM,
>
> > + PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC,
>
> > + pci_fixup_pericom_pi7c9x3g606gpc_bar0_mirror);
>
> > +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_PERICOM,
>
> > + PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC,
>
> > +
>
> > +pci_fixup_pericom_pi7c9x3g606gpc_bar0_mirror);
>
> > +
>
> > static void nvidia_ion_ahci_fixup(struct pci_dev *pdev) {
>
> > pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING;
>
> >
>
> > base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
>
> > --
>
> > 2.43.0
>
> >
>
>
>
--
i.
next prev parent reply other threads:[~2026-08-26 14:28 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-23 16:10 [RFC PATCH] PCI: Work around Pericom PI7C9X3G606GPC Port 4 BAR erratum Nirmoy Das
2026-07-23 16:16 ` sashiko-bot
2026-07-23 20:54 ` Bjorn Helgaas
2026-07-24 8:36 ` JC Chen[陳饒靜]
2026-08-26 14:28 ` Ilpo Järvinen [this message]
2026-08-27 0:13 ` JC Chen[陳饒靜]
2026-08-27 6:45 ` JC Chen[陳饒靜]
2026-08-31 15:29 ` Nirmoy Das
2026-09-01 2:51 ` JC Chen[陳饒靜]
2026-09-02 19:08 ` Nirmoy Das
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=b4d8e820-4cd5-7225-5078-678c4f191297@linux.intel.com \
--to=ilpo.jarvinen@linux.intel.com \
--cc=bhelgaas@google.com \
--cc=helgaas@kernel.org \
--cc=jc_chen@diodes.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=nirmoyd@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.