When __ttm_pool_alloc() fails to allocate a chunk at the device's
beneficial order and falls back to a smaller order, the object ends up
backed by a sub-optimal set of pages. Nothing currently records this, so
a driver has no way to know an object would benefit from being re-backed
with beneficial-order pages later.

Add a bool beneficial_order_failed to struct ttm_tt, initialised to
false in ttm_tt_init_fields() and reset at the start of each fresh
ttm_pool_alloc(). Set it in __ttm_pool_alloc() when an allocation at
exactly the beneficial order fails before dropping to a lower order.

Drivers can use this hint to queue the buffer object for later
defragmentation.

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 | 11 +++++++++++
 drivers/gpu/drm/ttm/ttm_tt.c   |  1 +
 include/drm/ttm/ttm_tt.h       |  8 ++++++++
 3 files changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
index 5b95f8f938f7..a1a74ccfcbf0 100644
--- a/drivers/gpu/drm/ttm/ttm_pool.c
+++ b/drivers/gpu/drm/ttm/ttm_pool.c
@@ -773,6 +773,7 @@ static int __ttm_pool_alloc(struct ttm_pool *pool, struct 
ttm_tt *tt,
                            struct ttm_pool_alloc_state *alloc,
                            struct ttm_pool_tt_restore *restore)
 {
+       const unsigned int beneficial_order = ttm_pool_beneficial_order(pool);
        enum ttm_caching page_caching;
        gfp_t gfp_flags = GFP_USER;
        pgoff_t caching_divide;
@@ -823,6 +824,15 @@ static int __ttm_pool_alloc(struct ttm_pool *pool, struct 
ttm_tt *tt,
                /* If that fails, lower the order if possible and retry. */
                if (!p) {
                        if (order) {
+                               /*
+                                * Failing to allocate at the device's 
beneficial
+                                * order means we are about to back this object
+                                * with a sub-optimal (smaller order) set of
+                                * pages. Record it so the driver can later try 
to
+                                * defragment the object back to beneficial 
order.
+                                */
+                               if (beneficial_order && order == 
beneficial_order)
+                                       tt->beneficial_order_failed = true;
                                --order;
                                page_caching = tt->caching;
                                allow_pools = true;
@@ -887,6 +897,7 @@ int ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
        if (WARN_ON(ttm_tt_is_backed_up(tt)))
                return -EINVAL;
 
+       tt->beneficial_order_failed = false;
        ttm_pool_alloc_state_init(tt, &alloc);
 
        return __ttm_pool_alloc(pool, tt, ctx, &alloc, NULL);
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index b645a1818184..27e09a58cf03 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -164,6 +164,7 @@ static void ttm_tt_init_fields(struct ttm_tt *ttm,
        ttm->caching = caching;
        ttm->restore = NULL;
        ttm->backup = NULL;
+       ttm->beneficial_order_failed = false;
 }
 
 int ttm_tt_init(struct ttm_tt *ttm, struct ttm_buffer_object *bo,
diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h
index 406437ad674b..55202362987a 100644
--- a/include/drm/ttm/ttm_tt.h
+++ b/include/drm/ttm/ttm_tt.h
@@ -126,6 +126,14 @@ struct ttm_tt {
        enum ttm_caching caching;
        /** @restore: Partial restoration from backup state. TTM private */
        struct ttm_pool_tt_restore *restore;
+       /**
+        * @beneficial_order_failed: Set by the TTM pool allocator when at least
+        * one chunk that could have been allocated at the pool's beneficial
+        * order had to fall back to a smaller order. This indicates that a
+        * sub-optimal set of pages was chosen for this object, and can be used
+        * by drivers to queue the buffer object for later defragmentation.
+        */
+       bool beneficial_order_failed;
 };
 
 /**
-- 
2.34.1

Reply via email to