diff options
Diffstat (limited to 'arch/powerpc/platforms/powernv/pci.c')
-rw-r--r-- | arch/powerpc/platforms/powernv/pci.c | 158 |
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 | ||
805 | static __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 | |||
825 | int 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 | ||
848 | int 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 | |||
868 | void 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 | |||
879 | unsigned 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 | |||
884 | struct iommu_table *pnv_pci_table_alloc(int nid) | 805 | struct 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 | ||
898 | long 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 | |||
920 | static 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 | |||
928 | void 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 | |||
963 | void 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 | |||
977 | void pnv_pci_dma_dev_setup(struct pci_dev *pdev) | 819 | void 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); |