drm/tegra: Add IOMMU support

When an IOMMU device is available on the platform bus, allocate an IOMMU
domain and attach the display controllers to it. The display controllers
can then scan out non-contiguous buffers by mapping them through the
IOMMU.

Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
Thierry Reding
2014-06-26 21:41:53 +02:00
parent 1d1e6fe9b5
commit df06b759f2
6 changed files with 309 additions and 34 deletions

View File

@@ -8,6 +8,7 @@
*/
#include <linux/host1x.h>
#include <linux/iommu.h>
#include "drm.h"
#include "gem.h"
@@ -33,6 +34,17 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
if (!tegra)
return -ENOMEM;
if (iommu_present(&platform_bus_type)) {
tegra->domain = iommu_domain_alloc(&platform_bus_type);
if (IS_ERR(tegra->domain)) {
err = PTR_ERR(tegra->domain);
goto free;
}
DRM_DEBUG("IOMMU context initialized\n");
drm_mm_init(&tegra->mm, 0, SZ_2G);
}
mutex_init(&tegra->clients_lock);
INIT_LIST_HEAD(&tegra->clients);
drm->dev_private = tegra;
@@ -76,6 +88,12 @@ fbdev:
tegra_drm_fb_free(drm);
config:
drm_mode_config_cleanup(drm);
if (tegra->domain) {
iommu_domain_free(tegra->domain);
drm_mm_takedown(&tegra->mm);
}
free:
kfree(tegra);
return err;
}
@@ -83,6 +101,7 @@ config:
static int tegra_drm_unload(struct drm_device *drm)
{
struct host1x_device *device = to_host1x_device(drm->dev);
struct tegra_drm *tegra = drm->dev_private;
int err;
drm_kms_helper_poll_fini(drm);
@@ -94,6 +113,11 @@ static int tegra_drm_unload(struct drm_device *drm)
if (err < 0)
return err;
if (tegra->domain) {
iommu_domain_free(tegra->domain);
drm_mm_takedown(&tegra->mm);
}
return 0;
}