aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/iommu.c')
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c49
1 files changed, 21 insertions, 28 deletions
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index a77bcaed80af..edea60b7ee90 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -140,7 +140,7 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
140 return ret; 140 return ret;
141} 141}
142 142
143static DEFINE_PER_CPU(u64 *, tce_page) = NULL; 143static DEFINE_PER_CPU(u64 *, tce_page);
144 144
145static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, 145static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
146 long npages, unsigned long uaddr, 146 long npages, unsigned long uaddr,
@@ -323,14 +323,13 @@ static void iommu_table_setparms(struct pci_controller *phb,
323static void iommu_table_setparms_lpar(struct pci_controller *phb, 323static void iommu_table_setparms_lpar(struct pci_controller *phb,
324 struct device_node *dn, 324 struct device_node *dn,
325 struct iommu_table *tbl, 325 struct iommu_table *tbl,
326 const void *dma_window, 326 const void *dma_window)
327 int bussubno)
328{ 327{
329 unsigned long offset, size; 328 unsigned long offset, size;
330 329
331 tbl->it_busno = bussubno;
332 of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size); 330 of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size);
333 331
332 tbl->it_busno = phb->bus->number;
334 tbl->it_base = 0; 333 tbl->it_base = 0;
335 tbl->it_blocksize = 16; 334 tbl->it_blocksize = 16;
336 tbl->it_type = TCE_PCI; 335 tbl->it_type = TCE_PCI;
@@ -450,14 +449,10 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
450 if (!ppci->iommu_table) { 449 if (!ppci->iommu_table) {
451 tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 450 tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
452 ppci->phb->node); 451 ppci->phb->node);
453 iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window, 452 iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
454 bus->number);
455 ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); 453 ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
456 pr_debug(" created table: %p\n", ppci->iommu_table); 454 pr_debug(" created table: %p\n", ppci->iommu_table);
457 } 455 }
458
459 if (pdn != dn)
460 PCI_DN(dn)->iommu_table = ppci->iommu_table;
461} 456}
462 457
463 458
@@ -533,21 +528,11 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
533 } 528 }
534 pr_debug(" parent is %s\n", pdn->full_name); 529 pr_debug(" parent is %s\n", pdn->full_name);
535 530
536 /* Check for parent == NULL so we don't try to setup the empty EADS
537 * slots on POWER4 machines.
538 */
539 if (dma_window == NULL || pdn->parent == NULL) {
540 pr_debug(" no dma window for device, linking to parent\n");
541 set_iommu_table_base(&dev->dev, PCI_DN(pdn)->iommu_table);
542 return;
543 }
544
545 pci = PCI_DN(pdn); 531 pci = PCI_DN(pdn);
546 if (!pci->iommu_table) { 532 if (!pci->iommu_table) {
547 tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 533 tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
548 pci->phb->node); 534 pci->phb->node);
549 iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window, 535 iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
550 pci->phb->bus->number);
551 pci->iommu_table = iommu_init_table(tbl, pci->phb->node); 536 pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
552 pr_debug(" created table: %p\n", pci->iommu_table); 537 pr_debug(" created table: %p\n", pci->iommu_table);
553 } else { 538 } else {
@@ -571,8 +556,7 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
571 556
572 switch (action) { 557 switch (action) {
573 case PSERIES_RECONFIG_REMOVE: 558 case PSERIES_RECONFIG_REMOVE:
574 if (pci && pci->iommu_table && 559 if (pci && pci->iommu_table)
575 of_get_property(np, "ibm,dma-window", NULL))
576 iommu_free_table(pci->iommu_table, np->full_name); 560 iommu_free_table(pci->iommu_table, np->full_name);
577 break; 561 break;
578 default: 562 default:
@@ -589,13 +573,8 @@ static struct notifier_block iommu_reconfig_nb = {
589/* These are called very early. */ 573/* These are called very early. */
590void iommu_init_early_pSeries(void) 574void iommu_init_early_pSeries(void)
591{ 575{
592 if (of_chosen && of_get_property(of_chosen, "linux,iommu-off", NULL)) { 576 if (of_chosen && of_get_property(of_chosen, "linux,iommu-off", NULL))
593 /* Direct I/O, IOMMU off */
594 ppc_md.pci_dma_dev_setup = NULL;
595 ppc_md.pci_dma_bus_setup = NULL;
596 set_pci_dma_ops(&dma_direct_ops);
597 return; 577 return;
598 }
599 578
600 if (firmware_has_feature(FW_FEATURE_LPAR)) { 579 if (firmware_has_feature(FW_FEATURE_LPAR)) {
601 if (firmware_has_feature(FW_FEATURE_MULTITCE)) { 580 if (firmware_has_feature(FW_FEATURE_MULTITCE)) {
@@ -622,3 +601,17 @@ void iommu_init_early_pSeries(void)
622 set_pci_dma_ops(&dma_iommu_ops); 601 set_pci_dma_ops(&dma_iommu_ops);
623} 602}
624 603
604static int __init disable_multitce(char *str)
605{
606 if (strcmp(str, "off") == 0 &&
607 firmware_has_feature(FW_FEATURE_LPAR) &&
608 firmware_has_feature(FW_FEATURE_MULTITCE)) {
609 printk(KERN_INFO "Disabling MULTITCE firmware feature\n");
610 ppc_md.tce_build = tce_build_pSeriesLP;
611 ppc_md.tce_free = tce_free_pSeriesLP;
612 powerpc_firmware_features &= ~FW_FEATURE_MULTITCE;
613 }
614 return 1;
615}
616
617__setup("multitce=", disable_multitce);