Skip to content

Commit 6eeddda

Browse files
sarah-walker-imgtecmripard
authored andcommitted
drm/imagination: Implement free list and HWRT create and destroy ioctls
Implement ioctls to create and destroy free lists and HWRT datasets. Free lists are used for GPU-side memory allocation during geometry processing. HWRT datasets are the FW-side structures representing render targets. Changes since v8: - Corrected license identifiers Changes since v6: - Fix out-of-bounds shift in get_cr_multisamplectl_val() Changes since v4: - Remove use of drm_gem_shmem_get_pages() Changes since v3: - Support free list grow requests from FW - Use drm_dev_{enter,exit} Co-developed-by: Boris Brezillon <[email protected]> Signed-off-by: Boris Brezillon <[email protected]> Co-developed-by: Donald Robson <[email protected]> Signed-off-by: Donald Robson <[email protected]> Signed-off-by: Sarah Walker <[email protected]> Link: https://lore.kernel.org/r/919358c5887a7628da588c455a5bb7e3ea4b47ae.1700668843.git.donald.robson@imgtec.com Signed-off-by: Maxime Ripard <[email protected]>
1 parent 927f3e0 commit 6eeddda

File tree

8 files changed

+1678
-4
lines changed

8 files changed

+1678
-4
lines changed

drivers/gpu/drm/imagination/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ powervr-y := \
88
pvr_device.o \
99
pvr_device_info.o \
1010
pvr_drv.o \
11+
pvr_free_list.o \
1112
pvr_fw.o \
1213
pvr_fw_meta.o \
1314
pvr_fw_mips.o \
1415
pvr_fw_startstop.o \
1516
pvr_fw_trace.o \
1617
pvr_gem.o \
18+
pvr_hwrt.o \
1719
pvr_mmu.o \
1820
pvr_power.o \
1921
pvr_vm.o \

