aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powernv/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/powernv/pci.c')
-rw-r--r--arch/powerpc/platforms/powernv/pci.c158
1 files changed, 0 insertions, 158 deletions
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index b265ecc0836a..13aef2323bbc 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -802,85 +802,6 @@ struct pci_ops pnv_pci_ops = {
802 .write = pnv_pci_write_config, 802 .write = pnv_pci_write_config,
803}; 803};
804 804
805static __be64 *pnv_tce(struct iommu_table *tbl, long idx)
806{
807 __be64 *tmp = ((__be64 *)tbl->it_base);
808 int level = tbl->it_indirect_levels;
809 const long shift = ilog2(tbl->it_level_size);
810 unsigned long mask = (tbl->it_level_size - 1) << (level * shift);
811
812 while (level) {
813 int n = (idx & mask) >> (level * shift);
814 unsigned long tce = be64_to_cpu(tmp[n]);
815
816 tmp = __va(tce & ~(TCE_PCI_READ | TCE_PCI_WRITE));
817 idx &= ~mask;
818 mask >>= shift;
819 --level;
820 }
821
822 return tmp + idx;
823}
824
825int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
826 unsigned long uaddr, enum dma_data_direction direction,
827 unsigned long attrs)
828{
829 u64 proto_tce = iommu_direction_to_tce_perm(direction);
830 u64 rpn = __pa(uaddr) >> tbl->it_page_shift;
831 long i;
832
833 if (proto_tce & TCE_PCI_WRITE)
834 proto_tce |= TCE_PCI_READ;
835
836 for (i = 0; i < npages; i++) {
837 unsigned long newtce = proto_tce |
838 ((rpn + i) << tbl->it_page_shift);
839 unsigned long idx = index - tbl->it_offset + i;
840
841 *(pnv_tce(tbl, idx)) = cpu_to_be64(newtce);
842 }
843
844 return 0;
845}
846
847#ifdef CONFIG_IOMMU_API
848int pnv_tce_xchg(struct iommu_table *tbl, long index,
849 unsigned long *hpa, enum dma_data_direction *direction)
850{
851 u64 proto_tce = iommu_direction_to_tce_perm(*direction);
852 unsigned long newtce = *hpa | proto_tce, oldtce;
853 unsigned long idx = index - tbl->it_offset;
854
855 BUG_ON(*hpa & ~IOMMU_PAGE_MASK(tbl));
856
857 if (newtce & TCE_PCI_WRITE)
858 newtce |= TCE_PCI_READ;
859
860 oldtce = be64_to_cpu(xchg(pnv_tce(tbl, idx), cpu_to_be64(newtce)));
861 *hpa = oldtce & ~(TCE_PCI_READ | TCE_PCI_WRITE);
862 *direction = iommu_tce_direction(oldtce);
863
864 return 0;
865}
866#endif
867
868void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
869{
870 long i;
871
872 for (i = 0; i < npages; i++) {
873 unsigned long idx = index - tbl->it_offset + i;
874
875 *(pnv_tce(tbl, idx)) = cpu_to_be64(0);
876 }
877}
878
879unsigned long pnv_tce_get(struct iommu_table *tbl, long index)
880{
881 return be64_to_cpu(*(pnv_tce(tbl, index - tbl->it_offset)));
882}
883
884struct iommu_table *pnv_pci_table_alloc(int nid) 805struct iommu_table *pnv_pci_table_alloc(int nid)
885{ 806{
886 struct iommu_table *tbl; 807 struct iommu_table *tbl;
@@ -895,85 +816,6 @@ struct iommu_table *pnv_pci_table_alloc(int nid)
895 return tbl; 816 return tbl;
896} 817}
897 818
898long pnv_pci_link_table_and_group(int node, int num,
899 struct iommu_table *tbl,
900 struct iommu_table_group *table_group)
901{
902 struct iommu_table_group_link *tgl = NULL;
903
904 if (WARN_ON(!tbl || !table_group))
905 return -EINVAL;
906
907 tgl = kzalloc_node(sizeof(struct iommu_table_group_link), GFP_KERNEL,
908 node);
909 if (!tgl)
910 return -ENOMEM;
911
912 tgl->table_group = table_group;
913 list_add_rcu(&tgl->next, &tbl->it_group_list);
914
915 table_group->tables[num] = tbl;
916
917 return 0;
918}
919
920static void pnv_iommu_table_group_link_free(struct rcu_head *head)
921{
922 struct iommu_table_group_link *tgl = container_of(head,
923 struct iommu_table_group_link, rcu);
924
925 kfree(tgl);
926}
927
928void pnv_pci_unlink_table_and_group(struct iommu_table *tbl,
929 struct iommu_table_group *table_group)
930{
931 long i;
932 bool found;
933 struct iommu_table_group_link *tgl;
934
935 if (!tbl || !table_group)
936 return;
937
938 /* Remove link to a group from table's list of attached groups */
939 found = false;
940 list_for_each_entry_rcu(tgl, &tbl->it_group_list, next) {
941 if (tgl->table_group == table_group) {
942 list_del_rcu(&tgl->next);
943 call_rcu(&tgl->rcu, pnv_iommu_table_group_link_free);
944 found = true;
945 break;
946 }
947 }
948 if (WARN_ON(!found))
949 return;
950
951 /* Clean a pointer to iommu_table in iommu_table_group::tables[] */
952 found = false;
953 for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
954 if (table_group->tables[i] == tbl) {
955 table_group->tables[i] = NULL;
956 found = true;
957 break;
958 }
959 }
960 WARN_ON(!found);
961}
962
963void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
964 void *tce_mem, u64 tce_size,
965 u64 dma_offset, unsigned page_shift)
966{
967 tbl->it_blocksize = 16;
968 tbl->it_base = (unsigned long)tce_mem;
969 tbl->it_page_shift = page_shift;
970 tbl->it_offset = dma_offset >> tbl->it_page_shift;
971 tbl->it_index = 0;
972 tbl->it_size = tce_size >> 3;
973 tbl->it_busno = 0;
974 tbl->it_type = TCE_PCI;
975}
976
977void pnv_pci_dma_dev_setup(struct pci_dev *pdev) 819void pnv_pci_dma_dev_setup(struct pci_dev *pdev)
978{ 820{
979 struct pci_controller *hose = pci_bus_to_host(pdev->bus); 821 struct pci_controller *hose = pci_bus_to_host(pdev->bus);