diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 7b70312..8272835 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1513,6 +1513,43 @@ void pci_enable_ari(struct pci_dev *dev) } /** + * pci_acs_enable - enable ACS if hardware support it + * @dev: the PCI device + */ +void pci_acs_init(struct pci_dev *dev) +{ + int pos; + u16 cap; + u16 ctrl; + + if (!dev->is_pcie) + return; + + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); + if (!pos) + return; + pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap); + + /* Source Validation */ + if (cap & PCI_EXP_ACS_V) + ctrl |= PCI_EXP_ACS_V; + + /* P2P Request Redirect */ + if (cap & PCI_EXP_ACS_R) + ctrl |= PCI_EXP_ACS_R; + + /* P2P Completion Redirect */ + if (cap & PCI_EXP_ACS_C) + ctrl |= PCI_EXP_ACS_C; + + /* Upstream Forwarding */ + if (cap & PCI_EXP_ACS_U) + ctrl |= PCI_EXP_ACS_U; + + pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); +} + +/** * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge * @dev: the PCI device * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTD, 4=INTD) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 5ff4d25..1d8976d 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -202,6 +202,7 @@ static inline int pci_ari_enabled(struct pci_bus *bus) { return bus->self && bus->self->ari_enabled; } +extern void pci_acs_init(struct pci_dev *dev); #ifdef CONFIG_PCI_QUIRKS extern int pci_is_reassigndev(struct pci_dev *dev); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 40e75f6..4a5ec9e 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -991,6 +991,9 @@ static void pci_init_capabilities(struct pci_dev *dev) /* Single Root I/O Virtualization */ pci_iov_init(dev); + + /* Access Control Service */ + pci_acs_init(dev); } void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index fcaee42..90014ad 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -492,6 +492,14 @@ #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ +#define PCI_EXP_ACS_V 0x01 /* Source Validation */ +#define PCI_EXP_ACS_B 0x02 /* Translation Blocking */ +#define PCI_EXP_ACS_R 0x04 /* P2P Request Redirect */ +#define PCI_EXP_ACS_C 0x08 /* P2P Completion Redirect */ +#define PCI_EXP_ACS_U 0x10 /* Upstream Forwarding */ +#define PCI_EXP_ACS_E 0x20 /* P2P Egress Control */ +#define PCI_EXP_ACS_T 0x40 /* Direct Translated P2P */ + /* Extended Capabilities (PCI-X 2.0 and Express) */ #define PCI_EXT_CAP_ID(header) (header & 0x0000ffff) #define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf) @@ -501,6 +509,7 @@ #define PCI_EXT_CAP_ID_VC 2 #define PCI_EXT_CAP_ID_DSN 3 #define PCI_EXT_CAP_ID_PWR 4 +#define PCI_EXT_CAP_ID_ACS 13 #define PCI_EXT_CAP_ID_ARI 14 #define PCI_EXT_CAP_ID_ATS 15 #define PCI_EXT_CAP_ID_SRIOV 16 @@ -661,4 +670,9 @@ #define PCI_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */ #define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */ +/* Access Control Service */ +#define PCI_ACS_CAP 0x04 /* ACS Capability Register */ +#define PCI_ACS_CTRL 0x06 /* ACS Control Register */ +#define PCI_ACS_EGRESS_CTL_V 0x08 /* ACS Egress Control Vector */ + #endif /* LINUX_PCI_REGS_H */