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

accel/ivpu: Make command queue ID allocated on XArray

Use XArray for dynamic command queue ID allocations instead of fixed
ones. This is required by upcoming changes to UAPI that will allow to
manage command queues by user space instead of having predefined number
of queues in a context.

Signed-off-by: Karol Wachowski <karol.wachowski@intel.com>
Reviewed-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
Signed-off-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241017145817.121590-8-jacek.lawrynowicz@linux.intel.com

authored by

Karol Wachowski and committed by
Jacek Lawrynowicz
76ad741e ae7af7d8

+60 -46
+6
drivers/accel/ivpu/ivpu_drv.c
··· 104 104 pm_runtime_get_sync(vdev->drm.dev); 105 105 mutex_lock(&vdev->context_list_lock); 106 106 file_priv_unbind(vdev, file_priv); 107 + drm_WARN_ON(&vdev->drm, !xa_empty(&file_priv->cmdq_xa)); 108 + xa_destroy(&file_priv->cmdq_xa); 107 109 mutex_unlock(&vdev->context_list_lock); 108 110 pm_runtime_put_autosuspend(vdev->drm.dev); 109 111 ··· 260 258 261 259 file_priv->job_limit.min = FIELD_PREP(IVPU_JOB_ID_CONTEXT_MASK, (file_priv->ctx.id - 1)); 262 260 file_priv->job_limit.max = file_priv->job_limit.min | IVPU_JOB_ID_JOB_MASK; 261 + 262 + xa_init_flags(&file_priv->cmdq_xa, XA_FLAGS_ALLOC1); 263 + file_priv->cmdq_limit.min = IVPU_CMDQ_MIN_ID; 264 + file_priv->cmdq_limit.max = IVPU_CMDQ_MAX_ID; 263 265 264 266 mutex_unlock(&vdev->context_list_lock); 265 267 drm_dev_exit(idx);
+6 -1
drivers/accel/ivpu/ivpu_drv.h
··· 52 52 #define IVPU_NUM_PRIORITIES 4 53 53 #define IVPU_NUM_CMDQS_PER_CTX (IVPU_NUM_PRIORITIES) 54 54 55 + #define IVPU_CMDQ_MIN_ID 1 56 + #define IVPU_CMDQ_MAX_ID 255 57 + 55 58 #define IVPU_PLATFORM_SILICON 0 56 59 #define IVPU_PLATFORM_SIMICS 2 57 60 #define IVPU_PLATFORM_FPGA 3 ··· 171 168 struct kref ref; 172 169 struct ivpu_device *vdev; 173 170 struct mutex lock; /* Protects cmdq */ 174 - struct ivpu_cmdq *cmdq[IVPU_NUM_CMDQS_PER_CTX]; 171 + struct xarray cmdq_xa; 175 172 struct ivpu_mmu_context ctx; 176 173 struct mutex ms_lock; /* Protects ms_instance_list, ms_info_bo */ 177 174 struct list_head ms_instance_list; 178 175 struct ivpu_bo *ms_info_bo; 179 176 struct xa_limit job_limit; 180 177 u32 job_id_next; 178 + struct xa_limit cmdq_limit; 179 + u32 cmdq_id_next; 181 180 bool has_mmu_faults; 182 181 bool bound; 183 182 bool aborted;
+46 -45
drivers/accel/ivpu/ivpu_job.c
··· 89 89 goto err_free_cmdq; 90 90 } 91 91 92 + ret = xa_alloc_cyclic(&file_priv->cmdq_xa, &cmdq->id, cmdq, file_priv->cmdq_limit, 93 + &file_priv->cmdq_id_next, GFP_KERNEL); 94 + if (ret < 0) { 95 + ivpu_err(vdev, "Failed to allocate command queue id: %d\n", ret); 96 + goto err_erase_db_xa; 97 + } 98 + 92 99 cmdq->mem = ivpu_bo_create_global(vdev, SZ_4K, DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE); 93 100 if (!cmdq->mem) 94 - goto err_erase_xa; 101 + goto err_erase_cmdq_xa; 95 102 96 103 ret = ivpu_preemption_buffers_create(vdev, file_priv, cmdq); 97 104 if (ret) ··· 106 99 107 100 return cmdq; 108 101 109 - err_erase_xa: 102 + err_erase_cmdq_xa: 103 + xa_erase(&file_priv->cmdq_xa, cmdq->id); 104 + err_erase_db_xa: 110 105 xa_erase(&vdev->db_xa, cmdq->db_id); 111 106 err_free_cmdq: 112 107 kfree(cmdq); ··· 132 123 struct ivpu_device *vdev = file_priv->vdev; 133 124 int ret; 134 125 135 - ret = ivpu_jsm_hws_create_cmdq(vdev, file_priv->ctx.id, file_priv->ctx.id, cmdq->db_id, 126 + ret = ivpu_jsm_hws_create_cmdq(vdev, file_priv->ctx.id, file_priv->ctx.id, cmdq->id, 136 127 task_pid_nr(current), engine, 137 128 cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); 138 129 if (ret) 139 130 return ret; 140 131 141 - ret = ivpu_jsm_hws_set_context_sched_properties(vdev, file_priv->ctx.id, cmdq->db_id, 132 + ret = ivpu_jsm_hws_set_context_sched_properties(vdev, file_priv->ctx.id, cmdq->id, 142 133 priority); 143 134 if (ret) 144 135 return ret; ··· 152 143 int ret; 153 144 154 145 if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) 155 - ret = ivpu_jsm_hws_register_db(vdev, file_priv->ctx.id, cmdq->db_id, cmdq->db_id, 146 + ret = ivpu_jsm_hws_register_db(vdev, file_priv->ctx.id, cmdq->id, cmdq->db_id, 156 147 cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); 157 148 else 158 149 ret = ivpu_jsm_register_db(vdev, file_priv->ctx.id, cmdq->db_id, 159 150 cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); 160 151 161 152 if (!ret) 162 - ivpu_dbg(vdev, JOB, "DB %d registered to ctx %d\n", cmdq->db_id, file_priv->ctx.id); 153 + ivpu_dbg(vdev, JOB, "DB %d registered to cmdq %d ctx %d\n", 154 + cmdq->db_id, cmdq->id, file_priv->ctx.id); 163 155 164 156 return ret; 165 157 } 166 158 167 159 static int 168 - ivpu_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq, u16 engine, u8 priority) 160 + ivpu_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq, u8 priority) 169 161 { 170 162 struct ivpu_device *vdev = file_priv->vdev; 171 163 struct vpu_job_queue_header *jobq_header; ··· 182 172 183 173 cmdq->jobq = (struct vpu_job_queue *)ivpu_bo_vaddr(cmdq->mem); 184 174 jobq_header = &cmdq->jobq->header; 185 - jobq_header->engine_idx = engine; 175 + jobq_header->engine_idx = VPU_ENGINE_COMPUTE; 186 176 jobq_header->head = 0; 187 177 jobq_header->tail = 0; 188 178 if (ivpu_test_mode & IVPU_TEST_MODE_TURBO) { ··· 193 183 wmb(); /* Flush WC buffer for jobq->header */ 194 184 195 185 if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) { 196 - ret = ivpu_hws_cmdq_init(file_priv, cmdq, engine, priority); 186 + ret = ivpu_hws_cmdq_init(file_priv, cmdq, VPU_ENGINE_COMPUTE, priority); 197 187 if (ret) 198 188 return ret; 199 189 } ··· 220 210 cmdq->db_registered = false; 221 211 222 212 if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) { 223 - ret = ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->db_id); 213 + ret = ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->id); 224 214 if (!ret) 225 - ivpu_dbg(vdev, JOB, "Command queue %d destroyed\n", cmdq->db_id); 215 + ivpu_dbg(vdev, JOB, "Command queue %d destroyed\n", cmdq->id); 226 216 } 227 217 228 218 ret = ivpu_jsm_unregister_db(vdev, cmdq->db_id); ··· 232 222 return 0; 233 223 } 234 224 235 - static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u16 engine, 236 - u8 priority) 225 + static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u8 priority) 237 226 { 238 - struct ivpu_cmdq *cmdq = file_priv->cmdq[priority]; 227 + struct ivpu_cmdq *cmdq; 228 + unsigned long cmdq_id; 239 229 int ret; 240 230 241 231 lockdep_assert_held(&file_priv->lock); 232 + 233 + xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) 234 + if (cmdq->priority == priority) 235 + break; 242 236 243 237 if (!cmdq) { 244 238 cmdq = ivpu_cmdq_alloc(file_priv); 245 239 if (!cmdq) 246 240 return NULL; 247 - file_priv->cmdq[priority] = cmdq; 241 + cmdq->priority = priority; 248 242 } 249 243 250 - ret = ivpu_cmdq_init(file_priv, cmdq, engine, priority); 244 + ret = ivpu_cmdq_init(file_priv, cmdq, priority); 251 245 if (ret) 252 246 return NULL; 253 247 254 248 return cmdq; 255 249 } 256 250 257 - static void ivpu_cmdq_release_locked(struct ivpu_file_priv *file_priv, u8 priority) 251 + void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv) 258 252 { 259 - struct ivpu_cmdq *cmdq = file_priv->cmdq[priority]; 253 + struct ivpu_cmdq *cmdq; 254 + unsigned long cmdq_id; 260 255 261 256 lockdep_assert_held(&file_priv->lock); 262 257 263 - if (cmdq) { 264 - file_priv->cmdq[priority] = NULL; 258 + xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) { 259 + xa_erase(&file_priv->cmdq_xa, cmdq_id); 265 260 ivpu_cmdq_fini(file_priv, cmdq); 266 261 ivpu_cmdq_free(file_priv, cmdq); 267 262 } 268 - } 269 - 270 - void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv) 271 - { 272 - u8 priority; 273 - 274 - lockdep_assert_held(&file_priv->lock); 275 - 276 - for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++) 277 - ivpu_cmdq_release_locked(file_priv, priority); 278 263 } 279 264 280 265 /* ··· 280 275 */ 281 276 static void ivpu_cmdq_reset(struct ivpu_file_priv *file_priv) 282 277 { 283 - u8 priority; 278 + struct ivpu_cmdq *cmdq; 279 + unsigned long cmdq_id; 284 280 285 281 mutex_lock(&file_priv->lock); 286 282 287 - for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++) { 288 - struct ivpu_cmdq *cmdq = file_priv->cmdq[priority]; 289 - 290 - if (cmdq) 291 - cmdq->db_registered = false; 292 - } 283 + xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) 284 + cmdq->db_registered = false; 293 285 294 286 mutex_unlock(&file_priv->lock); 295 287 } ··· 306 304 307 305 static void ivpu_cmdq_fini_all(struct ivpu_file_priv *file_priv) 308 306 { 309 - u8 priority; 307 + struct ivpu_cmdq *cmdq; 308 + unsigned long cmdq_id; 310 309 311 - for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++) { 312 - if (file_priv->cmdq[priority]) 313 - ivpu_cmdq_fini(file_priv, file_priv->cmdq[priority]); 314 - } 310 + xa_for_each(&file_priv->cmdq_xa, cmdq_id, cmdq) 311 + ivpu_cmdq_fini(file_priv, cmdq); 315 312 } 316 313 317 314 void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv) ··· 335 334 336 335 /* Check if there is space left in job queue */ 337 336 if (next_entry == header->head) { 338 - ivpu_dbg(vdev, JOB, "Job queue full: ctx %d engine %d db %d head %d tail %d\n", 339 - job->file_priv->ctx.id, job->engine_idx, cmdq->db_id, header->head, tail); 337 + ivpu_dbg(vdev, JOB, "Job queue full: ctx %d cmdq %d db %d head %d tail %d\n", 338 + job->file_priv->ctx.id, cmdq->id, cmdq->db_id, header->head, tail); 340 339 return -EBUSY; 341 340 } 342 341 ··· 523 522 524 523 mutex_lock(&file_priv->lock); 525 524 526 - cmdq = ivpu_cmdq_acquire(file_priv, job->engine_idx, priority); 525 + cmdq = ivpu_cmdq_acquire(file_priv, priority); 527 526 if (!cmdq) { 528 527 ivpu_warn_ratelimited(vdev, "Failed to get job queue, ctx %d engine %d prio %d\n", 529 528 file_priv->ctx.id, job->engine_idx, priority);
+2
drivers/accel/ivpu/ivpu_job.h
··· 28 28 struct ivpu_bo *secondary_preempt_buf; 29 29 struct ivpu_bo *mem; 30 30 u32 entry_count; 31 + u32 id; 31 32 u32 db_id; 32 33 bool db_registered; 34 + u8 priority; 33 35 }; 34 36 35 37 /**