gpu: host1x: Add IOMMU support
Add support for the Host1x unit to be located behind an IOMMU. This is required when gather buffers may be allocated non-contiguously in physical memory, as can be the case when TegraDRM is also using the IOMMU. Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:

committed by
Thierry Reding

parent
8cadb01d2c
commit
404bfb78da
@@ -27,6 +27,7 @@
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/host1x.h>
|
||||
#undef CREATE_TRACE_POINTS
|
||||
|
||||
#include "bus.h"
|
||||
#include "dev.h"
|
||||
@@ -168,16 +169,37 @@ static int host1x_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (iommu_present(&platform_bus_type)) {
|
||||
struct iommu_domain_geometry *geometry;
|
||||
unsigned long order;
|
||||
|
||||
host->domain = iommu_domain_alloc(&platform_bus_type);
|
||||
if (!host->domain)
|
||||
return -ENOMEM;
|
||||
|
||||
err = iommu_attach_device(host->domain, &pdev->dev);
|
||||
if (err)
|
||||
goto fail_free_domain;
|
||||
|
||||
geometry = &host->domain->geometry;
|
||||
|
||||
order = __ffs(host->domain->pgsize_bitmap);
|
||||
init_iova_domain(&host->iova, 1UL << order,
|
||||
geometry->aperture_start >> order,
|
||||
geometry->aperture_end >> order);
|
||||
host->iova_end = geometry->aperture_end;
|
||||
}
|
||||
|
||||
err = host1x_channel_list_init(host);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to initialize channel list\n");
|
||||
return err;
|
||||
goto fail_detach_device;
|
||||
}
|
||||
|
||||
err = clk_prepare_enable(host->clk);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to enable clock\n");
|
||||
return err;
|
||||
goto fail_detach_device;
|
||||
}
|
||||
|
||||
err = host1x_syncpt_init(host);
|
||||
@@ -206,6 +228,15 @@ fail_deinit_syncpt:
|
||||
host1x_syncpt_deinit(host);
|
||||
fail_unprepare_disable:
|
||||
clk_disable_unprepare(host->clk);
|
||||
fail_detach_device:
|
||||
if (host->domain) {
|
||||
put_iova_domain(&host->iova);
|
||||
iommu_detach_device(host->domain, &pdev->dev);
|
||||
}
|
||||
fail_free_domain:
|
||||
if (host->domain)
|
||||
iommu_domain_free(host->domain);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -218,6 +249,12 @@ static int host1x_remove(struct platform_device *pdev)
|
||||
host1x_syncpt_deinit(host);
|
||||
clk_disable_unprepare(host->clk);
|
||||
|
||||
if (host->domain) {
|
||||
put_iova_domain(&host->iova);
|
||||
iommu_detach_device(host->domain, &pdev->dev);
|
||||
iommu_domain_free(host->domain);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user