1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2025 Intel Corporation 4 */ 5 6 #include <linux/slab.h> 7 8 #include <drm/gpu_scheduler.h> 9 10 #include "xe_dep_job_types.h" 11 #include "xe_dep_scheduler.h" 12 #include "xe_device_types.h" 13 14 /** 15 * DOC: Xe Dependency Scheduler 16 * 17 * The Xe dependency scheduler is a simple wrapper built around the DRM 18 * scheduler to execute jobs once their dependencies are resolved (i.e., all 19 * input fences specified as dependencies are signaled). The jobs that are 20 * executed contain virtual functions to run (execute) and free the job, 21 * allowing a single dependency scheduler to handle jobs performing different 22 * operations. 23 * 24 * Example use cases include deferred resource freeing, TLB invalidations after 25 * bind jobs, etc. 26 */ 27 28 /** struct xe_dep_scheduler - Generic Xe dependency scheduler */ 29 struct xe_dep_scheduler { 30 /** @sched: DRM GPU scheduler */ 31 struct drm_gpu_scheduler sched; 32 /** @entity: DRM scheduler entity */ 33 struct drm_sched_entity entity; 34 /** @rcu: For safe freeing of exported dma fences */ 35 struct rcu_head rcu; 36 }; 37 38 static struct dma_fence *xe_dep_scheduler_run_job(struct drm_sched_job *drm_job) 39 { 40 struct xe_dep_job *dep_job = 41 container_of(drm_job, typeof(*dep_job), drm); 42 43 return dep_job->ops->run_job(dep_job); 44 } 45 46 static void xe_dep_scheduler_free_job(struct drm_sched_job *drm_job) 47 { 48 struct xe_dep_job *dep_job = 49 container_of(drm_job, typeof(*dep_job), drm); 50 51 dep_job->ops->free_job(dep_job); 52 } 53 54 static const struct drm_sched_backend_ops sched_ops = { 55 .run_job = xe_dep_scheduler_run_job, 56 .free_job = xe_dep_scheduler_free_job, 57 }; 58 59 /** 60 * xe_dep_scheduler_create() - Generic Xe dependency scheduler create 61 * @xe: Xe device 62 * @submit_wq: Submit workqueue struct (can be NULL) 63 * @name: Name of dependency scheduler 64 * @job_limit: Max dependency jobs that can be scheduled 65 * 66 * Create a generic Xe dependency scheduler and initialize internal DRM 67 * scheduler objects. 68 * 69 * Return: Generic Xe dependency scheduler object on success, ERR_PTR failure 70 */ 71 struct xe_dep_scheduler * 72 xe_dep_scheduler_create(struct xe_device *xe, 73 struct workqueue_struct *submit_wq, 74 const char *name, u32 job_limit) 75 { 76 struct xe_dep_scheduler *dep_scheduler; 77 struct drm_gpu_scheduler *sched; 78 const struct drm_sched_init_args args = { 79 .ops = &sched_ops, 80 .submit_wq = submit_wq, 81 .credit_limit = job_limit, 82 .timeout = MAX_SCHEDULE_TIMEOUT, 83 .name = name, 84 .dev = xe->drm.dev, 85 }; 86 int err; 87 88 dep_scheduler = kzalloc_obj(*dep_scheduler); 89 if (!dep_scheduler) 90 return ERR_PTR(-ENOMEM); 91 92 err = drm_sched_init(&dep_scheduler->sched, &args); 93 if (err) 94 goto err_free; 95 96 sched = &dep_scheduler->sched; 97 err = drm_sched_entity_init(&dep_scheduler->entity, 0, &sched, 1, NULL); 98 if (err) 99 goto err_sched; 100 101 init_rcu_head(&dep_scheduler->rcu); 102 103 return dep_scheduler; 104 105 err_sched: 106 drm_sched_fini(&dep_scheduler->sched); 107 err_free: 108 kfree(dep_scheduler); 109 110 return ERR_PTR(err); 111 } 112 113 /** 114 * xe_dep_scheduler_fini() - Generic Xe dependency scheduler finalize 115 * @dep_scheduler: Generic Xe dependency scheduler object 116 * 117 * Finalize internal DRM scheduler objects and free generic Xe dependency 118 * scheduler object 119 */ 120 void xe_dep_scheduler_fini(struct xe_dep_scheduler *dep_scheduler) 121 { 122 drm_sched_entity_fini(&dep_scheduler->entity); 123 drm_sched_fini(&dep_scheduler->sched); 124 /* 125 * RCU free due sched being exported via DRM scheduler fences 126 * (timeline name). 127 */ 128 kfree_rcu(dep_scheduler, rcu); 129 } 130 131 /** 132 * xe_dep_scheduler_entity() - Retrieve a generic Xe dependency scheduler 133 * DRM scheduler entity 134 * @dep_scheduler: Generic Xe dependency scheduler object 135 * 136 * Return: The generic Xe dependency scheduler's DRM scheduler entity 137 */ 138 struct drm_sched_entity * 139 xe_dep_scheduler_entity(struct xe_dep_scheduler *dep_scheduler) 140 { 141 return &dep_scheduler->entity; 142 } 143