Merge branch 'drm-next-4.4' of git://people.freedesktop.org/~agd5f/linux into drm...
[cascardo/linux.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_cs.c
index cb3c274..dfc4d02 100644 (file)
@@ -104,10 +104,11 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
                }
                break;
        case AMDGPU_HW_IP_DMA:
-               if (ring < 2) {
-                       *out_ring = &adev->sdma[ring].ring;
+               if (ring < adev->sdma.num_instances) {
+                       *out_ring = &adev->sdma.instance[ring].ring;
                } else {
-                       DRM_ERROR("only two SDMA rings are supported\n");
+                       DRM_ERROR("only %d SDMA rings are supported\n",
+                                 adev->sdma.num_instances);
                        return -EINVAL;
                }
                break;
@@ -177,7 +178,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
 
        /* get chunks */
        INIT_LIST_HEAD(&p->validated);
-       chunk_array_user = (uint64_t __user *)(cs->in.chunks);
+       chunk_array_user = (uint64_t __user *)(unsigned long)(cs->in.chunks);
        if (copy_from_user(chunk_array, chunk_array_user,
                           sizeof(uint64_t)*cs->in.num_chunks)) {
                ret = -EFAULT;
@@ -197,7 +198,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
                struct drm_amdgpu_cs_chunk user_chunk;
                uint32_t __user *cdata;
 
-               chunk_ptr = (void __user *)chunk_array[i];
+               chunk_ptr = (void __user *)(unsigned long)chunk_array[i];
                if (copy_from_user(&user_chunk, chunk_ptr,
                                       sizeof(struct drm_amdgpu_cs_chunk))) {
                        ret = -EFAULT;
@@ -208,7 +209,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
                p->chunks[i].length_dw = user_chunk.length_dw;
 
                size = p->chunks[i].length_dw;
-               cdata = (void __user *)user_chunk.chunk_data;
+               cdata = (void __user *)(unsigned long)user_chunk.chunk_data;
                p->chunks[i].user_ptr = cdata;
 
                p->chunks[i].kdata = drm_malloc_ab(size, sizeof(uint32_t));
@@ -567,9 +568,24 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
                        if (r)
                                return r;
                }
+
+       }
+
+       r = amdgpu_vm_clear_invalids(adev, vm, &p->ibs[0].sync);
+
+       if (amdgpu_vm_debug && p->bo_list) {
+               /* Invalidate all BOs to test for userspace bugs */
+               for (i = 0; i < p->bo_list->num_entries; i++) {
+                       /* ignore duplicates */
+                       bo = p->bo_list->array[i].robj;
+                       if (!bo)
+                               continue;
+
+                       amdgpu_vm_bo_invalidate(adev, bo);
+               }
        }
 
-       return amdgpu_vm_clear_invalids(adev, vm, &p->ibs[0].sync);
+       return r;
 }
 
 static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
@@ -593,7 +609,6 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
                }
        }
 
-       mutex_lock(&vm->mutex);
        r = amdgpu_bo_vm_update_pte(parser, vm);
        if (r) {
                goto out;
@@ -604,7 +619,6 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
                                       parser->filp);
 
 out:
-       mutex_unlock(&vm->mutex);
        return r;
 }
 
@@ -812,15 +826,14 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 {
        struct amdgpu_device *adev = dev->dev_private;
        union drm_amdgpu_cs *cs = data;
+       struct amdgpu_fpriv *fpriv = filp->driver_priv;
+       struct amdgpu_vm *vm = &fpriv->vm;
        struct amdgpu_cs_parser *parser;
        bool reserved_buffers = false;
        int i, r;
 
-       down_read(&adev->exclusive_lock);
-       if (!adev->accel_working) {
-               up_read(&adev->exclusive_lock);
+       if (!adev->accel_working)
                return -EBUSY;
-       }
 
        parser = amdgpu_cs_parser_create(adev, filp, NULL, NULL, 0);
        if (!parser)
@@ -828,12 +841,11 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        r = amdgpu_cs_parser_init(parser, data);
        if (r) {
                DRM_ERROR("Failed to initialize parser !\n");
-               kfree(parser);
-               up_read(&adev->exclusive_lock);
+               amdgpu_cs_parser_fini(parser, r, false);
                r = amdgpu_cs_handle_lockup(adev, r);
                return r;
        }
-
+       mutex_lock(&vm->mutex);
        r = amdgpu_cs_parser_relocs(parser);
        if (r == -ENOMEM)
                DRM_ERROR("Not enough memory for command submission!\n");
@@ -864,8 +876,10 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                struct amdgpu_job *job;
                struct amdgpu_ring * ring =  parser->ibs->ring;
                job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL);
-               if (!job)
-                       return -ENOMEM;
+               if (!job) {
+                       r = -ENOMEM;
+                       goto out;
+               }
                job->base.sched = &ring->sched;
                job->base.s_entity = &parser->ctx->rings[ring->idx].entity;
                job->adev = parser->adev;
@@ -900,14 +914,14 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 
                mutex_unlock(&job->job_lock);
                amdgpu_cs_parser_fini_late(parser);
-               up_read(&adev->exclusive_lock);
+               mutex_unlock(&vm->mutex);
                return 0;
        }
 
        cs->out.handle = parser->ibs[parser->num_ibs - 1].sequence;
 out:
        amdgpu_cs_parser_fini(parser, r, reserved_buffers);
-       up_read(&adev->exclusive_lock);
+       mutex_unlock(&vm->mutex);
        r = amdgpu_cs_handle_lockup(adev, r);
        return r;
 }