Commit d2776564 authored by Tejas Upadhyay's avatar Tejas Upadhyay Committed by Rodrigo Vivi

drm/xe: Add min/max cap for engine scheduler properties

Add sysfs entries for the min, max, and defaults for each of
engine scheduler controls for every hardware engine class.

Non-elevated user IOCTLs to set these controls must be within
the min-max ranges of the sysfs entries, elevated user can set
these controls to any value. However, introduced compile time
CONFIG min-max values which restricts elevated user to be in
compile time min-max range if at all sysfs min/max are violated.

Sysfs entries examples are,
DUT# cat /sys/class/drm/cardX/device/tileN/gtN/engines/ccs/.defaults/
job_timeout_max         job_timeout_ms          preempt_timeout_min     timeslice_duration_max  timeslice_duration_us
job_timeout_min         preempt_timeout_max     preempt_timeout_us      timeslice_duration_min

DUT# cat /sys/class/drm/card1/device/tileN/gtN/engines/ccs/
.defaults/              job_timeout_min         preempt_timeout_max     preempt_timeout_us      timeslice_duration_min
job_timeout_max         job_timeout_ms          preempt_timeout_min     timeslice_duration_max  timeslice_duration_us

V12:
   - Rebase
V11:
   - Make engine_get_prop_minmax and enforce_sched_limit static - Matt
   - use enum in place of string in engine_get_prop_minmax - Matt
   - no need to use enforce_sched_limit or no need to filter min/max
     per user type in sysfs - Matt
V10:
   - Add kernel doc for non-static func
   - Make helper to get min/max for range validation - Matt
   - Filter min/max per user type
V9 :
   - Rebase to use s/xe_engine/xe_hw_engine/ - Matt
V8 :
   - fix enforce_sched_limit and avoid code duplication - Niranjana
   - Make sure min < max - Niranjana
V7 :
   - Rebase to replace hw engine with eclass interface
   - return EINVAL in place of EPERM
   - Use some APIs to avoid code duplication
V6 :
   - Rebase changes to reflect per engine class props interface - MattB
   - Use #if ENABLED - MattB
   - Remove MAX_SCHED_TIMEOUT check as range validation is enough
V5 :
   - Rebase to resolve conflicts - CI
V4 :
   - Rebase
   - Update commit to reflect tile addition
   - Use XE_HW macro directly as they are already filtered
     for CONFIG checks - Niranjana
   - Add CONFIG for enable/disable min/max limitation
     on elevated user. Default is enable - Matt/Joonas
V3 :
   - Resolve CI hooks warning for kernel-doc
V2 :
   - Restric min/max setting to #define default min/max for
     elevated user - Himal
   - Remove unrelated changes from patch - Niranjana
