Commit ebd59851 authored by Christian König's avatar Christian König

drm/ttm: move swapout logic around v3

Move the iteration of the global lru into the new function
ttm_global_swapout() and use that instead in drivers.

v2: consistently return int
v3: fix build fail
Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Tested-by: default avatarNirmoy Das <nirmoy.das@amd.com>
Reviewed-by: default avatarHuang Rui <ray.huang@amd.com>
Reviewed-by: default avatarMatthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/424008/
parent 976677b5
...@@ -1193,56 +1193,35 @@ int ttm_bo_wait(struct ttm_buffer_object *bo, ...@@ -1193,56 +1193,35 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,
} }
EXPORT_SYMBOL(ttm_bo_wait); EXPORT_SYMBOL(ttm_bo_wait);
/* int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx,
* A buffer object shrink method that tries to swap out the first gfp_t gfp_flags)
* buffer object on the bo_global::swap_lru list.
*/
int ttm_bo_swapout(struct ttm_operation_ctx *ctx, gfp_t gfp_flags)
{ {
struct ttm_global *glob = &ttm_glob; struct ttm_global *glob = &ttm_glob;
struct ttm_buffer_object *bo;
int ret = -EBUSY;
bool locked; bool locked;
unsigned i; int ret;
spin_lock(&glob->lru_lock);
for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) {
list_for_each_entry(bo, &glob->swap_lru[i], swap) {
if (!ttm_bo_evict_swapout_allowable(bo, ctx, &locked,
NULL))
continue;
if (!ttm_bo_get_unless_zero(bo)) {
if (locked)
dma_resv_unlock(bo->base.resv);
continue;
}
ret = 0; if (!ttm_bo_evict_swapout_allowable(bo, ctx, &locked, NULL))
break; return -EBUSY;
}
if (!ret)
break;
}
if (ret) { if (!ttm_bo_get_unless_zero(bo)) {
spin_unlock(&glob->lru_lock); if (locked)
return ret; dma_resv_unlock(bo->base.resv);
return -EBUSY;
} }
if (bo->deleted) { if (bo->deleted) {
ret = ttm_bo_cleanup_refs(bo, false, false, locked); ttm_bo_cleanup_refs(bo, false, false, locked);
ttm_bo_put(bo); ttm_bo_put(bo);
return ret; return 0;
} }
ttm_bo_del_from_lru(bo); ttm_bo_del_from_lru(bo);
/* TODO: Cleanup the locking */
spin_unlock(&glob->lru_lock); spin_unlock(&glob->lru_lock);
/** /*
* Move to system cached * Move to system cached
*/ */
if (bo->mem.mem_type != TTM_PL_SYSTEM) { if (bo->mem.mem_type != TTM_PL_SYSTEM) {
struct ttm_operation_ctx ctx = { false, false }; struct ttm_operation_ctx ctx = { false, false };
struct ttm_resource evict_mem; struct ttm_resource evict_mem;
...@@ -1262,29 +1241,26 @@ int ttm_bo_swapout(struct ttm_operation_ctx *ctx, gfp_t gfp_flags) ...@@ -1262,29 +1241,26 @@ int ttm_bo_swapout(struct ttm_operation_ctx *ctx, gfp_t gfp_flags)
} }
} }
/** /*
* Make sure BO is idle. * Make sure BO is idle.
*/ */
ret = ttm_bo_wait(bo, false, false); ret = ttm_bo_wait(bo, false, false);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
goto out; goto out;
ttm_bo_unmap_virtual(bo); ttm_bo_unmap_virtual(bo);
/** /*
* Swap out. Buffer will be swapped in again as soon as * Swap out. Buffer will be swapped in again as soon as
* anyone tries to access a ttm page. * anyone tries to access a ttm page.
*/ */
if (bo->bdev->funcs->swap_notify) if (bo->bdev->funcs->swap_notify)
bo->bdev->funcs->swap_notify(bo); bo->bdev->funcs->swap_notify(bo);
ret = ttm_tt_swapout(bo->bdev, bo->ttm, gfp_flags); ret = ttm_tt_swapout(bo->bdev, bo->ttm, gfp_flags);
out: out:
/** /*
*
* Unreserve without putting on LRU to avoid swapping out an * Unreserve without putting on LRU to avoid swapping out an
* already swapped buffer. * already swapped buffer.
*/ */
...@@ -1293,7 +1269,6 @@ int ttm_bo_swapout(struct ttm_operation_ctx *ctx, gfp_t gfp_flags) ...@@ -1293,7 +1269,6 @@ int ttm_bo_swapout(struct ttm_operation_ctx *ctx, gfp_t gfp_flags)
ttm_bo_put(bo); ttm_bo_put(bo);
return ret; return ret;
} }
EXPORT_SYMBOL(ttm_bo_swapout);
void ttm_bo_tt_destroy(struct ttm_buffer_object *bo) void ttm_bo_tt_destroy(struct ttm_buffer_object *bo)
{ {
......
...@@ -102,6 +102,35 @@ static int ttm_global_init(void) ...@@ -102,6 +102,35 @@ static int ttm_global_init(void)
return ret; return ret;
} }
/**
* A buffer object shrink method that tries to swap out the first
* buffer object on the global::swap_lru list.
*/
int ttm_global_swapout(struct ttm_operation_ctx *ctx, gfp_t gfp_flags)
{
struct ttm_global *glob = &ttm_glob;
struct ttm_buffer_object *bo;
unsigned i;
int ret;
spin_lock(&glob->lru_lock);
for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) {
list_for_each_entry(bo, &glob->swap_lru[i], swap) {
uint32_t num_pages = bo->ttm->num_pages;
ret = ttm_bo_swapout(bo, ctx, gfp_flags);
/* ttm_bo_swapout has dropped the lru_lock */
if (!ret)
return num_pages;
if (ret != -EBUSY)
return ret;
}
}
spin_unlock(&glob->lru_lock);
return 0;
}
EXPORT_SYMBOL(ttm_global_swapout);
static void ttm_init_sysman(struct ttm_device *bdev) static void ttm_init_sysman(struct ttm_device *bdev)
{ {
struct ttm_resource_manager *man = &bdev->sysman; struct ttm_resource_manager *man = &bdev->sysman;
......
...@@ -369,7 +369,7 @@ static unsigned long ttm_tt_shrinker_scan(struct shrinker *shrink, ...@@ -369,7 +369,7 @@ static unsigned long ttm_tt_shrinker_scan(struct shrinker *shrink,
}; };
int ret; int ret;
ret = ttm_bo_swapout(&ctx, GFP_NOFS); ret = ttm_global_swapout(&ctx, GFP_NOFS);
return ret < 0 ? SHRINK_EMPTY : ret; return ret < 0 ? SHRINK_EMPTY : ret;
} }
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <drm/drm_device.h> #include <drm/drm_device.h>
#include <drm/drm_file.h> #include <drm/drm_file.h>
#include <drm/ttm/ttm_device.h>
#include "ttm_memory.h" #include "ttm_memory.h"
...@@ -277,7 +278,7 @@ static void ttm_shrink(struct ttm_mem_global *glob, bool from_wq, ...@@ -277,7 +278,7 @@ static void ttm_shrink(struct ttm_mem_global *glob, bool from_wq,
while (ttm_zones_above_swap_target(glob, from_wq, extra)) { while (ttm_zones_above_swap_target(glob, from_wq, extra)) {
spin_unlock(&glob->lock); spin_unlock(&glob->lock);
ret = ttm_bo_swapout(ctx, GFP_KERNEL); ret = ttm_global_swapout(ctx, GFP_KERNEL);
spin_lock(&glob->lock); spin_lock(&glob->lock);
if (unlikely(ret < 0)) if (unlikely(ret < 0))
break; break;
......
...@@ -1371,7 +1371,7 @@ static int vmw_pm_freeze(struct device *kdev) ...@@ -1371,7 +1371,7 @@ static int vmw_pm_freeze(struct device *kdev)
vmw_execbuf_release_pinned_bo(dev_priv); vmw_execbuf_release_pinned_bo(dev_priv);
vmw_resource_evict_all(dev_priv); vmw_resource_evict_all(dev_priv);
vmw_release_device_early(dev_priv); vmw_release_device_early(dev_priv);
while (ttm_bo_swapout(&ctx, GFP_KERNEL) > 0); while (ttm_global_swapout(&ctx, GFP_KERNEL) > 0);
if (dev_priv->enable_fb) if (dev_priv->enable_fb)
vmw_fifo_resource_dec(dev_priv); vmw_fifo_resource_dec(dev_priv);
if (atomic_read(&dev_priv->num_fifo_resources) != 0) { if (atomic_read(&dev_priv->num_fifo_resources) != 0) {
......
...@@ -560,7 +560,8 @@ ssize_t ttm_bo_io(struct ttm_device *bdev, struct file *filp, ...@@ -560,7 +560,8 @@ ssize_t ttm_bo_io(struct ttm_device *bdev, struct file *filp,
const char __user *wbuf, char __user *rbuf, const char __user *wbuf, char __user *rbuf,
size_t count, loff_t *f_pos, bool write); size_t count, loff_t *f_pos, bool write);
int ttm_bo_swapout(struct ttm_operation_ctx *ctx, gfp_t gfp_flags); int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx,
gfp_t gfp_flags);
/** /**
* ttm_bo_uses_embedded_gem_object - check if the given bo uses the * ttm_bo_uses_embedded_gem_object - check if the given bo uses the
......
...@@ -297,6 +297,8 @@ struct ttm_device { ...@@ -297,6 +297,8 @@ struct ttm_device {
struct delayed_work wq; struct delayed_work wq;
}; };
int ttm_global_swapout(struct ttm_operation_ctx *ctx, gfp_t gfp_flags);
static inline struct ttm_resource_manager * static inline struct ttm_resource_manager *
ttm_manager_type(struct ttm_device *bdev, int mem_type) ttm_manager_type(struct ttm_device *bdev, int mem_type)
{ {
......
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