Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.13-rc7 280 lines 7.3 kB view raw
1// SPDX-License-Identifier: MIT 2/* 3 * Copyright © 2024 Intel Corporation 4 */ 5 6#include <linux/bitmap.h> 7#include <linux/mutex.h> 8 9#include <drm/drm_managed.h> 10 11#include "xe_assert.h" 12#include "xe_gt_printk.h" 13#include "xe_guc.h" 14#include "xe_guc_id_mgr.h" 15#include "xe_guc_types.h" 16 17static struct xe_guc *idm_to_guc(struct xe_guc_id_mgr *idm) 18{ 19 return container_of(idm, struct xe_guc, submission_state.idm); 20} 21 22static struct xe_gt *idm_to_gt(struct xe_guc_id_mgr *idm) 23{ 24 return guc_to_gt(idm_to_guc(idm)); 25} 26 27static struct xe_device *idm_to_xe(struct xe_guc_id_mgr *idm) 28{ 29 return gt_to_xe(idm_to_gt(idm)); 30} 31 32#define idm_assert(idm, cond) xe_gt_assert(idm_to_gt(idm), cond) 33#define idm_mutex(idm) (&idm_to_guc(idm)->submission_state.lock) 34 35static void idm_print_locked(struct xe_guc_id_mgr *idm, struct drm_printer *p, int indent); 36 37static void __fini_idm(struct drm_device *drm, void *arg) 38{ 39 struct xe_guc_id_mgr *idm = arg; 40 41 mutex_lock(idm_mutex(idm)); 42 43 if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) { 44 unsigned int weight = bitmap_weight(idm->bitmap, idm->total); 45 46 if (weight) { 47 struct drm_printer p = xe_gt_info_printer(idm_to_gt(idm)); 48 49 xe_gt_err(idm_to_gt(idm), "GUC ID manager unclean (%u/%u)\n", 50 weight, idm->total); 51 idm_print_locked(idm, &p, 1); 52 } 53 } 54 55 bitmap_free(idm->bitmap); 56 idm->bitmap = NULL; 57 idm->total = 0; 58 idm->used = 0; 59 60 mutex_unlock(idm_mutex(idm)); 61} 62 63/** 64 * xe_guc_id_mgr_init() - Initialize GuC context ID Manager. 65 * @idm: the &xe_guc_id_mgr to initialize 66 * @limit: number of IDs to manage 67 * 68 * The bare-metal or PF driver can pass ~0 as &limit to indicate that all 69 * context IDs supported by the GuC firmware are available for use. 70 * 71 * Only VF drivers will have to provide explicit number of context IDs 72 * that they can use. 73 * 74 * Return: 0 on success or a negative error code on failure. 75 */ 76int xe_guc_id_mgr_init(struct xe_guc_id_mgr *idm, unsigned int limit) 77{ 78 int ret; 79 80 idm_assert(idm, !idm->bitmap); 81 idm_assert(idm, !idm->total); 82 idm_assert(idm, !idm->used); 83 84 if (limit == ~0) 85 limit = GUC_ID_MAX; 86 else if (limit > GUC_ID_MAX) 87 return -ERANGE; 88 else if (!limit) 89 return -EINVAL; 90 91 idm->bitmap = bitmap_zalloc(limit, GFP_KERNEL); 92 if (!idm->bitmap) 93 return -ENOMEM; 94 idm->total = limit; 95 96 ret = drmm_add_action_or_reset(&idm_to_xe(idm)->drm, __fini_idm, idm); 97 if (ret) 98 return ret; 99 100 xe_gt_dbg(idm_to_gt(idm), "using %u GuC ID%s\n", 101 idm->total, str_plural(idm->total)); 102 return 0; 103} 104 105static unsigned int find_last_zero_area(unsigned long *bitmap, 106 unsigned int total, 107 unsigned int count) 108{ 109 unsigned int found = total; 110 unsigned int rs, re, range; 111 112 for_each_clear_bitrange(rs, re, bitmap, total) { 113 range = re - rs; 114 if (range < count) 115 continue; 116 found = rs + (range - count); 117 } 118 return found; 119} 120 121static int idm_reserve_chunk_locked(struct xe_guc_id_mgr *idm, 122 unsigned int count, unsigned int retain) 123{ 124 int id; 125 126 idm_assert(idm, count); 127 lockdep_assert_held(idm_mutex(idm)); 128 129 if (!idm->total) 130 return -ENODATA; 131 132 if (retain) { 133 /* 134 * For IDs reservations (used on PF for VFs) we want to make 135 * sure there will be at least 'retain' available for the PF 136 */ 137 if (idm->used + count + retain > idm->total) 138 return -EDQUOT; 139 /* 140 * ... and we want to reserve highest IDs close to the end. 141 */ 142 id = find_last_zero_area(idm->bitmap, idm->total, count); 143 } else { 144 /* 145 * For regular IDs reservations (used by submission code) 146 * we start searching from the lower range of IDs. 147 */ 148 id = bitmap_find_next_zero_area(idm->bitmap, idm->total, 0, count, 0); 149 } 150 if (id >= idm->total) 151 return -ENOSPC; 152 153 bitmap_set(idm->bitmap, id, count); 154 idm->used += count; 155 156 return id; 157} 158 159static void idm_release_chunk_locked(struct xe_guc_id_mgr *idm, 160 unsigned int start, unsigned int count) 161{ 162 idm_assert(idm, count); 163 idm_assert(idm, count <= idm->used); 164 idm_assert(idm, start < idm->total); 165 idm_assert(idm, start + count - 1 < idm->total); 166 lockdep_assert_held(idm_mutex(idm)); 167 168 if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) { 169 unsigned int n; 170 171 for (n = 0; n < count; n++) 172 idm_assert(idm, test_bit(start + n, idm->bitmap)); 173 } 174 bitmap_clear(idm->bitmap, start, count); 175 idm->used -= count; 176} 177 178/** 179 * xe_guc_id_mgr_reserve_locked() - Reserve one or more GuC context IDs. 180 * @idm: the &xe_guc_id_mgr 181 * @count: number of IDs to allocate (can't be 0) 182 * 183 * This function is dedicated for the use by the GuC submission code, 184 * where submission lock is already taken. 185 * 186 * Return: ID of allocated GuC context or a negative error code on failure. 187 */ 188int xe_guc_id_mgr_reserve_locked(struct xe_guc_id_mgr *idm, unsigned int count) 189{ 190 return idm_reserve_chunk_locked(idm, count, 0); 191} 192 193/** 194 * xe_guc_id_mgr_release_locked() - Release one or more GuC context IDs. 195 * @idm: the &xe_guc_id_mgr 196 * @id: the GuC context ID to release 197 * @count: number of IDs to release (can't be 0) 198 * 199 * This function is dedicated for the use by the GuC submission code, 200 * where submission lock is already taken. 201 */ 202void xe_guc_id_mgr_release_locked(struct xe_guc_id_mgr *idm, unsigned int id, 203 unsigned int count) 204{ 205 return idm_release_chunk_locked(idm, id, count); 206} 207 208/** 209 * xe_guc_id_mgr_reserve() - Reserve a range of GuC context IDs. 210 * @idm: the &xe_guc_id_mgr 211 * @count: number of GuC context IDs to reserve (can't be 0) 212 * @retain: number of GuC context IDs to keep available (can't be 0) 213 * 214 * This function is dedicated for the use by the PF driver which expects that 215 * reserved range of IDs will be contiguous and that there will be at least 216 * &retain IDs still available for the PF after this reservation. 217 * 218 * Return: starting ID of the allocated GuC context ID range or 219 * a negative error code on failure. 220 */ 221int xe_guc_id_mgr_reserve(struct xe_guc_id_mgr *idm, 222 unsigned int count, unsigned int retain) 223{ 224 int ret; 225 226 idm_assert(idm, count); 227 idm_assert(idm, retain); 228 229 mutex_lock(idm_mutex(idm)); 230 ret = idm_reserve_chunk_locked(idm, count, retain); 231 mutex_unlock(idm_mutex(idm)); 232 233 return ret; 234} 235 236/** 237 * xe_guc_id_mgr_release() - Release a range of GuC context IDs. 238 * @idm: the &xe_guc_id_mgr 239 * @start: the starting ID of GuC context range to release 240 * @count: number of GuC context IDs to release 241 */ 242void xe_guc_id_mgr_release(struct xe_guc_id_mgr *idm, 243 unsigned int start, unsigned int count) 244{ 245 mutex_lock(idm_mutex(idm)); 246 idm_release_chunk_locked(idm, start, count); 247 mutex_unlock(idm_mutex(idm)); 248} 249 250static void idm_print_locked(struct xe_guc_id_mgr *idm, struct drm_printer *p, int indent) 251{ 252 unsigned int rs, re; 253 254 lockdep_assert_held(idm_mutex(idm)); 255 256 drm_printf_indent(p, indent, "total %u\n", idm->total); 257 if (!idm->bitmap) 258 return; 259 260 drm_printf_indent(p, indent, "used %u\n", idm->used); 261 for_each_set_bitrange(rs, re, idm->bitmap, idm->total) 262 drm_printf_indent(p, indent, "range %u..%u (%u)\n", rs, re - 1, re - rs); 263} 264 265/** 266 * xe_guc_id_mgr_print() - Print status of GuC ID Manager. 267 * @idm: the &xe_guc_id_mgr to print 268 * @p: the &drm_printer to print to 269 * @indent: tab indentation level 270 */ 271void xe_guc_id_mgr_print(struct xe_guc_id_mgr *idm, struct drm_printer *p, int indent) 272{ 273 mutex_lock(idm_mutex(idm)); 274 idm_print_locked(idm, p, indent); 275 mutex_unlock(idm_mutex(idm)); 276} 277 278#if IS_BUILTIN(CONFIG_DRM_XE_KUNIT_TEST) 279#include "tests/xe_guc_id_mgr_test.c" 280#endif