aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/ipmmu-vmsa.c115
1 files changed, 86 insertions, 29 deletions
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 368c852d9ee7..5d080cf11ba5 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -47,7 +47,8 @@ struct ipmmu_vmsa_domain {
47 47
48struct ipmmu_vmsa_archdata { 48struct ipmmu_vmsa_archdata {
49 struct ipmmu_vmsa_device *mmu; 49 struct ipmmu_vmsa_device *mmu;
50 unsigned int utlb; 50 unsigned int *utlbs;
51 unsigned int num_utlbs;
51}; 52};
52 53
53static DEFINE_SPINLOCK(ipmmu_devices_lock); 54static DEFINE_SPINLOCK(ipmmu_devices_lock);
@@ -900,6 +901,7 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain,
900 struct ipmmu_vmsa_device *mmu = archdata->mmu; 901 struct ipmmu_vmsa_device *mmu = archdata->mmu;
901 struct ipmmu_vmsa_domain *domain = io_domain->priv; 902 struct ipmmu_vmsa_domain *domain = io_domain->priv;
902 unsigned long flags; 903 unsigned long flags;
904 unsigned int i;
903 int ret = 0; 905 int ret = 0;
904 906
905 if (!mmu) { 907 if (!mmu) {
@@ -928,7 +930,8 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain,
928 if (ret < 0) 930 if (ret < 0)
929 return ret; 931 return ret;
930 932
931 ipmmu_utlb_enable(domain, archdata->utlb); 933 for (i = 0; i < archdata->num_utlbs; ++i)
934 ipmmu_utlb_enable(domain, archdata->utlbs[i]);
932 935
933 return 0; 936 return 0;
934} 937}
@@ -938,8 +941,10 @@ static void ipmmu_detach_device(struct iommu_domain *io_domain,
938{ 941{
939 struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu; 942 struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
940 struct ipmmu_vmsa_domain *domain = io_domain->priv; 943 struct ipmmu_vmsa_domain *domain = io_domain->priv;
944 unsigned int i;
941 945
942 ipmmu_utlb_disable(domain, archdata->utlb); 946 for (i = 0; i < archdata->num_utlbs; ++i)
947 ipmmu_utlb_disable(domain, archdata->utlbs[i]);
943 948
944 /* 949 /*
945 * TODO: Optimize by disabling the context when no device is attached. 950 * TODO: Optimize by disabling the context when no device is attached.
@@ -1003,10 +1008,12 @@ static phys_addr_t ipmmu_iova_to_phys(struct iommu_domain *io_domain,
1003 return __pfn_to_phys(pte_pfn(pte)) | (iova & ~PAGE_MASK); 1008 return __pfn_to_phys(pte_pfn(pte)) | (iova & ~PAGE_MASK);
1004} 1009}
1005 1010
1006static int ipmmu_find_utlb(struct ipmmu_vmsa_device *mmu, struct device *dev) 1011static int ipmmu_find_utlbs(struct ipmmu_vmsa_device *mmu, struct device *dev,
1012 unsigned int **_utlbs)
1007{ 1013{
1008 struct of_phandle_args args; 1014 unsigned int *utlbs;
1009 int ret; 1015 unsigned int i;
1016 int count;
1010 1017
1011 if (mmu->pdata) { 1018 if (mmu->pdata) {
1012 const struct ipmmu_vmsa_master *master = mmu->pdata->masters; 1019 const struct ipmmu_vmsa_master *master = mmu->pdata->masters;
@@ -1014,32 +1021,64 @@ static int ipmmu_find_utlb(struct ipmmu_vmsa_device *mmu, struct device *dev)
1014 unsigned int i; 1021 unsigned int i;
1015 1022
1016 for (i = 0; i < mmu->pdata->num_masters; ++i, ++master) { 1023 for (i = 0; i < mmu->pdata->num_masters; ++i, ++master) {
1017 if (strcmp(master->name, devname) == 0) 1024 if (strcmp(master->name, devname) == 0) {
1018 return master->utlb; 1025 utlbs = kmalloc(sizeof(*utlbs), GFP_KERNEL);
1026 if (!utlbs)
1027 return -ENOMEM;
1028
1029 utlbs[0] = master->utlb;
1030
1031 *_utlbs = utlbs;
1032 return 1;
1033 }
1019 } 1034 }
1020 1035
1021 return -1; 1036 return -EINVAL;
1022 } 1037 }
1023 1038
1024 ret = of_parse_phandle_with_args(dev->of_node, "iommus", 1039 count = of_count_phandle_with_args(dev->of_node, "iommus",
1025 "#iommu-cells", 0, &args); 1040 "#iommu-cells");
1026 if (ret < 0) 1041 if (count < 0)
1027 return -1; 1042 return -EINVAL;
1043
1044 utlbs = kcalloc(count, sizeof(*utlbs), GFP_KERNEL);
1045 if (!utlbs)
1046 return -ENOMEM;
1047
1048 for (i = 0; i < count; ++i) {
1049 struct of_phandle_args args;
1050 int ret;
1051
1052 ret = of_parse_phandle_with_args(dev->of_node, "iommus",
1053 "#iommu-cells", i, &args);
1054 if (ret < 0)
1055 goto error;
1056
1057 of_node_put(args.np);
1058
1059 if (args.np != mmu->dev->of_node || args.args_count != 1)
1060 goto error;
1061
1062 utlbs[i] = args.args[0];
1063 }
1028 1064
1029 of_node_put(args.np); 1065 *_utlbs = utlbs;
1030 1066
1031 if (args.np != mmu->dev->of_node || args.args_count != 1) 1067 return count;
1032 return -1;
1033 1068
1034 return args.args[0]; 1069error:
1070 kfree(utlbs);
1071 return -EINVAL;
1035} 1072}
1036 1073
1037static int ipmmu_add_device(struct device *dev) 1074static int ipmmu_add_device(struct device *dev)
1038{ 1075{
1039 struct ipmmu_vmsa_archdata *archdata; 1076 struct ipmmu_vmsa_archdata *archdata;
1040 struct ipmmu_vmsa_device *mmu; 1077 struct ipmmu_vmsa_device *mmu;
1041 struct iommu_group *group; 1078 struct iommu_group *group = NULL;
1042 int utlb = -1; 1079 unsigned int *utlbs = NULL;
1080 unsigned int i;
1081 int num_utlbs = 0;
1043 int ret; 1082 int ret;
1044 1083
1045 if (dev->archdata.iommu) { 1084 if (dev->archdata.iommu) {
@@ -1052,8 +1091,8 @@ static int ipmmu_add_device(struct device *dev)
1052 spin_lock(&ipmmu_devices_lock); 1091 spin_lock(&ipmmu_devices_lock);
1053 1092
1054 list_for_each_entry(mmu, &ipmmu_devices, list) { 1093 list_for_each_entry(mmu, &ipmmu_devices, list) {
1055 utlb = ipmmu_find_utlb(mmu, dev); 1094 num_utlbs = ipmmu_find_utlbs(mmu, dev, &utlbs);
1056 if (utlb >= 0) { 1095 if (num_utlbs) {
1057 /* 1096 /*
1058 * TODO Take a reference to the MMU to protect 1097 * TODO Take a reference to the MMU to protect
1059 * against device removal. 1098 * against device removal.
@@ -1064,17 +1103,22 @@ static int ipmmu_add_device(struct device *dev)
1064 1103
1065 spin_unlock(&ipmmu_devices_lock); 1104 spin_unlock(&ipmmu_devices_lock);
1066 1105
1067 if (utlb < 0) 1106 if (num_utlbs <= 0)
1068 return -ENODEV; 1107 return -ENODEV;
1069 1108
1070 if (utlb >= mmu->num_utlbs) 1109 for (i = 0; i < num_utlbs; ++i) {
1071 return -EINVAL; 1110 if (utlbs[i] >= mmu->num_utlbs) {
1111 ret = -EINVAL;
1112 goto error;
1113 }
1114 }
1072 1115
1073 /* Create a device group and add the device to it. */ 1116 /* Create a device group and add the device to it. */
1074 group = iommu_group_alloc(); 1117 group = iommu_group_alloc();
1075 if (IS_ERR(group)) { 1118 if (IS_ERR(group)) {
1076 dev_err(dev, "Failed to allocate IOMMU group\n"); 1119 dev_err(dev, "Failed to allocate IOMMU group\n");
1077 return PTR_ERR(group); 1120 ret = PTR_ERR(group);
1121 goto error;
1078 } 1122 }
1079 1123
1080 ret = iommu_group_add_device(group, dev); 1124 ret = iommu_group_add_device(group, dev);
@@ -1082,7 +1126,8 @@ static int ipmmu_add_device(struct device *dev)
1082 1126
1083 if (ret < 0) {