Add a beneficial_order_fault_inject debugfs fault attribute, mirroring backup_fault_inject, that forces allocation at the device's beneficial order to fail in __ttm_pool_alloc(). When triggered, both the pool take and the system page allocation are skipped for that order, so the allocation falls into the existing lower-the-order path that records tt->beneficial_order_failed (and bails out with -ENOMEM for defrag moves).
This lets the beneficial_order_failed tracking and the driver-side defrag path be exercised deterministically, without having to drive the system into real memory fragmentation to provoke a sub-optimal backing. The knob is registered at /sys/kernel/debug/ttm/beneficial_order_fault_inject and compiles out when CONFIG_FAULT_INJECTION is disabled. 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-opus-4.8 Signed-off-by: Matthew Brost <[email protected]> --- drivers/gpu/drm/ttm/ttm_pool.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c index 6e9a5481d876..3330df7bc61d 100644 --- a/drivers/gpu/drm/ttm/ttm_pool.c +++ b/drivers/gpu/drm/ttm/ttm_pool.c @@ -53,6 +53,7 @@ #ifdef CONFIG_FAULT_INJECTION #include <linux/fault-inject.h> static DECLARE_FAULT_ATTR(backup_fault_inject); +static DECLARE_FAULT_ATTR(beneficial_order_fault_inject); #else #define should_fail(...) false #endif @@ -802,11 +803,24 @@ static int __ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt, alloc->remaining_pages; order = ttm_pool_alloc_find_order(order, alloc)) { struct ttm_pool_type *pt; + bool fail_beneficial; + + /* + * Fault injection: pretend allocation at the device's + * beneficial order failed, forcing the object to be backed with + * a sub-optimal (smaller order) set of pages. Used to exercise + * the beneficial_order_failed tracking and the driver defrag + * path without having to drive the system into real memory + * fragmentation. + */ + fail_beneficial = IS_ENABLED(CONFIG_FAULT_INJECTION) && + beneficial_order && order >= beneficial_order && + should_fail(&beneficial_order_fault_inject, 1); /* First, try to allocate a page from a pool if one exists. */ p = NULL; pt = ttm_pool_select_type(pool, page_caching, order); - if (pt && allow_pools) + if (pt && allow_pools && !fail_beneficial) p = ttm_pool_type_take(pt, ttm_pool_nid(pool)); /* @@ -815,7 +829,7 @@ static int __ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt, * write-back cached pools of the same order. Consider removing * that behaviour. */ - if (!p) { + if (!p && !fail_beneficial) { page_caching = ttm_cached; allow_pools = false; p = ttm_pool_alloc_page(pool, gfp_flags, order, @@ -1453,6 +1467,9 @@ int ttm_pool_mgr_init(unsigned long num_pages) #ifdef CONFIG_FAULT_INJECTION fault_create_debugfs_attr("backup_fault_inject", ttm_debugfs_root, &backup_fault_inject); + fault_create_debugfs_attr("beneficial_order_fault_inject", + ttm_debugfs_root, + &beneficial_order_fault_inject); #endif #endif -- 2.34.1
