iommu/vt-d: Fix error in detect ATS capability
Current Intel IOMMU driver only matches a PCIe root port with the first DRHD unit with the samge segment number. It will report false result if there are multiple DRHD units with the same segment number, thus fail to detect ATS capability for some PCIe devices. This patch refines function dmar_find_matched_atsr_unit() to search all DRHD units with the same segment number. An example DMAR table entries as below: [1D0h 0464 2] Subtable Type : 0002 <Root Port ATS Capability> [1D2h 0466 2] Length : 0028 [1D4h 0468 1] Flags : 00 [1D5h 0469 1] Reserved : 00 [1D6h 0470 2] PCI Segment Number : 0000 [1D8h 0472 1] Device Scope Entry Type : 02 [1D9h 0473 1] Entry Length : 08 [1DAh 0474 2] Reserved : 0000 [1DCh 0476 1] Enumeration ID : 00 [1DDh 0477 1] PCI Bus Number : 00 [1DEh 0478 2] PCI Path : [02, 00] [1E0h 0480 1] Device Scope Entry Type : 02 [1E1h 0481 1] Entry Length : 08 [1E2h 0482 2] Reserved : 0000 [1E4h 0484 1] Enumeration ID : 00 [1E5h 0485 1] PCI Bus Number : 00 [1E6h 0486 2] PCI Path : [03, 00] [1E8h 0488 1] Device Scope Entry Type : 02 [1E9h 0489 1] Entry Length : 08 [1EAh 0490 2] Reserved : 0000 [1ECh 0492 1] Enumeration ID : 00 [1EDh 0493 1] PCI Bus Number : 00 [1EEh 0494 2] PCI Path : [03, 02] [1F0h 0496 1] Device Scope Entry Type : 02 [1F1h 0497 1] Entry Length : 08 [1F2h 0498 2] Reserved : 0000 [1F4h 0500 1] Enumeration ID : 00 [1F5h 0501 1] PCI Bus Number : 00 [1F6h 0502 2] PCI Path : [03, 03] [1F8h 0504 2] Subtable Type : 0002 <Root Port ATS Capability> [1FAh 0506 2] Length : 0020 [1FCh 0508 1] Flags : 00 [1FDh 0509 1] Reserved : 00 [1FEh 0510 2] PCI Segment Number : 0000 [200h 0512 1] Device Scope Entry Type : 02 [201h 0513 1] Entry Length : 08 [202h 0514 2] Reserved : 0000 [204h 0516 1] Enumeration ID : 00 [205h 0517 1] PCI Bus Number : 40 [206h 0518 2] PCI Path : [02, 00] [208h 0520 1] Device Scope Entry Type : 02 [209h 0521 1] Entry Length : 08 [20Ah 0522 2] Reserved : 0000 [20Ch 0524 1] Enumeration ID : 00 [20Dh 0525 1] PCI Bus Number : 40 [20Eh 0526 2] PCI Path : [02, 02] [210h 0528 1] Device Scope Entry Type : 02 [211h 0529 1] Entry Length : 08 [212h 0530 2] Reserved : 0000 [214h 0532 1] Enumeration ID : 00 [215h 0533 1] PCI Bus Number : 40 [216h 0534 2] PCI Path : [03, 00] [218h 0536 2] Subtable Type : 0002 <Root Port ATS Capability> [21Ah 0538 2] Length : 0020 [21Ch 0540 1] Flags : 00 [21Dh 0541 1] Reserved : 00 [21Eh 0542 2] PCI Segment Number : 0000 [220h 0544 1] Device Scope Entry Type : 02 [221h 0545 1] Entry Length : 08 [222h 0546 2] Reserved : 0000 [224h 0548 1] Enumeration ID : 00 [225h 0549 1] PCI Bus Number : 80 [226h 0550 2] PCI Path : [02, 00] [228h 0552 1] Device Scope Entry Type : 02 [229h 0553 1] Entry Length : 08 [22Ah 0554 2] Reserved : 0000 [22Ch 0556 1] Enumeration ID : 00 [22Dh 0557 1] PCI Bus Number : 80 [22Eh 0558 2] PCI Path : [02, 02] [230h 0560 1] Device Scope Entry Type : 02 [231h 0561 1] Entry Length : 08 [232h 0562 2] Reserved : 0000 [234h 0564 1] Enumeration ID : 00 [235h 0565 1] PCI Bus Number : 80 [236h 0566 2] PCI Path : [03, 00] [238h 0568 2] Subtable Type : 0002 <Root Port ATS Capability> [23Ah 0570 2] Length : 0020 [23Ch 0572 1] Flags : 00 [23Dh 0573 1] Reserved : 00 [23Eh 0574 2] PCI Segment Number : 0000 [240h 0576 1] Device Scope Entry Type : 02 [241h 0577 1] Entry Length : 08 [242h 0578 2] Reserved : 0000 [244h 0580 1] Enumeration ID : 00 [245h 0581 1] PCI Bus Number : C0 [246h 0582 2] PCI Path : [02, 00] [248h 0584 1] Device Scope Entry Type : 02 [249h 0585 1] Entry Length : 08 [24Ah 0586 2] Reserved : 0000 [24Ch 0588 1] Enumeration ID : 00 [24Dh 0589 1] PCI Bus Number : C0 [24Eh 0590 2] PCI Path : [02, 02] [250h 0592 1] Device Scope Entry Type : 02 [251h 0593 1] Entry Length : 08 [252h 0594 2] Reserved : 0000 [254h 0596 1] Enumeration ID : 00 [255h 0597 1] PCI Bus Number : C0 [256h 0598 2] PCI Path : [03, 00] Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Signed-off-by: Joerg Roedel <joro@8bytes.org>
This commit is contained in:
parent
a4eaa86c0c
commit
b5f82ddf22
|
@ -3562,37 +3562,34 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct pci_bus *bus;
|
struct pci_bus *bus;
|
||||||
|
struct pci_dev *bridge = NULL;
|
||||||
struct acpi_dmar_atsr *atsr;
|
struct acpi_dmar_atsr *atsr;
|
||||||
struct dmar_atsr_unit *atsru;
|
struct dmar_atsr_unit *atsru;
|
||||||
|
|
||||||
dev = pci_physfn(dev);
|
dev = pci_physfn(dev);
|
||||||
|
|
||||||
list_for_each_entry(atsru, &dmar_atsr_units, list) {
|
|
||||||
atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
|
|
||||||
if (atsr->segment == pci_domain_nr(dev->bus))
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
found:
|
|
||||||
for (bus = dev->bus; bus; bus = bus->parent) {
|
for (bus = dev->bus; bus; bus = bus->parent) {
|
||||||
struct pci_dev *bridge = bus->self;
|
bridge = bus->self;
|
||||||
|
|
||||||
if (!bridge || !pci_is_pcie(bridge) ||
|
if (!bridge || !pci_is_pcie(bridge) ||
|
||||||
pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
|
pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
|
||||||
if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT) {
|
|
||||||
for (i = 0; i < atsru->devices_cnt; i++)
|
|
||||||
if (atsru->devices[i] == bridge)
|
|
||||||
return 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!bridge)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (atsru->include_all)
|
list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
|
||||||
return 1;
|
atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
|
||||||
|
if (atsr->segment != pci_domain_nr(dev->bus))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i = 0; i < atsru->devices_cnt; i++)
|
||||||
|
if (atsru->devices[i] == bridge)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (atsru->include_all)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue