mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
a6bb79ab48
Currently the IOMMU code calls pm_runtime_get/put on the GPU or display device before doing a IOMMU operation. This was because usually the IOMMU driver didn't do power control of its own and since the hardware used the same clocks and power as the respective multimedia device it was a easy way to make sure that the power was available. Now two things have changed. First, the SMMU devices can do their own power control and more important bringing up the a6xx GPU isn't as easy as turning on some clocks. To bring the GPU up we need the GMU which itself needs the IOMMU so we have a chicken and egg problem. Luckily this is easily fixed by removing the pm_runtime calls from the functions and letting the device link to the IOMMU device handle the magic. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Tested-by: Bjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: Rob Clark <robdclark@gmail.com> Signed-off-by: Rob Clark <robdclark@chromium.org>
103 lines
2.7 KiB
C
103 lines
2.7 KiB
C
/*
|
|
* Copyright (C) 2013 Red Hat
|
|
* Author: Rob Clark <robdclark@gmail.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 as published by
|
|
* the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "msm_drv.h"
|
|
#include "msm_mmu.h"
|
|
|
|
struct msm_iommu {
|
|
struct msm_mmu base;
|
|
struct iommu_domain *domain;
|
|
};
|
|
#define to_msm_iommu(x) container_of(x, struct msm_iommu, base)
|
|
|
|
static int msm_fault_handler(struct iommu_domain *domain, struct device *dev,
|
|
unsigned long iova, int flags, void *arg)
|
|
{
|
|
struct msm_iommu *iommu = arg;
|
|
if (iommu->base.handler)
|
|
return iommu->base.handler(iommu->base.arg, iova, flags);
|
|
pr_warn_ratelimited("*** fault: iova=%08lx, flags=%d\n", iova, flags);
|
|
return 0;
|
|
}
|
|
|
|
static int msm_iommu_attach(struct msm_mmu *mmu, const char * const *names,
|
|
int cnt)
|
|
{
|
|
struct msm_iommu *iommu = to_msm_iommu(mmu);
|
|
|
|
return iommu_attach_device(iommu->domain, mmu->dev);
|
|
}
|
|
|
|
static void msm_iommu_detach(struct msm_mmu *mmu, const char * const *names,
|
|
int cnt)
|
|
{
|
|
struct msm_iommu *iommu = to_msm_iommu(mmu);
|
|
|
|
iommu_detach_device(iommu->domain, mmu->dev);
|
|
}
|
|
|
|
static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
|
|
struct sg_table *sgt, unsigned len, int prot)
|
|
{
|
|
struct msm_iommu *iommu = to_msm_iommu(mmu);
|
|
size_t ret;
|
|
|
|
ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot);
|
|
WARN_ON(!ret);
|
|
|
|
return (ret == len) ? 0 : -EINVAL;
|
|
}
|
|
|
|
static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, unsigned len)
|
|
{
|
|
struct msm_iommu *iommu = to_msm_iommu(mmu);
|
|
|
|
iommu_unmap(iommu->domain, iova, len);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void msm_iommu_destroy(struct msm_mmu *mmu)
|
|
{
|
|
struct msm_iommu *iommu = to_msm_iommu(mmu);
|
|
iommu_domain_free(iommu->domain);
|
|
kfree(iommu);
|
|
}
|
|
|
|
static const struct msm_mmu_funcs funcs = {
|
|
.attach = msm_iommu_attach,
|
|
.detach = msm_iommu_detach,
|
|
.map = msm_iommu_map,
|
|
.unmap = msm_iommu_unmap,
|
|
.destroy = msm_iommu_destroy,
|
|
};
|
|
|
|
struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain)
|
|
{
|
|
struct msm_iommu *iommu;
|
|
|
|
iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
|
|
if (!iommu)
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
iommu->domain = domain;
|
|
msm_mmu_init(&iommu->base, dev, &funcs);
|
|
iommu_set_fault_handler(domain, msm_fault_handler, iommu);
|
|
|
|
return &iommu->base;
|
|
}
|