| /* SPDX-License-Identifier: GPL-2.0-only OR MIT */ |
| /* Copyright (c) 2023 Imagination Technologies Ltd. */ |
| |
| #ifndef PVR_HWRT_H |
| #define PVR_HWRT_H |
| |
| #include <linux/compiler_attributes.h> |
| #include <linux/kref.h> |
| #include <linux/list.h> |
| #include <linux/types.h> |
| #include <linux/xarray.h> |
| #include <uapi/drm/pvr_drm.h> |
| |
| #include "pvr_device.h" |
| #include "pvr_rogue_fwif_shared.h" |
| |
| /* Forward declaration from pvr_free_list.h. */ |
| struct pvr_free_list; |
| |
| /* Forward declaration from pvr_gem.h. */ |
| struct pvr_fw_object; |
| |
| /** |
| * struct pvr_hwrt_data - structure representing HWRT data |
| */ |
| struct pvr_hwrt_data { |
| /** @fw_obj: FW object representing the FW-side structure. */ |
| struct pvr_fw_object *fw_obj; |
| |
| /** @data: Local copy of FW-side structure. */ |
| struct rogue_fwif_hwrtdata data; |
| |
| /** @freelist_node: List node connecting this HWRT to the local freelist. */ |
| struct list_head freelist_node; |
| |
| /** |
| * @srtc_obj: FW object representing shadow render target cache. |
| * |
| * Only valid if @max_rts > 1. |
| */ |
| struct pvr_fw_object *srtc_obj; |
| |
| /** |
| * @raa_obj: FW object representing renders accumulation array. |
| * |
| * Only valid if @max_rts > 1. |
| */ |
| struct pvr_fw_object *raa_obj; |
| |
| /** @hwrt_dataset: Back pointer to owning HWRT dataset. */ |
| struct pvr_hwrt_dataset *hwrt_dataset; |
| }; |
| |
| /** |
| * struct pvr_hwrt_dataset - structure representing a HWRT data set. |
| */ |
| struct pvr_hwrt_dataset { |
| /** @ref_count: Reference count of object. */ |
| struct kref ref_count; |
| |
| /** @pvr_dev: Pointer to device that owns this object. */ |
| struct pvr_device *pvr_dev; |
| |
| /** @common_fw_obj: FW object representing common FW-side structure. */ |
| struct pvr_fw_object *common_fw_obj; |
| |
| /** @common: Common HWRT data. */ |
| struct rogue_fwif_hwrtdata_common common; |
| |
| /** @data: HWRT data structures belonging to this set. */ |
| struct pvr_hwrt_data data[ROGUE_FWIF_NUM_RTDATAS]; |
| |
| /** @free_lists: Free lists used by HWRT data set. */ |
| struct pvr_free_list *free_lists[ROGUE_FWIF_NUM_RTDATA_FREELISTS]; |
| |
| /** @max_rts: Maximum render targets for this HWRT data set. */ |
| u16 max_rts; |
| }; |
| |
| struct pvr_hwrt_dataset * |
| pvr_hwrt_dataset_create(struct pvr_file *pvr_file, |
| struct drm_pvr_ioctl_create_hwrt_dataset_args *args); |
| |
| void |
| pvr_destroy_hwrt_datasets_for_file(struct pvr_file *pvr_file); |
| |
| /** |
| * pvr_hwrt_dataset_lookup() - Lookup HWRT dataset pointer from handle |
| * @pvr_file: Pointer to pvr_file structure. |
| * @handle: Object handle. |
| * |
| * Takes reference on dataset object. Call pvr_hwrt_dataset_put() to release. |
| * |
| * Returns: |
| * * The requested object on success, or |
| * * %NULL on failure (object does not exist in list, or is not a HWRT |
| * dataset) |
| */ |
| static __always_inline struct pvr_hwrt_dataset * |
| pvr_hwrt_dataset_lookup(struct pvr_file *pvr_file, u32 handle) |
| { |
| struct pvr_hwrt_dataset *hwrt; |
| |
| xa_lock(&pvr_file->hwrt_handles); |
| hwrt = xa_load(&pvr_file->hwrt_handles, handle); |
| |
| if (hwrt) |
| kref_get(&hwrt->ref_count); |
| |
| xa_unlock(&pvr_file->hwrt_handles); |
| |
| return hwrt; |
| } |
| |
| void |
| pvr_hwrt_dataset_put(struct pvr_hwrt_dataset *hwrt); |
| |
| /** |
| * pvr_hwrt_data_lookup() - Lookup HWRT data pointer from handle and index |
| * @pvr_file: Pointer to pvr_file structure. |
| * @handle: Object handle. |
| * @index: Index of RT data within dataset. |
| * |
| * Takes reference on dataset object. Call pvr_hwrt_data_put() to release. |
| * |
| * Returns: |
| * * The requested object on success, or |
| * * %NULL on failure (object does not exist in list, or is not a HWRT |
| * dataset, or index is out of range) |
| */ |
| static __always_inline struct pvr_hwrt_data * |
| pvr_hwrt_data_lookup(struct pvr_file *pvr_file, u32 handle, u32 index) |
| { |
| struct pvr_hwrt_dataset *hwrt_dataset = pvr_hwrt_dataset_lookup(pvr_file, handle); |
| |
| if (hwrt_dataset) { |
| if (index < ARRAY_SIZE(hwrt_dataset->data)) |
| return &hwrt_dataset->data[index]; |
| |
| pvr_hwrt_dataset_put(hwrt_dataset); |
| } |
| |
| return NULL; |
| } |
| |
| /** |
| * pvr_hwrt_data_put() - Release reference on HWRT data |
| * @hwrt: Pointer to HWRT data to release reference on |
| */ |
| static __always_inline void |
| pvr_hwrt_data_put(struct pvr_hwrt_data *hwrt) |
| { |
| if (hwrt) |
| pvr_hwrt_dataset_put(hwrt->hwrt_dataset); |
| } |
| |
| static __always_inline struct pvr_hwrt_data * |
| pvr_hwrt_data_get(struct pvr_hwrt_data *hwrt) |
| { |
| if (hwrt) |
| kref_get(&hwrt->hwrt_dataset->ref_count); |
| |
| return hwrt; |
| } |
| |
| #endif /* PVR_HWRT_H */ |