aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/omap-iommu.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2014-02-28 15:42:38 -0500
committerJoerg Roedel <joro@8bytes.org>2014-03-04 11:02:43 -0500
commit07a0203021149140f83e64a9ac5fe7ed09a74afc (patch)
tree274fe2bd2984aad36c941fb0d1b7988638784afd /drivers/iommu/omap-iommu.c
parentb148d5fb2ef7bd1441e95402effe22b7b34f9a73 (diff)
iommu/omap: Allocate archdata on the fly for DT-based devices
The OMAP IOMMU driver locates the IOMMU associated to a device using the IOMMU name stored in the device archdata iommu field. That field is expected to be populated by platform code and is left unset for DT-based devices. This results in a crash when the IOMMU driver attaches a domain to a device. Fix this by allocating the archdata iommu structure when devices are added and freeing when they are removed. Devices without an OF node, and devices without an iommus property in their OF node are ignored. The iommu name is initialized from the IOMMU device node name. This should be simplified when removing non-DT support completely from the IOMMU users as the IOMMU name won't be needed anymore, and the IOMMU device pointer could then be stored in the archdata iommu field directly. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> [s-anna@ti.com: updated to use device name instead of OF name] Signed-off-by: Suman Anna <s-anna@ti.com> Signed-off-by: Joerg Roedel <joro@8bytes.org>
Diffstat (limited to 'drivers/iommu/omap-iommu.c')
-rw-r--r--drivers/iommu/omap-iommu.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 28bc63143279..8acea87cbc0e 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1253,6 +1253,49 @@ static int omap_iommu_domain_has_cap(struct iommu_domain *domain,
1253 return 0; 1253 return 0;
1254} 1254}
1255 1255
1256static int omap_iommu_add_device(struct device *dev)
1257{
1258 struct omap_iommu_arch_data *arch_data;
1259 struct device_node *np;
1260
1261 /*
1262 * Allocate the archdata iommu structure for DT-based devices.
1263 *
1264 * TODO: Simplify this when removing non-DT support completely from the
1265 * IOMMU users.
1266 */
1267 if (!dev->of_node)
1268 return 0;
1269
1270 np = of_parse_phandle(dev->of_node, "iommus", 0);
1271 if (!np)
1272 return 0;
1273
1274 arch_data = kzalloc(sizeof(*arch_data), GFP_KERNEL);
1275 if (!arch_data) {
1276 of_node_put(np);
1277 return -ENOMEM;
1278 }
1279
1280 arch_data->name = kstrdup(dev_name(dev), GFP_KERNEL);
1281 dev->archdata.iommu = arch_data;
1282
1283 of_node_put(np);
1284
1285 return 0;
1286}
1287
1288static void omap_iommu_remove_device(struct device *dev)
1289{
1290 struct omap_iommu_arch_data *arch_data = dev->archdata.iommu;
1291
1292 if (!dev->of_node || !arch_data)
1293 return;
1294
1295 kfree(arch_data->name);
1296 kfree(arch_data);
1297}
1298
1256static struct iommu_ops omap_iommu_ops = { 1299static struct iommu_ops omap_iommu_ops = {
1257 .domain_init = omap_iommu_domain_init, 1300 .domain_init = omap_iommu_domain_init,
1258 .domain_destroy = omap_iommu_domain_destroy, 1301 .domain_destroy = omap_iommu_domain_destroy,
@@ -1262,6 +1305,8 @@ static struct iommu_ops omap_iommu_ops = {
1262 .unmap = omap_iommu_unmap, 1305 .unmap = omap_iommu_unmap,
1263 .iova_to_phys = omap_iommu_iova_to_phys, 1306 .iova_to_phys = omap_iommu_iova_to_phys,
1264 .domain_has_cap = omap_iommu_domain_has_cap, 1307 .domain_has_cap = omap_iommu_domain_has_cap,
1308 .add_device = omap_iommu_add_device,
1309 .remove_device = omap_iommu_remove_device,
1265 .pgsize_bitmap = OMAP_IOMMU_PGSIZES, 1310 .pgsize_bitmap = OMAP_IOMMU_PGSIZES,
1266}; 1311};
1267 1312