]> Git Repo - linux.git/blob - drivers/gpu/drm/imagination/pvr_free_list.c
crypto: akcipher - Drop sign/verify operations
[linux.git] / drivers / gpu / drm / imagination / pvr_free_list.c
1 // SPDX-License-Identifier: GPL-2.0-only OR MIT
2 /* Copyright (c) 2023 Imagination Technologies Ltd. */
3
4 #include "pvr_free_list.h"
5 #include "pvr_gem.h"
6 #include "pvr_hwrt.h"
7 #include "pvr_rogue_fwif.h"
8 #include "pvr_vm.h"
9
10 #include <drm/drm_gem.h>
11 #include <linux/slab.h>
12 #include <linux/xarray.h>
13 #include <uapi/drm/pvr_drm.h>
14
15 #define FREE_LIST_ENTRY_SIZE sizeof(u32)
16
17 #define FREE_LIST_ALIGNMENT \
18         ((ROGUE_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE / FREE_LIST_ENTRY_SIZE) - 1)
19
20 #define FREE_LIST_MIN_PAGES 50
21 #define FREE_LIST_MIN_PAGES_BRN66011 40
22 #define FREE_LIST_MIN_PAGES_ROGUEXE 25
23
24 /**
25  * pvr_get_free_list_min_pages() - Get minimum free list size for this device
26  * @pvr_dev: Device pointer.
27  *
28  * Returns:
29  *  * Minimum free list size, in PM physical pages.
30  */
31 u32
32 pvr_get_free_list_min_pages(struct pvr_device *pvr_dev)
33 {
34         u32 value;
35
36         if (PVR_HAS_FEATURE(pvr_dev, roguexe)) {
37                 if (PVR_HAS_QUIRK(pvr_dev, 66011))
38                         value = FREE_LIST_MIN_PAGES_BRN66011;
39                 else
40                         value = FREE_LIST_MIN_PAGES_ROGUEXE;
41         } else {
42                 value = FREE_LIST_MIN_PAGES;
43         }
44
45         return value;
46 }
47
48 static int
49 free_list_create_kernel_structure(struct pvr_file *pvr_file,
50                                   struct drm_pvr_ioctl_create_free_list_args *args,
51                                   struct pvr_free_list *free_list)
52 {
53         struct pvr_gem_object *free_list_obj;
54         struct pvr_vm_context *vm_ctx;
55         u64 free_list_size;
56         int err;
57
58         if (args->grow_threshold > 100 ||
59             args->initial_num_pages > args->max_num_pages ||
60             args->grow_num_pages > args->max_num_pages ||
61             args->max_num_pages == 0 ||
62             (args->initial_num_pages < args->max_num_pages && !args->grow_num_pages) ||
63             (args->initial_num_pages == args->max_num_pages && args->grow_num_pages))
64                 return -EINVAL;
65
66         if ((args->initial_num_pages & FREE_LIST_ALIGNMENT) ||
67             (args->max_num_pages & FREE_LIST_ALIGNMENT) ||
68             (args->grow_num_pages & FREE_LIST_ALIGNMENT))
69                 return -EINVAL;
70
71         vm_ctx = pvr_vm_context_lookup(pvr_file, args->vm_context_handle);
72         if (!vm_ctx)
73                 return -EINVAL;
74
75         free_list_obj = pvr_vm_find_gem_object(vm_ctx, args->free_list_gpu_addr,
76                                                NULL, &free_list_size);
77         if (!free_list_obj) {
78                 err = -EINVAL;
79                 goto err_put_vm_context;
80         }
81
82         if ((free_list_obj->flags & DRM_PVR_BO_ALLOW_CPU_USERSPACE_ACCESS) ||
83             !(free_list_obj->flags & DRM_PVR_BO_PM_FW_PROTECT) ||
84             free_list_size < (args->max_num_pages * FREE_LIST_ENTRY_SIZE)) {
85                 err = -EINVAL;
86                 goto err_put_free_list_obj;
87         }
88
89         free_list->pvr_dev = pvr_file->pvr_dev;
90         free_list->current_pages = 0;
91         free_list->max_pages = args->max_num_pages;
92         free_list->grow_pages = args->grow_num_pages;
93         free_list->grow_threshold = args->grow_threshold;
94         free_list->obj = free_list_obj;
95         free_list->free_list_gpu_addr = args->free_list_gpu_addr;
96         free_list->initial_num_pages = args->initial_num_pages;
97
98         pvr_vm_context_put(vm_ctx);
99
100         return 0;
101
102 err_put_free_list_obj:
103         pvr_gem_object_put(free_list_obj);
104
105 err_put_vm_context:
106         pvr_vm_context_put(vm_ctx);
107
108         return err;
109 }
110
111 static void
112 free_list_destroy_kernel_structure(struct pvr_free_list *free_list)
113 {
114         WARN_ON(!list_empty(&free_list->hwrt_list));
115
116         pvr_gem_object_put(free_list->obj);
117 }
118
119 /**
120  * calculate_free_list_ready_pages_locked() - Function to work out the number of free
121  *                                            list pages to reserve for growing within
122  *                                            the FW without having to wait for the
123  *                                            host to progress a grow request
124  * @free_list: Pointer to free list.
125  * @pages: Total pages currently in free list.
126  *
127  * If the threshold or grow size means less than the alignment size (4 pages on
128  * Rogue), then the feature is not used.
129  *
130  * Caller must hold &free_list->lock.
131  *
132  * Return: number of pages to reserve.
133  */
134 static u32
135 calculate_free_list_ready_pages_locked(struct pvr_free_list *free_list, u32 pages)
136 {
137         u32 ready_pages;
138
139         lockdep_assert_held(&free_list->lock);
140
141         ready_pages = ((pages * free_list->grow_threshold) / 100);
142
143         /* The number of pages must be less than the grow size. */
144         ready_pages = min(ready_pages, free_list->grow_pages);
145
146         /*
147          * The number of pages must be a multiple of the free list align size.
148          */
149         ready_pages &= ~FREE_LIST_ALIGNMENT;
150
151         return ready_pages;
152 }
153
154 static u32
155 calculate_free_list_ready_pages(struct pvr_free_list *free_list, u32 pages)
156 {
157         u32 ret;
158
159         mutex_lock(&free_list->lock);
160
161         ret = calculate_free_list_ready_pages_locked(free_list, pages);
162
163         mutex_unlock(&free_list->lock);
164
165         return ret;
166 }
167
168 static void
169 free_list_fw_init(void *cpu_ptr, void *priv)
170 {
171         struct rogue_fwif_freelist *fw_data = cpu_ptr;
172         struct pvr_free_list *free_list = priv;
173         u32 ready_pages;
174
175         /* Fill out FW structure */
176         ready_pages = calculate_free_list_ready_pages(free_list,
177                                                       free_list->initial_num_pages);
178
179         fw_data->max_pages = free_list->max_pages;
180         fw_data->current_pages = free_list->initial_num_pages - ready_pages;
181         fw_data->grow_pages = free_list->grow_pages;
182         fw_data->ready_pages = ready_pages;
183         fw_data->freelist_id = free_list->fw_id;
184         fw_data->grow_pending = false;
185         fw_data->current_stack_top = fw_data->current_pages - 1;
186         fw_data->freelist_dev_addr = free_list->free_list_gpu_addr;
187         fw_data->current_dev_addr = (fw_data->freelist_dev_addr +
188                                      ((fw_data->max_pages - fw_data->current_pages) *
189                                       FREE_LIST_ENTRY_SIZE)) &
190                                     ~((u64)ROGUE_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE - 1);
191 }
192
193 static int
194 free_list_create_fw_structure(struct pvr_file *pvr_file,
195                               struct drm_pvr_ioctl_create_free_list_args *args,
196                               struct pvr_free_list *free_list)
197 {
198         struct pvr_device *pvr_dev = pvr_file->pvr_dev;
199
200         /*
201          * Create and map the FW structure so we can initialise it. This is not
202          * accessed on the CPU side post-initialisation so the mapping lifetime
203          * is only for this function.
204          */
205         free_list->fw_data = pvr_fw_object_create_and_map(pvr_dev, sizeof(*free_list->fw_data),
206                                                           PVR_BO_FW_FLAGS_DEVICE_UNCACHED,
207                                                           free_list_fw_init, free_list,
208                                                           &free_list->fw_obj);
209         if (IS_ERR(free_list->fw_data))
210                 return PTR_ERR(free_list->fw_data);
211
212         return 0;
213 }
214
215 static void
216 free_list_destroy_fw_structure(struct pvr_free_list *free_list)
217 {
218         pvr_fw_object_unmap_and_destroy(free_list->fw_obj);
219 }
220
221 static int
222 pvr_free_list_insert_pages_locked(struct pvr_free_list *free_list,
223                                   struct sg_table *sgt, u32 offset, u32 num_pages)
224 {
225         struct sg_dma_page_iter dma_iter;
226         u32 *page_list;
227
228         lockdep_assert_held(&free_list->lock);
229
230         page_list = pvr_gem_object_vmap(free_list->obj);
231         if (IS_ERR(page_list))
232                 return PTR_ERR(page_list);
233
234         offset /= FREE_LIST_ENTRY_SIZE;
235         /* clang-format off */
236         for_each_sgtable_dma_page(sgt, &dma_iter, 0) {
237                 dma_addr_t dma_addr = sg_page_iter_dma_address(&dma_iter);
238                 u64 dma_pfn = dma_addr >>
239                                ROGUE_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT;
240                 u32 dma_addr_offset;
241
242                 BUILD_BUG_ON(ROGUE_BIF_PM_PHYSICAL_PAGE_SIZE > PAGE_SIZE);
243
244                 for (dma_addr_offset = 0; dma_addr_offset < PAGE_SIZE;
245                      dma_addr_offset += ROGUE_BIF_PM_PHYSICAL_PAGE_SIZE) {
246                         WARN_ON_ONCE(dma_pfn >> 32);
247
248                         page_list[offset++] = (u32)dma_pfn;
249                         dma_pfn++;
250
251                         num_pages--;
252                         if (!num_pages)
253                                 break;
254                 }
255
256                 if (!num_pages)
257                         break;
258         }
259         /* clang-format on */
260
261         /* Make sure our free_list update is flushed. */
262         wmb();
263
264         pvr_gem_object_vunmap(free_list->obj);
265
266         return 0;
267 }
268
269 static int
270 pvr_free_list_insert_node_locked(struct pvr_free_list_node *free_list_node)
271 {
272         struct pvr_free_list *free_list = free_list_node->free_list;
273         struct sg_table *sgt;
274         u32 start_page;
275         u32 offset;
276         int err;
277
278         lockdep_assert_held(&free_list->lock);
279
280         start_page = free_list->max_pages - free_list->current_pages -
281                      free_list_node->num_pages;
282         offset = (start_page * FREE_LIST_ENTRY_SIZE) &
283                   ~((u64)ROGUE_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE - 1);
284
285         sgt = drm_gem_shmem_get_pages_sgt(&free_list_node->mem_obj->base);
286         if (WARN_ON(IS_ERR(sgt)))
287                 return PTR_ERR(sgt);
288
289         err = pvr_free_list_insert_pages_locked(free_list, sgt,
290                                                 offset, free_list_node->num_pages);
291         if (!err)
292                 free_list->current_pages += free_list_node->num_pages;
293
294         return err;
295 }
296
297 static int
298 pvr_free_list_grow(struct pvr_free_list *free_list, u32 num_pages)
299 {
300         struct pvr_device *pvr_dev = free_list->pvr_dev;
301         struct pvr_free_list_node *free_list_node;
302         int err;
303
304         mutex_lock(&free_list->lock);
305
306         if (num_pages & FREE_LIST_ALIGNMENT) {
307                 err = -EINVAL;
308                 goto err_unlock;
309         }
310
311         free_list_node = kzalloc(sizeof(*free_list_node), GFP_KERNEL);
312         if (!free_list_node) {
313                 err = -ENOMEM;
314                 goto err_unlock;
315         }
316
317         free_list_node->num_pages = num_pages;
318         free_list_node->free_list = free_list;
319
320         free_list_node->mem_obj = pvr_gem_object_create(pvr_dev,
321                                                         num_pages <<
322                                                         ROGUE_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
323                                                         PVR_BO_FW_FLAGS_DEVICE_CACHED);
324         if (IS_ERR(free_list_node->mem_obj)) {
325                 err = PTR_ERR(free_list_node->mem_obj);
326                 goto err_free;
327         }
328
329         err = pvr_free_list_insert_node_locked(free_list_node);
330         if (err)
331                 goto err_destroy_gem_object;
332
333         list_add_tail(&free_list_node->node, &free_list->mem_block_list);
334
335         /*
336          * Reserve a number ready pages to allow the FW to process OOM quickly
337          * and asynchronously request a grow.
338          */
339         free_list->ready_pages =
340                 calculate_free_list_ready_pages_locked(free_list,
341                                                        free_list->current_pages);
342         free_list->current_pages -= free_list->ready_pages;
343
344         mutex_unlock(&free_list->lock);
345
346         return 0;
347
348 err_destroy_gem_object:
349         pvr_gem_object_put(free_list_node->mem_obj);
350
351 err_free:
352         kfree(free_list_node);
353
354 err_unlock:
355         mutex_unlock(&free_list->lock);
356
357         return err;
358 }
359
360 void pvr_free_list_process_grow_req(struct pvr_device *pvr_dev,
361                                     struct rogue_fwif_fwccb_cmd_freelist_gs_data *req)
362 {
363         struct pvr_free_list *free_list = pvr_free_list_lookup_id(pvr_dev, req->freelist_id);
364         struct rogue_fwif_kccb_cmd resp_cmd = {
365                 .cmd_type = ROGUE_FWIF_KCCB_CMD_FREELIST_GROW_UPDATE,
366         };
367         struct rogue_fwif_freelist_gs_data *resp = &resp_cmd.cmd_data.free_list_gs_data;
368         u32 grow_pages = 0;
369
370         /* If we don't have a freelist registered for this ID, we can't do much. */
371         if (WARN_ON(!free_list))
372                 return;
373
374         /* Since the FW made the request, it has already consumed the ready pages,
375          * update the host struct.
376          */
377         free_list->current_pages += free_list->ready_pages;
378         free_list->ready_pages = 0;
379
380         /* If the grow succeeds, update the grow_pages argument. */
381         if (!pvr_free_list_grow(free_list, free_list->grow_pages))
382                 grow_pages = free_list->grow_pages;
383
384         /* Now prepare the response and send it back to the FW. */
385         pvr_fw_object_get_fw_addr(free_list->fw_obj, &resp->freelist_fw_addr);
386         resp->delta_pages = grow_pages;
387         resp->new_pages = free_list->current_pages + free_list->ready_pages;
388         resp->ready_pages = free_list->ready_pages;
389         pvr_free_list_put(free_list);
390
391         WARN_ON(pvr_kccb_send_cmd(pvr_dev, &resp_cmd, NULL));
392 }
393
394 static void
395 pvr_free_list_free_node(struct pvr_free_list_node *free_list_node)
396 {
397         pvr_gem_object_put(free_list_node->mem_obj);
398
399         kfree(free_list_node);
400 }
401
402 /**
403  * pvr_free_list_create() - Create a new free list and return an object pointer
404  * @pvr_file: Pointer to pvr_file structure.
405  * @args: Creation arguments from userspace.
406  *
407  * Return:
408  *  * Pointer to new free_list, or
409  *  * ERR_PTR(-%ENOMEM) on out of memory.
410  */
411 struct pvr_free_list *
412 pvr_free_list_create(struct pvr_file *pvr_file,
413                      struct drm_pvr_ioctl_create_free_list_args *args)
414 {
415         struct pvr_free_list *free_list;
416         int err;
417
418         /* Create and fill out the kernel structure */
419         free_list = kzalloc(sizeof(*free_list), GFP_KERNEL);
420
421         if (!free_list)
422                 return ERR_PTR(-ENOMEM);
423
424         kref_init(&free_list->ref_count);
425         INIT_LIST_HEAD(&free_list->mem_block_list);
426         INIT_LIST_HEAD(&free_list->hwrt_list);
427         mutex_init(&free_list->lock);
428
429         err = free_list_create_kernel_structure(pvr_file, args, free_list);
430         if (err < 0)
431                 goto err_free;
432
433         /* Allocate global object ID for firmware. */
434         err = xa_alloc(&pvr_file->pvr_dev->free_list_ids,
435                        &free_list->fw_id,
436                        free_list,
437                        xa_limit_32b,
438                        GFP_KERNEL);
439         if (err)
440                 goto err_destroy_kernel_structure;
441
442         err = free_list_create_fw_structure(pvr_file, args, free_list);
443         if (err < 0)
444                 goto err_free_fw_id;
445
446         err = pvr_free_list_grow(free_list, args->initial_num_pages);
447         if (err < 0)
448                 goto err_fw_struct_cleanup;
449
450         return free_list;
451
452 err_fw_struct_cleanup:
453         WARN_ON(pvr_fw_structure_cleanup(free_list->pvr_dev,
454                                          ROGUE_FWIF_CLEANUP_FREELIST,
455                                          free_list->fw_obj, 0));
456
457 err_free_fw_id:
458         xa_erase(&free_list->pvr_dev->free_list_ids, free_list->fw_id);
459
460 err_destroy_kernel_structure:
461         free_list_destroy_kernel_structure(free_list);
462
463 err_free:
464         mutex_destroy(&free_list->lock);
465         kfree(free_list);
466
467         return ERR_PTR(err);
468 }
469
470 static void
471 pvr_free_list_release(struct kref *ref_count)
472 {
473         struct pvr_free_list *free_list =
474                 container_of(ref_count, struct pvr_free_list, ref_count);
475         struct list_head *pos, *n;
476         int err;
477
478         xa_erase(&free_list->pvr_dev->free_list_ids, free_list->fw_id);
479
480         err = pvr_fw_structure_cleanup(free_list->pvr_dev,
481                                        ROGUE_FWIF_CLEANUP_FREELIST,
482                                        free_list->fw_obj, 0);
483         if (err == -EBUSY) {
484                 /* Flush the FWCCB to process any HWR or freelist reconstruction
485                  * request that might keep the freelist busy, and try again.
486                  */
487                 pvr_fwccb_process(free_list->pvr_dev);
488                 err = pvr_fw_structure_cleanup(free_list->pvr_dev,
489                                                ROGUE_FWIF_CLEANUP_FREELIST,
490                                                free_list->fw_obj, 0);
491         }
492
493         WARN_ON(err);
494
495         /* clang-format off */
496         list_for_each_safe(pos, n, &free_list->mem_block_list) {
497                 struct pvr_free_list_node *free_list_node =
498                         container_of(pos, struct pvr_free_list_node, node);
499
500                 list_del(pos);
501                 pvr_free_list_free_node(free_list_node);
502         }
503         /* clang-format on */
504
505         free_list_destroy_kernel_structure(free_list);
506         free_list_destroy_fw_structure(free_list);
507         mutex_destroy(&free_list->lock);
508         kfree(free_list);
509 }
510
511 /**
512  * pvr_destroy_free_lists_for_file: Destroy any free lists associated with the
513  * given file.
514  * @pvr_file: Pointer to pvr_file structure.
515  *
516  * Removes all free lists associated with @pvr_file from the device free_list
517  * list and drops initial references. Free lists will then be destroyed once
518  * all outstanding references are dropped.
519  */
520 void pvr_destroy_free_lists_for_file(struct pvr_file *pvr_file)
521 {
522         struct pvr_free_list *free_list;
523         unsigned long handle;
524
525         xa_for_each(&pvr_file->free_list_handles, handle, free_list) {
526                 (void)free_list;
527                 pvr_free_list_put(xa_erase(&pvr_file->free_list_handles, handle));
528         }
529 }
530
531 /**
532  * pvr_free_list_put() - Release reference on free list
533  * @free_list: Pointer to list to release reference on
534  */
535 void
536 pvr_free_list_put(struct pvr_free_list *free_list)
537 {
538         if (free_list)
539                 kref_put(&free_list->ref_count, pvr_free_list_release);
540 }
541
542 void pvr_free_list_add_hwrt(struct pvr_free_list *free_list, struct pvr_hwrt_data *hwrt_data)
543 {
544         mutex_lock(&free_list->lock);
545
546         list_add_tail(&hwrt_data->freelist_node, &free_list->hwrt_list);
547
548         mutex_unlock(&free_list->lock);
549 }
550
551 void pvr_free_list_remove_hwrt(struct pvr_free_list *free_list, struct pvr_hwrt_data *hwrt_data)
552 {
553         mutex_lock(&free_list->lock);
554
555         list_del(&hwrt_data->freelist_node);
556
557         mutex_unlock(&free_list->lock);
558 }
559
560 static void
561 pvr_free_list_reconstruct(struct pvr_device *pvr_dev, u32 freelist_id)
562 {
563         struct pvr_free_list *free_list = pvr_free_list_lookup_id(pvr_dev, freelist_id);
564         struct pvr_free_list_node *free_list_node;
565         struct rogue_fwif_freelist *fw_data;
566         struct pvr_hwrt_data *hwrt_data;
567
568         if (!free_list)
569                 return;
570
571         mutex_lock(&free_list->lock);
572
573         /* Rebuild the free list based on the memory block list. */
574         free_list->current_pages = 0;
575
576         list_for_each_entry(free_list_node, &free_list->mem_block_list, node)
577                 WARN_ON(pvr_free_list_insert_node_locked(free_list_node));
578
579         /*
580          * Remove the ready pages, which are reserved to allow the FW to process OOM quickly and
581          * asynchronously request a grow.
582          */
583         free_list->current_pages -= free_list->ready_pages;
584
585         fw_data = free_list->fw_data;
586         fw_data->current_stack_top = fw_data->current_pages - 1;
587         fw_data->allocated_page_count = 0;
588         fw_data->allocated_mmu_page_count = 0;
589
590         /* Reset the state of any associated HWRTs. */
591         list_for_each_entry(hwrt_data, &free_list->hwrt_list, freelist_node) {
592                 struct rogue_fwif_hwrtdata *hwrt_fw_data = pvr_fw_object_vmap(hwrt_data->fw_obj);
593
594                 if (!WARN_ON(IS_ERR(hwrt_fw_data))) {
595                         hwrt_fw_data->state = ROGUE_FWIF_RTDATA_STATE_HWR;
596                         hwrt_fw_data->hwrt_data_flags &= ~HWRTDATA_HAS_LAST_GEOM;
597                 }
598
599                 pvr_fw_object_vunmap(hwrt_data->fw_obj);
600         }
601
602         mutex_unlock(&free_list->lock);
603
604         pvr_free_list_put(free_list);
605 }
606
607 void
608 pvr_free_list_process_reconstruct_req(struct pvr_device *pvr_dev,
609                                 struct rogue_fwif_fwccb_cmd_freelists_reconstruction_data *req)
610 {
611         struct rogue_fwif_kccb_cmd resp_cmd = {
612                 .cmd_type = ROGUE_FWIF_KCCB_CMD_FREELISTS_RECONSTRUCTION_UPDATE,
613         };
614         struct rogue_fwif_freelists_reconstruction_data *resp =
615                 &resp_cmd.cmd_data.free_lists_reconstruction_data;
616
617         for (u32 i = 0; i < req->freelist_count; i++)
618                 pvr_free_list_reconstruct(pvr_dev, req->freelist_ids[i]);
619
620         resp->freelist_count = req->freelist_count;
621         memcpy(resp->freelist_ids, req->freelist_ids,
622                req->freelist_count * sizeof(resp->freelist_ids[0]));
623
624         WARN_ON(pvr_kccb_send_cmd(pvr_dev, &resp_cmd, NULL));
625 }
This page took 0.069707 seconds and 4 git commands to generate.