uint64_t addr, struct amdgpu_bo **bo);
#include "amdgpu_object.h"
-
#endif
#include "amdgpu.h"
#include "amdgpu_trace.h"
+static void amdgpu_job_free_handler(struct work_struct *ws)
+{
+ struct amdgpu_job *job = container_of(ws, struct amdgpu_job, base.work_free_job);
+ kfree(job);
+}
+
int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
struct amdgpu_job **job)
{
(*job)->adev = adev;
(*job)->ibs = (void *)&(*job)[1];
(*job)->num_ibs = num_ibs;
+ INIT_WORK(&(*job)->base.work_free_job, amdgpu_job_free_handler);
amdgpu_sync_create(&(*job)->sync);
amdgpu_bo_unref(&job->uf.bo);
amdgpu_sync_free(&job->sync);
- kfree(job);
+
+ if (!job->base.use_sched)
+ kfree(job);
}
int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring,
return added;
}
+static void amd_sched_free_job(struct fence *f, struct fence_cb *cb) {
+ struct amd_sched_job *job = container_of(cb, struct amd_sched_job, cb_free_job);
+ schedule_work(&job->work_free_job);
+}
+
/**
* Submit a job to the job queue
*
{
struct amd_sched_entity *entity = sched_job->s_entity;
+ sched_job->use_sched = 1;
+ fence_add_callback(&sched_job->s_fence->base,
+ &sched_job->cb_free_job, amd_sched_free_job);
trace_amd_sched_job(sched_job);
wait_event(entity->sched->job_scheduled,
amd_sched_entity_in(sched_job));
/**
* A scheduler entity is a wrapper around a job queue or a group
- * of other entities. Entities take turns emitting jobs from their
+ * of other entities. Entities take turns emitting jobs from their
* job queues to corresponding hardware ring based on scheduling
* policy.
*/
struct amd_gpu_scheduler *sched;
struct amd_sched_entity *s_entity;
struct amd_sched_fence *s_fence;
+ bool use_sched; /* true if the job goes to scheduler */
+ struct fence_cb cb_free_job;
+ struct work_struct work_free_job;
};
extern const struct fence_ops amd_sched_fence_ops;