aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0381-drm-amd-add-basic-scheduling-framework.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0381-drm-amd-add-basic-scheduling-framework.patch')
-rw-r--r--common/recipes-kernel/linux/files/0381-drm-amd-add-basic-scheduling-framework.patch737
1 files changed, 0 insertions, 737 deletions
diff --git a/common/recipes-kernel/linux/files/0381-drm-amd-add-basic-scheduling-framework.patch b/common/recipes-kernel/linux/files/0381-drm-amd-add-basic-scheduling-framework.patch
deleted file mode 100644
index 477188d5..00000000
--- a/common/recipes-kernel/linux/files/0381-drm-amd-add-basic-scheduling-framework.patch
+++ /dev/null
@@ -1,737 +0,0 @@
-From a72ce6f84109c1dec1ab236d65979d3250668af3 Mon Sep 17 00:00:00 2001
-From: Jammy Zhou <Jammy.Zhou@amd.com>
-Date: Fri, 22 May 2015 18:55:07 +0800
-Subject: [PATCH 0381/1050] drm/amd: add basic scheduling framework
-
-run queue:
-A set of entities scheduling commands for the same ring. It
-implements the scheduling policy that selects the next entity to
-emit commands from.
-
-entity:
-A scheduler entity is a wrapper around a job queue or a group of
-other entities. This can be used to build hierarchies of entities.
-For example all job queue entities belonging to the same process
-may be placed in a higher level entity and scheduled against other
-process entities.
-Entities take turns emitting jobs from their job queue to the
-corresponding hardware ring, in accordance with the scheduler policy.
-
-Signed-off-by: Shaoyun Liu <Shaoyun.Liu@amd.com>
-Signed-off-by: Chunming Zhou <David1.Zhou@amd.com>
-Signed-off-by: Jammy Zhou <Jammy.Zhou@amd.com>
-Acked-by: Christian K?nig <christian.koenig@amd.com>
-Reviewed-by: Jammy Zhou <Jammy.Zhou@amd.com>
----
- drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 531 ++++++++++++++++++++++++++
- drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 160 ++++++++
- 2 files changed, 691 insertions(+)
- create mode 100644 drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
- create mode 100644 drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
-
-diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
-new file mode 100644
-index 0000000..296496c
---- /dev/null
-+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
-@@ -0,0 +1,531 @@
-+/*
-+ * Copyright 2015 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-+ * OTHER DEALINGS IN THE SOFTWARE.
-+ *
-+ *
-+ */
-+#include <linux/kthread.h>
-+#include <linux/wait.h>
-+#include <linux/sched.h>
-+#include <drm/drmP.h>
-+#include "gpu_scheduler.h"
-+
-+/* Initialize a given run queue struct */
-+static void init_rq(struct amd_run_queue *rq)
-+{
-+ INIT_LIST_HEAD(&rq->head.list);
-+ rq->head.belongto_rq = rq;
-+ mutex_init(&rq->lock);
-+ atomic_set(&rq->nr_entity, 0);
-+ rq->current_entity = &rq->head;
-+}
-+
-+/* Note: caller must hold the lock or in a atomic context */
-+static void rq_remove_entity(struct amd_run_queue *rq,
-+ struct amd_sched_entity *entity)
-+{
-+ if (rq->current_entity == entity)
-+ rq->current_entity = list_entry(entity->list.prev,
-+ typeof(*entity), list);
-+ list_del_init(&entity->list);
-+ atomic_dec(&rq->nr_entity);
-+}
-+
-+static void rq_add_entity(struct amd_run_queue *rq,
-+ struct amd_sched_entity *entity)
-+{
-+ list_add_tail(&entity->list, &rq->head.list);
-+ atomic_inc(&rq->nr_entity);
-+}
-+
-+/**
-+ * Select next entity from a specified run queue with round robin policy.
-+ * It could return the same entity as current one if current is the only
-+ * available one in the queue. Return NULL if nothing available.
-+ */
-+static struct amd_sched_entity *rq_select_entity(struct amd_run_queue *rq)
-+{
-+ struct amd_sched_entity *p = rq->current_entity;
-+ int i = atomic_read(&rq->nr_entity) + 1; /*real count + dummy head*/
-+ while (i) {
-+ p = list_entry(p->list.next, typeof(*p), list);
-+ if (!rq->check_entity_status(p)) {
-+ rq->current_entity = p;
-+ break;
-+ }
-+ i--;
-+ }
-+ return i ? p : NULL;
-+}
-+
-+static bool context_entity_is_waiting(struct amd_context_entity *entity)
-+{
-+ /* TODO: sync obj for multi-ring synchronization */
-+ return false;
-+}
-+
-+static int gpu_entity_check_status(struct amd_sched_entity *entity)
-+{
-+ struct amd_context_entity *tmp = NULL;
-+
-+ if (entity == &entity->belongto_rq->head)
-+ return -1;
-+
-+ tmp = container_of(entity, typeof(*tmp), generic_entity);
-+ if (kfifo_is_empty(&tmp->job_queue) ||
-+ context_entity_is_waiting(tmp))
-+ return -1;
-+
-+ return 0;
-+}
-+
-+/**
-+ * Note: This function should only been called inside scheduler main
-+ * function for thread safety, there is no other protection here.
-+ * return ture if scheduler has something ready to run.
-+ *
-+ * For active_hw_rq, there is only one producer(scheduler thread) and
-+ * one consumer(ISR). It should be safe to use this function in scheduler
-+ * main thread to decide whether to continue emit more IBs.
-+*/
-+static bool is_scheduler_ready(struct amd_gpu_scheduler *sched)
-+{
-+ return !kfifo_is_full(&sched->active_hw_rq);
-+}
-+
-+/**
-+ * Select next entity from the kernel run queue, if not available,
-+ * return null.
-+*/
-+static struct amd_context_entity *kernel_rq_select_context(
-+ struct amd_gpu_scheduler *sched)
-+{
-+ struct amd_sched_entity *sched_entity = NULL;
-+ struct amd_context_entity *tmp = NULL;
-+ struct amd_run_queue *rq = &sched->kernel_rq;
-+
-+ mutex_lock(&rq->lock);
-+ sched_entity = rq_select_entity(rq);
-+ if (sched_entity)
-+ tmp = container_of(sched_entity,
-+ typeof(*tmp),
-+ generic_entity);
-+ mutex_unlock(&rq->lock);
-+ return tmp;
-+}
-+
-+/**
-+ * Select next entity containing real IB submissions
-+*/
-+static struct amd_context_entity *select_context(
-+ struct amd_gpu_scheduler *sched)
-+{
-+ struct amd_context_entity *wake_entity = NULL;
-+ struct amd_context_entity *tmp;
-+ struct amd_run_queue *rq;
-+
-+ if (!is_scheduler_ready(sched))
-+ return NULL;
-+
-+ /* Kernel run queue has higher priority than normal run queue*/
-+ tmp = kernel_rq_select_context(sched);
-+ if (tmp != NULL)
-+ goto exit;
-+
-+ WARN_ON(offsetof(struct amd_context_entity, generic_entity) != 0);
-+
-+ rq = &sched->sched_rq;
-+ mutex_lock(&rq->lock);
-+ tmp = container_of(rq_select_entity(rq),
-+ typeof(*tmp), generic_entity);
-+ mutex_unlock(&rq->lock);
-+exit:
-+ if (sched->current_entity && (sched->current_entity != tmp))
-+ wake_entity = sched->current_entity;
-+ sched->current_entity = tmp;
-+ if (wake_entity)
-+ wake_up(&wake_entity->wait_queue);
-+ return tmp;
-+}
-+
-+/**
-+ * Init a context entity used by scheduler when submit to HW ring.
-+ *
-+ * @sched The pointer to the scheduler
-+ * @entity The pointer to a valid amd_context_entity
-+ * @parent The parent entity of this amd_context_entity
-+ * @rq The run queue this entity belongs
-+ * @context_id The context id for this entity
-+ *
-+ * return 0 if succeed. negative error code on failure
-+*/
-+int amd_context_entity_init(struct amd_gpu_scheduler *sched,
-+ struct amd_context_entity *entity,
-+ struct amd_sched_entity *parent,
-+ struct amd_run_queue *rq,
-+ uint32_t context_id)
-+{
-+ uint64_t seq_ring = 0;
-+
-+ if (!(sched && entity && rq))
-+ return -EINVAL;
-+
-+ memset(entity, 0, sizeof(struct amd_context_entity));
-+ seq_ring = ((uint64_t)sched->ring_id) << 60;
-+ spin_lock_init(&entity->lock);
-+ entity->generic_entity.belongto_rq = rq;
-+ entity->generic_entity.parent = parent;
-+ entity->scheduler = sched;
-+ init_waitqueue_head(&entity->wait_queue);
-+ init_waitqueue_head(&entity->wait_emit);
-+ if(kfifo_alloc(&entity->job_queue,
-+ AMD_MAX_JOB_ENTRY_PER_CONTEXT * sizeof(void *),
-+ GFP_KERNEL))
-+ return -EINVAL;
-+
-+ spin_lock_init(&entity->queue_lock);
-+ entity->tgid = (context_id == AMD_KERNEL_CONTEXT_ID) ?
-+ AMD_KERNEL_PROCESS_ID : current->tgid;
-+ entity->context_id = context_id;
-+ atomic64_set(&entity->last_emitted_v_seq, seq_ring);
-+ atomic64_set(&entity->last_queued_v_seq, seq_ring);
-+ atomic64_set(&entity->last_signaled_v_seq, seq_ring);
-+
-+ /* Add the entity to the run queue */
-+ mutex_lock(&rq->lock);
-+ rq_add_entity(rq, &entity->generic_entity);
-+ mutex_unlock(&rq->lock);
-+ return 0;
-+}
-+
-+/**
-+ * Query if entity is initialized
-+ *
-+ * @sched Pointer to scheduler instance
-+ * @entity The pointer to a valid scheduler entity
-+ *
-+ * return true if entity is initialized, false otherwise
-+*/
-+static bool is_context_entity_initialized(struct amd_gpu_scheduler *sched,
-+ struct amd_context_entity *entity)
-+{
-+ return entity->scheduler == sched &&
-+ entity->generic_entity.belongto_rq != NULL;
-+}
-+
-+static bool is_context_entity_idle(struct amd_gpu_scheduler *sched,
-+ struct amd_context_entity *entity)
-+{
-+ /**
-+ * Idle means no pending IBs, and the entity is not
-+ * currently being used.
-+ */
-+ barrier();
-+ if ((sched->current_entity != entity) &&
-+ kfifo_is_empty(&entity->job_queue))
-+ return true;
-+
-+ return false;
-+}
-+
-+/**
-+ * Destroy a context entity
-+ *
-+ * @sched Pointer to scheduler instance
-+ * @entity The pointer to a valid scheduler entity
-+ *
-+ * return 0 if succeed. negative error code on failure
-+ */
-+int amd_context_entity_fini(struct amd_gpu_scheduler *sched,
-+ struct amd_context_entity *entity)
-+{
-+ int r = 0;
-+ struct amd_run_queue *rq = entity->generic_entity.belongto_rq;
-+
-+ if (!is_context_entity_initialized(sched, entity))
-+ return 0;
-+
-+ /**
-+ * The client will not queue more IBs during this fini, consume existing
-+ * queued IBs
-+ */
-+ r = wait_event_timeout(
-+ entity->wait_queue,
-+ is_context_entity_idle(sched, entity),
-+ msecs_to_jiffies(AMD_GPU_WAIT_IDLE_TIMEOUT_IN_MS)
-+ ) ? 0 : -1;
-+
-+ if (r) {
-+ if (entity->is_pending)
-+ DRM_INFO("Entity %u is in waiting state during fini,\
-+ all pending ibs will be canceled.\n",
-+ entity->context_id);
-+ }
-+
-+ mutex_lock(&rq->lock);
-+ rq_remove_entity(rq, &entity->generic_entity);
-+ mutex_unlock(&rq->lock);
-+ kfifo_free(&entity->job_queue);
-+ return r;
-+}
-+
-+/**
-+ * Submit a normal job to the job queue
-+ *
-+ * @sched The pointer to the scheduler
-+ * @c_entity The pointer to amd_context_entity
-+ * @job The pointer to job required to submit
-+ * return 0 if succeed. -1 if failed.
-+ * -2 indicate queue is full for this client, client should wait untill
-+ * scheduler consum some queued command.
-+ * -1 other fail.
-+*/
-+int amd_sched_push_job(struct amd_gpu_scheduler *sched,
-+ struct amd_context_entity *c_entity,
-+ void *job)
-+{
-+ while (kfifo_in_spinlocked(&c_entity->job_queue, &job, sizeof(void *),
-+ &c_entity->queue_lock) != sizeof(void *)) {
-+ /**
-+ * Current context used up all its IB slots
-+ * wait here, or need to check whether GPU is hung
-+ */
-+ schedule();
-+ }
-+
-+ wake_up_interruptible(&sched->wait_queue);
-+ return 0;
-+}
-+
-+/**
-+ * Check the virtual sequence number for specified context
-+ *
-+ * @seq The virtual sequence number to check
-+ * @c_entity The pointer to a valid amd_context_entity
-+ *
-+ * return 0 if signaled, -1 else.
-+*/
-+int amd_sched_check_ts(struct amd_context_entity *c_entity, uint64_t seq)
-+{
-+ return (seq <= atomic64_read(&c_entity->last_signaled_v_seq)) ? 0 : -1;
-+}
-+
-+/**
-+ * Wait for a virtual sequence number to be signaled or timeout
-+ *
-+ * @c_entity The pointer to a valid context entity
-+ * @seq The virtual sequence number to wait
-+ * @intr Interruptible or not
-+ * @timeout Timeout in ms, wait infinitely if <0
-+ * @emit wait for emit or signal
-+ *
-+ * return =0 signaled , <0 failed
-+*/
-+static int amd_sched_wait(struct amd_context_entity *c_entity,
-+ uint64_t seq,
-+ bool intr,
-+ long timeout,
-+ bool emit)
-+{
-+ atomic64_t *v_seq = emit ? &c_entity->last_emitted_v_seq :
-+ &c_entity->last_signaled_v_seq;
-+ wait_queue_head_t *wait_queue = emit ? &c_entity->wait_emit :
-+ &c_entity->wait_queue;
-+
-+ if (intr && (timeout < 0)) {
-+ wait_event_interruptible(
-+ *wait_queue,
-+ seq <= atomic64_read(v_seq));
-+ return 0;
-+ } else if (intr && (timeout >= 0)) {
-+ wait_event_interruptible_timeout(
-+ *wait_queue,
-+ seq <= atomic64_read(v_seq),
-+ msecs_to_jiffies(timeout));
-+ return (seq <= atomic64_read(v_seq)) ?
-+ 0 : -1;
-+ } else if (!intr && (timeout < 0)) {
-+ wait_event(
-+ *wait_queue,
-+ seq <= atomic64_read(v_seq));
-+ return 0;
-+ } else if (!intr && (timeout >= 0)) {
-+ wait_event_timeout(
-+ *wait_queue,
-+ seq <= atomic64_read(v_seq),
-+ msecs_to_jiffies(timeout));
-+ return (seq <= atomic64_read(v_seq)) ?
-+ 0 : -1;
-+ }
-+ return 0;
-+}
-+
-+int amd_sched_wait_signal(struct amd_context_entity *c_entity,
-+ uint64_t seq,
-+ bool intr,
-+ long timeout)
-+{
-+ return amd_sched_wait(c_entity, seq, intr, timeout, false);
-+}
-+
-+int amd_sched_wait_emit(struct amd_context_entity *c_entity,
-+ uint64_t seq,
-+ bool intr,
-+ long timeout)
-+{
-+ return amd_sched_wait(c_entity, seq, intr, timeout, true);
-+}
-+
-+static int amd_sched_main(void *param)
-+{
-+ int r;
-+ void *job;
-+ struct sched_param sparam = {.sched_priority = 1};
-+ struct amd_context_entity *c_entity = NULL;
-+ struct amd_gpu_scheduler *sched = (struct amd_gpu_scheduler *)param;
-+
-+ sched_setscheduler(current, SCHED_FIFO, &sparam);
-+
-+ while (!kthread_should_stop()) {
-+ wait_event_interruptible(sched->wait_queue,
-+ is_scheduler_ready(sched) &&
-+ (c_entity = select_context(sched)));
-+ r = kfifo_out(&c_entity->job_queue, &job, sizeof(void *));
-+ if (r != sizeof(void *))
-+ continue;
-+ r = sched->ops->prepare_job(sched, c_entity, job);
-+ if (!r)
-+ WARN_ON(kfifo_in_spinlocked(
-+ &sched->active_hw_rq,
-+ &job,
-+ sizeof(void *),
-+ &sched->queue_lock) != sizeof(void *));
-+ mutex_lock(&sched->sched_lock);
-+ sched->ops->run_job(sched, c_entity, job);
-+ mutex_unlock(&sched->sched_lock);
-+ }
-+ return 0;
-+}
-+
-+uint64_t amd_sched_get_handled_seq(struct amd_gpu_scheduler *sched)
-+{
-+ return sched->last_handled_seq;
-+}
-+
-+/**
-+ * ISR to handle EOP inetrrupts
-+ *
-+ * @sched: gpu scheduler
-+ *
-+*/
-+void amd_sched_isr(struct amd_gpu_scheduler *sched)
-+{
-+ int r;
-+ void *job;
-+ r = kfifo_out_spinlocked(&sched->active_hw_rq,
-+ &job, sizeof(void *),
-+ &sched->queue_lock);
-+
-+ if (r != sizeof(void *))
-+ job = NULL;
-+
-+ sched->ops->process_job(sched, job);
-+ sched->last_handled_seq++;
-+ wake_up_interruptible(&sched->wait_queue);
-+}
-+
-+/**
-+ * Create a gpu scheduler
-+ *
-+ * @device The device context for this scheduler
-+ * @ops The backend operations for this scheduler.
-+ * @id The scheduler is per ring, here is ring id.
-+ * @granularity The minumum ms unit the scheduler will scheduled.
-+ * @preemption Indicate whether this ring support preemption, 0 is no.
-+ *
-+ * return the pointer to scheduler for success, otherwise return NULL
-+*/
-+struct amd_gpu_scheduler *amd_sched_create(void *device,
-+ struct amd_sched_backend_ops *ops,
-+ unsigned ring,
-+ unsigned granularity,
-+ unsigned preemption)
-+{
-+ struct amd_gpu_scheduler *sched;
-+ char name[20] = "gpu_sched[0]";
-+
-+ sched = kzalloc(sizeof(struct amd_gpu_scheduler), GFP_KERNEL);
-+ if (!sched)
-+ return NULL;
-+
-+ sched->device = device;
-+ sched->ops = ops;
-+ sched->granularity = granularity;
-+ sched->ring_id = ring;
-+ sched->preemption = preemption;
-+ sched->last_handled_seq = 0;
-+
-+ snprintf(name, sizeof(name), "gpu_sched[%d]", ring);
-+ mutex_init(&sched->sched_lock);
-+ spin_lock_init(&sched->queue_lock);
-+ init_rq(&sched->sched_rq);
-+ sched->sched_rq.check_entity_status = gpu_entity_check_status;
-+
-+ init_rq(&sched->kernel_rq);
-+ sched->kernel_rq.check_entity_status = gpu_entity_check_status;
-+
-+ init_waitqueue_head(&sched->wait_queue);
-+ if(kfifo_alloc(&sched->active_hw_rq,
-+ AMD_MAX_ACTIVE_HW_SUBMISSION * sizeof(void *),
-+ GFP_KERNEL)) {
-+ kfree(sched);
-+ return NULL;
-+ }
-+
-+ /* Each scheduler will run on a seperate kernel thread */
-+ sched->thread = kthread_create(amd_sched_main, sched, name);
-+ if (sched->thread) {
-+ wake_up_process(sched->thread);
-+ DRM_INFO("Create gpu scheduler for id %d successfully.\n",
-+ ring);
-+ return sched;
-+ }
-+
-+ DRM_ERROR("Failed to create scheduler for id %d.\n", ring);
-+ kfifo_free(&sched->active_hw_rq);
-+ kfree(sched);
-+ return NULL;
-+}
-+
-+/**
-+ * Destroy a gpu scheduler
-+ *
-+ * @sched The pointer to the scheduler
-+ *
-+ * return 0 if succeed. -1 if failed.
-+ */
-+int amd_sched_destroy(struct amd_gpu_scheduler *sched)
-+{
-+ kthread_stop(sched->thread);
-+ kfifo_free(&sched->active_hw_rq);
-+ kfree(sched);
-+ return 0;
-+}
-+
-diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
-new file mode 100644
-index 0000000..a6226e1
---- /dev/null
-+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
-@@ -0,0 +1,160 @@
-+/*
-+ * Copyright 2015 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-+ * OTHER DEALINGS IN THE SOFTWARE.
-+ *
-+ */
-+
-+#ifndef _GPU_SCHEDULER_H_
-+#define _GPU_SCHEDULER_H_
-+
-+#include <linux/kfifo.h>
-+
-+#define AMD_MAX_ACTIVE_HW_SUBMISSION 2
-+#define AMD_MAX_JOB_ENTRY_PER_CONTEXT 16
-+
-+#define AMD_KERNEL_CONTEXT_ID 0
-+#define AMD_KERNEL_PROCESS_ID 0
-+
-+#define AMD_GPU_WAIT_IDLE_TIMEOUT_IN_MS 3000
-+
-+struct amd_gpu_scheduler;
-+struct amd_run_queue;
-+
-+/**
-+ * A scheduler entity is a wrapper around a job queue or a group
-+ * of other entities. Entities take turns emitting jobs from their
-+ * job queues to corresponding hardware ring based on scheduling
-+ * policy.
-+*/
-+struct amd_sched_entity {
-+ struct list_head list;
-+ struct amd_run_queue *belongto_rq;
-+ struct amd_sched_entity *parent;
-+};
-+
-+/**
-+ * Run queue is a set of entities scheduling command submissions for
-+ * one specific ring. It implements the scheduling policy that selects
-+ * the next entity to emit commands from.
-+*/
-+struct amd_run_queue {
-+ struct mutex lock;
-+ atomic_t nr_entity;
-+ struct amd_sched_entity head;
-+ struct amd_sched_entity *current_entity;
-+ /**
-+ * Return 0 means this entity can be scheduled
-+ * Return -1 means this entity cannot be scheduled for reasons,
-+ * i.e, it is the head, or these is no job, etc
-+ */
-+ int (*check_entity_status)(struct amd_sched_entity *entity);
-+};
-+
-+/**
-+ * Context based scheduler entity, there can be multiple entities for
-+ * each context, and one entity per ring
-+*/
-+struct amd_context_entity {
-+ struct amd_sched_entity generic_entity;
-+ spinlock_t lock;
-+ /* the virtual_seq is unique per context per ring */
-+ atomic64_t last_queued_v_seq;
-+ atomic64_t last_emitted_v_seq;
-+ atomic64_t last_signaled_v_seq;
-+ pid_t tgid;
-+ uint32_t context_id;
-+ /* the job_queue maintains the jobs submitted by clients */
-+ struct kfifo job_queue;
-+ spinlock_t queue_lock;
-+ struct amd_gpu_scheduler *scheduler;
-+ wait_queue_head_t wait_queue;
-+ wait_queue_head_t wait_emit;
-+ bool is_pending;
-+};
-+
-+/**
-+ * Define the backend operations called by the scheduler,
-+ * these functions should be implemented in driver side
-+*/
-+struct amd_sched_backend_ops {
-+ int (*prepare_job)(struct amd_gpu_scheduler *sched,
-+ struct amd_context_entity *c_entity,
-+ void *job);
-+ void (*run_job)(struct amd_gpu_scheduler *sched,
-+ struct amd_context_entity *c_entity,
-+ void *job);
-+ void (*process_job)(struct amd_gpu_scheduler *sched, void *job);
-+};
-+
-+/**
-+ * One scheduler is implemented for each hardware ring
-+*/
-+struct amd_gpu_scheduler {
-+ void *device;
-+ struct task_struct *thread;
-+ struct amd_run_queue sched_rq;
-+ struct amd_run_queue kernel_rq;
-+ struct kfifo active_hw_rq;
-+ struct amd_sched_backend_ops *ops;
-+ uint32_t ring_id;
-+ uint32_t granularity; /* in ms unit */
-+ uint32_t preemption;
-+ uint64_t last_handled_seq;
-+ wait_queue_head_t wait_queue;
-+ struct amd_context_entity *current_entity;
-+ struct mutex sched_lock;
-+ spinlock_t queue_lock;
-+};
-+
-+
-+struct amd_gpu_scheduler *amd_sched_create(void *device,
-+ struct amd_sched_backend_ops *ops,
-+ uint32_t ring,
-+ uint32_t granularity,
-+ uint32_t preemption);
-+
-+int amd_sched_destroy(struct amd_gpu_scheduler *sched);
-+
-+int amd_sched_push_job(struct amd_gpu_scheduler *sched,
-+ struct amd_context_entity *c_entity,
-+ void *job);
-+
-+int amd_sched_check_ts(struct amd_context_entity *c_entity, uint64_t seq);
-+
-+int amd_sched_wait_signal(struct amd_context_entity *c_entity,
-+ uint64_t seq, bool intr, long timeout);
-+int amd_sched_wait_emit(struct amd_context_entity *c_entity,
-+ uint64_t seq,
-+ bool intr,
-+ long timeout);
-+
-+void amd_sched_isr(struct amd_gpu_scheduler *sched);
-+uint64_t amd_sched_get_handled_seq(struct amd_gpu_scheduler *sched);
-+
-+int amd_context_entity_fini(struct amd_gpu_scheduler *sched,
-+ struct amd_context_entity *entity);
-+
-+int amd_context_entity_init(struct amd_gpu_scheduler *sched,
-+ struct amd_context_entity *entity,
-+ struct amd_sched_entity *parent,
-+ struct amd_run_queue *rq,
-+ uint32_t context_id);
-+
-+#endif
---
-1.9.1
-