Add Kconfig.profile options to make XE_BO_DEFRAG_* defines configurable: - DRM_XE_BO_DEFRAG_RECLAIM_BACKOFF_THRESHOLD: Threshold for TTM reclaim backoff - DRM_XE_BO_DEFRAG_SIZE_LIMIT: Maximum number of bytes to defrag per work run - DRM_XE_BO_DEFRAG_INTERVAL_MS: Default delay before defrag worker runs - DRM_XE_BO_DEFRAG_INTERVAL_MAX_MS: Upper bound for defrag worker interval
Update xe_bo.c to use these Kconfig options as defaults via #ifdef guards, maintaining backward compatibility with hardcoded values when not configured. Additionally, disable defrag completely when XE_BO_DEFRAG_SIZE_LIMIT is set less than 2M by returning early from xe_bo_defrag_update() (and xe_bo_defrag_remove()) so BOs are never added to the defrag list or the worker kicked; xe_bo_defrag_add() and xe_bo_defrag_schedule() assert the limit is at least 2M. Cc: Carlos Santa <[email protected]> Cc: Ryan Neph <[email protected]> Cc: Christian Koenig <[email protected]> Cc: Huang Rui <[email protected]> Cc: Matthew Auld <[email protected]> Cc: Maarten Lankhorst <[email protected]> Cc: Maxime Ripard <[email protected]> Cc: Thomas Zimmermann <[email protected]> Cc: David Airlie <[email protected]> Cc: Simona Vetter <[email protected]> Cc: [email protected] Cc: [email protected] Cc: Thomas Hellström <[email protected]> Assisted-by: GitHub_Copilot:claude-haiku-4.5 Signed-off-by: Matthew Brost <[email protected]> --- drivers/gpu/drm/xe/Kconfig.profile | 40 ++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_bo.c | 26 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/drivers/gpu/drm/xe/Kconfig.profile b/drivers/gpu/drm/xe/Kconfig.profile index e07517d120e0..e0aade41f53e 100644 --- a/drivers/gpu/drm/xe/Kconfig.profile +++ b/drivers/gpu/drm/xe/Kconfig.profile @@ -74,3 +74,43 @@ config DRM_XE_ENABLE_SCHEDTIMEOUT_LIMIT 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. + +config DRM_XE_BO_DEFRAG_RECLAIM_BACKOFF_THRESHOLD + int "BO defrag reclaim backoff threshold" + default 2 + range 1 1000 + help + Once this many BOs are tracked on the device defrag list (i.e. were + backed with a sub-optimal page order), request that the TTM pool backs + off from aggressive reclaim at the beneficial order during populate, + so that allocations make forward progress instead of stalling. + +config DRM_XE_BO_DEFRAG_SIZE_LIMIT + int "Maximum bytes to defrag per work run" + default 33554432 + range 0 1073741824 + help + Maximum number of bytes the defrag worker will process in a single run + before yielding and rescheduling itself. Set to less than large page + size (2M) to disable defrag. A defrag move synchronously reallocates + and re-copies a BO's backing store, which is not free. If a large + number of BOs become eligible at once, processing them all in one + worker run would hold things up for a long, unbounded stretch. + Instead, cap the work done per run and requeue, spreading the defrag + effort out over time. + +config DRM_XE_BO_DEFRAG_INTERVAL_MS + int "Default delay before defrag worker run (ms)" + default 25 + range 1 1000 + help + Default delay before (re)running the defrag worker, in milliseconds. + +config DRM_XE_BO_DEFRAG_INTERVAL_MAX_MS + int "Upper bound for defrag worker interval (ms)" + default 15000 + range 100 1000000 + help + Upper bound for the (exponentially backed off) defrag worker interval, + in milliseconds, so repeated failures don't push the retry arbitrarily + far out. 15000 ms = 15 seconds. diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index c1bbcf0d21ed..405316d0d116 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -49,7 +49,11 @@ * aggressive reclaim at the beneficial order during populate, so that * allocations make forward progress instead of stalling. */ +#ifdef CONFIG_DRM_XE_BO_DEFRAG_RECLAIM_BACKOFF_THRESHOLD +#define XE_BO_DEFRAG_RECLAIM_BACKOFF_THRESHOLD CONFIG_DRM_XE_BO_DEFRAG_RECLAIM_BACKOFF_THRESHOLD +#else #define XE_BO_DEFRAG_RECLAIM_BACKOFF_THRESHOLD 2 +#endif /* * Maximum number of bytes of newly (re)allocated backing the defrag worker will @@ -65,17 +69,31 @@ * Only pages a move truly reallocates are charged; pages harvested from the old * backing are free, so an object larger than the budget is upgraded in * budget-sized slices across runs. + * + * Set to 0 to disable defrag completely. */ +#ifdef CONFIG_DRM_XE_BO_DEFRAG_SIZE_LIMIT +#define XE_BO_DEFRAG_SIZE_LIMIT CONFIG_DRM_XE_BO_DEFRAG_SIZE_LIMIT +#else #define XE_BO_DEFRAG_SIZE_LIMIT SZ_32M +#endif /* Default delay before (re)running the defrag worker, in milliseconds. */ +#ifdef CONFIG_DRM_XE_BO_DEFRAG_INTERVAL_MS +#define XE_BO_DEFRAG_INTERVAL_MS CONFIG_DRM_XE_BO_DEFRAG_INTERVAL_MS +#else #define XE_BO_DEFRAG_INTERVAL_MS 25 +#endif /* * Upper bound for the (exponentially backed off) defrag worker interval, in * milliseconds, so repeated failures don't push the retry arbitrarily far out. */ +#ifdef CONFIG_DRM_XE_BO_DEFRAG_INTERVAL_MAX_MS +#define XE_BO_DEFRAG_INTERVAL_MAX_MS CONFIG_DRM_XE_BO_DEFRAG_INTERVAL_MAX_MS +#else #define XE_BO_DEFRAG_INTERVAL_MAX_MS 15000 /* 15 seconds */ +#endif static void xe_bo_defrag_worker(struct work_struct *w); static void xe_place_from_ttm_type(u32 mem_type, struct ttm_place *place); @@ -1120,6 +1138,7 @@ int xe_bo_defrag_init(struct xe_device *xe) static void xe_bo_defrag_schedule(struct xe_device *xe) { + xe_assert(xe, XE_BO_DEFRAG_SIZE_LIMIT >= SZ_2M); schedule_delayed_work(&xe->mem.defrag.worker, msecs_to_jiffies(xe->mem.defrag.interval_ms)); } @@ -1146,6 +1165,7 @@ static void xe_bo_defrag_add(struct xe_bo *bo) xe_bo_assert_held(bo); xe_assert(xe, xe_bo_needs_defrag(bo)); + xe_assert(xe, XE_BO_DEFRAG_SIZE_LIMIT >= SZ_2M); scoped_guard(spinlock, &xe->mem.defrag.lock) { if (list_empty(&bo->defrag_link)) { @@ -1179,6 +1199,9 @@ static void xe_bo_defrag_remove(struct xe_bo *bo) { xe_bo_assert_held(bo); + if (XE_BO_DEFRAG_SIZE_LIMIT < SZ_2M) + return; + if (list_empty(&bo->defrag_link)) return; @@ -1198,6 +1221,9 @@ static void xe_bo_defrag_update(struct xe_bo *bo) { xe_bo_assert_held(bo); + if (XE_BO_DEFRAG_SIZE_LIMIT < SZ_2M) + return; + if (xe_bo_needs_defrag(bo)) xe_bo_defrag_add(bo); else -- 2.34.1
