Commit 569f0a86 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'etnaviv/next' of https://git.pengutronix.de/git/lst/linux into drm-next

From: Lucas Stach <l.stach@pengutronix.de>
"not much to de-stage this time. Changes from Philipp and Souptick to
use memset32 more and switch the fault handler to the new vm_fault_t
and two small fixes for issues that can be hit in rare corner cases
from me."
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1533563808.2809.7.camel@pengutronix.de
parents a7ccc5a4 5b147465
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/time64.h> #include <linux/time64.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <linux/mm_types.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
...@@ -53,7 +54,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, ...@@ -53,7 +54,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
struct drm_file *file); struct drm_file *file);
int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma); int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma);
int etnaviv_gem_fault(struct vm_fault *vmf); vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf);
int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset); int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset);
struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj); struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj);
void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj); void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj);
......
...@@ -169,31 +169,30 @@ int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -169,31 +169,30 @@ int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma)
return obj->ops->mmap(obj, vma); return obj->ops->mmap(obj, vma);
} }
int etnaviv_gem_fault(struct vm_fault *vmf) vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
{ {
struct vm_area_struct *vma = vmf->vma; struct vm_area_struct *vma = vmf->vma;
struct drm_gem_object *obj = vma->vm_private_data; struct drm_gem_object *obj = vma->vm_private_data;
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
struct page **pages, *page; struct page **pages, *page;
pgoff_t pgoff; pgoff_t pgoff;
int ret; int err;
/* /*
* Make sure we don't parallel update on a fault, nor move or remove * Make sure we don't parallel update on a fault, nor move or remove
* something from beneath our feet. Note that vm_insert_page() is * something from beneath our feet. Note that vmf_insert_page() is
* specifically coded to take care of this, so we don't have to. * specifically coded to take care of this, so we don't have to.
*/ */
ret = mutex_lock_interruptible(&etnaviv_obj->lock); err = mutex_lock_interruptible(&etnaviv_obj->lock);
if (ret) if (err)
goto out; return VM_FAULT_NOPAGE;
/* make sure we have pages attached now */ /* make sure we have pages attached now */
pages = etnaviv_gem_get_pages(etnaviv_obj); pages = etnaviv_gem_get_pages(etnaviv_obj);
mutex_unlock(&etnaviv_obj->lock); mutex_unlock(&etnaviv_obj->lock);
if (IS_ERR(pages)) { if (IS_ERR(pages)) {
ret = PTR_ERR(pages); err = PTR_ERR(pages);
goto out; return vmf_error(err);
} }
/* We don't use vmf->pgoff since that has the fake offset: */ /* We don't use vmf->pgoff since that has the fake offset: */
...@@ -204,25 +203,7 @@ int etnaviv_gem_fault(struct vm_fault *vmf) ...@@ -204,25 +203,7 @@ int etnaviv_gem_fault(struct vm_fault *vmf)
VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address, VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
page_to_pfn(page), page_to_pfn(page) << PAGE_SHIFT); page_to_pfn(page), page_to_pfn(page) << PAGE_SHIFT);
ret = vm_insert_page(vma, vmf->address, page); return vmf_insert_page(vma, vmf->address, page);
out:
switch (ret) {
case -EAGAIN:
case 0:
case -ERESTARTSYS:
case -EINTR:
case -EBUSY:
/*
* EBUSY is ok: this just means that another thread
* already did the job.
*/
return VM_FAULT_NOPAGE;
case -ENOMEM:
return VM_FAULT_OOM;
default:
return VM_FAULT_SIGBUS;
}
} }
int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset) int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset)
......
...@@ -388,9 +388,9 @@ static void submit_cleanup(struct kref *kref) ...@@ -388,9 +388,9 @@ static void submit_cleanup(struct kref *kref)
dma_fence_put(submit->in_fence); dma_fence_put(submit->in_fence);
if (submit->out_fence) { if (submit->out_fence) {
/* first remove from IDR, so fence can not be found anymore */ /* first remove from IDR, so fence can not be found anymore */
mutex_lock(&submit->gpu->fence_idr_lock); mutex_lock(&submit->gpu->fence_lock);
idr_remove(&submit->gpu->fence_idr, submit->out_fence_id); idr_remove(&submit->gpu->fence_idr, submit->out_fence_id);
mutex_unlock(&submit->gpu->fence_idr_lock); mutex_unlock(&submit->gpu->fence_lock);
dma_fence_put(submit->out_fence); dma_fence_put(submit->out_fence);
} }
kfree(submit->pmrs); kfree(submit->pmrs);
......
...@@ -799,6 +799,7 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) ...@@ -799,6 +799,7 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
free_buffer: free_buffer:
etnaviv_cmdbuf_free(&gpu->buffer); etnaviv_cmdbuf_free(&gpu->buffer);
gpu->buffer.suballoc = NULL;
destroy_iommu: destroy_iommu:
etnaviv_iommu_destroy(gpu->mmu); etnaviv_iommu_destroy(gpu->mmu);
gpu->mmu = NULL; gpu->mmu = NULL;
...@@ -1726,7 +1727,7 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev) ...@@ -1726,7 +1727,7 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
gpu->dev = &pdev->dev; gpu->dev = &pdev->dev;
mutex_init(&gpu->lock); mutex_init(&gpu->lock);
mutex_init(&gpu->fence_idr_lock); mutex_init(&gpu->fence_lock);
/* Map registers: */ /* Map registers: */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
...@@ -118,7 +118,7 @@ struct etnaviv_gpu { ...@@ -118,7 +118,7 @@ struct etnaviv_gpu {
u32 idle_mask; u32 idle_mask;
/* Fencing support */ /* Fencing support */
struct mutex fence_idr_lock; struct mutex fence_lock;
struct idr fence_idr; struct idr fence_idr;
u32 next_fence; u32 next_fence;
u32 active_fence; u32 active_fence;
......
...@@ -119,8 +119,7 @@ static size_t etnaviv_iommuv2_unmap(struct etnaviv_iommu_domain *domain, ...@@ -119,8 +119,7 @@ static size_t etnaviv_iommuv2_unmap(struct etnaviv_iommu_domain *domain,
static int etnaviv_iommuv2_init(struct etnaviv_iommuv2_domain *etnaviv_domain) static int etnaviv_iommuv2_init(struct etnaviv_iommuv2_domain *etnaviv_domain)
{ {
u32 *p; int ret;
int ret, i;
/* allocate scratch page */ /* allocate scratch page */
etnaviv_domain->base.bad_page_cpu = etnaviv_domain->base.bad_page_cpu =
...@@ -131,9 +130,9 @@ static int etnaviv_iommuv2_init(struct etnaviv_iommuv2_domain *etnaviv_domain) ...@@ -131,9 +130,9 @@ static int etnaviv_iommuv2_init(struct etnaviv_iommuv2_domain *etnaviv_domain)
ret = -ENOMEM; ret = -ENOMEM;
goto fail_mem; goto fail_mem;
} }
p = etnaviv_domain->base.bad_page_cpu;
for (i = 0; i < SZ_4K / 4; i++) memset32(etnaviv_domain->base.bad_page_cpu, 0xdead55aa,
*p++ = 0xdead55aa; SZ_4K / sizeof(u32));
etnaviv_domain->pta_cpu = dma_alloc_wc(etnaviv_domain->base.dev, etnaviv_domain->pta_cpu = dma_alloc_wc(etnaviv_domain->base.dev,
SZ_4K, &etnaviv_domain->pta_dma, SZ_4K, &etnaviv_domain->pta_dma,
......
...@@ -140,28 +140,38 @@ static const struct drm_sched_backend_ops etnaviv_sched_ops = { ...@@ -140,28 +140,38 @@ static const struct drm_sched_backend_ops etnaviv_sched_ops = {
int etnaviv_sched_push_job(struct drm_sched_entity *sched_entity, int etnaviv_sched_push_job(struct drm_sched_entity *sched_entity,
struct etnaviv_gem_submit *submit) struct etnaviv_gem_submit *submit)
{ {
int ret; int ret = 0;
/*
* Hold the fence lock across the whole operation to avoid jobs being
* pushed out of order with regard to their sched fence seqnos as
* allocated in drm_sched_job_init.
*/
mutex_lock(&submit->gpu->fence_lock);
ret = drm_sched_job_init(&submit->sched_job, sched_entity, ret = drm_sched_job_init(&submit->sched_job, sched_entity,
submit->cmdbuf.ctx); submit->cmdbuf.ctx);
if (ret) if (ret)
return ret; goto out_unlock;
submit->out_fence = dma_fence_get(&submit->sched_job.s_fence->finished); submit->out_fence = dma_fence_get(&submit->sched_job.s_fence->finished);
mutex_lock(&submit->gpu->fence_idr_lock);
submit->out_fence_id = idr_alloc_cyclic(&submit->gpu->fence_idr, submit->out_fence_id = idr_alloc_cyclic(&submit->gpu->fence_idr,
submit->out_fence, 0, submit->out_fence, 0,
INT_MAX, GFP_KERNEL); INT_MAX, GFP_KERNEL);
mutex_unlock(&submit->gpu->fence_idr_lock); if (submit->out_fence_id < 0) {
if (submit->out_fence_id < 0) ret = -ENOMEM;
return -ENOMEM; goto out_unlock;
}
/* the scheduler holds on to the job now */ /* the scheduler holds on to the job now */
kref_get(&submit->refcount); kref_get(&submit->refcount);
drm_sched_entity_push_job(&submit->sched_job, sched_entity); drm_sched_entity_push_job(&submit->sched_job, sched_entity);
return 0; out_unlock:
mutex_unlock(&submit->gpu->fence_lock);
return ret;
} }
int etnaviv_sched_init(struct etnaviv_gpu *gpu) int etnaviv_sched_init(struct etnaviv_gpu *gpu)
......
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