VT-d: fix segment number being ignored when searching DRHD
On platforms with multiple PCI segments, any of the segments can have a DRHD with INCLUDE_PCI_ALL flag. So need to check the DRHD's segment number against the PCI device's when searching its DRHD. Signed-off-by: Yu Zhao <yu.zhao@intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
This commit is contained in:
@@ -191,26 +191,17 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
|
|||||||
static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru)
|
static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru)
|
||||||
{
|
{
|
||||||
struct acpi_dmar_hardware_unit *drhd;
|
struct acpi_dmar_hardware_unit *drhd;
|
||||||
static int include_all;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
|
drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
|
||||||
|
|
||||||
if (!dmaru->include_all)
|
if (dmaru->include_all)
|
||||||
|
return 0;
|
||||||
|
|
||||||
ret = dmar_parse_dev_scope((void *)(drhd + 1),
|
ret = dmar_parse_dev_scope((void *)(drhd + 1),
|
||||||
((void *)drhd) + drhd->header.length,
|
((void *)drhd) + drhd->header.length,
|
||||||
&dmaru->devices_cnt, &dmaru->devices,
|
&dmaru->devices_cnt, &dmaru->devices,
|
||||||
drhd->segment);
|
drhd->segment);
|
||||||
else {
|
|
||||||
/* Only allow one INCLUDE_ALL */
|
|
||||||
if (include_all) {
|
|
||||||
printk(KERN_WARNING PREFIX "Only one INCLUDE_ALL "
|
|
||||||
"device scope is allowed\n");
|
|
||||||
ret = -EINVAL;
|
|
||||||
}
|
|
||||||
include_all = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
list_del(&dmaru->list);
|
list_del(&dmaru->list);
|
||||||
kfree(dmaru);
|
kfree(dmaru);
|
||||||
@@ -384,12 +375,21 @@ int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
|
|||||||
struct dmar_drhd_unit *
|
struct dmar_drhd_unit *
|
||||||
dmar_find_matched_drhd_unit(struct pci_dev *dev)
|
dmar_find_matched_drhd_unit(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
struct dmar_drhd_unit *drhd = NULL;
|
struct dmar_drhd_unit *dmaru = NULL;
|
||||||
|
struct acpi_dmar_hardware_unit *drhd;
|
||||||
|
|
||||||
list_for_each_entry(drhd, &dmar_drhd_units, list) {
|
list_for_each_entry(dmaru, &dmar_drhd_units, list) {
|
||||||
if (drhd->include_all || dmar_pci_device_match(drhd->devices,
|
drhd = container_of(dmaru->hdr,
|
||||||
drhd->devices_cnt, dev))
|
struct acpi_dmar_hardware_unit,
|
||||||
return drhd;
|
header);
|
||||||
|
|
||||||
|
if (dmaru->include_all &&
|
||||||
|
drhd->segment == pci_domain_nr(dev->bus))
|
||||||
|
return dmaru;
|
||||||
|
|
||||||
|
if (dmar_pci_device_match(dmaru->devices,
|
||||||
|
dmaru->devices_cnt, dev))
|
||||||
|
return dmaru;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Reference in New Issue
Block a user