Skip to content

Commit 4e33789

Browse files
committed
NVIDIA: SAUCE: PCI: quirks: mirror PI7C9X3G606GPC Port 4 BAR0
Some Pericom/Diodes PI7C9X3G606GPC switches require downstream Port 4 BAR0 to mirror BAR0 of the immediate upstream port. Firmware may apply this during boot, but Linux PCI resource assignment can move the upstream BAR0 and leave Port 4 without the required mirror. Diodes confirmed that Tile0/P4 is OS-visible as device 04, function 0 on the bus below the upstream port. Add a final and early resume quirk for that downstream function. The quirk verifies that the immediate upstream bridge is the same switch, then writes Port 4 BAR0 from the upstream BAR0 after resource assignment and during early resume. Port 4 BAR0 may read back as zero even after a successful write, so the write must be validated by platform-specific means. Change-Id: I01079d67c4f665da5162180db929e2fe43d64ac2 Signed-off-by: Nirmoy Das <nirmoyd@nvidia.com>
1 parent bc8a6c3 commit 4e33789

2 files changed

Lines changed: 53 additions & 0 deletions

File tree

drivers/pci/quirks.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6259,6 +6259,58 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_PERICOM, 0xb404,
62596259
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_PERICOM, 0xb404,
62606260
pci_fixup_pericom_acs_store_forward);
62616261

6262+
/*
6263+
* Some Pericom/Diodes PI7C9X3G606GPC switches require downstream Port 4
6264+
* BAR 0 to mirror BAR 0 of the immediate upstream port. Firmware may
6265+
* program this during boot, but Linux resource assignment can move the
6266+
* upstream BAR.
6267+
*
6268+
* Diodes confirmed Tile0/P4 appears to Linux as device 4, function 0 on
6269+
* the bus below the upstream port. Match that downstream function and
6270+
* re-apply the mirror after resource assignment and early resume.
6271+
*/
6272+
static void pci_fixup_pericom_pi7c9x3g606gpc_bar0_mirror(struct pci_dev *pdev)
6273+
{
6274+
struct pci_dev *upstream;
6275+
u32 bar, upstream_bar;
6276+
6277+
if (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)
6278+
return;
6279+
6280+
if (PCI_SLOT(pdev->devfn) != 4 || PCI_FUNC(pdev->devfn))
6281+
return;
6282+
6283+
upstream = pci_upstream_bridge(pdev);
6284+
if (!upstream || upstream->vendor != PCI_VENDOR_ID_PERICOM ||
6285+
upstream->device != PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC ||
6286+
pci_pcie_type(upstream) != PCI_EXP_TYPE_UPSTREAM)
6287+
return;
6288+
6289+
pci_read_config_dword(upstream, PCI_BASE_ADDRESS_0, &upstream_bar);
6290+
if (upstream_bar & PCI_BASE_ADDRESS_SPACE_IO)
6291+
return;
6292+
6293+
if (!(upstream_bar & PCI_BASE_ADDRESS_MEM_MASK)) {
6294+
pci_warn(pdev, "skipping PI7C9X3G606GPC BAR0 mirror workaround because upstream BAR 0 is unassigned\n");
6295+
return;
6296+
}
6297+
6298+
pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &bar);
6299+
if (bar == upstream_bar)
6300+
return;
6301+
6302+
/* Port 4 BAR 0 may read back as zero even after a successful write. */
6303+
pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, upstream_bar);
6304+
pci_info(pdev, "wrote upstream BAR 0 %#x to Port 4 BAR 0 for PI7C9X3G606GPC BAR0 mirror workaround\n",
6305+
upstream_bar);
6306+
}
6307+
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_PERICOM,
6308+
PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC,
6309+
pci_fixup_pericom_pi7c9x3g606gpc_bar0_mirror);
6310+
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_PERICOM,
6311+
PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC,
6312+
pci_fixup_pericom_pi7c9x3g606gpc_bar0_mirror);
6313+
62626314
static void nvidia_ion_ahci_fixup(struct pci_dev *pdev)
62636315
{
62646316
pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING;

include/linux/pci_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,6 +1848,7 @@
18481848
#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
18491849

18501850
#define PCI_VENDOR_ID_PERICOM 0x12D8
1851+
#define PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC 0xc008
18511852
#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951
18521853
#define PCI_DEVICE_ID_PERICOM_PI7C9X7952 0x7952
18531854
#define PCI_DEVICE_ID_PERICOM_PI7C9X7954 0x7954

0 commit comments

Comments
 (0)