diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/iommu.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/iommu.c | 90 |
1 files changed, 46 insertions, 44 deletions
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 556c279a789d..3c95392f4f41 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -309,7 +309,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, | |||
309 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; | 309 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; |
310 | } | 310 | } |
311 | 311 | ||
312 | static void iommu_bus_setup_pSeries(struct pci_bus *bus) | 312 | static void pci_dma_bus_setup_pSeries(struct pci_bus *bus) |
313 | { | 313 | { |
314 | struct device_node *dn; | 314 | struct device_node *dn; |
315 | struct iommu_table *tbl; | 315 | struct iommu_table *tbl; |
@@ -318,10 +318,9 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
318 | struct pci_dn *pci; | 318 | struct pci_dn *pci; |
319 | int children; | 319 | int children; |
320 | 320 | ||
321 | DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); | ||
322 | |||
323 | dn = pci_bus_to_OF_node(bus); | 321 | dn = pci_bus_to_OF_node(bus); |
324 | pci = PCI_DN(dn); | 322 | |
323 | DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name); | ||
325 | 324 | ||
326 | if (bus->self) { | 325 | if (bus->self) { |
327 | /* This is not a root bus, any setup will be done for the | 326 | /* This is not a root bus, any setup will be done for the |
@@ -329,6 +328,7 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
329 | */ | 328 | */ |
330 | return; | 329 | return; |
331 | } | 330 | } |
331 | pci = PCI_DN(dn); | ||
332 | 332 | ||
333 | /* Check if the ISA bus on the system is under | 333 | /* Check if the ISA bus on the system is under |
334 | * this PHB. | 334 | * this PHB. |
@@ -390,17 +390,17 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
390 | } | 390 | } |
391 | 391 | ||
392 | 392 | ||
393 | static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | 393 | static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) |
394 | { | 394 | { |
395 | struct iommu_table *tbl; | 395 | struct iommu_table *tbl; |
396 | struct device_node *dn, *pdn; | 396 | struct device_node *dn, *pdn; |
397 | struct pci_dn *ppci; | 397 | struct pci_dn *ppci; |
398 | const void *dma_window = NULL; | 398 | const void *dma_window = NULL; |
399 | 399 | ||
400 | DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); | ||
401 | |||
402 | dn = pci_bus_to_OF_node(bus); | 400 | dn = pci_bus_to_OF_node(bus); |
403 | 401 | ||
402 | DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name); | ||
403 | |||
404 | /* Find nearest ibm,dma-window, walking up the device tree */ | 404 | /* Find nearest ibm,dma-window, walking up the device tree */ |
405 | for (pdn = dn; pdn != NULL; pdn = pdn->parent) { | 405 | for (pdn = dn; pdn != NULL; pdn = pdn->parent) { |
406 | dma_window = get_property(pdn, "ibm,dma-window", NULL); | 406 | dma_window = get_property(pdn, "ibm,dma-window", NULL); |
@@ -409,11 +409,15 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
409 | } | 409 | } |
410 | 410 | ||
411 | if (dma_window == NULL) { | 411 | if (dma_window == NULL) { |
412 | DBG("iommu_bus_setup_pSeriesLP: bus %s seems to have no ibm,dma-window property\n", dn->full_name); | 412 | DBG(" no ibm,dma-window property !\n"); |
413 | return; | 413 | return; |
414 | } | 414 | } |
415 | 415 | ||
416 | ppci = PCI_DN(pdn); | 416 | ppci = PCI_DN(pdn); |
417 | |||
418 | DBG(" parent is %s, iommu_table: 0x%p\n", | ||
419 | pdn->full_name, ppci->iommu_table); | ||
420 | |||
417 | if (!ppci->iommu_table) { | 421 | if (!ppci->iommu_table) { |
418 | /* Bussubno hasn't been copied yet. | 422 | /* Bussubno hasn't been copied yet. |
419 | * Do it now because iommu_table_setparms_lpar needs it. | 423 | * Do it now because iommu_table_setparms_lpar needs it. |
@@ -427,6 +431,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
427 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); | 431 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); |
428 | 432 | ||
429 | ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); | 433 | ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); |
434 | DBG(" created table: %p\n", ppci->iommu_table); | ||
430 | } | 435 | } |
431 | 436 | ||
432 | if (pdn != dn) | 437 | if (pdn != dn) |
@@ -434,27 +439,27 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
434 | } | 439 | } |
435 | 440 | ||
436 | 441 | ||
437 | static void iommu_dev_setup_pSeries(struct pci_dev *dev) | 442 | static void pci_dma_dev_setup_pSeries(struct pci_dev *dev) |
438 | { | 443 | { |
439 | struct device_node *dn, *mydn; | 444 | struct device_node *dn; |
440 | struct iommu_table *tbl; | 445 | struct iommu_table *tbl; |
441 | 446 | ||
442 | DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, pci_name(dev)); | 447 | DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev)); |
443 | 448 | ||
444 | mydn = dn = pci_device_to_OF_node(dev); | 449 | dn = dev->dev.archdata.of_node; |
445 | 450 | ||
446 | /* If we're the direct child of a root bus, then we need to allocate | 451 | /* If we're the direct child of a root bus, then we need to allocate |
447 | * an iommu table ourselves. The bus setup code should have setup | 452 | * an iommu table ourselves. The bus setup code should have setup |
448 | * the window sizes already. | 453 | * the window sizes already. |
449 | */ | 454 | */ |
450 | if (!dev->bus->self) { | 455 | if (!dev->bus->self) { |
456 | struct pci_controller *phb = PCI_DN(dn)->phb; | ||
457 | |||
451 | DBG(" --> first child, no bridge. Allocating iommu table.\n"); | 458 | DBG(" --> first child, no bridge. Allocating iommu table.\n"); |
452 | tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, | 459 | tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, |
453 | PCI_DN(dn)->phb->node); | 460 | phb->node); |
454 | iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); | 461 | iommu_table_setparms(phb, dn, tbl); |
455 | PCI_DN(dn)->iommu_table = iommu_init_table(tbl, | 462 | dev->dev.archdata.dma_data = iommu_init_table(tbl, phb->node); |
456 | PCI_DN(dn)->phb->node); | ||
457 | |||
458 | return; | 463 | return; |
459 | } | 464 | } |
460 | 465 | ||
@@ -465,11 +470,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev) | |||
465 | while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL) | 470 | while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL) |
466 | dn = dn->parent; | 471 | dn = dn->parent; |
467 | 472 | ||
468 | if (dn && PCI_DN(dn)) { | 473 | if (dn && PCI_DN(dn)) |
469 | PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table; | 474 | dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table; |
470 | } else { | 475 | else |
471 | DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, pci_name(dev)); | 476 | printk(KERN_WARNING "iommu: Device %s has no iommu table\n", |
472 | } | 477 | pci_name(dev)); |
473 | } | 478 | } |
474 | 479 | ||
475 | static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) | 480 | static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) |
@@ -495,13 +500,15 @@ static struct notifier_block iommu_reconfig_nb = { | |||
495 | .notifier_call = iommu_reconfig_notifier, | 500 | .notifier_call = iommu_reconfig_notifier, |
496 | }; | 501 | }; |
497 | 502 | ||
498 | static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | 503 | static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) |
499 | { | 504 | { |
500 | struct device_node *pdn, *dn; | 505 | struct device_node *pdn, *dn; |
501 | struct iommu_table *tbl; | 506 | struct iommu_table *tbl; |
502 | const void *dma_window = NULL; | 507 | const void *dma_window = NULL; |
503 | struct pci_dn *pci; | 508 | struct pci_dn *pci; |
504 | 509 | ||
510 | DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev)); | ||
511 | |||
505 | /* dev setup for LPAR is a little tricky, since the device tree might | 512 | /* dev setup for LPAR is a little tricky, since the device tree might |
506 | * contain the dma-window properties per-device and not neccesarily | 513 | * contain the dma-window properties per-device and not neccesarily |
507 | * for the bus. So we need to search upwards in the tree until we | 514 | * for the bus. So we need to search upwards in the tree until we |
@@ -509,9 +516,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
509 | * already allocated. | 516 | * already allocated. |
510 | */ | 517 | */ |
511 | dn = pci_device_to_OF_node(dev); | 518 | dn = pci_device_to_OF_node(dev); |
512 | 519 | DBG(" node is %s\n", dn->full_name); | |
513 | DBG("iommu_dev_setup_pSeriesLP, dev %p (%s) %s\n", | ||
514 | dev, pci_name(dev), dn->full_name); | ||
515 | 520 | ||
516 | for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; | 521 | for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; |
517 | pdn = pdn->parent) { | 522 | pdn = pdn->parent) { |
@@ -520,16 +525,17 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
520 | break; | 525 | break; |
521 | } | 526 | } |
522 | 527 | ||
528 | DBG(" parent is %s\n", pdn->full_name); | ||
529 | |||
523 | /* Check for parent == NULL so we don't try to setup the empty EADS | 530 | /* Check for parent == NULL so we don't try to setup the empty EADS |
524 | * slots on POWER4 machines. | 531 | * slots on POWER4 machines. |
525 | */ | 532 | */ |
526 | if (dma_window == NULL || pdn->parent == NULL) { | 533 | if (dma_window == NULL || pdn->parent == NULL) { |
527 | DBG("No dma window for device, linking to parent\n"); | 534 | DBG(" no dma window for device, linking to parent\n"); |
528 | PCI_DN(dn)->iommu_table = PCI_DN(pdn)->iommu_table; | 535 | dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table; |
529 | return; | 536 | return; |
530 | } else { | ||
531 | DBG("Found DMA window, allocating table\n"); | ||
532 | } | 537 | } |
538 | DBG(" found DMA window, table: %p\n", pci->iommu_table); | ||
533 | 539 | ||
534 | pci = PCI_DN(pdn); | 540 | pci = PCI_DN(pdn); |
535 | if (!pci->iommu_table) { | 541 | if (!pci->iommu_table) { |
@@ -542,24 +548,20 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
542 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); | 548 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); |
543 | 549 | ||
544 | pci->iommu_table = iommu_init_table(tbl, pci->phb->node); | 550 | pci->iommu_table = iommu_init_table(tbl, pci->phb->node); |
551 | DBG(" created table: %p\n", pci->iommu_table); | ||
545 | } | 552 | } |
546 | 553 | ||
547 | if (pdn != dn) | 554 | dev->dev.archdata.dma_data = pci->iommu_table; |
548 | PCI_DN(dn)->iommu_table = pci->iommu_table; | ||
549 | } | 555 | } |
550 | 556 | ||
551 | static void iommu_bus_setup_null(struct pci_bus *b) { } | ||
552 | static void iommu_dev_setup_null(struct pci_dev *d) { } | ||
553 | |||
554 | /* These are called very early. */ | 557 | /* These are called very early. */ |
555 | void iommu_init_early_pSeries(void) | 558 | void iommu_init_early_pSeries(void) |
556 | { | 559 | { |
557 | if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) { | 560 | if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) { |
558 | /* Direct I/O, IOMMU off */ | 561 | /* Direct I/O, IOMMU off */ |
559 | ppc_md.iommu_dev_setup = iommu_dev_setup_null; | 562 | ppc_md.pci_dma_dev_setup = NULL; |
560 | ppc_md.iommu_bus_setup = iommu_bus_setup_null; | 563 | ppc_md.pci_dma_bus_setup = NULL; |
561 | pci_direct_iommu_init(); | 564 | pci_dma_ops = &dma_direct_ops; |
562 | |||
563 | return; | 565 | return; |
564 | } | 566 | } |
565 | 567 | ||
@@ -572,19 +574,19 @@ void iommu_init_early_pSeries(void) | |||
572 | ppc_md.tce_free = tce_free_pSeriesLP; | 574 | ppc_md.tce_free = tce_free_pSeriesLP; |
573 | } | 575 | } |
574 | ppc_md.tce_get = tce_get_pSeriesLP; | 576 | ppc_md.tce_get = tce_get_pSeriesLP; |
575 | ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP; | 577 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP; |
576 | ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP; | 578 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP; |
577 | } else { | 579 | } else { |
578 | ppc_md.tce_build = tce_build_pSeries; | 580 | ppc_md.tce_build = tce_build_pSeries; |
579 | ppc_md.tce_free = tce_free_pSeries; | 581 | ppc_md.tce_free = tce_free_pSeries; |
580 | ppc_md.tce_get = tce_get_pseries; | 582 | ppc_md.tce_get = tce_get_pseries; |
581 | ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries; | 583 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeries; |
582 | ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries; | 584 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeries; |
583 | } | 585 | } |
584 | 586 | ||
585 | 587 | ||
586 | pSeries_reconfig_notifier_register(&iommu_reconfig_nb); | 588 | pSeries_reconfig_notifier_register(&iommu_reconfig_nb); |
587 | 589 | ||
588 | pci_iommu_init(); | 590 | pci_dma_ops = &dma_iommu_ops; |
589 | } | 591 | } |
590 | 592 | ||