Commit 1267a4df authored by Jordan Crouse's avatar Jordan Crouse Committed by Rob Clark

drm/msm: Attach the GPU MMU when it is created

Currently the GPU MMU is attached in the adreno_gpu code but as
more and more of the GPU initialization moves to the generic
GPU path we have a need to map and use GPU memory earlier and
earlier.  There isn't any reason to defer attaching the MMU
until later so attach it right after the address space is
created so it can be used immediately.
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent ac1b5ab4
...@@ -817,10 +817,9 @@ static void a5xx_fault_detect_irq(struct msm_gpu *gpu) ...@@ -817,10 +817,9 @@ static void a5xx_fault_detect_irq(struct msm_gpu *gpu)
{ {
struct drm_device *dev = gpu->dev; struct drm_device *dev = gpu->dev;
struct msm_drm_private *priv = dev->dev_private; struct msm_drm_private *priv = dev->dev_private;
struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu);
dev_err(dev->dev, "gpu fault ring %d fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n", dev_err(dev->dev, "gpu fault fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n",
ring ? ring->id : -1, ring ? ring->seqno : 0, gpu->funcs->last_fence(gpu),
gpu_read(gpu, REG_A5XX_RBBM_STATUS), gpu_read(gpu, REG_A5XX_RBBM_STATUS),
gpu_read(gpu, REG_A5XX_CP_RB_RPTR), gpu_read(gpu, REG_A5XX_CP_RB_RPTR),
gpu_read(gpu, REG_A5XX_CP_RB_WPTR), gpu_read(gpu, REG_A5XX_CP_RB_WPTR),
......
...@@ -337,11 +337,6 @@ void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords) ...@@ -337,11 +337,6 @@ void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords)
DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name); DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name);
} }
static const char *iommu_ports[] = {
"gfx3d_user", "gfx3d_priv",
"gfx3d1_user", "gfx3d1_priv",
};
int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
struct adreno_gpu *adreno_gpu, const struct adreno_gpu_funcs *funcs) struct adreno_gpu *adreno_gpu, const struct adreno_gpu_funcs *funcs)
{ {
...@@ -373,15 +368,15 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, ...@@ -373,15 +368,15 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
adreno_gpu_config.ringsz = RB_SIZE; adreno_gpu_config.ringsz = RB_SIZE;
pm_runtime_set_autosuspend_delay(&pdev->dev, DRM_MSM_INACTIVE_PERIOD);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base, ret = msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base,
adreno_gpu->info->name, &adreno_gpu_config); adreno_gpu->info->name, &adreno_gpu_config);
if (ret) if (ret)
return ret; return ret;
pm_runtime_set_autosuspend_delay(&pdev->dev, DRM_MSM_INACTIVE_PERIOD);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = request_firmware(&adreno_gpu->pm4, adreno_gpu->info->pm4fw, drm->dev); ret = request_firmware(&adreno_gpu->pm4, adreno_gpu->info->pm4fw, drm->dev);
if (ret) { if (ret) {
dev_err(drm->dev, "failed to load %s PM4 firmware: %d\n", dev_err(drm->dev, "failed to load %s PM4 firmware: %d\n",
...@@ -396,14 +391,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, ...@@ -396,14 +391,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
return ret; return ret;
} }
if (gpu->aspace && gpu->aspace->mmu) {
struct msm_mmu *mmu = gpu->aspace->mmu;
ret = mmu->funcs->attach(mmu, iommu_ports,
ARRAY_SIZE(iommu_ports));
if (ret)
return ret;
}
adreno_gpu->memptrs_bo = msm_gem_new(drm, sizeof(*adreno_gpu->memptrs), adreno_gpu->memptrs_bo = msm_gem_new(drm, sizeof(*adreno_gpu->memptrs),
MSM_BO_UNCACHED); MSM_BO_UNCACHED);
if (IS_ERR(adreno_gpu->memptrs_bo)) { if (IS_ERR(adreno_gpu->memptrs_bo)) {
...@@ -446,10 +433,4 @@ void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu) ...@@ -446,10 +433,4 @@ void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu)
release_firmware(adreno_gpu->pfp); release_firmware(adreno_gpu->pfp);
msm_gpu_cleanup(gpu); msm_gpu_cleanup(gpu);
if (gpu->aspace) {
gpu->aspace->mmu->funcs->detach(gpu->aspace->mmu,
iommu_ports, ARRAY_SIZE(iommu_ports));
msm_gem_address_space_put(gpu->aspace);
}
} }
...@@ -562,11 +562,49 @@ static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu) ...@@ -562,11 +562,49 @@ static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu)
return 0; return 0;
} }
static struct msm_gem_address_space *
msm_gpu_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev,
uint64_t va_start, uint64_t va_end)
{
struct iommu_domain *iommu;
struct msm_gem_address_space *aspace;
int ret;
/*
* Setup IOMMU.. eventually we will (I think) do this once per context
* and have separate page tables per context. For now, to keep things
* simple and to get something working, just use a single address space:
*/
iommu = iommu_domain_alloc(&platform_bus_type);
if (!iommu)
return NULL;
iommu->geometry.aperture_start = va_start;
iommu->geometry.aperture_end = va_end;
dev_info(gpu->dev->dev, "%s: using IOMMU\n", gpu->name);
aspace = msm_gem_address_space_create(&pdev->dev, iommu, "gpu");
if (IS_ERR(aspace)) {
dev_err(gpu->dev->dev, "failed to init iommu: %ld\n",
PTR_ERR(aspace));
iommu_domain_free(iommu);
return ERR_CAST(aspace);
}
ret = aspace->mmu->funcs->attach(aspace->mmu, NULL, 0);
if (ret) {
msm_gem_address_space_put(aspace);
return ERR_PTR(ret);
}
return aspace;
}
int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs, struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs,
const char *name, struct msm_gpu_config *config) const char *name, struct msm_gpu_config *config)
{ {
struct iommu_domain *iommu;
int ret; int ret;
if (WARN_ON(gpu->num_perfcntrs > ARRAY_SIZE(gpu->last_cntrs))) if (WARN_ON(gpu->num_perfcntrs > ARRAY_SIZE(gpu->last_cntrs)))
...@@ -636,28 +674,19 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, ...@@ -636,28 +674,19 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
if (IS_ERR(gpu->gpu_cx)) if (IS_ERR(gpu->gpu_cx))
gpu->gpu_cx = NULL; gpu->gpu_cx = NULL;
/* Setup IOMMU.. eventually we will (I think) do this once per context gpu->pdev = pdev;
* and have separate page tables per context. For now, to keep things platform_set_drvdata(pdev, gpu);
* simple and to get something working, just use a single address space:
*/ bs_init(gpu);
iommu = iommu_domain_alloc(&platform_bus_type);
if (iommu) {
iommu->geometry.aperture_start = config->va_start;
iommu->geometry.aperture_end = config->va_end;
dev_info(drm->dev, "%s: using IOMMU\n", name);
gpu->aspace = msm_gem_address_space_create(&pdev->dev,
iommu, "gpu");
if (IS_ERR(gpu->aspace)) {
ret = PTR_ERR(gpu->aspace);
dev_err(drm->dev, "failed to init iommu: %d\n", ret);
gpu->aspace = NULL;
iommu_domain_free(iommu);
goto fail;
}
} else { gpu->aspace = msm_gpu_create_address_space(gpu, pdev,
config->va_start, config->va_end);
if (gpu->aspace == NULL)
dev_info(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name); dev_info(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);
else if (IS_ERR(gpu->aspace)) {
ret = PTR_ERR(gpu->aspace);
goto fail;
} }
/* Create ringbuffer: */ /* Create ringbuffer: */
...@@ -669,14 +698,10 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, ...@@ -669,14 +698,10 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
goto fail; goto fail;
} }
gpu->pdev = pdev;
platform_set_drvdata(pdev, gpu);
bs_init(gpu);
return 0; return 0;
fail: fail:
platform_set_drvdata(pdev, NULL);
return ret; return ret;
} }
...@@ -693,7 +718,9 @@ void msm_gpu_cleanup(struct msm_gpu *gpu) ...@@ -693,7 +718,9 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
msm_gem_put_iova(gpu->rb->bo, gpu->aspace); msm_gem_put_iova(gpu->rb->bo, gpu->aspace);
msm_ringbuffer_destroy(gpu->rb); msm_ringbuffer_destroy(gpu->rb);
} }
if (gpu->aspace) {
if (gpu->fctx) gpu->aspace->mmu->funcs->detach(gpu->aspace->mmu,
msm_fence_context_free(gpu->fctx); NULL, 0);
msm_gem_address_space_put(gpu->aspace);
}
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment