]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/xe/multi_queue: Add support for multi queue dynamic priority change
authorNiranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Thu, 11 Dec 2025 01:02:55 +0000 (17:02 -0800)
committerNiranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Fri, 12 Dec 2025 03:21:14 +0000 (19:21 -0800)
Support dynamic priority change for multi queue group queues via
exec queue set_property ioctl. Issue CGP_SYNC command to GuC through
the drm scheduler message interface for priority to take effect.

v2: Move is_multi_queue check to exec_queue layer and assert
    is_multi_queue being set in guc submission layer (Matt Brost)
v3: Assert CGP_SYNC message length is valid (Matt Brost)

Signed-off-by: Pallavi Mishra <pallavi.mishra@intel.com>
Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Link: https://patch.msgid.link/20251211010249.1647839-26-niranjana.vishwanathapura@intel.com
drivers/gpu/drm/xe/xe_exec_queue.c
drivers/gpu/drm/xe/xe_exec_queue_types.h
drivers/gpu/drm/xe/xe_guc_submit.c

index d738a9fea1e173dab6c76efeb0cae7ffbc8182e3..256e2ce1fe6981d0d79dfcd1840a24585448e728 100644 (file)
@@ -771,9 +771,16 @@ static int exec_queue_set_multi_queue_priority(struct xe_device *xe, struct xe_e
        if (XE_IOCTL_DBG(xe, value > XE_MULTI_QUEUE_PRIORITY_HIGH))
                return -EINVAL;
 
-       q->multi_queue.priority = value;
+       /* For queue creation time (!q->xef) setting, just store the priority value */
+       if (!q->xef) {
+               q->multi_queue.priority = value;
+               return 0;
+       }
 
-       return 0;
+       if (!xe_exec_queue_is_multi_queue(q))
+               return -EINVAL;
+
+       return q->ops->set_multi_queue_priority(q, value);
 }
 
 typedef int (*xe_exec_queue_set_property_fn)(struct xe_device *xe,
index 46e5f4715a0da194584e2b41c854a2f1396e1d91..1c285ac128689ceac4a1c323c37471ab93fd4d6d 100644 (file)
@@ -260,6 +260,9 @@ struct xe_exec_queue_ops {
        int (*set_timeslice)(struct xe_exec_queue *q, u32 timeslice_us);
        /** @set_preempt_timeout: Set preemption timeout for exec queue */
        int (*set_preempt_timeout)(struct xe_exec_queue *q, u32 preempt_timeout_us);
+       /** @set_multi_queue_priority: Set multi queue priority */
+       int (*set_multi_queue_priority)(struct xe_exec_queue *q,
+                                       enum xe_multi_queue_priority priority);
        /**
         * @suspend: Suspend exec queue from executing, allowed to be called
         * multiple times in a row before resume with the caveat that
index 7cca03d4296c63d25d7938c70a17bc99ff516ba3..2f467cc1929f1e68827220cf30536bbdbd58e4c0 100644 (file)
@@ -1779,10 +1779,34 @@ static void __guc_exec_queue_process_msg_resume(struct xe_sched_msg *msg)
        }
 }
 
-#define CLEANUP                1       /* Non-zero values to catch uninitialized msg */
-#define SET_SCHED_PROPS        2
-#define SUSPEND                3
-#define RESUME         4
+static void __guc_exec_queue_process_msg_set_multi_queue_priority(struct xe_sched_msg *msg)
+{
+       struct xe_exec_queue *q = msg->private_data;
+
+       if (guc_exec_queue_allowed_to_change_state(q)) {
+#define MAX_MULTI_QUEUE_CGP_SYNC_SIZE        (2)
+               struct xe_guc *guc = exec_queue_to_guc(q);
+               struct xe_exec_queue_group *group = q->multi_queue.group;
+               u32 action[MAX_MULTI_QUEUE_CGP_SYNC_SIZE];
+               int len = 0;
+
+               action[len++] = XE_GUC_ACTION_MULTI_QUEUE_CONTEXT_CGP_SYNC;
+               action[len++] = group->primary->guc->id;
+
+               xe_gt_assert(guc_to_gt(guc), len <= MAX_MULTI_QUEUE_CGP_SYNC_SIZE);
+#undef MAX_MULTI_QUEUE_CGP_SYNC_SIZE
+
+               xe_guc_exec_queue_group_cgp_sync(guc, q, action, len);
+       }
+
+       kfree(msg);
+}
+
+#define CLEANUP                                1       /* Non-zero values to catch uninitialized msg */
+#define SET_SCHED_PROPS                        2
+#define SUSPEND                                3
+#define RESUME                         4
+#define SET_MULTI_QUEUE_PRIORITY       5
 #define OPCODE_MASK    0xf
 #define MSG_LOCKED     BIT(8)
 #define MSG_HEAD       BIT(9)
@@ -1806,6 +1830,9 @@ static void guc_exec_queue_process_msg(struct xe_sched_msg *msg)
        case RESUME:
                __guc_exec_queue_process_msg_resume(msg);
                break;
+       case SET_MULTI_QUEUE_PRIORITY:
+               __guc_exec_queue_process_msg_set_multi_queue_priority(msg);
+               break;
        default:
                XE_WARN_ON("Unknown message type");
        }
@@ -2022,6 +2049,27 @@ static int guc_exec_queue_set_preempt_timeout(struct xe_exec_queue *q,
        return 0;
 }
 
+static int guc_exec_queue_set_multi_queue_priority(struct xe_exec_queue *q,
+                                                  enum xe_multi_queue_priority priority)
+{
+       struct xe_sched_msg *msg;
+
+       xe_gt_assert(guc_to_gt(exec_queue_to_guc(q)), xe_exec_queue_is_multi_queue(q));
+
+       if (q->multi_queue.priority == priority ||
+           exec_queue_killed_or_banned_or_wedged(q))
+               return 0;
+
+       msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
+       q->multi_queue.priority = priority;
+       guc_exec_queue_add_msg(q, msg, SET_MULTI_QUEUE_PRIORITY);
+
+       return 0;
+}
+
 static int guc_exec_queue_suspend(struct xe_exec_queue *q)
 {
        struct xe_gpu_scheduler *sched = &q->guc->sched;
@@ -2113,6 +2161,7 @@ static const struct xe_exec_queue_ops guc_exec_queue_ops = {
        .set_priority = guc_exec_queue_set_priority,
        .set_timeslice = guc_exec_queue_set_timeslice,
        .set_preempt_timeout = guc_exec_queue_set_preempt_timeout,
+       .set_multi_queue_priority = guc_exec_queue_set_multi_queue_priority,
        .suspend = guc_exec_queue_suspend,
        .suspend_wait = guc_exec_queue_suspend_wait,
        .resume = guc_exec_queue_resume,