Skip to content

Commit c2c4176

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: I86222773f9bb321ea3e24df7fb1b4a3f84a008a4 Signed-off-by: Nirmoy Das <nirmoyd@nvidia.com>
1 parent 42cad5f commit c2c4176

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
@@ -6261,6 +6261,58 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_PERICOM, 0x2303,
62616261
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_PERICOM, 0x2303,
62626262
pci_fixup_pericom_acs_store_forward);
62636263

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

18521852
#define PCI_VENDOR_ID_PERICOM 0x12D8
1853+
#define PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC 0xc008
18531854
#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951
18541855
#define PCI_DEVICE_ID_PERICOM_PI7C9X7952 0x7952
18551856
#define PCI_DEVICE_ID_PERICOM_PI7C9X7954 0x7954

0 commit comments

Comments
 (0)