Reviewed-by: default avatarNiranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: default avatarMatthew Brost <matthew.brost@intel.com>
Signed-off-by: default avatarTejas Upadhyay <tejas.upadhyay@intel.com>
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent 69838d63
......@@ -63,3 +63,9 @@ depends on DRM_XE
depends on EXPERT
source "drivers/gpu/drm/xe/Kconfig.debug"
endmenu
menu "drm/xe Profile Guided Optimisation"
visible if EXPERT
depends on DRM_XE
source "drivers/gpu/drm/xe/Kconfig.profile"
endmenu
config DRM_XE_JOB_TIMEOUT_MAX
int "Default max job timeout (ms)"
default 10000 # milliseconds
help
Configures the default max job timeout after which job will
be forcefully taken away from scheduler.
config DRM_XE_JOB_TIMEOUT_MIN
int "Default min job timeout (ms)"
default 1 # milliseconds
help
Configures the default min job timeout after which job will
be forcefully taken away from scheduler.
config DRM_XE_TIMESLICE_MAX
int "Default max timeslice duration (us)"
default 10000000 # microseconds
help
Configures the default max timeslice duration between multiple
contexts by guc scheduling.
config DRM_XE_TIMESLICE_MIN
int "Default min timeslice duration (us)"
default 1 # microseconds
help
Configures the default min timeslice duration between multiple
contexts by guc scheduling.
config DRM_XE_PREEMPT_TIMEOUT_MAX
int "Default max preempt timeout (us)"
default 10000000 # microseconds
help
Configures the default max preempt timeout after which context
will be forcefully taken away and higher priority context will
run.
config DRM_XE_PREEMPT_TIMEOUT_MIN
int "Default min preempt timeout (us)"
default 1 # microseconds
help
Configures the default min preempt timeout after which context
will be forcefully taken away and higher priority context will
run.
config DRM_XE_ENABLE_SCHEDTIMEOUT_LIMIT
bool "Default configuration of limitation on scheduler timeout"
default y
help
Configures the enablement of limitation on scheduler timeout
to apply to applicable user. For elevated user, all above MIN
and MAX values will apply when this configuration is enable to
apply limitation. By default limitation is applied.
......@@ -13,6 +13,7 @@
#include "xe_device.h"
#include "xe_gt.h"
#include "xe_hw_engine_class_sysfs.h"
#include "xe_hw_fence.h"
#include "xe_lrc.h"
#include "xe_macros.h"
......@@ -22,6 +23,13 @@
#include "xe_trace.h"
#include "xe_vm.h"
enum xe_exec_queue_sched_prop {
XE_EXEC_QUEUE_JOB_TIMEOUT = 0,
XE_EXEC_QUEUE_TIMESLICE = 1,
XE_EXEC_QUEUE_PREEMPT_TIMEOUT = 2,
XE_EXEC_QUEUE_SCHED_PROP_MAX = 3,
};
static struct xe_exec_queue *__xe_exec_queue_create(struct xe_device *xe,
struct xe_vm *vm,
u32 logical_mask,
......@@ -201,11 +209,69 @@ static int exec_queue_set_priority(struct xe_device *xe, struct xe_exec_queue *q
return q->ops->set_priority(q, value);
}
static bool xe_exec_queue_enforce_schedule_limit(void)
{
#if IS_ENABLED(CONFIG_DRM_XE_ENABLE_SCHEDTIMEOUT_LIMIT)
return true;
#else
return !capable(CAP_SYS_NICE);
#endif
}
static void
xe_exec_queue_get_prop_minmax(struct xe_hw_engine_class_intf *eclass,
enum xe_exec_queue_sched_prop prop,
u32 *min, u32 *max)
{
switch (prop) {
case XE_EXEC_QUEUE_JOB_TIMEOUT:
*min = eclass->sched_props.job_timeout_min;
*max = eclass->sched_props.job_timeout_max;
break;
case XE_EXEC_QUEUE_TIMESLICE:
*min = eclass->sched_props.timeslice_min;
*max = eclass->sched_props.timeslice_max;
break;
case XE_EXEC_QUEUE_PREEMPT_TIMEOUT:
*min = eclass->sched_props.preempt_timeout_min;
*max = eclass->sched_props.preempt_timeout_max;
break;
default:
break;
}
#if IS_ENABLED(CONFIG_DRM_XE_ENABLE_SCHEDTIMEOUT_LIMIT)
if (capable(CAP_SYS_NICE)) {
switch (prop) {
case XE_EXEC_QUEUE_JOB_TIMEOUT:
*min = XE_HW_ENGINE_JOB_TIMEOUT_MIN;
*max = XE_HW_ENGINE_JOB_TIMEOUT_MAX;
break;
case XE_EXEC_QUEUE_TIMESLICE:
*min = XE_HW_ENGINE_TIMESLICE_MIN;
*max = XE_HW_ENGINE_TIMESLICE_MAX;
break;
case XE_EXEC_QUEUE_PREEMPT_TIMEOUT:
*min = XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN;
*max = XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX;
break;
default:
break;
}
}
#endif
}
static int exec_queue_set_timeslice(struct xe_device *xe, struct xe_exec_queue *q,
u64 value, bool create)
{
if (!capable(CAP_SYS_NICE))
return -EPERM;
u32 min = 0, max = 0;
xe_exec_queue_get_prop_minmax(q->hwe->eclass,
XE_EXEC_QUEUE_TIMESLICE, &min, &max);
if (xe_exec_queue_enforce_schedule_limit() &&
!xe_hw_engine_timeout_in_range(value, min, max))
return -EINVAL;
return q->ops->set_timeslice(q, value);
}
......@@ -214,8 +280,14 @@ static int exec_queue_set_preemption_timeout(struct xe_device *xe,
struct xe_exec_queue *q, u64 value,
bool create)
{
if (!capable(CAP_SYS_NICE))
return -EPERM;
u32 min = 0, max = 0;
xe_exec_queue_get_prop_minmax(q->hwe->eclass,
XE_EXEC_QUEUE_PREEMPT_TIMEOUT, &min, &max);
if (xe_exec_queue_enforce_schedule_limit() &&
!xe_hw_engine_timeout_in_range(value, min, max))
return -EINVAL;
return q->ops->set_preempt_timeout(q, value);
}
......@@ -279,11 +351,17 @@ static int exec_queue_set_persistence(struct xe_device *xe, struct xe_exec_queue
static int exec_queue_set_job_timeout(struct xe_device *xe, struct xe_exec_queue *q,
u64 value, bool create)
{
u32 min = 0, max = 0;
if (XE_IOCTL_DBG(xe, !create))
return -EINVAL;
if (!capable(CAP_SYS_NICE))
return -EPERM;
xe_exec_queue_get_prop_minmax(q->hwe->eclass,
XE_EXEC_QUEUE_JOB_TIMEOUT, &min, &max);
if (xe_exec_queue_enforce_schedule_limit() &&
!xe_hw_engine_timeout_in_range(value, min, max))
return -EINVAL;
return q->ops->set_job_timeout(q, value);
}
......
......@@ -364,8 +364,16 @@ static void hw_engine_init_early(struct xe_gt *gt, struct xe_hw_engine *hwe,
if (!gt->eclass[hwe->class].sched_props.job_timeout_ms) {
gt->eclass[hwe->class].sched_props.job_timeout_ms = 5 * 1000;
gt->eclass[hwe->class].sched_props.job_timeout_min = XE_HW_ENGINE_JOB_TIMEOUT_MIN;
gt->eclass[hwe->class].sched_props.job_timeout_max = XE_HW_ENGINE_JOB_TIMEOUT_MAX;
gt->eclass[hwe->class].sched_props.timeslice_us = 1 * 1000;
gt->eclass[hwe->class].sched_props.timeslice_min = XE_HW_ENGINE_TIMESLICE_MIN;
gt->eclass[hwe->class].sched_props.timeslice_max = XE_HW_ENGINE_TIMESLICE_MAX;
gt->eclass[hwe->class].sched_props.preempt_timeout_us = 640 * 1000;
gt->eclass[hwe->class].sched_props.preempt_timeout_min =
XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN;
gt->eclass[hwe->class].sched_props.preempt_timeout_max =
XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX;
/* Record default props */
gt->eclass[hwe->class].defaults = gt->eclass[hwe->class].sched_props;
}
......
......@@ -10,6 +10,37 @@
struct drm_printer;
#ifdef CONFIG_DRM_XE_JOB_TIMEOUT_MIN
#define XE_HW_ENGINE_JOB_TIMEOUT_MIN CONFIG_DRM_XE_JOB_TIMEOUT_MIN
#else
#define XE_HW_ENGINE_JOB_TIMEOUT_MIN 1
#endif
#ifdef CONFIG_DRM_XE_JOB_TIMEOUT_MAX
#define XE_HW_ENGINE_JOB_TIMEOUT_MAX CONFIG_DRM_XE_JOB_TIMEOUT_MAX
#else
#define XE_HW_ENGINE_JOB_TIMEOUT_MAX (10 * 1000)
#endif
#ifdef CONFIG_DRM_XE_TIMESLICE_MIN
#define XE_HW_ENGINE_TIMESLICE_MIN CONFIG_DRM_XE_TIMESLICE_MIN
#else
#define XE_HW_ENGINE_TIMESLICE_MIN 1
#endif
#ifdef CONFIG_DRM_XE_TIMESLICE_MAX
#define XE_HW_ENGINE_TIMESLICE_MAX CONFIG_DRM_XE_TIMESLICE_MAX
#else
#define XE_HW_ENGINE_TIMESLICE_MAX (10 * 1000 * 1000)
#endif
#ifdef CONFIG_DRM_XE_PREEMPT_TIMEOUT_MIN
#define XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN CONFIG_DRM_XE_PREEMPT_TIMEOUT_MIN
#else
#define XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN 1
#endif
#ifdef CONFIG_DRM_XE_PREEMPT_TIMEOUT_MAX
#define XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX CONFIG_DRM_XE_PREEMPT_TIMEOUT_MAX
#else
#define XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX (10 * 1000 * 1000)
#endif
int xe_hw_engines_init_early(struct xe_gt *gt);
int xe_hw_engines_init(struct xe_gt *gt);
void xe_hw_engine_handle_irq(struct xe_hw_engine *hwe, u16 intr_vec);
......
......@@ -12,6 +12,7 @@ struct xe_gt;
struct xe_hw_engine_class_intf;
int xe_hw_engine_class_sysfs_init(struct xe_gt *gt);
bool xe_hw_engine_timeout_in_range(u64 timeout, u64 min, u64 max);
/**
* struct kobj_eclass - A eclass's kobject struct that connects the kobject and the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment