diff options
-rw-r--r-- | drivers/iommu/omap-iommu.c | 39 | ||||
-rw-r--r-- | drivers/iommu/omap-iommu.h | 1 |
2 files changed, 39 insertions, 1 deletions
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index ef44fc740da7..95dfca36ccb9 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c | |||
@@ -943,9 +943,13 @@ static int omap_iommu_probe(struct platform_device *pdev) | |||
943 | return err; | 943 | return err; |
944 | platform_set_drvdata(pdev, obj); | 944 | platform_set_drvdata(pdev, obj); |
945 | 945 | ||
946 | obj->group = iommu_group_alloc(); | ||
947 | if (IS_ERR(obj->group)) | ||
948 | return PTR_ERR(obj->group); | ||
949 | |||
946 | err = iommu_device_sysfs_add(&obj->iommu, obj->dev, NULL, obj->name); | 950 | err = iommu_device_sysfs_add(&obj->iommu, obj->dev, NULL, obj->name); |
947 | if (err) | 951 | if (err) |
948 | return err; | 952 | goto out_group; |
949 | 953 | ||
950 | iommu_device_set_ops(&obj->iommu, &omap_iommu_ops); | 954 | iommu_device_set_ops(&obj->iommu, &omap_iommu_ops); |
951 | 955 | ||
@@ -959,10 +963,13 @@ static int omap_iommu_probe(struct platform_device *pdev) | |||
959 | omap_iommu_debugfs_add(obj); | 963 | omap_iommu_debugfs_add(obj); |
960 | 964 | ||
961 | dev_info(&pdev->dev, "%s registered\n", obj->name); | 965 | dev_info(&pdev->dev, "%s registered\n", obj->name); |
966 | |||
962 | return 0; | 967 | return 0; |
963 | 968 | ||
964 | out_sysfs: | 969 | out_sysfs: |
965 | iommu_device_sysfs_remove(&obj->iommu); | 970 | iommu_device_sysfs_remove(&obj->iommu); |
971 | out_group: | ||
972 | iommu_group_put(obj->group); | ||
966 | return err; | 973 | return err; |
967 | } | 974 | } |
968 | 975 | ||
@@ -970,6 +977,9 @@ static int omap_iommu_remove(struct platform_device *pdev) | |||
970 | { | 977 | { |
971 | struct omap_iommu *obj = platform_get_drvdata(pdev); | 978 | struct omap_iommu *obj = platform_get_drvdata(pdev); |
972 | 979 | ||
980 | iommu_group_put(obj->group); | ||
981 | obj->group = NULL; | ||
982 | |||
973 | iommu_device_sysfs_remove(&obj->iommu); | 983 | iommu_device_sysfs_remove(&obj->iommu); |
974 | iommu_device_unregister(&obj->iommu); | 984 | iommu_device_unregister(&obj->iommu); |
975 | 985 | ||
@@ -1217,6 +1227,7 @@ static int omap_iommu_add_device(struct device *dev) | |||
1217 | { | 1227 | { |
1218 | struct omap_iommu_arch_data *arch_data; | 1228 | struct omap_iommu_arch_data *arch_data; |
1219 | struct omap_iommu *oiommu; | 1229 | struct omap_iommu *oiommu; |
1230 | struct iommu_group *group; | ||
1220 | struct device_node *np; | 1231 | struct device_node *np; |
1221 | struct platform_device *pdev; | 1232 | struct platform_device *pdev; |
1222 | int ret; | 1233 | int ret; |
@@ -1262,6 +1273,19 @@ static int omap_iommu_add_device(struct device *dev) | |||
1262 | arch_data->iommu_dev = oiommu; | 1273 | arch_data->iommu_dev = oiommu; |
1263 | dev->archdata.iommu = arch_data; | 1274 | dev->archdata.iommu = arch_data; |
1264 | 1275 | ||
1276 | /* | ||
1277 | * IOMMU group initialization calls into omap_iommu_device_group, which | ||
1278 | * needs a valid dev->archdata.iommu pointer | ||
1279 | */ | ||
1280 | group = iommu_group_get_for_dev(dev); | ||
1281 | if (IS_ERR(group)) { | ||
1282 | iommu_device_unlink(&oiommu->iommu, dev); | ||
1283 | dev->archdata.iommu = NULL; | ||
1284 | kfree(arch_data); | ||
1285 | return PTR_ERR(group); | ||
1286 | } | ||
1287 | iommu_group_put(group); | ||
1288 | |||
1265 | of_node_put(np); | 1289 | of_node_put(np); |
1266 | 1290 | ||
1267 | return 0; | 1291 | return 0; |
@@ -1275,12 +1299,24 @@ static void omap_iommu_remove_device(struct device *dev) | |||
1275 | return; | 1299 | return; |
1276 | 1300 | ||
1277 | iommu_device_unlink(&arch_data->iommu_dev->iommu, dev); | 1301 | iommu_device_unlink(&arch_data->iommu_dev->iommu, dev); |
1302 | iommu_group_remove_device(dev); | ||
1278 | 1303 | ||
1279 | dev->archdata.iommu = NULL; | 1304 | dev->archdata.iommu = NULL; |
1280 | kfree(arch_data); | 1305 | kfree(arch_data); |
1281 | 1306 | ||
1282 | } | 1307 | } |
1283 | 1308 | ||
1309 | static struct iommu_group *omap_iommu_device_group(struct device *dev) | ||
1310 | { | ||
1311 | struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; | ||
1312 | struct iommu_group *group = NULL; | ||
1313 | |||
1314 | if (arch_data->iommu_dev) | ||
1315 | group = arch_data->iommu_dev->group; | ||
1316 | |||
1317 | return group; | ||
1318 | } | ||
1319 | |||
1284 | static const struct iommu_ops omap_iommu_ops = { | 1320 | static const struct iommu_ops omap_iommu_ops = { |
1285 | .domain_alloc = omap_iommu_domain_alloc, | 1321 | .domain_alloc = omap_iommu_domain_alloc, |
1286 | .domain_free = omap_iommu_domain_free, | 1322 | .domain_free = omap_iommu_domain_free, |
@@ -1292,6 +1328,7 @@ static const struct iommu_ops omap_iommu_ops = { | |||
1292 | .iova_to_phys = omap_iommu_iova_to_phys, | 1328 | .iova_to_phys = omap_iommu_iova_to_phys, |
1293 | .add_device = omap_iommu_add_device, | 1329 | .add_device = omap_iommu_add_device, |
1294 | .remove_device = omap_iommu_remove_device, | 1330 | .remove_device = omap_iommu_remove_device, |
1331 | .device_group = omap_iommu_device_group, | ||
1295 | .pgsize_bitmap = OMAP_IOMMU_PGSIZES, | 1332 | .pgsize_bitmap = OMAP_IOMMU_PGSIZES, |
1296 | }; | 1333 | }; |
1297 | 1334 | ||
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h index 758958a4712c..6e70515e6038 100644 --- a/drivers/iommu/omap-iommu.h +++ b/drivers/iommu/omap-iommu.h | |||
@@ -70,6 +70,7 @@ struct omap_iommu { | |||
70 | u32 id; | 70 | u32 id; |
71 | 71 | ||
72 | struct iommu_device iommu; | 72 | struct iommu_device iommu; |
73 | struct iommu_group *group; | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | /** | 76 | /** |