|
@@ -27,6 +27,7 @@
|
|
|
#include <linux/mm.h>
|
|
|
#include <linux/platform_data/x86/apple.h>
|
|
|
#include <linux/pm_runtime.h>
|
|
|
+#include <linux/switchtec.h>
|
|
|
#include <asm/dma.h> /* isa_dma_bridge_buggy */
|
|
|
#include "pci.h"
|
|
|
|
|
@@ -4862,3 +4863,142 @@ int pci_idt_bus_quirk(struct pci_bus *bus, int devfn, u32 *l, int timeout)
|
|
|
|
|
|
return found;
|
|
|
}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Microsemi Switchtec NTB uses devfn proxy IDs to move TLPs between
|
|
|
+ * NT endpoints via the internal switch fabric. These IDs replace the
|
|
|
+ * originating requestor ID TLPs which access host memory on peer NTB
|
|
|
+ * ports. Therefore, all proxy IDs must be aliased to the NTB device
|
|
|
+ * to permit access when the IOMMU is turned on.
|
|
|
+ */
|
|
|
+static void quirk_switchtec_ntb_dma_alias(struct pci_dev *pdev)
|
|
|
+{
|
|
|
+ void __iomem *mmio;
|
|
|
+ struct ntb_info_regs __iomem *mmio_ntb;
|
|
|
+ struct ntb_ctrl_regs __iomem *mmio_ctrl;
|
|
|
+ struct sys_info_regs __iomem *mmio_sys_info;
|
|
|
+ u64 partition_map;
|
|
|
+ u8 partition;
|
|
|
+ int pp;
|
|
|
+
|
|
|
+ if (pci_enable_device(pdev)) {
|
|
|
+ pci_err(pdev, "Cannot enable Switchtec device\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ mmio = pci_iomap(pdev, 0, 0);
|
|
|
+ if (mmio == NULL) {
|
|
|
+ pci_disable_device(pdev);
|
|
|
+ pci_err(pdev, "Cannot iomap Switchtec device\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ pci_info(pdev, "Setting Switchtec proxy ID aliases\n");
|
|
|
+
|
|
|
+ mmio_ntb = mmio + SWITCHTEC_GAS_NTB_OFFSET;
|
|
|
+ mmio_ctrl = (void __iomem *) mmio_ntb + SWITCHTEC_NTB_REG_CTRL_OFFSET;
|
|
|
+ mmio_sys_info = mmio + SWITCHTEC_GAS_SYS_INFO_OFFSET;
|
|
|
+
|
|
|
+ partition = ioread8(&mmio_ntb->partition_id);
|
|
|
+
|
|
|
+ partition_map = ioread32(&mmio_ntb->ep_map);
|
|
|
+ partition_map |= ((u64) ioread32(&mmio_ntb->ep_map + 4)) << 32;
|
|
|
+ partition_map &= ~(1ULL << partition);
|
|
|
+
|
|
|
+ for (pp = 0; pp < (sizeof(partition_map) * 8); pp++) {
|
|
|
+ struct ntb_ctrl_regs __iomem *mmio_peer_ctrl;
|
|
|
+ u32 table_sz = 0;
|
|
|
+ int te;
|
|
|
+
|
|
|
+ if (!(partition_map & (1ULL << pp)))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ pci_dbg(pdev, "Processing partition %d\n", pp);
|
|
|
+
|
|
|
+ mmio_peer_ctrl = &mmio_ctrl[pp];
|
|
|
+
|
|
|
+ table_sz = ioread16(&mmio_peer_ctrl->req_id_table_size);
|
|
|
+ if (!table_sz) {
|
|
|
+ pci_warn(pdev, "Partition %d table_sz 0\n", pp);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (table_sz > 512) {
|
|
|
+ pci_warn(pdev,
|
|
|
+ "Invalid Switchtec partition %d table_sz %d\n",
|
|
|
+ pp, table_sz);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (te = 0; te < table_sz; te++) {
|
|
|
+ u32 rid_entry;
|
|
|
+ u8 devfn;
|
|
|
+
|
|
|
+ rid_entry = ioread32(&mmio_peer_ctrl->req_id_table[te]);
|
|
|
+ devfn = (rid_entry >> 1) & 0xFF;
|
|
|
+ pci_dbg(pdev,
|
|
|
+ "Aliasing Partition %d Proxy ID %02x.%d\n",
|
|
|
+ pp, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
|
|
+ pci_add_dma_alias(pdev, devfn);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pci_iounmap(pdev, mmio);
|
|
|
+ pci_disable_device(pdev);
|
|
|
+}
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8531,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8532,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8533,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8534,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8535,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8536,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8543,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8544,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8545,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8546,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8551,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8552,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8553,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8554,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8555,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8556,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8561,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8562,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8563,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8564,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8565,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8566,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8571,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8572,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8573,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8574,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8575,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MICROSEMI, 0x8576,
|
|
|
+ quirk_switchtec_ntb_dma_alias);
|