Skip to content

Commit f171d75

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 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 after 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: I139ffad14467cabd4cc8491823f36e34bc876ea1 Signed-off-by: Nirmoy Das <nirmoyd@nvidia.com>
1 parent 704a746 commit f171d75

2 files changed

Lines changed: 59 additions & 0 deletions

File tree

drivers/pci/quirks.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6282,6 +6282,64 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_PERICOM, 0xb404,
62826282
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_PERICOM, 0xb404,
62836283
pci_fixup_pericom_acs_store_forward);
62846284

6285+
/*
6286+
* Some Pericom/Diodes PI7C9X3G606GPC switches require downstream Port 4
6287+
* BAR 0 to mirror BAR 0 of the immediate upstream port. Firmware may
6288+
* program this during boot, but Linux resource assignment can move the
6289+
* upstream BAR.
6290+
*
6291+
* Diodes confirmed Tile0/P4 appears to Linux as device 4, function 0 on
6292+
* the bus below the upstream port. Match that downstream function and
6293+
* re-apply the mirror after resource assignment and resume.
6294+
*/
6295+
static void pci_fixup_pericom_pi7c9x3g606gpc_bar0_mirror(struct pci_dev *pdev)
6296+
{
6297+
struct pci_dev *upstream;
6298+
u32 bar, upstream_bar;
6299+
6300+
if (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)
6301+
return;
6302+
6303+
if (PCI_SLOT(pdev->devfn) != 4 || PCI_FUNC(pdev->devfn))
6304+
return;
6305+
6306+
upstream = pci_upstream_bridge(pdev);
6307+
if (!upstream || upstream->vendor != PCI_VENDOR_ID_PERICOM ||
6308+
upstream->device != PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC ||
6309+
pci_pcie_type(upstream) != PCI_EXP_TYPE_UPSTREAM)
6310+
return;
6311+
6312+
pci_read_config_dword(upstream, PCI_BASE_ADDRESS_0, &upstream_bar);
6313+
if (upstream_bar & PCI_BASE_ADDRESS_SPACE_IO)
6314+
return;
6315+
6316+
if ((upstream_bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
6317+
PCI_BASE_ADDRESS_MEM_TYPE_64) {
6318+
pci_warn(pdev, "skipping PI7C9X3G606GPC BAR0 mirror workaround for 64-bit upstream BAR 0\n");
6319+
return;
6320+
}
6321+
6322+
if (!(upstream_bar & PCI_BASE_ADDRESS_MEM_MASK)) {
6323+
pci_warn(pdev, "skipping PI7C9X3G606GPC BAR0 mirror workaround because upstream BAR 0 is unassigned\n");
6324+
return;
6325+
}
6326+
6327+
pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &bar);
6328+
if (bar == upstream_bar)
6329+
return;
6330+
6331+
/* Port 4 BAR 0 may read back as zero even after a successful write. */
6332+
pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, upstream_bar);
6333+
pci_info(pdev, "wrote upstream BAR 0 %#x to Port 4 BAR 0 for PI7C9X3G606GPC BAR0 mirror workaround\n",
6334+
upstream_bar);
6335+
}
6336+
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_PERICOM,
6337+
PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC,
6338+
pci_fixup_pericom_pi7c9x3g606gpc_bar0_mirror);
6339+
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_PERICOM,
6340+
PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC,
6341+
pci_fixup_pericom_pi7c9x3g606gpc_bar0_mirror);
6342+
62856343
static void nvidia_ion_ahci_fixup(struct pci_dev *pdev)
62866344
{
62876345
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
@@ -1845,6 +1845,7 @@
18451845
#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
18461846

18471847
#define PCI_VENDOR_ID_PERICOM 0x12D8
1848+
#define PCI_DEVICE_ID_PERICOM_PI7C9X3G606GPC 0xc008
18481849
#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951
18491850
#define PCI_DEVICE_ID_PERICOM_PI7C9X7952 0x7952
18501851
#define PCI_DEVICE_ID_PERICOM_PI7C9X7954 0x7954

0 commit comments

Comments
 (0)