aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd
diff options
context:
space:
mode:
authorAndrey Grodzovsky <andrey.grodzovsky@amd.com>2018-07-06 14:16:54 -0400
committerAlex Deucher <alexander.deucher@amd.com>2018-07-16 16:29:47 -0400
commit964d0fbf6301d3dc8dfad19ffab5a06d002d27f1 (patch)
treeb158d245de63e888bf20897b8f8cecb7fb6cede1 /drivers/gpu/drm/amd
parent8415afbd86ddd8a268a8450286bc58b2bb3b83d1 (diff)
drm/amdgpu: Allow to create BO lists in CS ioctl v3
This change is to support MESA performace optimization. Modify CS IOCTL to allow its input as command buffer and an array of buffer handles to create a temporay bo list and then destroy it when IOCTL completes. This saves on calling for BO_LIST create and destry IOCTLs in MESA and by this improves performance. v2: Avoid inserting the temp list into idr struct. v3: Remove idr alloation from amdgpu_bo_list_create. Remove useless argument from amdgpu_cs_parser_fini Minor cosmetic stuff. v4: Revert amdgpu_bo_list_destroy back to static Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Chunming Zhou <david1.zhou@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c88
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c48
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c3
4 files changed, 107 insertions, 40 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 53435da158c2..c6c1e8dc919f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -732,6 +732,14 @@ void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list,
732 struct list_head *validated); 732 struct list_head *validated);
733void amdgpu_bo_list_put(struct amdgpu_bo_list *list); 733void amdgpu_bo_list_put(struct amdgpu_bo_list *list);
734void amdgpu_bo_list_free(struct amdgpu_bo_list *list); 734void amdgpu_bo_list_free(struct amdgpu_bo_list *list);
735int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in,
736 struct drm_amdgpu_bo_list_entry **info_param);
737
738int amdgpu_bo_list_create(struct amdgpu_device *adev,
739 struct drm_file *filp,
740 struct drm_amdgpu_bo_list_entry *info,
741 unsigned num_entries,
742 struct amdgpu_bo_list **list);
735 743
736/* 744/*
737 * GFX stuff 745 * GFX stuff
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
index 92be7f6de197..7679c068c89a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
@@ -55,15 +55,15 @@ static void amdgpu_bo_list_release_rcu(struct kref *ref)
55 kfree_rcu(list, rhead); 55 kfree_rcu(list, rhead);
56} 56}
57 57
58static int amdgpu_bo_list_create(struct amdgpu_device *adev, 58int amdgpu_bo_list_create(struct amdgpu_device *adev,
59 struct drm_file *filp, 59 struct drm_file *filp,
60 struct drm_amdgpu_bo_list_entry *info, 60 struct drm_amdgpu_bo_list_entry *info,
61 unsigned num_entries, 61 unsigned num_entries,
62 int *id) 62 struct amdgpu_bo_list **list_out)
63{ 63{
64 int r;
65 struct amdgpu_fpriv *fpriv = filp->driver_priv;
66 struct amdgpu_bo_list *list; 64 struct amdgpu_bo_list *list;
65 int r;
66
67 67
68 list = kzalloc(sizeof(struct amdgpu_bo_list), GFP_KERNEL); 68 list = kzalloc(sizeof(struct amdgpu_bo_list), GFP_KERNEL);
69 if (!list) 69 if (!list)
@@ -78,16 +78,7 @@ static int amdgpu_bo_list_create(struct amdgpu_device *adev,
78 return r; 78 return r;
79 } 79 }
80 80
81 /* idr alloc should be called only after initialization of bo list. */ 81 *list_out = list;
82 mutex_lock(&fpriv->bo_list_lock);
83 r = idr_alloc(&fpriv->bo_list_handles, list, 1, 0, GFP_KERNEL);
84 mutex_unlock(&fpriv->bo_list_lock);
85 if (r < 0) {
86 amdgpu_bo_list_free(list);
87 return r;
88 }
89 *id = r;
90
91 return 0; 82 return 0;
92} 83}
93 84
@@ -263,55 +254,79 @@ void amdgpu_bo_list_free(struct amdgpu_bo_list *list)
263 kfree(list); 254 kfree(list);
264} 255}
265 256
266int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data, 257int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in,
267 struct drm_file *filp) 258 struct drm_amdgpu_bo_list_entry **info_param)
268{ 259{
260 const void __user *uptr = u64_to_user_ptr(in->bo_info_ptr);
269 const uint32_t info_size = sizeof(struct drm_amdgpu_bo_list_entry); 261 const uint32_t info_size = sizeof(struct drm_amdgpu_bo_list_entry);
270
271 struct amdgpu_device *adev = dev->dev_private;
272 struct amdgpu_fpriv *fpriv = filp->driver_priv;
273 union drm_amdgpu_bo_list *args = data;
274 uint32_t handle = args->in.list_handle;
275 const void __user *uptr = u64_to_user_ptr(args->in.bo_info_ptr);
276
277 struct drm_amdgpu_bo_list_entry *info; 262 struct drm_amdgpu_bo_list_entry *info;
278 struct amdgpu_bo_list *list;
279
280 int r; 263 int r;
281 264
282 info = kvmalloc_array(args->in.bo_number, 265 info = kvmalloc_array(in->bo_number, info_size, GFP_KERNEL);
283 sizeof(struct drm_amdgpu_bo_list_entry), GFP_KERNEL);
284 if (!info) 266 if (!info)
285 return -ENOMEM; 267 return -ENOMEM;
286 268
287 /* copy the handle array from userspace to a kernel buffer */ 269 /* copy the handle array from userspace to a kernel buffer */
288 r = -EFAULT; 270 r = -EFAULT;
289 if (likely(info_size == args->in.bo_info_size)) { 271 if (likely(info_size == in->bo_info_size)) {
290 unsigned long bytes = args->in.bo_number * 272 unsigned long bytes = in->bo_number *
291 args->in.bo_info_size; 273 in->bo_info_size;
292 274
293 if (copy_from_user(info, uptr, bytes)) 275 if (copy_from_user(info, uptr, bytes))
294 goto error_free; 276 goto error_free;
295 277
296 } else { 278 } else {
297 unsigned long bytes = min(args->in.bo_info_size, info_size); 279 unsigned long bytes = min(in->bo_info_size, info_size);
298 unsigned i; 280 unsigned i;
299 281
300 memset(info, 0, args->in.bo_number * info_size); 282 memset(info, 0, in->bo_number * info_size);
301 for (i = 0; i < args->in.bo_number; ++i) { 283 for (i = 0; i < in->bo_number; ++i) {
302 if (copy_from_user(&info[i], uptr, bytes)) 284 if (copy_from_user(&info[i], uptr, bytes))
303 goto error_free; 285 goto error_free;
304 286
305 uptr += args->in.bo_info_size; 287 uptr += in->bo_info_size;
306 } 288 }
307 } 289 }
308 290
291 *info_param = info;
292 return 0;
293
294error_free:
295 kvfree(info);
296 return r;
297}
298
299int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data,
300 struct drm_file *filp)
301{
302 struct amdgpu_device *adev = dev->dev_private;
303 struct amdgpu_fpriv *fpriv = filp->driver_priv;
304 union drm_amdgpu_bo_list *args = data;
305 uint32_t handle = args->in.list_handle;
306 struct drm_amdgpu_bo_list_entry *info = NULL;
307 struct amdgpu_bo_list *list;
308 int r;
309
310 r = amdgpu_bo_create_list_entry_array(&args->in, &info);
311 if (r)
312 goto error_free;
313
309 switch (args->in.operation) { 314 switch (args->in.operation) {
310 case AMDGPU_BO_LIST_OP_CREATE: 315 case AMDGPU_BO_LIST_OP_CREATE:
311 r = amdgpu_bo_list_create(adev, filp, info, args->in.bo_number, 316 r = amdgpu_bo_list_create(adev, filp, info, args->in.bo_number,
312 &handle); 317 &list);
313 if (r) 318 if (r)
314 goto error_free; 319 goto error_free;
320
321 mutex_lock(&fpriv->bo_list_lock);
322 r = idr_alloc(&fpriv->bo_list_handles, list, 1, 0, GFP_KERNEL);
323 mutex_unlock(&fpriv->bo_list_lock);
324 if (r < 0) {
325 amdgpu_bo_list_free(list);
326 return r;
327 }
328
329 handle = r;
315 break; 330 break;
316 331
317 case AMDGPU_BO_LIST_OP_DESTROY: 332 case AMDGPU_BO_LIST_OP_DESTROY:
@@ -345,6 +360,7 @@ int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data,
345 return 0; 360 return 0;
346 361
347error_free: 362error_free:
348 kvfree(info); 363 if (info)
364 kvfree(info);
349 return r; 365 return r;
350} 366}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 5a2a5ba29f9a..6d8df76b5a5d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -66,11 +66,35 @@ static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p,
66 return 0; 66 return 0;
67} 67}
68 68
69static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) 69static int amdgpu_cs_bo_handles_chunk(struct amdgpu_cs_parser *p,
70 struct drm_amdgpu_bo_list_in *data)
71{
72 int r;
73 struct drm_amdgpu_bo_list_entry *info = NULL;
74
75 r = amdgpu_bo_create_list_entry_array(data, &info);
76 if (r)
77 return r;
78
79 r = amdgpu_bo_list_create(p->adev, p->filp, info, data->bo_number,
80 &p->bo_list);
81 if (r)
82 goto error_free;
83
84 kvfree(info);
85 return 0;
86
87error_free:
88 if (info)
89 kvfree(info);
90
91 return r;
92}
93
94static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs *cs)
70{ 95{
71 struct amdgpu_fpriv *fpriv = p->filp->driver_priv; 96 struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
72 struct amdgpu_vm *vm = &fpriv->vm; 97 struct amdgpu_vm *vm = &fpriv->vm;
73 union drm_amdgpu_cs *cs = data;
74 uint64_t *chunk_array_user; 98 uint64_t *chunk_array_user;
75 uint64_t *chunk_array; 99 uint64_t *chunk_array;
76 unsigned size, num_ibs = 0; 100 unsigned size, num_ibs = 0;
@@ -164,6 +188,19 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
164 188
165 break; 189 break;
166 190
191 case AMDGPU_CHUNK_ID_BO_HANDLES:
192 size = sizeof(struct drm_amdgpu_bo_list_in);
193 if (p->chunks[i].length_dw * sizeof(uint32_t) < size) {
194 ret = -EINVAL;
195 goto free_partial_kdata;
196 }
197
198 ret = amdgpu_cs_bo_handles_chunk(p, p->chunks[i].kdata);
199 if (ret)
200 goto free_partial_kdata;
201
202 break;
203
167 case AMDGPU_CHUNK_ID_DEPENDENCIES: 204 case AMDGPU_CHUNK_ID_DEPENDENCIES:
168 case AMDGPU_CHUNK_ID_SYNCOBJ_IN: 205 case AMDGPU_CHUNK_ID_SYNCOBJ_IN:
169 case AMDGPU_CHUNK_ID_SYNCOBJ_OUT: 206 case AMDGPU_CHUNK_ID_SYNCOBJ_OUT:
@@ -534,7 +571,12 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
534 571
535 INIT_LIST_HEAD(&p->validated); 572 INIT_LIST_HEAD(&p->validated);
536 573
537 p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle); 574 /* p->bo_list could already be assigned if AMDGPU_CHUNK_ID_BO_HANDLES is present */
575 if (!p->bo_list)
576 p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle);
577 else
578 mutex_lock(&p->bo_list->lock);
579
538 if (p->bo_list) { 580 if (p->bo_list) {
539 amdgpu_bo_list_get_list(p->bo_list, &p->validated); 581 amdgpu_bo_list_get_list(p->bo_list, &p->validated);
540 if (p->bo_list->first_userptr != p->bo_list->num_entries) 582 if (p->bo_list->first_userptr != p->bo_list->num_entries)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 06aede194bf8..529500c94675 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -69,9 +69,10 @@
69 * - 3.24.0 - Add high priority compute support for gfx9 69 * - 3.24.0 - Add high priority compute support for gfx9
70 * - 3.25.0 - Add support for sensor query info (stable pstate sclk/mclk). 70 * - 3.25.0 - Add support for sensor query info (stable pstate sclk/mclk).
71 * - 3.26.0 - GFX9: Process AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE. 71 * - 3.26.0 - GFX9: Process AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE.
72 * - 3.27.0 - Add new chunk to to AMDGPU_CS to enable BO_LIST creation.
72 */ 73 */
73#define KMS_DRIVER_MAJOR 3 74#define KMS_DRIVER_MAJOR 3
74#define KMS_DRIVER_MINOR 26 75#define KMS_DRIVER_MINOR 27
75#define KMS_DRIVER_PATCHLEVEL 0 76#define KMS_DRIVER_PATCHLEVEL 0
76 77
77int amdgpu_vram_limit = 0; 78int amdgpu_vram_limit = 0;