drivers/gpu/drm/imagination/pvr_ccb.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "pvr_ccb.h"
55
#include "pvr_device.h"
66
#include "pvr_drv.h"
7+
#include "pvr_free_list.h"
78
#include "pvr_fw.h"
89
#include "pvr_gem.h"
910
#include "pvr_power.h"
@@ -139,6 +140,15 @@ process_fwccb_command(struct pvr_device *pvr_dev, struct rogue_fwif_fwccb_cmd *c
139140
pvr_power_reset(pvr_dev, false);
140141
break;
141142

143+
case ROGUE_FWIF_FWCCB_CMD_FREELISTS_RECONSTRUCTION:
144+
pvr_free_list_process_reconstruct_req(pvr_dev,
145+
&cmd->cmd_data.cmd_freelists_reconstruction);
146+
break;
147+
148+
case ROGUE_FWIF_FWCCB_CMD_FREELIST_GROW:
149+
pvr_free_list_process_grow_req(pvr_dev, &cmd->cmd_data.cmd_free_list_gs);
150+
break;
151+
142152
default:
143153
drm_info(from_pvr_device(pvr_dev), "Received unknown FWCCB command %x\n",
144154
cmd->cmd_type);

drivers/gpu/drm/imagination/pvr_device.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,14 @@ struct pvr_device {
152152
*/
153153
atomic_t mmu_flush_cache_flags;
154154

155+
/**
156+
* @free_list_ids: Array of free lists belonging to this device. Array members
157+
* are of type "struct pvr_free_list *".
158+
*
159+
* This array is used to allocate IDs used by the firmware.
160+
*/
161+
struct xarray free_list_ids;
162+
155163
struct {
156164
/** @work: Work item for watchdog callback. */
157165
struct delayed_work work;
@@ -247,6 +255,22 @@ struct pvr_file {
247255
*/
248256
struct pvr_device *pvr_dev;
249257

258+
/**
259+
* @free_list_handles: Array of free lists belonging to this file. Array
260+
* members are of type "struct pvr_free_list *".
261+
*
262+
* This array is used to allocate handles returned to userspace.
263+
*/
264+
struct xarray free_list_handles;
265+
266+
/**
267+
* @hwrt_handles: Array of HWRT datasets belonging to this file. Array
268+
* members are of type "struct pvr_hwrt_dataset *".
269+
*
270+
* This array is used to allocate handles returned to userspace.
271+
*/
272+
struct xarray hwrt_handles;
273+
250274
/**
251275
* @vm_ctx_handles: Array of VM contexts belonging to this file. Array
252276
* members are of type "struct pvr_vm_context *".

drivers/gpu/drm/imagination/pvr_drv.c

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
#include "pvr_device.h"
55
#include "pvr_drv.h"
6+
#include "pvr_free_list.h"
67
#include "pvr_gem.h"
8+
#include "pvr_hwrt.h"
79
#include "pvr_mmu.h"
810
#include "pvr_power.h"
911
#include "pvr_rogue_defs.h"
@@ -711,7 +713,41 @@ static int
711713
pvr_ioctl_create_free_list(struct drm_device *drm_dev, void *raw_args,
712714
struct drm_file *file)
713715
{
714-
return -ENOTTY;
716+
struct drm_pvr_ioctl_create_free_list_args *args = raw_args;
717+
struct pvr_file *pvr_file = to_pvr_file(file);
718+
struct pvr_free_list *free_list;
719+
int idx;
720+
int err;
721+
722+
if (!drm_dev_enter(drm_dev, &idx))
723+
return -EIO;
724+
725+
free_list = pvr_free_list_create(pvr_file, args);
726+
if (IS_ERR(free_list)) {
727+
err = PTR_ERR(free_list);
728+
goto err_drm_dev_exit;
729+
}
730+
731+
/* Allocate object handle for userspace. */
732+
err = xa_alloc(&pvr_file->free_list_handles,
733+
&args->handle,
734+
free_list,
735+
xa_limit_32b,
736+
GFP_KERNEL);
737+
if (err < 0)
738+
goto err_cleanup;
739+
740+
drm_dev_exit(idx);
741+
742+
return 0;
743+
744+
err_cleanup:
745+
pvr_free_list_put(free_list);
746+
747+
err_drm_dev_exit:
748+
drm_dev_exit(idx);
749+
750+
return err;
715751
}
716752

717753
/**
@@ -731,7 +767,19 @@ static int
731767
pvr_ioctl_destroy_free_list(struct drm_device *drm_dev, void *raw_args,
732768
struct drm_file *file)
733769
{
734-
return -ENOTTY;
770+
struct drm_pvr_ioctl_destroy_free_list_args *args = raw_args;
771+
struct pvr_file *pvr_file = to_pvr_file(file);
772+
struct pvr_free_list *free_list;
773+
774+
if (args->_padding_4)
775+
return -EINVAL;
776+
777+
free_list = xa_erase(&pvr_file->free_list_handles, args->handle);
778+
if (!free_list)
779+
return -EINVAL;
780+
781+
pvr_free_list_put(free_list);
782+
return 0;
735783
}
736784

737785
/**
@@ -751,7 +799,41 @@ static int
751799
pvr_ioctl_create_hwrt_dataset(struct drm_device *drm_dev, void *raw_args,
752800
struct drm_file *file)
753801
{
754-
return -ENOTTY;
802+
struct drm_pvr_ioctl_create_hwrt_dataset_args *args = raw_args;
803+
struct pvr_file *pvr_file = to_pvr_file(file);
804+
struct pvr_hwrt_dataset *hwrt;
805+
int idx;
806+
int err;
807+
808+
if (!drm_dev_enter(drm_dev, &idx))
809+
return -EIO;
810+
811+
hwrt = pvr_hwrt_dataset_create(pvr_file, args);
812+
if (IS_ERR(hwrt)) {
813+
err = PTR_ERR(hwrt);
814+
goto err_drm_dev_exit;
815+
}
816+
817+
/* Allocate object handle for userspace. */
818+
err = xa_alloc(&pvr_file->hwrt_handles,
819+
&args->handle,
820+
hwrt,
821+
xa_limit_32b,
822+
GFP_KERNEL);
823+
if (err < 0)
824+
goto err_cleanup;
825+
826+
drm_dev_exit(idx);
827+
828+
return 0;
829+
830+
err_cleanup:
831+
pvr_hwrt_dataset_put(hwrt);
832+
833+
err_drm_dev_exit:
834+
drm_dev_exit(idx);
835+
836+
return err;
755837
}
756838

757839
/**
@@ -771,7 +853,19 @@ static int
771853
pvr_ioctl_destroy_hwrt_dataset(struct drm_device *drm_dev, void *raw_args,
772854
struct drm_file *file)
773855
{
774-
return -ENOTTY;
856+
struct drm_pvr_ioctl_destroy_hwrt_dataset_args *args = raw_args;
857+
struct pvr_file *pvr_file = to_pvr_file(file);
858+
struct pvr_hwrt_dataset *hwrt;
859+
860+
if (args->_padding_4)
861+
return -EINVAL;
862+
863+
hwrt = xa_erase(&pvr_file->hwrt_handles, args->handle);
864+
if (!hwrt)
865+
return -EINVAL;
866+
867+
pvr_hwrt_dataset_put(hwrt);
868+
return 0;
775869
}
776870

777871
/**
@@ -1195,6 +1289,8 @@ pvr_drm_driver_open(struct drm_device *drm_dev, struct drm_file *file)
11951289
*/
11961290
pvr_file->pvr_dev = pvr_dev;
11971291

1292+
xa_init_flags(&pvr_file->free_list_handles, XA_FLAGS_ALLOC1);
1293+
xa_init_flags(&pvr_file->hwrt_handles, XA_FLAGS_ALLOC1);
11981294
xa_init_flags(&pvr_file->vm_ctx_handles, XA_FLAGS_ALLOC1);
11991295

12001296
/*
@@ -1223,6 +1319,8 @@ pvr_drm_driver_postclose(__always_unused struct drm_device *drm_dev,
12231319
struct pvr_file *pvr_file = to_pvr_file(file);
12241320

12251321
/* Drop references on any remaining objects. */
1322+
pvr_destroy_free_lists_for_file(pvr_file);
1323+
pvr_destroy_hwrt_datasets_for_file(pvr_file);
12261324
pvr_destroy_vm_contexts_for_file(pvr_file);
12271325

12281326
kfree(pvr_file);
@@ -1281,6 +1379,8 @@ pvr_probe(struct platform_device *plat_dev)
12811379
if (err)
12821380
goto err_device_fini;
12831381

1382+
xa_init_flags(&pvr_dev->free_list_ids, XA_FLAGS_ALLOC1);
1383+
12841384
return 0;
12851385

12861386
err_device_fini:
@@ -1298,6 +1398,10 @@ pvr_remove(struct platform_device *plat_dev)
12981398
struct drm_device *drm_dev = platform_get_drvdata(plat_dev);
12991399
struct pvr_device *pvr_dev = to_pvr_device(drm_dev);
13001400

1401+
WARN_ON(!xa_empty(&pvr_dev->free_list_ids));
1402+
1403+
xa_destroy(&pvr_dev->free_list_ids);
1404+
13011405
pm_runtime_suspend(drm_dev->dev);
13021406
pvr_device_fini(pvr_dev);
13031407
drm_dev_unplug(drm_dev);

0 commit comments

Comments
 (0)