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