at v6.19 192 lines 6.7 kB view raw
1/* SPDX-License-Identifier: MIT */ 2/* 3 * Copyright © 2024 Intel Corporation 4 */ 5#ifndef _XE_VALIDATION_H_ 6#define _XE_VALIDATION_H_ 7 8#include <linux/dma-resv.h> 9#include <linux/types.h> 10#include <linux/rwsem.h> 11 12struct drm_exec; 13struct drm_gem_object; 14struct drm_gpuvm_exec; 15struct xe_device; 16 17#ifdef CONFIG_PROVE_LOCKING 18/** 19 * xe_validation_lockdep() - Assert that a drm_exec locking transaction can 20 * be initialized at this point. 21 */ 22static inline void xe_validation_lockdep(void) 23{ 24 struct ww_acquire_ctx ticket; 25 26 ww_acquire_init(&ticket, &reservation_ww_class); 27 ww_acquire_fini(&ticket); 28} 29#else 30static inline void xe_validation_lockdep(void) 31{ 32} 33#endif 34 35/* 36 * Various values of the drm_exec pointer where we've not (yet) 37 * implemented full ww locking. 38 * 39 * XE_VALIDATION_UNIMPLEMENTED means implementation is pending. 40 * A lockdep check is made to assure that a drm_exec locking 41 * transaction can actually take place where the macro is 42 * used. If this asserts, the exec pointer needs to be assigned 43 * higher up in the callchain and passed down. 44 * 45 * XE_VALIDATION_UNSUPPORTED is for dma-buf code only where 46 * the dma-buf layer doesn't support WW locking. 47 * 48 * XE_VALIDATION_OPT_OUT is for simplification of kunit tests where 49 * exhaustive eviction isn't necessary. 50 */ 51#define __XE_VAL_UNIMPLEMENTED -EINVAL 52#define XE_VALIDATION_UNIMPLEMENTED (xe_validation_lockdep(), \ 53 (struct drm_exec *)ERR_PTR(__XE_VAL_UNIMPLEMENTED)) 54 55#define __XE_VAL_UNSUPPORTED -EOPNOTSUPP 56#define XE_VALIDATION_UNSUPPORTED ((struct drm_exec *)ERR_PTR(__XE_VAL_UNSUPPORTED)) 57 58#define __XE_VAL_OPT_OUT -ENOMEM 59#define XE_VALIDATION_OPT_OUT (xe_validation_lockdep(), \ 60 (struct drm_exec *)ERR_PTR(__XE_VAL_OPT_OUT)) 61#ifdef CONFIG_DRM_XE_DEBUG 62void xe_validation_assert_exec(const struct xe_device *xe, const struct drm_exec *exec, 63 const struct drm_gem_object *obj); 64#else 65#define xe_validation_assert_exec(_xe, _exec, _obj) \ 66 do { \ 67 (void)_xe; (void)_exec; (void)_obj; \ 68 } while (0) 69#endif 70 71/** 72 * struct xe_validation_device - The domain for exhaustive eviction 73 * @lock: The lock used to exclude other processes from allocating graphics memory 74 * 75 * The struct xe_validation_device represents the domain for which we want to use 76 * exhaustive eviction. The @lock is typically grabbed in read mode for allocations 77 * but when graphics memory allocation fails, it is retried with the write mode held. 78 */ 79struct xe_validation_device { 80 struct rw_semaphore lock; 81}; 82 83/** 84 * struct xe_val_flags - Flags for xe_validation_ctx_init(). 85 * @exclusive: Start the validation transaction by locking out all other validators. 86 * @no_block: Don't block on initialization. 87 * @interruptible: Block interruptible if blocking. Implies initializing the drm_exec 88 * context with the DRM_EXEC_INTERRUPTIBLE_WAIT flag. 89 * @exec_ignore_duplicates: Initialize the drm_exec context with the 90 * DRM_EXEC_IGNORE_DUPLICATES flag. 91 */ 92struct xe_val_flags { 93 u32 exclusive :1; 94 u32 no_block :1; 95 u32 interruptible :1; 96 u32 exec_ignore_duplicates :1; 97}; 98 99/** 100 * struct xe_validation_ctx - A struct drm_exec subclass with support for 101 * exhaustive eviction 102 * @exec: The drm_exec object base class. Note that we use a pointer instead of 103 * embedding to avoid diamond inheritance. 104 * @val: The exhaustive eviction domain. 105 * @val_flags: Copy of the struct xe_val_flags passed to xe_validation_ctx_init. 106 * @lock_held: Whether The domain lock is currently held. 107 * @lock_held_exclusive: Whether the domain lock is held in exclusive mode. 108 * @request_exclusive: Whether to lock exclusively (write mode) the next time 109 * the domain lock is locked. 110 * @exec_flags: The drm_exec flags used for drm_exec (re-)initialization. 111 * @nr: The drm_exec nr parameter used for drm_exec (re-)initialization. 112 */ 113struct xe_validation_ctx { 114 struct drm_exec *exec; 115 struct xe_validation_device *val; 116 struct xe_val_flags val_flags; 117 bool lock_held; 118 bool lock_held_exclusive; 119 bool request_exclusive; 120 u32 exec_flags; 121 unsigned int nr; 122}; 123 124int xe_validation_ctx_init(struct xe_validation_ctx *ctx, struct xe_validation_device *val, 125 struct drm_exec *exec, const struct xe_val_flags flags); 126 127int xe_validation_exec_lock(struct xe_validation_ctx *ctx, struct drm_gpuvm_exec *vm_exec, 128 struct xe_validation_device *val); 129 130void xe_validation_ctx_fini(struct xe_validation_ctx *ctx); 131 132bool xe_validation_should_retry(struct xe_validation_ctx *ctx, int *ret); 133 134/** 135 * xe_validation_retry_on_oom() - Retry on oom in an xe_validaton transaction 136 * @_ctx: Pointer to the xe_validation_ctx 137 * @_ret: The current error value possibly holding -ENOMEM 138 * 139 * Use this in way similar to drm_exec_retry_on_contention(). 140 * If @_ret contains -ENOMEM the transaction is restarted once in a way that 141 * blocks other transactions and allows exhastive eviction. If the transaction 142 * was already restarted once, Just return the -ENOMEM. May also set 143 * _ret to -EINTR if not retrying and waits are interruptible. 144 * May only be used within a drm_exec_until_all_locked() loop. 145 */ 146#define xe_validation_retry_on_oom(_ctx, _ret) \ 147 do { \ 148 if (xe_validation_should_retry(_ctx, _ret)) \ 149 goto *__drm_exec_retry_ptr; \ 150 } while (0) 151 152/** 153 * xe_validation_device_init - Initialize a struct xe_validation_device 154 * @val: The xe_validation_device to init. 155 */ 156static inline void 157xe_validation_device_init(struct xe_validation_device *val) 158{ 159 init_rwsem(&val->lock); 160} 161 162/* 163 * Make guard() and scoped_guard() work with xe_validation_ctx 164 * so that we can exit transactions without caring about the 165 * cleanup. 166 */ 167DEFINE_CLASS(xe_validation, struct xe_validation_ctx *, 168 if (_T) xe_validation_ctx_fini(_T);, 169 ({*_ret = xe_validation_ctx_init(_ctx, _val, _exec, _flags); 170 *_ret ? NULL : _ctx; }), 171 struct xe_validation_ctx *_ctx, struct xe_validation_device *_val, 172 struct drm_exec *_exec, const struct xe_val_flags _flags, int *_ret); 173static inline void *class_xe_validation_lock_ptr(class_xe_validation_t *_T) 174{return *_T; } 175#define class_xe_validation_is_conditional true 176 177/** 178 * xe_validation_guard() - An auto-cleanup xe_validation_ctx transaction 179 * @_ctx: The xe_validation_ctx. 180 * @_val: The xe_validation_device. 181 * @_exec: The struct drm_exec object 182 * @_flags: Flags for the xe_validation_ctx initialization. 183 * @_ret: Return in / out parameter. May be set by this macro. Typically 0 when called. 184 * 185 * This macro is will initiate a drm_exec transaction with additional support for 186 * exhaustive eviction. 187 */ 188#define xe_validation_guard(_ctx, _val, _exec, _flags, _ret) \ 189 scoped_guard(xe_validation, _ctx, _val, _exec, _flags, &_ret) \ 190 drm_exec_until_all_locked(_exec) 191 192#endif