diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2011-08-23 20:05:20 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-09-21 04:21:54 -0400 |
commit | 318fe7df9d8456f778451b01913b5d0dc0a25854 (patch) | |
tree | b134ae443ed05996f98660469590034ff19f76b5 /drivers/iommu | |
parent | c2c7286ac6d996a8ffc8d391d782ba35570b1236 (diff) |
iommu: Move IOMMU specific code to intel-iommu.c
Move the IOMMU specific routines to intel-iommu.c leaving the
dmar.c to the common ACPI dmar code shared between DMA-remapping
and Interrupt-remapping.
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: yinghai@kernel.org
Cc: youquan.song@intel.com
Cc: joerg.roedel@amd.com
Cc: tony.luck@intel.com
Cc: dwmw2@infradead.org
Link: http://lkml.kernel.org/r/20110824001456.282401285@sbsiddha-desk.sc.intel.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/dmar.c | 171 | ||||
-rw-r--r-- | drivers/iommu/intel-iommu.c | 151 |
2 files changed, 159 insertions, 163 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 17adf1ebcb13..a10ccf2432c8 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c | |||
@@ -118,8 +118,8 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope, | |||
118 | return 0; | 118 | return 0; |
119 | } | 119 | } |
120 | 120 | ||
121 | static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, | 121 | int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, |
122 | struct pci_dev ***devices, u16 segment) | 122 | struct pci_dev ***devices, u16 segment) |
123 | { | 123 | { |
124 | struct acpi_dmar_device_scope *scope; | 124 | struct acpi_dmar_device_scope *scope; |
125 | void * tmp = start; | 125 | void * tmp = start; |
@@ -217,133 +217,6 @@ static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru) | |||
217 | return ret; | 217 | return ret; |
218 | } | 218 | } |
219 | 219 | ||
220 | #ifdef CONFIG_DMAR | ||
221 | LIST_HEAD(dmar_rmrr_units); | ||
222 | |||
223 | static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr) | ||
224 | { | ||
225 | list_add(&rmrr->list, &dmar_rmrr_units); | ||
226 | } | ||
227 | |||
228 | |||
229 | static int __init | ||
230 | dmar_parse_one_rmrr(struct acpi_dmar_header *header) | ||
231 | { | ||
232 | struct acpi_dmar_reserved_memory *rmrr; | ||
233 | struct dmar_rmrr_unit *rmrru; | ||
234 | |||
235 | rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL); | ||
236 | if (!rmrru) | ||
237 | return -ENOMEM; | ||
238 | |||
239 | rmrru->hdr = header; | ||
240 | rmrr = (struct acpi_dmar_reserved_memory *)header; | ||
241 | rmrru->base_address = rmrr->base_address; | ||
242 | rmrru->end_address = rmrr->end_address; | ||
243 | |||
244 | dmar_register_rmrr_unit(rmrru); | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static int __init | ||
249 | rmrr_parse_dev(struct dmar_rmrr_unit *rmrru) | ||
250 | { | ||
251 | struct acpi_dmar_reserved_memory *rmrr; | ||
252 | int ret; | ||
253 | |||
254 | rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr; | ||
255 | ret = dmar_parse_dev_scope((void *)(rmrr + 1), | ||
256 | ((void *)rmrr) + rmrr->header.length, | ||
257 | &rmrru->devices_cnt, &rmrru->devices, rmrr->segment); | ||
258 | |||
259 | if (ret || (rmrru->devices_cnt == 0)) { | ||
260 | list_del(&rmrru->list); | ||
261 | kfree(rmrru); | ||
262 | } | ||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | static LIST_HEAD(dmar_atsr_units); | ||
267 | |||
268 | static int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr) | ||
269 | { | ||
270 | struct acpi_dmar_atsr *atsr; | ||
271 | struct dmar_atsr_unit *atsru; | ||
272 | |||
273 | atsr = container_of(hdr, struct acpi_dmar_atsr, header); | ||
274 | atsru = kzalloc(sizeof(*atsru), GFP_KERNEL); | ||
275 | if (!atsru) | ||
276 | return -ENOMEM; | ||
277 | |||
278 | atsru->hdr = hdr; | ||
279 | atsru->include_all = atsr->flags & 0x1; | ||
280 | |||
281 | list_add(&atsru->list, &dmar_atsr_units); | ||
282 | |||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru) | ||
287 | { | ||
288 | int rc; | ||
289 | struct acpi_dmar_atsr *atsr; | ||
290 | |||
291 | if (atsru->include_all) | ||
292 | return 0; | ||
293 | |||
294 | atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); | ||
295 | rc = dmar_parse_dev_scope((void *)(atsr + 1), | ||
296 | (void *)atsr + atsr->header.length, | ||
297 | &atsru->devices_cnt, &atsru->devices, | ||
298 | atsr->segment); | ||
299 | if (rc || !atsru->devices_cnt) { | ||
300 | list_del(&atsru->list); | ||
301 | kfree(atsru); | ||
302 | } | ||
303 | |||
304 | return rc; | ||
305 | } | ||
306 | |||
307 | int dmar_find_matched_atsr_unit(struct pci_dev *dev) | ||
308 | { | ||
309 | int i; | ||
310 | struct pci_bus *bus; | ||
311 | struct acpi_dmar_atsr *atsr; | ||
312 | struct dmar_atsr_unit *atsru; | ||
313 | |||
314 | dev = pci_physfn(dev); | ||
315 | |||
316 | list_for_each_entry(atsru, &dmar_atsr_units, list) { | ||
317 | atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); | ||
318 | if (atsr->segment == pci_domain_nr(dev->bus)) | ||
319 | goto found; | ||
320 | } | ||
321 | |||
322 | return 0; | ||
323 | |||
324 | found: | ||
325 | for (bus = dev->bus; bus; bus = bus->parent) { | ||
326 | struct pci_dev *bridge = bus->self; | ||
327 | |||
328 | if (!bridge || !pci_is_pcie(bridge) || | ||
329 | bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) | ||
330 | return 0; | ||
331 | |||
332 | if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) { | ||
333 | for (i = 0; i < atsru->devices_cnt; i++) | ||
334 | if (atsru->devices[i] == bridge) | ||
335 | return 1; | ||
336 | break; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | if (atsru->include_all) | ||
341 | return 1; | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | #endif | ||
346 | |||
347 | #ifdef CONFIG_ACPI_NUMA | 220 | #ifdef CONFIG_ACPI_NUMA |
348 | static int __init | 221 | static int __init |
349 | dmar_parse_one_rhsa(struct acpi_dmar_header *header) | 222 | dmar_parse_one_rhsa(struct acpi_dmar_header *header) |
@@ -484,14 +357,10 @@ parse_dmar_table(void) | |||
484 | ret = dmar_parse_one_drhd(entry_header); | 357 | ret = dmar_parse_one_drhd(entry_header); |
485 | break; | 358 | break; |
486 | case ACPI_DMAR_TYPE_RESERVED_MEMORY: | 359 | case ACPI_DMAR_TYPE_RESERVED_MEMORY: |
487 | #ifdef CONFIG_DMAR | ||
488 | ret = dmar_parse_one_rmrr(entry_header); | 360 | ret = dmar_parse_one_rmrr(entry_header); |
489 | #endif | ||
490 | break; | 361 | break; |
491 | case ACPI_DMAR_TYPE_ATSR: | 362 | case ACPI_DMAR_TYPE_ATSR: |
492 | #ifdef CONFIG_DMAR | ||
493 | ret = dmar_parse_one_atsr(entry_header); | 363 | ret = dmar_parse_one_atsr(entry_header); |
494 | #endif | ||
495 | break; | 364 | break; |
496 | case ACPI_DMAR_HARDWARE_AFFINITY: | 365 | case ACPI_DMAR_HARDWARE_AFFINITY: |
497 | #ifdef CONFIG_ACPI_NUMA | 366 | #ifdef CONFIG_ACPI_NUMA |
@@ -564,30 +433,18 @@ int __init dmar_dev_scope_init(void) | |||
564 | if (dmar_dev_scope_initialized) | 433 | if (dmar_dev_scope_initialized) |
565 | return dmar_dev_scope_initialized; | 434 | return dmar_dev_scope_initialized; |
566 | 435 | ||
436 | if (list_empty(&dmar_drhd_units)) | ||
437 | goto fail; | ||
438 | |||
567 | list_for_each_entry_safe(drhd, drhd_n, &dmar_drhd_units, list) { | 439 | list_for_each_entry_safe(drhd, drhd_n, &dmar_drhd_units, list) { |
568 | ret = dmar_parse_dev(drhd); | 440 | ret = dmar_parse_dev(drhd); |
569 | if (ret) | 441 | if (ret) |
570 | goto fail; | 442 | goto fail; |
571 | } | 443 | } |
572 | 444 | ||
573 | #ifdef CONFIG_DMAR | 445 | ret = dmar_parse_rmrr_atsr_dev(); |
574 | { | 446 | if (ret) |
575 | struct dmar_rmrr_unit *rmrr, *rmrr_n; | 447 | goto fail; |
576 | struct dmar_atsr_unit *atsr, *atsr_n; | ||
577 | |||
578 | list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) { | ||
579 | ret = rmrr_parse_dev(rmrr); | ||
580 | if (ret) | ||
581 | goto fail; | ||
582 | } | ||
583 | |||
584 | list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) { | ||
585 | ret = atsr_parse_dev(atsr); | ||
586 | if (ret) | ||
587 | goto fail; | ||
588 | } | ||
589 | } | ||
590 | #endif | ||
591 | 448 | ||
592 | dmar_dev_scope_initialized = 1; | 449 | dmar_dev_scope_initialized = 1; |
593 | return 0; | 450 | return 0; |
@@ -620,14 +477,6 @@ int __init dmar_table_init(void) | |||
620 | return -ENODEV; | 477 | return -ENODEV; |
621 | } | 478 | } |
622 | 479 | ||
623 | #ifdef CONFIG_DMAR | ||
624 | if (list_empty(&dmar_rmrr_units)) | ||
625 | printk(KERN_INFO PREFIX "No RMRR found\n"); | ||
626 | |||
627 | if (list_empty(&dmar_atsr_units)) | ||
628 | printk(KERN_INFO PREFIX "No ATSR found\n"); | ||
629 | #endif | ||
630 | |||
631 | return 0; | 480 | return 0; |
632 | } | 481 | } |
633 | 482 | ||
@@ -767,7 +616,6 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
767 | goto err_unmap; | 616 | goto err_unmap; |
768 | } | 617 | } |
769 | 618 | ||
770 | #ifdef CONFIG_DMAR | ||
771 | agaw = iommu_calculate_agaw(iommu); | 619 | agaw = iommu_calculate_agaw(iommu); |
772 | if (agaw < 0) { | 620 | if (agaw < 0) { |
773 | printk(KERN_ERR | 621 | printk(KERN_ERR |
@@ -782,7 +630,6 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
782 | iommu->seq_id); | 630 | iommu->seq_id); |
783 | goto err_unmap; | 631 | goto err_unmap; |
784 | } | 632 | } |
785 | #endif | ||
786 | iommu->agaw = agaw; | 633 | iommu->agaw = agaw; |
787 | iommu->msagaw = msagaw; | 634 | iommu->msagaw = msagaw; |
788 | 635 | ||
@@ -826,9 +673,7 @@ void free_iommu(struct intel_iommu *iommu) | |||
826 | if (!iommu) | 673 | if (!iommu) |
827 | return; | 674 | return; |
828 | 675 | ||
829 | #ifdef CONFIG_DMAR | ||
830 | free_dmar_iommu(iommu); | 676 | free_dmar_iommu(iommu); |
831 | #endif | ||
832 | 677 | ||
833 | if (iommu->reg) | 678 | if (iommu->reg) |
834 | iounmap(iommu->reg); | 679 | iounmap(iommu->reg); |
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index df69618177c5..e8eb4c5302b0 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -3390,6 +3390,151 @@ static void __init init_iommu_pm_ops(void) | |||
3390 | static inline void init_iommu_pm_ops(void) {} | 3390 | static inline void init_iommu_pm_ops(void) {} |
3391 | #endif /* CONFIG_PM */ | 3391 | #endif /* CONFIG_PM */ |
3392 | 3392 | ||
3393 | LIST_HEAD(dmar_rmrr_units); | ||
3394 | |||
3395 | static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr) | ||
3396 | { | ||
3397 | list_add(&rmrr->list, &dmar_rmrr_units); | ||
3398 | } | ||
3399 | |||
3400 | |||
3401 | int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header) | ||
3402 | { | ||
3403 | struct acpi_dmar_reserved_memory *rmrr; | ||
3404 | struct dmar_rmrr_unit *rmrru; | ||
3405 | |||
3406 | rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL); | ||
3407 | if (!rmrru) | ||
3408 | return -ENOMEM; | ||
3409 | |||
3410 | rmrru->hdr = header; | ||
3411 | rmrr = (struct acpi_dmar_reserved_memory *)header; | ||
3412 | rmrru->base_address = rmrr->base_address; | ||
3413 | rmrru->end_address = rmrr->end_address; | ||
3414 | |||
3415 | dmar_register_rmrr_unit(rmrru); | ||
3416 | return 0; | ||
3417 | } | ||
3418 | |||
3419 | static int __init | ||
3420 | rmrr_parse_dev(struct dmar_rmrr_unit *rmrru) | ||
3421 | { | ||
3422 | struct acpi_dmar_reserved_memory *rmrr; | ||
3423 | int ret; | ||
3424 | |||
3425 | rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr; | ||
3426 | ret = dmar_parse_dev_scope((void *)(rmrr + 1), | ||
3427 | ((void *)rmrr) + rmrr->header.length, | ||
3428 | &rmrru->devices_cnt, &rmrru->devices, rmrr->segment); | ||
3429 | |||
3430 | if (ret || (rmrru->devices_cnt == 0)) { | ||
3431 | list_del(&rmrru->list); | ||
3432 | kfree(rmrru); | ||
3433 | } | ||
3434 | return ret; | ||
3435 | } | ||
3436 | |||
3437 | static LIST_HEAD(dmar_atsr_units); | ||
3438 | |||
3439 | int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr) | ||
3440 | { | ||
3441 | struct acpi_dmar_atsr *atsr; | ||
3442 | struct dmar_atsr_unit *atsru; | ||
3443 | |||
3444 | atsr = container_of(hdr, struct acpi_dmar_atsr, header); | ||
3445 | atsru = kzalloc(sizeof(*atsru), GFP_KERNEL); | ||
3446 | if (!atsru) | ||
3447 | return -ENOMEM; | ||
3448 | |||
3449 | atsru->hdr = hdr; | ||
3450 | atsru->include_all = atsr->flags & 0x1; | ||
3451 | |||
3452 | list_add(&atsru->list, &dmar_atsr_units); | ||
3453 | |||
3454 | return 0; | ||
3455 | } | ||
3456 | |||
3457 | static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru) | ||
3458 | { | ||
3459 | int rc; | ||
3460 | struct acpi_dmar_atsr *atsr; | ||
3461 | |||
3462 | if (atsru->include_all) | ||
3463 | return 0; | ||
3464 | |||
3465 | atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); | ||
3466 | rc = dmar_parse_dev_scope((void *)(atsr + 1), | ||
3467 | (void *)atsr + atsr->header.length, | ||
3468 | &atsru->devices_cnt, &atsru->devices, | ||
3469 | atsr->segment); | ||
3470 | if (rc || !atsru->devices_cnt) { | ||
3471 | list_del(&atsru->list); | ||
3472 | kfree(atsru); | ||
3473 | } | ||
3474 | |||
3475 | return rc; | ||
3476 | } | ||
3477 | |||
3478 | int dmar_find_matched_atsr_unit(struct pci_dev *dev) | ||
3479 | { | ||
3480 | int i; | ||
3481 | struct pci_bus *bus; | ||
3482 | struct acpi_dmar_atsr *atsr; | ||
3483 | struct dmar_atsr_unit *atsru; | ||
3484 | |||
3485 | dev = pci_physfn(dev); | ||
3486 | |||
3487 | list_for_each_entry(atsru, &dmar_atsr_units, list) { | ||
3488 | atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); | ||
3489 | if (atsr->segment == pci_domain_nr(dev->bus)) | ||
3490 | goto found; | ||
3491 | } | ||
3492 | |||
3493 | return 0; | ||
3494 | |||
3495 | found: | ||
3496 | for (bus = dev->bus; bus; bus = bus->parent) { | ||
3497 | struct pci_dev *bridge = bus->self; | ||
3498 | |||
3499 | if (!bridge || !pci_is_pcie(bridge) || | ||
3500 | bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) | ||
3501 | return 0; | ||
3502 | |||
3503 | if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) { | ||
3504 | for (i = 0; i < atsru->devices_cnt; i++) | ||
3505 | if (atsru->devices[i] == bridge) | ||
3506 | return 1; | ||
3507 | break; | ||
3508 | } | ||
3509 | } | ||
3510 | |||
3511 | if (atsru->include_all) | ||
3512 | return 1; | ||
3513 | |||
3514 | return 0; | ||
3515 | } | ||
3516 | |||
3517 | int dmar_parse_rmrr_atsr_dev(void) | ||
3518 | { | ||
3519 | struct dmar_rmrr_unit *rmrr, *rmrr_n; | ||
3520 | struct dmar_atsr_unit *atsr, *atsr_n; | ||
3521 | int ret = 0; | ||
3522 | |||
3523 | list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) { | ||
3524 | ret = rmrr_parse_dev(rmrr); | ||
3525 | if (ret) | ||
3526 | return ret; | ||
3527 | } | ||
3528 | |||
3529 | list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) { | ||
3530 | ret = atsr_parse_dev(atsr); | ||
3531 | if (ret) | ||
3532 | return ret; | ||
3533 | } | ||
3534 | |||
3535 | return ret; | ||
3536 | } | ||
3537 | |||
3393 | /* | 3538 | /* |
3394 | * Here we only respond to action of unbound device from driver. | 3539 | * Here we only respond to action of unbound device from driver. |
3395 | * | 3540 | * |
@@ -3454,6 +3599,12 @@ int __init intel_iommu_init(void) | |||
3454 | return -ENODEV; | 3599 | return -ENODEV; |
3455 | } | 3600 | } |
3456 | 3601 | ||
3602 | if (list_empty(&dmar_rmrr_units)) | ||
3603 | printk(KERN_INFO "DMAR: No RMRR found\n"); | ||
3604 | |||
3605 | if (list_empty(&dmar_atsr_units)) | ||
3606 | printk(KERN_INFO "DMAR: No ATSR found\n"); | ||
3607 | |||
3457 | if (dmar_init_reserved_ranges()) { | 3608 | if (dmar_init_reserved_ranges()) { |
3458 | if (force_on) | 3609 | if (force_on) |
3459 | panic("tboot: Failed to reserve iommu ranges\n"); | 3610 | panic("tboot: Failed to reserve iommu ranges\n"); |