Revert r276949 and redo the fix for PCIe/PCI bridges, which do not
follow specification and do not provide PCIe capability. Verify if the port above such bridge is downstream PCIe (or root port) and treat the bridge as PCIe/PCI then. This allows to avoid maintaining the table of device ids for bridges without capability, while still calculate correct request originator for devices behind the bridge. Submitted by: Jason Harmening <jason.harmening@gmail.com> MFC after: 1 week
This commit is contained in:
parent
c06167fbd3
commit
af02586229
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=279117
@ -98,6 +98,8 @@ dmar_get_requester(device_t dev, uint16_t *rid)
|
||||
devclass_t pci_class;
|
||||
device_t l, pci, pcib, pcip, pcibp, requester;
|
||||
int cap_offset;
|
||||
uint16_t pcie_flags;
|
||||
bool bridge_is_pcie;
|
||||
|
||||
pci_class = devclass_find("pci");
|
||||
l = requester = dev;
|
||||
@ -144,13 +146,30 @@ dmar_get_requester(device_t dev, uint16_t *rid)
|
||||
} else {
|
||||
/*
|
||||
* Device is not PCIe, it cannot be seen as a
|
||||
* requester by DMAR unit.
|
||||
* requester by DMAR unit. Check whether the
|
||||
* bridge is PCIe.
|
||||
*/
|
||||
requester = pcibp;
|
||||
bridge_is_pcie = pci_find_cap(pcib, PCIY_EXPRESS,
|
||||
&cap_offset) == 0;
|
||||
requester = pcib;
|
||||
|
||||
/* Check whether the bus above the bridge is PCIe. */
|
||||
if (pci_find_cap(pcibp, PCIY_EXPRESS,
|
||||
&cap_offset) == 0) {
|
||||
/*
|
||||
* Check for a buggy PCIe/PCI bridge that
|
||||
* doesn't report the express capability. If
|
||||
* the bridge above it is express but isn't a
|
||||
* PCI bridge, then we know pcib is actually a
|
||||
* PCIe/PCI bridge.
|
||||
*/
|
||||
if (!bridge_is_pcie && pci_find_cap(pcibp,
|
||||
PCIY_EXPRESS, &cap_offset) == 0) {
|
||||
pcie_flags = pci_read_config(pcibp,
|
||||
cap_offset + PCIER_FLAGS, 2);
|
||||
if ((pcie_flags & PCIEM_FLAGS_TYPE) !=
|
||||
PCIEM_TYPE_PCI_BRIDGE)
|
||||
bridge_is_pcie = true;
|
||||
}
|
||||
|
||||
if (bridge_is_pcie) {
|
||||
/*
|
||||
* The current device is not PCIe, but
|
||||
* the bridge above it is. This is a
|
||||
@ -168,6 +187,7 @@ dmar_get_requester(device_t dev, uint16_t *rid)
|
||||
* non-taken transactions.
|
||||
*/
|
||||
*rid = PCI_RID(pci_get_bus(l), 0, 0);
|
||||
l = pcibp;
|
||||
} else {
|
||||
/*
|
||||
* Neither the device nor the bridge
|
||||
@ -177,8 +197,8 @@ dmar_get_requester(device_t dev, uint16_t *rid)
|
||||
* requester ID.
|
||||
*/
|
||||
*rid = pci_get_rid(pcib);
|
||||
l = pcib;
|
||||
}
|
||||
l = pcibp;
|
||||
}
|
||||
}
|
||||
return (requester);
|
||||
|
Loading…
Reference in New Issue
Block a user