aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/quirks.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r--drivers/pci/quirks.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 1be2894ada70..d274e07b3386 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -4497,7 +4497,7 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
static bool pci_quirk_cavium_acs_match(struct pci_dev *dev)
{
- if (!pci_is_pcie(dev) || pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
+ if (!pci_is_pcie(dev))
return false;
switch (dev->device) {
@@ -5777,3 +5777,42 @@ static void nvidia_ion_ahci_fixup(struct pci_dev *pdev)
pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING;
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup);
+
+/* Marvell cnf10ka (0xba00) requires fix for device at slot (0xe), func. 0x0
+ * Wrong values for BAR0 and BAR4 are fetched from config space.
+ * There are some devices that doesn't require fixing, so the fix is not always
+ * applied. Deciding factor is curent value of BAR0/BAR4.
+ * Config. space for cnf10ka is read-only, Changing the registers isn't possible
+ */
+#define CAVIUM_XCP0_ADDR_OK 0x000082c000000000ULL /* Correct PCI BAR base */
+#define CAVIUM_XCP0_FIX_MASK 0xffffffff00000000ULL
+#define CAVIUM_XCP0_SHOULD_FIX(addr) \
+ (((addr) & CAVIUM_XCP0_FIX_MASK) != CAVIUM_XCP0_ADDR_OK)
+#define CAVIUM_XCP0_FIX_ADDR(addr) \
+ (((addr) & (~CAVIUM_XCP0_FIX_MASK)) | CAVIUM_XCP0_ADDR_OK)
+
+static void quirk_cavium_xcp0_bar_fixup(struct pci_dev *dev)
+{
+ int i;
+
+ if (dev->subsystem_device == 0xba00 && dev->devfn == 0xe0) {
+ for (i = 0; i < PCI_STD_RESOURCE_END; i++) {
+
+ struct resource *r = &dev->resource[i];
+ int ret;
+
+ if (!(r->flags & IORESOURCE_MEM))
+ continue;
+
+ /* There are revision of HW that not need fixup */
+ if (CAVIUM_XCP0_SHOULD_FIX(r->start)) {
+ r->start = CAVIUM_XCP0_FIX_ADDR(r->start);
+ r->end = CAVIUM_XCP0_FIX_ADDR(r->end);
+ ret = pci_claim_resource(dev, i);
+ pci_info(dev, "Fixup (%d) %llx - %llx/%lx. (%d)\n",
+ i, r->start, r->end, r->flags, ret);
+ }
+ }
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CAVIUM, 0xa067, quirk_cavium_xcp0_bar_fixup);