diff options
Diffstat (limited to 'drivers/pci/dmar.c')
-rw-r--r-- | drivers/pci/dmar.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 691b3adeb870..f5a662a50acb 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; | ||
388 | 380 | ||
389 | list_for_each_entry(drhd, &dmar_drhd_units, list) { | 381 | list_for_each_entry(dmaru, &dmar_drhd_units, list) { |
390 | if (drhd->include_all || dmar_pci_device_match(drhd->devices, | 382 | drhd = container_of(dmaru->hdr, |
391 | drhd->devices_cnt, dev)) | 383 | struct acpi_dmar_hardware_unit, |
392 | return drhd; | 384 | header); |
385 | |||
386 | if (dmaru->include_all && | ||
387 | drhd->segment == pci_domain_nr(dev->bus)) | ||
388 | return dmaru; | ||
389 | |||
390 | if (dmar_pci_device_match(dmaru->devices, | ||
391 | dmaru->devices_cnt, dev)) | ||
392 | return dmaru; | ||
393 | } | 393 | } |
394 | 394 | ||
395 | return NULL; | 395 | return NULL; |
@@ -491,6 +491,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
491 | int map_size; | 491 | int map_size; |
492 | u32 ver; | 492 | u32 ver; |
493 | static int iommu_allocated = 0; | 493 | static int iommu_allocated = 0; |
494 | int agaw; | ||
494 | 495 | ||
495 | iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); | 496 | iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); |
496 | if (!iommu) | 497 | if (!iommu) |
@@ -506,6 +507,15 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
506 | iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); | 507 | iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); |
507 | iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); | 508 | iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); |
508 | 509 | ||
510 | agaw = iommu_calculate_agaw(iommu); | ||
511 | if (agaw < 0) { | ||
512 | printk(KERN_ERR | ||
513 | "Cannot get a valid agaw for iommu (seq_id = %d)\n", | ||
514 | iommu->seq_id); | ||
515 | goto error; | ||
516 | } | ||
517 | iommu->agaw = agaw; | ||
518 | |||
509 | /* the registers might be more than one page */ | 519 | /* the registers might be more than one page */ |
510 | map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), | 520 | map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), |
511 | cap_max_fault_reg_offset(iommu->cap)); | 521 | cap_max_fault_reg_offset(iommu->cap)); |