diff options
author | Yu Zhao <yu.zhao@intel.com> | 2008-12-22 03:54:58 -0500 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2009-01-03 06:05:28 -0500 |
commit | 2e824f79240476d57a8589f46232cabf151efe90 (patch) | |
tree | 0e6011ff3237ba92ddae39029ea501358c7de6b7 | |
parent | 19c239ce3d089fee339d1ab7e97b43d6f0557ce5 (diff) |
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>
-rw-r--r-- | drivers/pci/dmar.c | 36 |
1 files changed, 18 insertions, 18 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 691b3adeb870..5f164ff3026e 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -191,26 +191,17 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header) | |||
191 | static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru) | 191 | static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru) |
192 | { | 192 | { |
193 | struct acpi_dmar_hardware_unit *drhd; | 193 | struct acpi_dmar_hardware_unit *drhd; |
194 | static int include_all; | ||
195 | int ret = 0; | 194 | int ret = 0; |
196 | 195 | ||
197 | drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr; | 196 | drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr; |
198 | 197 | ||
199 | if (!dmaru->include_all) | 198 | if (dmaru->include_all) |
200 | ret = dmar_parse_dev_scope((void *)(drhd + 1), | 199 | return 0; |
200 | |||
201 | ret = dmar_parse_dev_scope((void *)(drhd + 1), | ||
201 | ((void *)drhd) + drhd->header.length, | 202 | ((void *)drhd) + drhd->header.length, |
202 | &dmaru->devices_cnt, &dmaru->devices, | 203 | &dmaru->devices_cnt, &dmaru->devices, |
203 | drhd->segment); | 204 | drhd->segment); |
204 | else { | ||
205 | /* Only allow one INCLUDE_ALL */ | ||
206 | if (include_all) { | ||
207 | printk(KERN_WARNING PREFIX "Only one INCLUDE_ALL " | ||
208 | "device scope is allowed\n"); | ||
209 | ret = -EINVAL; | ||
210 | } | ||
211 | include_all = 1; | ||
212 | } | ||
213 | |||
214 | if (ret) { | 205 | if (ret) { |
215 | list_del(&dmaru->list); | 206 | list_del(&dmaru->list); |
216 | kfree(dmaru); | 207 | kfree(dmaru); |
@@ -384,12 +375,21 @@ int dmar_pci_device_match(struct pci_dev *devices[], int cnt, | |||
384 | struct dmar_drhd_unit * | 375 | struct dmar_drhd_unit * |
385 | dmar_find_matched_drhd_unit(struct pci_dev *dev) | 376 | dmar_find_matched_drhd_unit(struct pci_dev *dev) |
386 | { | 377 | { |
387 | struct dmar_drhd_unit *drhd = NULL; | 378 | struct dmar_drhd_unit *dmaru = NULL; |
379 | struct acpi_dmar_hardware_unit *drhd; | ||
380 | |||
381 | list_for_each_entry(dmaru, &dmar_drhd_units, list) { | ||
382 | drhd = container_of(dmaru->hdr, | ||
383 | struct acpi_dmar_hardware_unit, | ||
384 | header); | ||
385 | |||
386 | if (dmaru->include_all && | ||
387 | drhd->segment == pci_domain_nr(dev->bus)) | ||
388 | return dmaru; | ||
388 | 389 | ||
389 | list_for_each_entry(drhd, &dmar_drhd_units, list) { | 390 | if (dmar_pci_device_match(dmaru->devices, |
390 | if (drhd->include_all || dmar_pci_device_match(drhd->devices, | 391 | dmaru->devices_cnt, dev)) |
391 | drhd->devices_cnt, dev)) | 392 | return dmaru; |
392 | return drhd; | ||
393 | } | 393 | } |
394 | 394 | ||
395 | return NULL; | 395 | return NULL; |