18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 OR MIT */
28c2ecf20Sopenharmony_ci/**************************************************************************
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA
58c2ecf20Sopenharmony_ci * All Rights Reserved.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
88c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the
98c2ecf20Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
108c2ecf20Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
118c2ecf20Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
128c2ecf20Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
138c2ecf20Sopenharmony_ci * the following conditions:
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the
168c2ecf20Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
178c2ecf20Sopenharmony_ci * of the Software.
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
208c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
218c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
228c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
238c2ecf20Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
248c2ecf20Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
258c2ecf20Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci **************************************************************************/
288c2ecf20Sopenharmony_ci#ifndef _VMWGFX_VALIDATION_H_
298c2ecf20Sopenharmony_ci#define _VMWGFX_VALIDATION_H_
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#include <linux/list.h>
328c2ecf20Sopenharmony_ci#include <linux/ww_mutex.h>
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#include <drm/drm_hashtab.h>
358c2ecf20Sopenharmony_ci#include <drm/ttm/ttm_execbuf_util.h>
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define VMW_RES_DIRTY_NONE 0
388c2ecf20Sopenharmony_ci#define VMW_RES_DIRTY_SET BIT(0)
398c2ecf20Sopenharmony_ci#define VMW_RES_DIRTY_CLEAR BIT(1)
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci/**
428c2ecf20Sopenharmony_ci * struct vmw_validation_mem - Custom interface to provide memory reservations
438c2ecf20Sopenharmony_ci * for the validation code.
448c2ecf20Sopenharmony_ci * @reserve_mem: Callback to reserve memory
458c2ecf20Sopenharmony_ci * @unreserve_mem: Callback to unreserve memory
468c2ecf20Sopenharmony_ci * @gran: Reservation granularity. Contains a hint how much memory should
478c2ecf20Sopenharmony_ci * be reserved in each call to @reserve_mem(). A slow implementation may want
488c2ecf20Sopenharmony_ci * reservation to be done in large batches.
498c2ecf20Sopenharmony_ci */
508c2ecf20Sopenharmony_cistruct vmw_validation_mem {
518c2ecf20Sopenharmony_ci	int (*reserve_mem)(struct vmw_validation_mem *m, size_t size);
528c2ecf20Sopenharmony_ci	void (*unreserve_mem)(struct vmw_validation_mem *m, size_t size);
538c2ecf20Sopenharmony_ci	size_t gran;
548c2ecf20Sopenharmony_ci};
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/**
578c2ecf20Sopenharmony_ci * struct vmw_validation_context - Per command submission validation context
588c2ecf20Sopenharmony_ci * @ht: Hash table used to find resource- or buffer object duplicates
598c2ecf20Sopenharmony_ci * @resource_list: List head for resource validation metadata
608c2ecf20Sopenharmony_ci * @resource_ctx_list: List head for resource validation metadata for
618c2ecf20Sopenharmony_ci * resources that need to be validated before those in @resource_list
628c2ecf20Sopenharmony_ci * @bo_list: List head for buffer objects
638c2ecf20Sopenharmony_ci * @page_list: List of pages used by the memory allocator
648c2ecf20Sopenharmony_ci * @ticket: Ticked used for ww mutex locking
658c2ecf20Sopenharmony_ci * @res_mutex: Pointer to mutex used for resource reserving
668c2ecf20Sopenharmony_ci * @merge_dups: Whether to merge metadata for duplicate resources or
678c2ecf20Sopenharmony_ci * buffer objects
688c2ecf20Sopenharmony_ci * @mem_size_left: Free memory left in the last page in @page_list
698c2ecf20Sopenharmony_ci * @page_address: Kernel virtual address of the last page in @page_list
708c2ecf20Sopenharmony_ci * @vm: A pointer to the memory reservation interface or NULL if no
718c2ecf20Sopenharmony_ci * memory reservation is needed.
728c2ecf20Sopenharmony_ci * @vm_size_left: Amount of reserved memory that so far has not been allocated.
738c2ecf20Sopenharmony_ci * @total_mem: Amount of reserved memory.
748c2ecf20Sopenharmony_ci */
758c2ecf20Sopenharmony_cistruct vmw_validation_context {
768c2ecf20Sopenharmony_ci	struct drm_open_hash *ht;
778c2ecf20Sopenharmony_ci	struct list_head resource_list;
788c2ecf20Sopenharmony_ci	struct list_head resource_ctx_list;
798c2ecf20Sopenharmony_ci	struct list_head bo_list;
808c2ecf20Sopenharmony_ci	struct list_head page_list;
818c2ecf20Sopenharmony_ci	struct ww_acquire_ctx ticket;
828c2ecf20Sopenharmony_ci	struct mutex *res_mutex;
838c2ecf20Sopenharmony_ci	unsigned int merge_dups;
848c2ecf20Sopenharmony_ci	unsigned int mem_size_left;
858c2ecf20Sopenharmony_ci	u8 *page_address;
868c2ecf20Sopenharmony_ci	struct vmw_validation_mem *vm;
878c2ecf20Sopenharmony_ci	size_t vm_size_left;
888c2ecf20Sopenharmony_ci	size_t total_mem;
898c2ecf20Sopenharmony_ci};
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistruct vmw_buffer_object;
928c2ecf20Sopenharmony_cistruct vmw_resource;
938c2ecf20Sopenharmony_cistruct vmw_fence_obj;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci#if 0
968c2ecf20Sopenharmony_ci/**
978c2ecf20Sopenharmony_ci * DECLARE_VAL_CONTEXT - Declare a validation context with initialization
988c2ecf20Sopenharmony_ci * @_name: The name of the variable
998c2ecf20Sopenharmony_ci * @_ht: The hash table used to find dups or NULL if none
1008c2ecf20Sopenharmony_ci * @_merge_dups: Whether to merge duplicate buffer object- or resource
1018c2ecf20Sopenharmony_ci * entries. If set to true, ideally a hash table pointer should be supplied
1028c2ecf20Sopenharmony_ci * as well unless the number of resources and buffer objects per validation
1038c2ecf20Sopenharmony_ci * is known to be very small
1048c2ecf20Sopenharmony_ci */
1058c2ecf20Sopenharmony_ci#endif
1068c2ecf20Sopenharmony_ci#define DECLARE_VAL_CONTEXT(_name, _ht, _merge_dups)			\
1078c2ecf20Sopenharmony_ci	struct vmw_validation_context _name =				\
1088c2ecf20Sopenharmony_ci	{ .ht = _ht,							\
1098c2ecf20Sopenharmony_ci	  .resource_list = LIST_HEAD_INIT((_name).resource_list),	\
1108c2ecf20Sopenharmony_ci	  .resource_ctx_list = LIST_HEAD_INIT((_name).resource_ctx_list), \
1118c2ecf20Sopenharmony_ci	  .bo_list = LIST_HEAD_INIT((_name).bo_list),			\
1128c2ecf20Sopenharmony_ci	  .page_list = LIST_HEAD_INIT((_name).page_list),		\
1138c2ecf20Sopenharmony_ci	  .res_mutex = NULL,						\
1148c2ecf20Sopenharmony_ci	  .merge_dups = _merge_dups,					\
1158c2ecf20Sopenharmony_ci	  .mem_size_left = 0,						\
1168c2ecf20Sopenharmony_ci	}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci/**
1198c2ecf20Sopenharmony_ci * vmw_validation_has_bos - return whether the validation context has
1208c2ecf20Sopenharmony_ci * any buffer objects registered.
1218c2ecf20Sopenharmony_ci *
1228c2ecf20Sopenharmony_ci * @ctx: The validation context
1238c2ecf20Sopenharmony_ci * Returns: Whether any buffer objects are registered
1248c2ecf20Sopenharmony_ci */
1258c2ecf20Sopenharmony_cistatic inline bool
1268c2ecf20Sopenharmony_civmw_validation_has_bos(struct vmw_validation_context *ctx)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	return !list_empty(&ctx->bo_list);
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci/**
1328c2ecf20Sopenharmony_ci * vmw_validation_set_val_mem - Register a validation mem object for
1338c2ecf20Sopenharmony_ci * validation memory reservation
1348c2ecf20Sopenharmony_ci * @ctx: The validation context
1358c2ecf20Sopenharmony_ci * @vm: Pointer to a struct vmw_validation_mem
1368c2ecf20Sopenharmony_ci *
1378c2ecf20Sopenharmony_ci * Must be set before the first attempt to allocate validation memory.
1388c2ecf20Sopenharmony_ci */
1398c2ecf20Sopenharmony_cistatic inline void
1408c2ecf20Sopenharmony_civmw_validation_set_val_mem(struct vmw_validation_context *ctx,
1418c2ecf20Sopenharmony_ci			   struct vmw_validation_mem *vm)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	ctx->vm = vm;
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci/**
1478c2ecf20Sopenharmony_ci * vmw_validation_set_ht - Register a hash table for duplicate finding
1488c2ecf20Sopenharmony_ci * @ctx: The validation context
1498c2ecf20Sopenharmony_ci * @ht: Pointer to a hash table to use for duplicate finding
1508c2ecf20Sopenharmony_ci * This function is intended to be used if the hash table wasn't
1518c2ecf20Sopenharmony_ci * available at validation context declaration time
1528c2ecf20Sopenharmony_ci */
1538c2ecf20Sopenharmony_cistatic inline void vmw_validation_set_ht(struct vmw_validation_context *ctx,
1548c2ecf20Sopenharmony_ci					 struct drm_open_hash *ht)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	ctx->ht = ht;
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci/**
1608c2ecf20Sopenharmony_ci * vmw_validation_bo_reserve - Reserve buffer objects registered with a
1618c2ecf20Sopenharmony_ci * validation context
1628c2ecf20Sopenharmony_ci * @ctx: The validation context
1638c2ecf20Sopenharmony_ci * @intr: Perform waits interruptible
1648c2ecf20Sopenharmony_ci *
1658c2ecf20Sopenharmony_ci * Return: Zero on success, -ERESTARTSYS when interrupted, negative error
1668c2ecf20Sopenharmony_ci * code on failure
1678c2ecf20Sopenharmony_ci */
1688c2ecf20Sopenharmony_cistatic inline int
1698c2ecf20Sopenharmony_civmw_validation_bo_reserve(struct vmw_validation_context *ctx,
1708c2ecf20Sopenharmony_ci			  bool intr)
1718c2ecf20Sopenharmony_ci{
1728c2ecf20Sopenharmony_ci	return ttm_eu_reserve_buffers(&ctx->ticket, &ctx->bo_list, intr,
1738c2ecf20Sopenharmony_ci				      NULL);
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci/**
1778c2ecf20Sopenharmony_ci * vmw_validation_bo_fence - Unreserve and fence buffer objects registered
1788c2ecf20Sopenharmony_ci * with a validation context
1798c2ecf20Sopenharmony_ci * @ctx: The validation context
1808c2ecf20Sopenharmony_ci *
1818c2ecf20Sopenharmony_ci * This function unreserves the buffer objects previously reserved using
1828c2ecf20Sopenharmony_ci * vmw_validation_bo_reserve, and fences them with a fence object.
1838c2ecf20Sopenharmony_ci */
1848c2ecf20Sopenharmony_cistatic inline void
1858c2ecf20Sopenharmony_civmw_validation_bo_fence(struct vmw_validation_context *ctx,
1868c2ecf20Sopenharmony_ci			struct vmw_fence_obj *fence)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	ttm_eu_fence_buffer_objects(&ctx->ticket, &ctx->bo_list,
1898c2ecf20Sopenharmony_ci				    (void *) fence);
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci/**
1938c2ecf20Sopenharmony_ci * vmw_validation_context_init - Initialize a validation context
1948c2ecf20Sopenharmony_ci * @ctx: Pointer to the validation context to initialize
1958c2ecf20Sopenharmony_ci *
1968c2ecf20Sopenharmony_ci * This function initializes a validation context with @merge_dups set
1978c2ecf20Sopenharmony_ci * to false
1988c2ecf20Sopenharmony_ci */
1998c2ecf20Sopenharmony_cistatic inline void
2008c2ecf20Sopenharmony_civmw_validation_context_init(struct vmw_validation_context *ctx)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	memset(ctx, 0, sizeof(*ctx));
2038c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&ctx->resource_list);
2048c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&ctx->resource_ctx_list);
2058c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&ctx->bo_list);
2068c2ecf20Sopenharmony_ci}
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci/**
2098c2ecf20Sopenharmony_ci * vmw_validation_align - Align a validation memory allocation
2108c2ecf20Sopenharmony_ci * @val: The size to be aligned
2118c2ecf20Sopenharmony_ci *
2128c2ecf20Sopenharmony_ci * Returns: @val aligned to the granularity used by the validation memory
2138c2ecf20Sopenharmony_ci * allocator.
2148c2ecf20Sopenharmony_ci */
2158c2ecf20Sopenharmony_cistatic inline unsigned int vmw_validation_align(unsigned int val)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	return ALIGN(val, sizeof(long));
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ciint vmw_validation_add_bo(struct vmw_validation_context *ctx,
2218c2ecf20Sopenharmony_ci			  struct vmw_buffer_object *vbo,
2228c2ecf20Sopenharmony_ci			  bool as_mob, bool cpu_blit);
2238c2ecf20Sopenharmony_ciint vmw_validation_bo_validate_single(struct ttm_buffer_object *bo,
2248c2ecf20Sopenharmony_ci				      bool interruptible,
2258c2ecf20Sopenharmony_ci				      bool validate_as_mob);
2268c2ecf20Sopenharmony_ciint vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr);
2278c2ecf20Sopenharmony_civoid vmw_validation_unref_lists(struct vmw_validation_context *ctx);
2288c2ecf20Sopenharmony_ciint vmw_validation_add_resource(struct vmw_validation_context *ctx,
2298c2ecf20Sopenharmony_ci				struct vmw_resource *res,
2308c2ecf20Sopenharmony_ci				size_t priv_size,
2318c2ecf20Sopenharmony_ci				u32 dirty,
2328c2ecf20Sopenharmony_ci				void **p_node,
2338c2ecf20Sopenharmony_ci				bool *first_usage);
2348c2ecf20Sopenharmony_civoid vmw_validation_drop_ht(struct vmw_validation_context *ctx);
2358c2ecf20Sopenharmony_ciint vmw_validation_res_reserve(struct vmw_validation_context *ctx,
2368c2ecf20Sopenharmony_ci			       bool intr);
2378c2ecf20Sopenharmony_civoid vmw_validation_res_unreserve(struct vmw_validation_context *ctx,
2388c2ecf20Sopenharmony_ci				  bool backoff);
2398c2ecf20Sopenharmony_civoid vmw_validation_res_switch_backup(struct vmw_validation_context *ctx,
2408c2ecf20Sopenharmony_ci				      void *val_private,
2418c2ecf20Sopenharmony_ci				      struct vmw_buffer_object *vbo,
2428c2ecf20Sopenharmony_ci				      unsigned long backup_offset);
2438c2ecf20Sopenharmony_ciint vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr);
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ciint vmw_validation_prepare(struct vmw_validation_context *ctx,
2468c2ecf20Sopenharmony_ci			   struct mutex *mutex, bool intr);
2478c2ecf20Sopenharmony_civoid vmw_validation_revert(struct vmw_validation_context *ctx);
2488c2ecf20Sopenharmony_civoid vmw_validation_done(struct vmw_validation_context *ctx,
2498c2ecf20Sopenharmony_ci			 struct vmw_fence_obj *fence);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_civoid *vmw_validation_mem_alloc(struct vmw_validation_context *ctx,
2528c2ecf20Sopenharmony_ci			       unsigned int size);
2538c2ecf20Sopenharmony_ciint vmw_validation_preload_bo(struct vmw_validation_context *ctx);
2548c2ecf20Sopenharmony_ciint vmw_validation_preload_res(struct vmw_validation_context *ctx,
2558c2ecf20Sopenharmony_ci			       unsigned int size);
2568c2ecf20Sopenharmony_civoid vmw_validation_res_set_dirty(struct vmw_validation_context *ctx,
2578c2ecf20Sopenharmony_ci				  void *val_private, u32 dirty);
2588c2ecf20Sopenharmony_civoid vmw_validation_bo_backoff(struct vmw_validation_context *ctx);
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci#endif
261