aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/cell/iommu.c113
1 files changed, 108 insertions, 5 deletions
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 3b7078453e7f..208005ca262c 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -199,6 +199,8 @@ static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
199 base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW | 199 base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW |
200 (window->ioid & IOPTE_IOID_Mask); 200 (window->ioid & IOPTE_IOID_Mask);
201#endif 201#endif
202 if (unlikely(dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs)))
203 base_pte &= ~IOPTE_SO_RW;
202 204
203 io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset); 205 io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
204 206
@@ -539,7 +541,9 @@ static struct cbe_iommu *cell_iommu_for_node(int nid)
539static unsigned long cell_dma_direct_offset; 541static unsigned long cell_dma_direct_offset;
540 542
541static unsigned long dma_iommu_fixed_base; 543static unsigned long dma_iommu_fixed_base;
542struct dma_mapping_ops dma_iommu_fixed_ops; 544
545/* iommu_fixed_is_weak is set if booted with iommu_fixed=weak */
546static int iommu_fixed_is_weak;
543 547
544static struct iommu_table *cell_get_iommu_table(struct device *dev) 548static struct iommu_table *cell_get_iommu_table(struct device *dev)
545{ 549{
@@ -563,6 +567,98 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev)
563 return &window->table; 567 return &window->table;
564} 568}
565 569
570/* A coherent allocation implies strong ordering */
571
572static void *dma_fixed_alloc_coherent(struct device *dev, size_t size,
573 dma_addr_t *dma_handle, gfp_t flag)
574{
575 if (iommu_fixed_is_weak)
576 return iommu_alloc_coherent(dev, cell_get_iommu_table(dev),
577 size, dma_handle,
578 device_to_mask(dev), flag,
579 dev->archdata.numa_node);
580 else
581 return dma_direct_ops.alloc_coherent(dev, size, dma_handle,
582 flag);
583}
584
585static void dma_fixed_free_coherent(struct device *dev, size_t size,
586 void *vaddr, dma_addr_t dma_handle)
587{
588 if (iommu_fixed_is_weak)
589 iommu_free_coherent(cell_get_iommu_table(dev), size, vaddr,
590 dma_handle);
591 else
592 dma_direct_ops.free_coherent(dev, size, vaddr, dma_handle);
593}
594
595static dma_addr_t dma_fixed_map_single(struct device *dev, void *ptr,
596 size_t size,
597 enum dma_data_direction direction,
598 struct dma_attrs *attrs)
599{
600 if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
601 return dma_direct_ops.map_single(dev, ptr, size, direction,
602 attrs);
603 else
604 return iommu_map_single(dev, cell_get_iommu_table(dev), ptr,
605 size, device_to_mask(dev), direction,
606 attrs);
607}
608
609static void dma_fixed_unmap_single(struct device *dev, dma_addr_t dma_addr,
610 size_t size,
611 enum dma_data_direction direction,
612 struct dma_attrs *attrs)
613{
614 if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
615 dma_direct_ops.unmap_single(dev, dma_addr, size, direction,
616 attrs);
617 else
618 iommu_unmap_single(cell_get_iommu_table(dev), dma_addr, size,
619 direction, attrs);
620}
621
622static int dma_fixed_map_sg(struct device *dev, struct scatterlist *sg,
623 int nents, enum dma_data_direction direction,
624 struct dma_attrs *attrs)
625{
626 if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
627 return dma_direct_ops.map_sg(dev, sg, nents, direction, attrs);
628 else
629 return iommu_map_sg(dev, cell_get_iommu_table(dev), sg, nents,
630 device_to_mask(dev), direction, attrs);
631}
632
633static void dma_fixed_unmap_sg(struct device *dev, struct scatterlist *sg,
634 int nents, enum dma_data_direction direction,
635 struct dma_attrs *attrs)
636{
637 if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
638 dma_direct_ops.unmap_sg(dev, sg, nents, direction, attrs);
639 else
640 iommu_unmap_sg(cell_get_iommu_table(dev), sg, nents, direction,
641 attrs);
642}
643
644static int dma_fixed_dma_supported(struct device *dev, u64 mask)
645{
646 return mask == DMA_64BIT_MASK;
647}
648
649static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask);
650
651struct dma_mapping_ops dma_iommu_fixed_ops = {
652 .alloc_coherent = dma_fixed_alloc_coherent,
653 .free_coherent = dma_fixed_free_coherent,
654 .map_single = dma_fixed_map_single,
655 .unmap_single = dma_fixed_unmap_single,
656 .map_sg = dma_fixed_map_sg,
657 .unmap_sg = dma_fixed_unmap_sg,
658 .dma_supported = dma_fixed_dma_supported,
659 .set_dma_mask = dma_set_mask_and_switch,
660};
661
566static void cell_dma_dev_setup_fixed(struct device *dev); 662static void cell_dma_dev_setup_fixed(struct device *dev);
567 663
568static void cell_dma_dev_setup(struct device *dev) 664static void cell_dma_dev_setup(struct device *dev)
@@ -919,9 +1015,16 @@ static void cell_iommu_setup_fixed_ptab(struct cbe_iommu *iommu,
919 1015
920 pr_debug("iommu: mapping 0x%lx pages from 0x%lx\n", fsize, fbase); 1016 pr_debug("iommu: mapping 0x%lx pages from 0x%lx\n", fsize, fbase);
921 1017
922 base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW 1018 base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M
923 | (cell_iommu_get_ioid(np) & IOPTE_IOID_Mask); 1019 | (cell_iommu_get_ioid(np) & IOPTE_IOID_Mask);
924 1020
1021 if (iommu_fixed_is_weak)
1022 pr_info("IOMMU: Using weak ordering for fixed mapping\n");
1023 else {
1024 pr_info("IOMMU: Using strong ordering for fixed mapping\n");
1025 base_pte |= IOPTE_SO_RW;
1026 }
1027
925 for (uaddr = 0; uaddr < fsize; uaddr += (1 << 24)) { 1028 for (uaddr = 0; uaddr < fsize; uaddr += (1 << 24)) {
926 /* Don't touch the dynamic region */ 1029 /* Don't touch the dynamic region */
927 ioaddr = uaddr + fbase; 1030 ioaddr = uaddr + fbase;
@@ -1037,9 +1140,6 @@ static int __init cell_iommu_fixed_mapping_init(void)
1037 cell_iommu_setup_window(iommu, np, dbase, dsize, 0); 1140 cell_iommu_setup_window(iommu, np, dbase, dsize, 0);
1038 } 1141 }
1039 1142
1040 dma_iommu_fixed_ops = dma_direct_ops;
1041 dma_iommu_fixed_ops.set_dma_mask = dma_set_mask_and_switch;
1042
1043 dma_iommu_ops.set_dma_mask = dma_set_mask_and_switch; 1143 dma_iommu_ops.set_dma_mask = dma_set_mask_and_switch;
1044 set_pci_dma_ops(&dma_iommu_ops); 1144 set_pci_dma_ops(&dma_iommu_ops);
1045 1145
@@ -1053,6 +1153,9 @@ static int __init setup_iommu_fixed(char *str)
1053 if (strcmp(str, "off") == 0) 1153 if (strcmp(str, "off") == 0)
1054 iommu_fixed_disabled = 1; 1154 iommu_fixed_disabled = 1;
1055 1155
1156 else if (strcmp(str, "weak") == 0)
1157 iommu_fixed_is_weak = 1;
1158
1056 return 1; 1159 return 1;
1057} 1160}
1058__setup("iommu_fixed=", setup_iommu_fixed); 1161__setup("iommu_fixed=", setup_iommu_fixed);