linux/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
<<
>>
Prefs
   1/*
   2 * Copyright 2017 Valve Corporation
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: Andres Rodriguez <andresx7@gmail.com>
  23 */
  24
  25#include <linux/fdtable.h>
  26#include <linux/file.h>
  27#include <linux/pid.h>
  28
  29#include <drm/amdgpu_drm.h>
  30
  31#include "amdgpu.h"
  32#include "amdgpu_sched.h"
  33#include "amdgpu_vm.h"
  34
  35int amdgpu_to_sched_priority(int amdgpu_priority,
  36                             enum drm_sched_priority *prio)
  37{
  38        switch (amdgpu_priority) {
  39        case AMDGPU_CTX_PRIORITY_VERY_HIGH:
  40                *prio = DRM_SCHED_PRIORITY_HIGH;
  41                break;
  42        case AMDGPU_CTX_PRIORITY_HIGH:
  43                *prio = DRM_SCHED_PRIORITY_HIGH;
  44                break;
  45        case AMDGPU_CTX_PRIORITY_NORMAL:
  46                *prio = DRM_SCHED_PRIORITY_NORMAL;
  47                break;
  48        case AMDGPU_CTX_PRIORITY_LOW:
  49        case AMDGPU_CTX_PRIORITY_VERY_LOW:
  50                *prio = DRM_SCHED_PRIORITY_MIN;
  51                break;
  52        case AMDGPU_CTX_PRIORITY_UNSET:
  53                *prio = DRM_SCHED_PRIORITY_UNSET;
  54                break;
  55        default:
  56                WARN(1, "Invalid context priority %d\n", amdgpu_priority);
  57                return -EINVAL;
  58        }
  59
  60        return 0;
  61}
  62
  63static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev,
  64                                                  int fd,
  65                                                  enum drm_sched_priority priority)
  66{
  67        struct fd f = fdget(fd);
  68        struct amdgpu_fpriv *fpriv;
  69        struct amdgpu_ctx *ctx;
  70        uint32_t id;
  71        int r;
  72
  73        if (!f.file)
  74                return -EINVAL;
  75
  76        r = amdgpu_file_to_fpriv(f.file, &fpriv);
  77        if (r) {
  78                fdput(f);
  79                return r;
  80        }
  81
  82        idr_for_each_entry(&fpriv->ctx_mgr.ctx_handles, ctx, id)
  83                amdgpu_ctx_priority_override(ctx, priority);
  84
  85        fdput(f);
  86        return 0;
  87}
  88
  89static int amdgpu_sched_context_priority_override(struct amdgpu_device *adev,
  90                                                  int fd,
  91                                                  unsigned ctx_id,
  92                                                  enum drm_sched_priority priority)
  93{
  94        struct fd f = fdget(fd);
  95        struct amdgpu_fpriv *fpriv;
  96        struct amdgpu_ctx *ctx;
  97        int r;
  98
  99        if (!f.file)
 100                return -EINVAL;
 101
 102        r = amdgpu_file_to_fpriv(f.file, &fpriv);
 103        if (r) {
 104                fdput(f);
 105                return r;
 106        }
 107
 108        ctx = amdgpu_ctx_get(fpriv, ctx_id);
 109
 110        if (!ctx) {
 111                fdput(f);
 112                return -EINVAL;
 113        }
 114
 115        amdgpu_ctx_priority_override(ctx, priority);
 116        amdgpu_ctx_put(ctx);
 117        fdput(f);
 118
 119        return 0;
 120}
 121
 122int amdgpu_sched_ioctl(struct drm_device *dev, void *data,
 123                       struct drm_file *filp)
 124{
 125        union drm_amdgpu_sched *args = data;
 126        struct amdgpu_device *adev = drm_to_adev(dev);
 127        enum drm_sched_priority priority;
 128        int r;
 129
 130        /* First check the op, then the op's argument.
 131         */
 132        switch (args->in.op) {
 133        case AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE:
 134        case AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE:
 135                break;
 136        default:
 137                DRM_ERROR("Invalid sched op specified: %d\n", args->in.op);
 138                return -EINVAL;
 139        }
 140
 141        r = amdgpu_to_sched_priority(args->in.priority, &priority);
 142        if (r)
 143                return r;
 144
 145        switch (args->in.op) {
 146        case AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE:
 147                r = amdgpu_sched_process_priority_override(adev,
 148                                                           args->in.fd,
 149                                                           priority);
 150                break;
 151        case AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE:
 152                r = amdgpu_sched_context_priority_override(adev,
 153                                                           args->in.fd,
 154                                                           args->in.ctx_id,
 155                                                           priority);
 156                break;
 157        default:
 158                /* Impossible.
 159                 */
 160                r = -EINVAL;
 161                break;
 162        }
 163
 164        return r;
 165}
 166