/* * drm_create_iommu_mapping - create a mapping structure * * @drm_dev: DRM device */ int drm_create_iommu_mapping(struct drm_device *drm_dev) { struct dma_iommu_mapping *mapping = NULL; struct exynos_drm_private *priv = drm_dev->dev_private; struct device *dev = drm_dev->dev; if (!priv->da_start) priv->da_start = EXYNOS_DEV_ADDR_START; if (!priv->da_space_size) priv->da_space_size = EXYNOS_DEV_ADDR_SIZE; if (!priv->da_space_order) priv->da_space_order = EXYNOS_DEV_ADDR_ORDER; mapping = arm_iommu_create_mapping(&platform_bus_type, priv->da_start, priv->da_space_size, priv->da_space_order); if (IS_ERR(mapping)) return PTR_ERR(mapping); dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL); if (!dev->dma_parms) goto error; dma_set_max_seg_size(dev, 0xffffffffu); dev->archdata.mapping = mapping; return 0; error: arm_iommu_release_mapping(mapping); return -ENOMEM; }
static void nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) { #if IS_ENABLED(CONFIG_IOMMU_API) struct device *dev = &tdev->pdev->dev; unsigned long pgsize_bitmap; int ret; #if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) if (dev->archdata.mapping) { struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev); arm_iommu_detach_device(dev); arm_iommu_release_mapping(mapping); } #endif if (!tdev->func->iommu_bit) return; mutex_init(&tdev->iommu.mutex); if (iommu_present(&platform_bus_type)) { tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type); if (!tdev->iommu.domain) goto error; /* * A IOMMU is only usable if it supports page sizes smaller * or equal to the system's PAGE_SIZE, with a preference if * both are equal. */ pgsize_bitmap = tdev->iommu.domain->ops->pgsize_bitmap; if (pgsize_bitmap & PAGE_SIZE) { tdev->iommu.pgshift = PAGE_SHIFT; } else { tdev->iommu.pgshift = fls(pgsize_bitmap & ~PAGE_MASK); if (tdev->iommu.pgshift == 0) { dev_warn(dev, "unsupported IOMMU page size\n"); goto free_domain; } tdev->iommu.pgshift -= 1; } ret = iommu_attach_device(tdev->iommu.domain, dev); if (ret) goto free_domain; ret = nvkm_mm_init(&tdev->iommu.mm, 0, 0, (1ULL << tdev->func->iommu_bit) >> tdev->iommu.pgshift, 1); if (ret) goto detach_device; }
void exynos_drm_cleanup_dma(struct drm_device *drm) { struct exynos_drm_private *priv = drm->dev_private; if (!IS_ENABLED(CONFIG_EXYNOS_IOMMU)) return; arm_iommu_release_mapping(priv->mapping); priv->mapping = NULL; priv->dma_dev = NULL; }
static int tegra_iommu_create_map(struct device *dev) { int err; struct dma_iommu_mapping *map; map = arm_iommu_create_mapping(&platform_bus_type, TEGRA_IOMMU_BASE, TEGRA_IOMMU_SIZE, 0); if (IS_ERR(map)) return PTR_ERR(map); err = arm_iommu_attach_device(dev, map); if (err) { arm_iommu_release_mapping(map); return err; } return 0; }
static void tegra_iommu_delete_map(struct device *dev) { arm_iommu_release_mapping(dev->archdata.mapping); }
/* * drm_release_iommu_mapping - release iommu mapping structure * * @drm_dev: DRM device * * if mapping->kref becomes 0 then all things related to iommu mapping * will be released */ void drm_release_iommu_mapping(struct drm_device *drm_dev) { struct device *dev = drm_dev->dev; arm_iommu_release_mapping(dev->archdata.mapping); }