aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/dmar.c
diff options
context:
space:
mode:
authorYu Zhao <yu.zhao@intel.com>2008-12-22 03:54:58 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2009-01-03 06:05:28 -0500
commit2e824f79240476d57a8589f46232cabf151efe90 (patch)
tree0e6011ff3237ba92ddae39029ea501358c7de6b7 /drivers/pci/dmar.c
parent19c239ce3d089fee339d1ab7e97b43d6f0557ce5 (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>
Diffstat (limited to 'drivers/pci/dmar.c')
-rw-r--r--drivers/pci/dmar.c36
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)
191static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru) 191static 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,
384struct dmar_drhd_unit * 375struct dmar_drhd_unit *
385dmar_find_matched_drhd_unit(struct pci_dev *dev) 376dmar_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;