Merge branch 'pci/switchtec'
- Add DMA alias quirk for Microsemi Switchtec NTB (Doug Meyer) - Expand documentation for pci_add_dma_alias() (Logan Gunthorpe) * pci/switchtec: PCI: Expand documentation for pci_add_dma_alias() PCI: Add DMA alias quirk for Microsemi Switchtec NTB switchtec: Use generic PCI Vendor ID and Class Code # Conflicts: # drivers/pci/quirks.c
This commit is contained in:
commit
e7aaf90f9d
6 changed files with 163 additions and 14 deletions
|
@ -19,6 +19,7 @@
|
|||
#include <linux/kthread.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ntb.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
MODULE_DESCRIPTION("Microsemi Switchtec(tm) NTB Driver");
|
||||
MODULE_VERSION("0.1");
|
||||
|
@ -1487,7 +1488,7 @@ static int switchtec_ntb_add(struct device *dev,
|
|||
|
||||
stdev->sndev = NULL;
|
||||
|
||||
if (stdev->pdev->class != MICROSEMI_NTB_CLASSCODE)
|
||||
if (stdev->pdev->class != (PCI_CLASS_BRIDGE_OTHER << 8))
|
||||
return -ENODEV;
|
||||
|
||||
sndev = kzalloc_node(sizeof(*sndev), GFP_KERNEL, dev_to_node(dev));
|
||||
|
|
|
@ -5710,8 +5710,19 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode,
|
|||
* @dev: the PCI device for which alias is added
|
||||
* @devfn: alias slot and function
|
||||
*
|
||||
* This helper encodes 8-bit devfn as bit number in dma_alias_mask.
|
||||
* It should be called early, preferably as PCI fixup header quirk.
|
||||
* This helper encodes an 8-bit devfn as a bit number in dma_alias_mask
|
||||
* which is used to program permissible bus-devfn source addresses for DMA
|
||||
* requests in an IOMMU. These aliases factor into IOMMU group creation
|
||||
* and are useful for devices generating DMA requests beyond or different
|
||||
* from their logical bus-devfn. Examples include device quirks where the
|
||||
* device simply uses the wrong devfn, as well as non-transparent bridges
|
||||
* where the alias may be a proxy for devices in another domain.
|
||||
*
|
||||
* IOMMU group creation is performed during device discovery or addition,
|
||||
* prior to any potential DMA mapping and therefore prior to driver probing
|
||||
* (especially for userspace assigned devices where IOMMU group definition
|
||||
* cannot be left as a userspace activity). DMA aliases should therefore
|
||||
* be configured via quirks, such as the PCI fixup header quirk.
|
||||
*/
|
||||
void pci_add_dma_alias(struct pci_dev *dev, u8 devfn)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -641,7 +641,7 @@ static int ioctl_event_summary(struct switchtec_dev *stdev,
|
|||
|
||||
for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++) {
|
||||
reg = ioread16(&stdev->mmio_pff_csr[i].vendor_id);
|
||||
if (reg != MICROSEMI_VENDOR_ID)
|
||||
if (reg != PCI_VENDOR_ID_MICROSEMI)
|
||||
break;
|
||||
|
||||
reg = ioread32(&stdev->mmio_pff_csr[i].pff_event_summary);
|
||||
|
@ -1203,7 +1203,7 @@ static void init_pff(struct switchtec_dev *stdev)
|
|||
|
||||
for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++) {
|
||||
reg = ioread16(&stdev->mmio_pff_csr[i].vendor_id);
|
||||
if (reg != MICROSEMI_VENDOR_ID)
|
||||
if (reg != PCI_VENDOR_ID_MICROSEMI)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1267,7 +1267,7 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
|
|||
struct switchtec_dev *stdev;
|
||||
int rc;
|
||||
|
||||
if (pdev->class == MICROSEMI_NTB_CLASSCODE)
|
||||
if (pdev->class == (PCI_CLASS_BRIDGE_OTHER << 8))
|
||||
request_module_nowait("ntb_hw_switchtec");
|
||||
|
||||
stdev = stdev_create(pdev);
|
||||
|
@ -1321,19 +1321,19 @@ static void switchtec_pci_remove(struct pci_dev *pdev)
|
|||
|
||||
#define SWITCHTEC_PCI_DEVICE(device_id) \
|
||||
{ \
|
||||
.vendor = MICROSEMI_VENDOR_ID, \
|
||||
.vendor = PCI_VENDOR_ID_MICROSEMI, \
|
||||
.device = device_id, \
|
||||
.subvendor = PCI_ANY_ID, \
|
||||
.subdevice = PCI_ANY_ID, \
|
||||
.class = MICROSEMI_MGMT_CLASSCODE, \
|
||||
.class = (PCI_CLASS_MEMORY_OTHER << 8), \
|
||||
.class_mask = 0xFFFFFFFF, \
|
||||
}, \
|
||||
{ \
|
||||
.vendor = MICROSEMI_VENDOR_ID, \
|
||||
.vendor = PCI_VENDOR_ID_MICROSEMI, \
|
||||
.device = device_id, \
|
||||
.subvendor = PCI_ANY_ID, \
|
||||
.subdevice = PCI_ANY_ID, \
|
||||
.class = MICROSEMI_NTB_CLASSCODE, \
|
||||
.class = (PCI_CLASS_BRIDGE_OTHER << 8), \
|
||||
.class_mask = 0xFFFFFFFF, \
|
||||
}
|
||||
|
||||
|
|
|
@ -1668,6 +1668,7 @@
|
|||
#define PCI_DEVICE_ID_COMPEX_ENET100VG4 0x0112
|
||||
|
||||
#define PCI_VENDOR_ID_PMC_Sierra 0x11f8
|
||||
#define PCI_VENDOR_ID_MICROSEMI 0x11f8
|
||||
|
||||
#define PCI_VENDOR_ID_RP 0x11fe
|
||||
#define PCI_DEVICE_ID_RP32INTF 0x0001
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/cdev.h>
|
||||
|
||||
#define MICROSEMI_VENDOR_ID 0x11f8
|
||||
#define MICROSEMI_NTB_CLASSCODE 0x068000
|
||||
#define MICROSEMI_MGMT_CLASSCODE 0x058000
|
||||
|
||||
#define SWITCHTEC_MRPC_PAYLOAD_SIZE 1024
|
||||
#define SWITCHTEC_MAX_PFF_CSR 48
|
||||
|
||||
|
|
Loading…
Reference in a new issue