diff options
-rw-r--r-- | drivers/pci/pci.c | 35 | ||||
-rw-r--r-- | drivers/pci/pci.h | 2 | ||||
-rw-r--r-- | drivers/pci/probe.c | 5 | ||||
-rw-r--r-- | include/linux/pci_regs.h | 13 |
4 files changed, 55 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4859669f0ab5..557218222826 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -1546,6 +1546,41 @@ void pci_enable_ari(struct pci_dev *dev) | |||
1546 | } | 1546 | } |
1547 | 1547 | ||
1548 | /** | 1548 | /** |
1549 | * pci_enable_acs - enable ACS if hardware support it | ||
1550 | * @dev: the PCI device | ||
1551 | */ | ||
1552 | void pci_enable_acs(struct pci_dev *dev) | ||
1553 | { | ||
1554 | int pos; | ||
1555 | u16 cap; | ||
1556 | u16 ctrl; | ||
1557 | |||
1558 | if (!dev->is_pcie) | ||
1559 | return; | ||
1560 | |||
1561 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); | ||
1562 | if (!pos) | ||
1563 | return; | ||
1564 | |||
1565 | pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap); | ||
1566 | pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl); | ||
1567 | |||
1568 | /* Source Validation */ | ||
1569 | ctrl |= (cap & PCI_ACS_SV); | ||
1570 | |||
1571 | /* P2P Request Redirect */ | ||
1572 | ctrl |= (cap & PCI_ACS_RR); | ||
1573 | |||
1574 | /* P2P Completion Redirect */ | ||
1575 | ctrl |= (cap & PCI_ACS_CR); | ||
1576 | |||
1577 | /* Upstream Forwarding */ | ||
1578 | ctrl |= (cap & PCI_ACS_UF); | ||
1579 | |||
1580 | pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); | ||
1581 | } | ||
1582 | |||
1583 | /** | ||
1549 | * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge | 1584 | * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge |
1550 | * @dev: the PCI device | 1585 | * @dev: the PCI device |
1551 | * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTD, 4=INTD) | 1586 | * @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 d92d1954a2fb..33ed8e0aba1e 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -311,4 +311,6 @@ static inline int pci_resource_alignment(struct pci_dev *dev, | |||
311 | return resource_alignment(res); | 311 | return resource_alignment(res); |
312 | } | 312 | } |
313 | 313 | ||
314 | extern void pci_enable_acs(struct pci_dev *dev); | ||
315 | |||
314 | #endif /* DRIVERS_PCI_H */ | 316 | #endif /* DRIVERS_PCI_H */ |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2adb47574d86..aac5b156a5c5 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/cpumask.h> | 11 | #include <linux/cpumask.h> |
12 | #include <linux/pci-aspm.h> | 12 | #include <linux/pci-aspm.h> |
13 | #include <linux/iommu.h> | ||
13 | #include "pci.h" | 14 | #include "pci.h" |
14 | 15 | ||
15 | #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ | 16 | #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ |
@@ -1004,6 +1005,10 @@ static void pci_init_capabilities(struct pci_dev *dev) | |||
1004 | 1005 | ||
1005 | /* Single Root I/O Virtualization */ | 1006 | /* Single Root I/O Virtualization */ |
1006 | pci_iov_init(dev); | 1007 | pci_iov_init(dev); |
1008 | |||
1009 | /* Enable ACS P2P upstream forwarding */ | ||
1010 | if (iommu_found()) | ||
1011 | pci_enable_acs(dev); | ||
1007 | } | 1012 | } |
1008 | 1013 | ||
1009 | void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) | 1014 | 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 dd0bed4f1cf0..d798770f08cd 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h | |||
@@ -502,6 +502,7 @@ | |||
502 | #define PCI_EXT_CAP_ID_VC 2 | 502 | #define PCI_EXT_CAP_ID_VC 2 |
503 | #define PCI_EXT_CAP_ID_DSN 3 | 503 | #define PCI_EXT_CAP_ID_DSN 3 |
504 | #define PCI_EXT_CAP_ID_PWR 4 | 504 | #define PCI_EXT_CAP_ID_PWR 4 |
505 | #define PCI_EXT_CAP_ID_ACS 13 | ||
505 | #define PCI_EXT_CAP_ID_ARI 14 | 506 | #define PCI_EXT_CAP_ID_ARI 14 |
506 | #define PCI_EXT_CAP_ID_ATS 15 | 507 | #define PCI_EXT_CAP_ID_ATS 15 |
507 | #define PCI_EXT_CAP_ID_SRIOV 16 | 508 | #define PCI_EXT_CAP_ID_SRIOV 16 |
@@ -662,4 +663,16 @@ | |||
662 | #define PCI_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */ | 663 | #define PCI_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */ |
663 | #define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */ | 664 | #define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */ |
664 | 665 | ||
666 | /* Access Control Service */ | ||
667 | #define PCI_ACS_CAP 0x04 /* ACS Capability Register */ | ||
668 | #define PCI_ACS_SV 0x01 /* Source Validation */ | ||
669 | #define PCI_ACS_TB 0x02 /* Translation Blocking */ | ||
670 | #define PCI_ACS_RR 0x04 /* P2P Request Redirect */ | ||
671 | #define PCI_ACS_CR 0x08 /* P2P Completion Redirect */ | ||
672 | #define PCI_ACS_UF 0x10 /* Upstream Forwarding */ | ||
673 | #define PCI_ACS_EC 0x20 /* P2P Egress Control */ | ||
674 | #define PCI_ACS_DT 0x40 /* Direct Translated P2P */ | ||
675 | #define PCI_ACS_CTRL 0x06 /* ACS Control Register */ | ||
676 | #define PCI_ACS_EGRESS_CTL_V 0x08 /* ACS Egress Control Vector */ | ||
677 | |||
665 | #endif /* LINUX_PCI_REGS_H */ | 678 | #endif /* LINUX_PCI_REGS_H */ |