LCOV - code coverage report
Current view: top level - drivers/gpu/drm/ttm - ttm_bo.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 441 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 33 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 OR MIT */
       2             : /**************************************************************************
       3             :  *
       4             :  * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
       5             :  * All Rights Reserved.
       6             :  *
       7             :  * Permission is hereby granted, free of charge, to any person obtaining a
       8             :  * copy of this software and associated documentation files (the
       9             :  * "Software"), to deal in the Software without restriction, including
      10             :  * without limitation the rights to use, copy, modify, merge, publish,
      11             :  * distribute, sub license, and/or sell copies of the Software, and to
      12             :  * permit persons to whom the Software is furnished to do so, subject to
      13             :  * the following conditions:
      14             :  *
      15             :  * The above copyright notice and this permission notice (including the
      16             :  * next paragraph) shall be included in all copies or substantial portions
      17             :  * of the Software.
      18             :  *
      19             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      20             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      21             :  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
      22             :  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
      23             :  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
      24             :  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
      25             :  * USE OR OTHER DEALINGS IN THE SOFTWARE.
      26             :  *
      27             :  **************************************************************************/
      28             : /*
      29             :  * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
      30             :  */
      31             : 
      32             : #define pr_fmt(fmt) "[TTM] " fmt
      33             : 
      34             : #include <drm/ttm/ttm_bo_driver.h>
      35             : #include <drm/ttm/ttm_placement.h>
      36             : #include <linux/jiffies.h>
      37             : #include <linux/slab.h>
      38             : #include <linux/sched.h>
      39             : #include <linux/mm.h>
      40             : #include <linux/file.h>
      41             : #include <linux/module.h>
      42             : #include <linux/atomic.h>
      43             : #include <linux/dma-resv.h>
      44             : 
      45             : #include "ttm_module.h"
      46             : 
      47             : /* default destructor */
      48           0 : static void ttm_bo_default_destroy(struct ttm_buffer_object *bo)
      49             : {
      50           0 :         kfree(bo);
      51           0 : }
      52             : 
      53           0 : static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo,
      54             :                                         struct ttm_placement *placement)
      55             : {
      56           0 :         struct drm_printer p = drm_debug_printer(TTM_PFX);
      57             :         struct ttm_resource_manager *man;
      58             :         int i, mem_type;
      59             : 
      60           0 :         drm_printf(&p, "No space for %p (%lu pages, %zuK, %zuM)\n",
      61           0 :                    bo, bo->resource->num_pages, bo->base.size >> 10,
      62           0 :                    bo->base.size >> 20);
      63           0 :         for (i = 0; i < placement->num_placement; i++) {
      64           0 :                 mem_type = placement->placement[i].mem_type;
      65           0 :                 drm_printf(&p, "  placement[%d]=0x%08X (%d)\n",
      66             :                            i, placement->placement[i].flags, mem_type);
      67           0 :                 man = ttm_manager_type(bo->bdev, mem_type);
      68           0 :                 ttm_resource_manager_debug(man, &p);
      69             :         }
      70           0 : }
      71             : 
      72             : /**
      73             :  * ttm_bo_move_to_lru_tail
      74             :  *
      75             :  * @bo: The buffer object.
      76             :  *
      77             :  * Move this BO to the tail of all lru lists used to lookup and reserve an
      78             :  * object. This function must be called with struct ttm_global::lru_lock
      79             :  * held, and is used to make a BO less likely to be considered for eviction.
      80             :  */
      81           0 : void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo)
      82             : {
      83             :         dma_resv_assert_held(bo->base.resv);
      84             : 
      85           0 :         if (bo->resource)
      86           0 :                 ttm_resource_move_to_lru_tail(bo->resource);
      87           0 : }
      88             : EXPORT_SYMBOL(ttm_bo_move_to_lru_tail);
      89             : 
      90             : /**
      91             :  * ttm_bo_set_bulk_move - update BOs bulk move object
      92             :  *
      93             :  * @bo: The buffer object.
      94             :  *
      95             :  * Update the BOs bulk move object, making sure that resources are added/removed
      96             :  * as well. A bulk move allows to move many resource on the LRU at once,
      97             :  * resulting in much less overhead of maintaining the LRU.
      98             :  * The only requirement is that the resources stay together on the LRU and are
      99             :  * never separated. This is enforces by setting the bulk_move structure on a BO.
     100             :  * ttm_lru_bulk_move_tail() should be used to move all resources to the tail of
     101             :  * their LRU list.
     102             :  */
     103           0 : void ttm_bo_set_bulk_move(struct ttm_buffer_object *bo,
     104             :                           struct ttm_lru_bulk_move *bulk)
     105             : {
     106             :         dma_resv_assert_held(bo->base.resv);
     107             : 
     108           0 :         if (bo->bulk_move == bulk)
     109             :                 return;
     110             : 
     111           0 :         spin_lock(&bo->bdev->lru_lock);
     112           0 :         if (bo->resource)
     113           0 :                 ttm_resource_del_bulk_move(bo->resource, bo);
     114           0 :         bo->bulk_move = bulk;
     115           0 :         if (bo->resource)
     116           0 :                 ttm_resource_add_bulk_move(bo->resource, bo);
     117           0 :         spin_unlock(&bo->bdev->lru_lock);
     118             : }
     119             : EXPORT_SYMBOL(ttm_bo_set_bulk_move);
     120             : 
     121           0 : static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
     122             :                                   struct ttm_resource *mem, bool evict,
     123             :                                   struct ttm_operation_ctx *ctx,
     124             :                                   struct ttm_place *hop)
     125             : {
     126             :         struct ttm_resource_manager *old_man, *new_man;
     127           0 :         struct ttm_device *bdev = bo->bdev;
     128             :         int ret;
     129             : 
     130           0 :         old_man = ttm_manager_type(bdev, bo->resource->mem_type);
     131           0 :         new_man = ttm_manager_type(bdev, mem->mem_type);
     132             : 
     133           0 :         ttm_bo_unmap_virtual(bo);
     134             : 
     135             :         /*
     136             :          * Create and bind a ttm if required.
     137             :          */
     138             : 
     139           0 :         if (new_man->use_tt) {
     140             :                 /* Zero init the new TTM structure if the old location should
     141             :                  * have used one as well.
     142             :                  */
     143           0 :                 ret = ttm_tt_create(bo, old_man->use_tt);
     144           0 :                 if (ret)
     145             :                         goto out_err;
     146             : 
     147           0 :                 if (mem->mem_type != TTM_PL_SYSTEM) {
     148           0 :                         ret = ttm_tt_populate(bo->bdev, bo->ttm, ctx);
     149           0 :                         if (ret)
     150             :                                 goto out_err;
     151             :                 }
     152             :         }
     153             : 
     154           0 :         ret = dma_resv_reserve_fences(bo->base.resv, 1);
     155           0 :         if (ret)
     156             :                 goto out_err;
     157             : 
     158           0 :         ret = bdev->funcs->move(bo, evict, ctx, mem, hop);
     159           0 :         if (ret) {
     160           0 :                 if (ret == -EMULTIHOP)
     161             :                         return ret;
     162             :                 goto out_err;
     163             :         }
     164             : 
     165           0 :         ctx->bytes_moved += bo->base.size;
     166           0 :         return 0;
     167             : 
     168             : out_err:
     169           0 :         new_man = ttm_manager_type(bdev, bo->resource->mem_type);
     170           0 :         if (!new_man->use_tt)
     171           0 :                 ttm_bo_tt_destroy(bo);
     172             : 
     173             :         return ret;
     174             : }
     175             : 
     176             : /*
     177             :  * Call bo::reserved.
     178             :  * Will release GPU memory type usage on destruction.
     179             :  * This is the place to put in driver specific hooks to release
     180             :  * driver private resources.
     181             :  * Will release the bo::reserved lock.
     182             :  */
     183             : 
     184           0 : static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo)
     185             : {
     186           0 :         if (bo->bdev->funcs->delete_mem_notify)
     187           0 :                 bo->bdev->funcs->delete_mem_notify(bo);
     188             : 
     189           0 :         ttm_bo_tt_destroy(bo);
     190           0 :         ttm_resource_free(bo, &bo->resource);
     191           0 : }
     192             : 
     193           0 : static int ttm_bo_individualize_resv(struct ttm_buffer_object *bo)
     194             : {
     195             :         int r;
     196             : 
     197           0 :         if (bo->base.resv == &bo->base._resv)
     198             :                 return 0;
     199             : 
     200           0 :         BUG_ON(!dma_resv_trylock(&bo->base._resv));
     201             : 
     202           0 :         r = dma_resv_copy_fences(&bo->base._resv, bo->base.resv);
     203           0 :         dma_resv_unlock(&bo->base._resv);
     204           0 :         if (r)
     205             :                 return r;
     206             : 
     207           0 :         if (bo->type != ttm_bo_type_sg) {
     208             :                 /* This works because the BO is about to be destroyed and nobody
     209             :                  * reference it any more. The only tricky case is the trylock on
     210             :                  * the resv object while holding the lru_lock.
     211             :                  */
     212           0 :                 spin_lock(&bo->bdev->lru_lock);
     213           0 :                 bo->base.resv = &bo->base._resv;
     214           0 :                 spin_unlock(&bo->bdev->lru_lock);
     215             :         }
     216             : 
     217             :         return r;
     218             : }
     219             : 
     220           0 : static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo)
     221             : {
     222           0 :         struct dma_resv *resv = &bo->base._resv;
     223             :         struct dma_resv_iter cursor;
     224             :         struct dma_fence *fence;
     225             : 
     226             :         dma_resv_iter_begin(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP);
     227           0 :         dma_resv_for_each_fence_unlocked(&cursor, fence) {
     228           0 :                 if (!fence->ops->signaled)
     229           0 :                         dma_fence_enable_sw_signaling(fence);
     230             :         }
     231           0 :         dma_resv_iter_end(&cursor);
     232           0 : }
     233             : 
     234             : /**
     235             :  * ttm_bo_cleanup_refs
     236             :  * If bo idle, remove from lru lists, and unref.
     237             :  * If not idle, block if possible.
     238             :  *
     239             :  * Must be called with lru_lock and reservation held, this function
     240             :  * will drop the lru lock and optionally the reservation lock before returning.
     241             :  *
     242             :  * @bo:                    The buffer object to clean-up
     243             :  * @interruptible:         Any sleeps should occur interruptibly.
     244             :  * @no_wait_gpu:           Never wait for gpu. Return -EBUSY instead.
     245             :  * @unlock_resv:           Unlock the reservation lock as well.
     246             :  */
     247             : 
     248           0 : static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,
     249             :                                bool interruptible, bool no_wait_gpu,
     250             :                                bool unlock_resv)
     251             : {
     252           0 :         struct dma_resv *resv = &bo->base._resv;
     253             :         int ret;
     254             : 
     255           0 :         if (dma_resv_test_signaled(resv, DMA_RESV_USAGE_BOOKKEEP))
     256             :                 ret = 0;
     257             :         else
     258           0 :                 ret = -EBUSY;
     259             : 
     260           0 :         if (ret && !no_wait_gpu) {
     261             :                 long lret;
     262             : 
     263           0 :                 if (unlock_resv)
     264           0 :                         dma_resv_unlock(bo->base.resv);
     265           0 :                 spin_unlock(&bo->bdev->lru_lock);
     266             : 
     267           0 :                 lret = dma_resv_wait_timeout(resv, DMA_RESV_USAGE_BOOKKEEP,
     268             :                                              interruptible,
     269             :                                              30 * HZ);
     270             : 
     271           0 :                 if (lret < 0)
     272           0 :                         return lret;
     273           0 :                 else if (lret == 0)
     274             :                         return -EBUSY;
     275             : 
     276           0 :                 spin_lock(&bo->bdev->lru_lock);
     277           0 :                 if (unlock_resv && !dma_resv_trylock(bo->base.resv)) {
     278             :                         /*
     279             :                          * We raced, and lost, someone else holds the reservation now,
     280             :                          * and is probably busy in ttm_bo_cleanup_memtype_use.
     281             :                          *
     282             :                          * Even if it's not the case, because we finished waiting any
     283             :                          * delayed destruction would succeed, so just return success
     284             :                          * here.
     285             :                          */
     286           0 :                         spin_unlock(&bo->bdev->lru_lock);
     287           0 :                         return 0;
     288             :                 }
     289             :                 ret = 0;
     290             :         }
     291             : 
     292           0 :         if (ret || unlikely(list_empty(&bo->ddestroy))) {
     293           0 :                 if (unlock_resv)
     294           0 :                         dma_resv_unlock(bo->base.resv);
     295           0 :                 spin_unlock(&bo->bdev->lru_lock);
     296           0 :                 return ret;
     297             :         }
     298             : 
     299           0 :         list_del_init(&bo->ddestroy);
     300           0 :         spin_unlock(&bo->bdev->lru_lock);
     301           0 :         ttm_bo_cleanup_memtype_use(bo);
     302             : 
     303           0 :         if (unlock_resv)
     304           0 :                 dma_resv_unlock(bo->base.resv);
     305             : 
     306           0 :         ttm_bo_put(bo);
     307             : 
     308           0 :         return 0;
     309             : }
     310             : 
     311             : /*
     312             :  * Traverse the delayed list, and call ttm_bo_cleanup_refs on all
     313             :  * encountered buffers.
     314             :  */
     315           0 : bool ttm_bo_delayed_delete(struct ttm_device *bdev, bool remove_all)
     316             : {
     317             :         struct list_head removed;
     318             :         bool empty;
     319             : 
     320           0 :         INIT_LIST_HEAD(&removed);
     321             : 
     322           0 :         spin_lock(&bdev->lru_lock);
     323           0 :         while (!list_empty(&bdev->ddestroy)) {
     324             :                 struct ttm_buffer_object *bo;
     325             : 
     326           0 :                 bo = list_first_entry(&bdev->ddestroy, struct ttm_buffer_object,
     327             :                                       ddestroy);
     328           0 :                 list_move_tail(&bo->ddestroy, &removed);
     329           0 :                 if (!ttm_bo_get_unless_zero(bo))
     330           0 :                         continue;
     331             : 
     332           0 :                 if (remove_all || bo->base.resv != &bo->base._resv) {
     333           0 :                         spin_unlock(&bdev->lru_lock);
     334           0 :                         dma_resv_lock(bo->base.resv, NULL);
     335             : 
     336           0 :                         spin_lock(&bdev->lru_lock);
     337           0 :                         ttm_bo_cleanup_refs(bo, false, !remove_all, true);
     338             : 
     339           0 :                 } else if (dma_resv_trylock(bo->base.resv)) {
     340           0 :                         ttm_bo_cleanup_refs(bo, false, !remove_all, true);
     341             :                 } else {
     342           0 :                         spin_unlock(&bdev->lru_lock);
     343             :                 }
     344             : 
     345           0 :                 ttm_bo_put(bo);
     346           0 :                 spin_lock(&bdev->lru_lock);
     347             :         }
     348           0 :         list_splice_tail(&removed, &bdev->ddestroy);
     349           0 :         empty = list_empty(&bdev->ddestroy);
     350           0 :         spin_unlock(&bdev->lru_lock);
     351             : 
     352           0 :         return empty;
     353             : }
     354             : 
     355           0 : static void ttm_bo_release(struct kref *kref)
     356             : {
     357           0 :         struct ttm_buffer_object *bo =
     358           0 :             container_of(kref, struct ttm_buffer_object, kref);
     359           0 :         struct ttm_device *bdev = bo->bdev;
     360             :         int ret;
     361             : 
     362           0 :         WARN_ON_ONCE(bo->pin_count);
     363           0 :         WARN_ON_ONCE(bo->bulk_move);
     364             : 
     365           0 :         if (!bo->deleted) {
     366           0 :                 ret = ttm_bo_individualize_resv(bo);
     367           0 :                 if (ret) {
     368             :                         /* Last resort, if we fail to allocate memory for the
     369             :                          * fences block for the BO to become idle
     370             :                          */
     371           0 :                         dma_resv_wait_timeout(bo->base.resv,
     372             :                                               DMA_RESV_USAGE_BOOKKEEP, false,
     373             :                                               30 * HZ);
     374             :                 }
     375             : 
     376           0 :                 if (bo->bdev->funcs->release_notify)
     377           0 :                         bo->bdev->funcs->release_notify(bo);
     378             : 
     379           0 :                 drm_vma_offset_remove(bdev->vma_manager, &bo->base.vma_node);
     380           0 :                 ttm_mem_io_free(bdev, bo->resource);
     381             :         }
     382             : 
     383           0 :         if (!dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP) ||
     384           0 :             !dma_resv_trylock(bo->base.resv)) {
     385             :                 /* The BO is not idle, resurrect it for delayed destroy */
     386           0 :                 ttm_bo_flush_all_fences(bo);
     387           0 :                 bo->deleted = true;
     388             : 
     389           0 :                 spin_lock(&bo->bdev->lru_lock);
     390             : 
     391             :                 /*
     392             :                  * Make pinned bos immediately available to
     393             :                  * shrinkers, now that they are queued for
     394             :                  * destruction.
     395             :                  *
     396             :                  * FIXME: QXL is triggering this. Can be removed when the
     397             :                  * driver is fixed.
     398             :                  */
     399           0 :                 if (bo->pin_count) {
     400           0 :                         bo->pin_count = 0;
     401           0 :                         ttm_resource_move_to_lru_tail(bo->resource);
     402             :                 }
     403             : 
     404           0 :                 kref_init(&bo->kref);
     405           0 :                 list_add_tail(&bo->ddestroy, &bdev->ddestroy);
     406           0 :                 spin_unlock(&bo->bdev->lru_lock);
     407             : 
     408           0 :                 schedule_delayed_work(&bdev->wq,
     409             :                                       ((HZ / 100) < 1) ? 1 : HZ / 100);
     410             :                 return;
     411             :         }
     412             : 
     413           0 :         spin_lock(&bo->bdev->lru_lock);
     414           0 :         list_del(&bo->ddestroy);
     415           0 :         spin_unlock(&bo->bdev->lru_lock);
     416             : 
     417           0 :         ttm_bo_cleanup_memtype_use(bo);
     418           0 :         dma_resv_unlock(bo->base.resv);
     419             : 
     420           0 :         atomic_dec(&ttm_glob.bo_count);
     421           0 :         bo->destroy(bo);
     422             : }
     423             : 
     424           0 : void ttm_bo_put(struct ttm_buffer_object *bo)
     425             : {
     426           0 :         kref_put(&bo->kref, ttm_bo_release);
     427           0 : }
     428             : EXPORT_SYMBOL(ttm_bo_put);
     429             : 
     430           0 : int ttm_bo_lock_delayed_workqueue(struct ttm_device *bdev)
     431             : {
     432           0 :         return cancel_delayed_work_sync(&bdev->wq);
     433             : }
     434             : EXPORT_SYMBOL(ttm_bo_lock_delayed_workqueue);
     435             : 
     436           0 : void ttm_bo_unlock_delayed_workqueue(struct ttm_device *bdev, int resched)
     437             : {
     438           0 :         if (resched)
     439           0 :                 schedule_delayed_work(&bdev->wq,
     440             :                                       ((HZ / 100) < 1) ? 1 : HZ / 100);
     441           0 : }
     442             : EXPORT_SYMBOL(ttm_bo_unlock_delayed_workqueue);
     443             : 
     444           0 : static int ttm_bo_bounce_temp_buffer(struct ttm_buffer_object *bo,
     445             :                                      struct ttm_resource **mem,
     446             :                                      struct ttm_operation_ctx *ctx,
     447             :                                      struct ttm_place *hop)
     448             : {
     449             :         struct ttm_placement hop_placement;
     450             :         struct ttm_resource *hop_mem;
     451             :         int ret;
     452             : 
     453           0 :         hop_placement.num_placement = hop_placement.num_busy_placement = 1;
     454           0 :         hop_placement.placement = hop_placement.busy_placement = hop;
     455             : 
     456             :         /* find space in the bounce domain */
     457           0 :         ret = ttm_bo_mem_space(bo, &hop_placement, &hop_mem, ctx);
     458           0 :         if (ret)
     459             :                 return ret;
     460             :         /* move to the bounce domain */
     461           0 :         ret = ttm_bo_handle_move_mem(bo, hop_mem, false, ctx, NULL);
     462           0 :         if (ret) {
     463           0 :                 ttm_resource_free(bo, &hop_mem);
     464             :                 return ret;
     465             :         }
     466             :         return 0;
     467             : }
     468             : 
     469           0 : static int ttm_bo_evict(struct ttm_buffer_object *bo,
     470             :                         struct ttm_operation_ctx *ctx)
     471             : {
     472           0 :         struct ttm_device *bdev = bo->bdev;
     473             :         struct ttm_resource *evict_mem;
     474             :         struct ttm_placement placement;
     475             :         struct ttm_place hop;
     476           0 :         int ret = 0;
     477             : 
     478           0 :         memset(&hop, 0, sizeof(hop));
     479             : 
     480             :         dma_resv_assert_held(bo->base.resv);
     481             : 
     482           0 :         placement.num_placement = 0;
     483           0 :         placement.num_busy_placement = 0;
     484           0 :         bdev->funcs->evict_flags(bo, &placement);
     485             : 
     486           0 :         if (!placement.num_placement && !placement.num_busy_placement) {
     487           0 :                 ret = ttm_bo_wait(bo, true, false);
     488           0 :                 if (ret)
     489             :                         return ret;
     490             : 
     491             :                 /*
     492             :                  * Since we've already synced, this frees backing store
     493             :                  * immediately.
     494             :                  */
     495           0 :                 return ttm_bo_pipeline_gutting(bo);
     496             :         }
     497             : 
     498           0 :         ret = ttm_bo_mem_space(bo, &placement, &evict_mem, ctx);
     499           0 :         if (ret) {
     500           0 :                 if (ret != -ERESTARTSYS) {
     501           0 :                         pr_err("Failed to find memory space for buffer 0x%p eviction\n",
     502             :                                bo);
     503           0 :                         ttm_bo_mem_space_debug(bo, &placement);
     504             :                 }
     505             :                 goto out;
     506             :         }
     507             : 
     508             : bounce:
     509           0 :         ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop);
     510           0 :         if (ret == -EMULTIHOP) {
     511           0 :                 ret = ttm_bo_bounce_temp_buffer(bo, &evict_mem, ctx, &hop);
     512           0 :                 if (ret) {
     513           0 :                         pr_err("Buffer eviction failed\n");
     514           0 :                         ttm_resource_free(bo, &evict_mem);
     515           0 :                         goto out;
     516             :                 }
     517             :                 /* try and move to final place now. */
     518             :                 goto bounce;
     519             :         }
     520             : out:
     521             :         return ret;
     522             : }
     523             : 
     524           0 : bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
     525             :                               const struct ttm_place *place)
     526             : {
     527             :         dma_resv_assert_held(bo->base.resv);
     528           0 :         if (bo->resource->mem_type == TTM_PL_SYSTEM)
     529             :                 return true;
     530             : 
     531             :         /* Don't evict this BO if it's outside of the
     532             :          * requested placement range
     533             :          */
     534           0 :         if (place->fpfn >= (bo->resource->start + bo->resource->num_pages) ||
     535           0 :             (place->lpfn && place->lpfn <= bo->resource->start))
     536             :                 return false;
     537             : 
     538           0 :         return true;
     539             : }
     540             : EXPORT_SYMBOL(ttm_bo_eviction_valuable);
     541             : 
     542             : /*
     543             :  * Check the target bo is allowable to be evicted or swapout, including cases:
     544             :  *
     545             :  * a. if share same reservation object with ctx->resv, have assumption
     546             :  * reservation objects should already be locked, so not lock again and
     547             :  * return true directly when either the opreation allow_reserved_eviction
     548             :  * or the target bo already is in delayed free list;
     549             :  *
     550             :  * b. Otherwise, trylock it.
     551             :  */
     552           0 : static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo,
     553             :                                            struct ttm_operation_ctx *ctx,
     554             :                                            const struct ttm_place *place,
     555             :                                            bool *locked, bool *busy)
     556             : {
     557           0 :         bool ret = false;
     558             : 
     559           0 :         if (bo->base.resv == ctx->resv) {
     560             :                 dma_resv_assert_held(bo->base.resv);
     561           0 :                 if (ctx->allow_res_evict)
     562           0 :                         ret = true;
     563           0 :                 *locked = false;
     564           0 :                 if (busy)
     565           0 :                         *busy = false;
     566             :         } else {
     567           0 :                 ret = dma_resv_trylock(bo->base.resv);
     568           0 :                 *locked = ret;
     569           0 :                 if (busy)
     570           0 :                         *busy = !ret;
     571             :         }
     572             : 
     573           0 :         if (ret && place && (bo->resource->mem_type != place->mem_type ||
     574           0 :                 !bo->bdev->funcs->eviction_valuable(bo, place))) {
     575           0 :                 ret = false;
     576           0 :                 if (*locked) {
     577           0 :                         dma_resv_unlock(bo->base.resv);
     578           0 :                         *locked = false;
     579             :                 }
     580             :         }
     581             : 
     582           0 :         return ret;
     583             : }
     584             : 
     585             : /**
     586             :  * ttm_mem_evict_wait_busy - wait for a busy BO to become available
     587             :  *
     588             :  * @busy_bo: BO which couldn't be locked with trylock
     589             :  * @ctx: operation context
     590             :  * @ticket: acquire ticket
     591             :  *
     592             :  * Try to lock a busy buffer object to avoid failing eviction.
     593             :  */
     594           0 : static int ttm_mem_evict_wait_busy(struct ttm_buffer_object *busy_bo,
     595             :                                    struct ttm_operation_ctx *ctx,
     596             :                                    struct ww_acquire_ctx *ticket)
     597             : {
     598             :         int r;
     599             : 
     600           0 :         if (!busy_bo || !ticket)
     601             :                 return -EBUSY;
     602             : 
     603           0 :         if (ctx->interruptible)
     604           0 :                 r = dma_resv_lock_interruptible(busy_bo->base.resv,
     605             :                                                           ticket);
     606             :         else
     607           0 :                 r = dma_resv_lock(busy_bo->base.resv, ticket);
     608             : 
     609             :         /*
     610             :          * TODO: It would be better to keep the BO locked until allocation is at
     611             :          * least tried one more time, but that would mean a much larger rework
     612             :          * of TTM.
     613             :          */
     614           0 :         if (!r)
     615           0 :                 dma_resv_unlock(busy_bo->base.resv);
     616             : 
     617           0 :         return r == -EDEADLK ? -EBUSY : r;
     618             : }
     619             : 
     620           0 : int ttm_mem_evict_first(struct ttm_device *bdev,
     621             :                         struct ttm_resource_manager *man,
     622             :                         const struct ttm_place *place,
     623             :                         struct ttm_operation_ctx *ctx,
     624             :                         struct ww_acquire_ctx *ticket)
     625             : {
     626           0 :         struct ttm_buffer_object *bo = NULL, *busy_bo = NULL;
     627             :         struct ttm_resource_cursor cursor;
     628             :         struct ttm_resource *res;
     629           0 :         bool locked = false;
     630             :         int ret;
     631             : 
     632           0 :         spin_lock(&bdev->lru_lock);
     633           0 :         ttm_resource_manager_for_each_res(man, &cursor, res) {
     634             :                 bool busy;
     635             : 
     636           0 :                 if (!ttm_bo_evict_swapout_allowable(res->bo, ctx, place,
     637             :                                                     &locked, &busy)) {
     638           0 :                         if (busy && !busy_bo && ticket !=
     639           0 :                             dma_resv_locking_ctx(res->bo->base.resv))
     640           0 :                                 busy_bo = res->bo;
     641           0 :                         continue;
     642             :                 }
     643             : 
     644           0 :                 if (ttm_bo_get_unless_zero(res->bo)) {
     645           0 :                         bo = res->bo;
     646           0 :                         break;
     647             :                 }
     648           0 :                 if (locked)
     649           0 :                         dma_resv_unlock(res->bo->base.resv);
     650             :         }
     651             : 
     652           0 :         if (!bo) {
     653           0 :                 if (busy_bo && !ttm_bo_get_unless_zero(busy_bo))
     654           0 :                         busy_bo = NULL;
     655           0 :                 spin_unlock(&bdev->lru_lock);
     656           0 :                 ret = ttm_mem_evict_wait_busy(busy_bo, ctx, ticket);
     657           0 :                 if (busy_bo)
     658             :                         ttm_bo_put(busy_bo);
     659             :                 return ret;
     660             :         }
     661             : 
     662           0 :         if (bo->deleted) {
     663           0 :                 ret = ttm_bo_cleanup_refs(bo, ctx->interruptible,
     664           0 :                                           ctx->no_wait_gpu, locked);
     665           0 :                 ttm_bo_put(bo);
     666           0 :                 return ret;
     667             :         }
     668             : 
     669           0 :         spin_unlock(&bdev->lru_lock);
     670             : 
     671           0 :         ret = ttm_bo_evict(bo, ctx);
     672           0 :         if (locked)
     673           0 :                 ttm_bo_unreserve(bo);
     674             :         else
     675           0 :                 ttm_bo_move_to_lru_tail_unlocked(bo);
     676             : 
     677           0 :         ttm_bo_put(bo);
     678           0 :         return ret;
     679             : }
     680             : 
     681             : /**
     682             :  * ttm_bo_pin - Pin the buffer object.
     683             :  * @bo: The buffer object to pin
     684             :  *
     685             :  * Make sure the buffer is not evicted any more during memory pressure.
     686             :  * @bo must be unpinned again by calling ttm_bo_unpin().
     687             :  */
     688           0 : void ttm_bo_pin(struct ttm_buffer_object *bo)
     689             : {
     690             :         dma_resv_assert_held(bo->base.resv);
     691           0 :         WARN_ON_ONCE(!kref_read(&bo->kref));
     692           0 :         spin_lock(&bo->bdev->lru_lock);
     693           0 :         if (bo->resource)
     694           0 :                 ttm_resource_del_bulk_move(bo->resource, bo);
     695           0 :         ++bo->pin_count;
     696           0 :         spin_unlock(&bo->bdev->lru_lock);
     697           0 : }
     698             : EXPORT_SYMBOL(ttm_bo_pin);
     699             : 
     700             : /**
     701             :  * ttm_bo_unpin - Unpin the buffer object.
     702             :  * @bo: The buffer object to unpin
     703             :  *
     704             :  * Allows the buffer object to be evicted again during memory pressure.
     705             :  */
     706           0 : void ttm_bo_unpin(struct ttm_buffer_object *bo)
     707             : {
     708             :         dma_resv_assert_held(bo->base.resv);
     709           0 :         WARN_ON_ONCE(!kref_read(&bo->kref));
     710           0 :         if (WARN_ON_ONCE(!bo->pin_count))
     711             :                 return;
     712             : 
     713           0 :         spin_lock(&bo->bdev->lru_lock);
     714           0 :         --bo->pin_count;
     715           0 :         if (bo->resource)
     716           0 :                 ttm_resource_add_bulk_move(bo->resource, bo);
     717           0 :         spin_unlock(&bo->bdev->lru_lock);
     718             : }
     719             : EXPORT_SYMBOL(ttm_bo_unpin);
     720             : 
     721             : /*
     722             :  * Add the last move fence to the BO as kernel dependency and reserve a new
     723             :  * fence slot.
     724             :  */
     725           0 : static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
     726             :                                  struct ttm_resource_manager *man,
     727             :                                  struct ttm_resource *mem,
     728             :                                  bool no_wait_gpu)
     729             : {
     730             :         struct dma_fence *fence;
     731             :         int ret;
     732             : 
     733           0 :         spin_lock(&man->move_lock);
     734           0 :         fence = dma_fence_get(man->move);
     735           0 :         spin_unlock(&man->move_lock);
     736             : 
     737           0 :         if (!fence)
     738             :                 return 0;
     739             : 
     740           0 :         if (no_wait_gpu) {
     741           0 :                 ret = dma_fence_is_signaled(fence) ? 0 : -EBUSY;
     742           0 :                 dma_fence_put(fence);
     743           0 :                 return ret;
     744             :         }
     745             : 
     746           0 :         dma_resv_add_fence(bo->base.resv, fence, DMA_RESV_USAGE_KERNEL);
     747             : 
     748           0 :         ret = dma_resv_reserve_fences(bo->base.resv, 1);
     749           0 :         dma_fence_put(fence);
     750           0 :         return ret;
     751             : }
     752             : 
     753             : /*
     754             :  * Repeatedly evict memory from the LRU for @mem_type until we create enough
     755             :  * space, or we've evicted everything and there isn't enough space.
     756             :  */
     757           0 : static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
     758             :                                   const struct ttm_place *place,
     759             :                                   struct ttm_resource **mem,
     760             :                                   struct ttm_operation_ctx *ctx)
     761             : {
     762           0 :         struct ttm_device *bdev = bo->bdev;
     763             :         struct ttm_resource_manager *man;
     764             :         struct ww_acquire_ctx *ticket;
     765             :         int ret;
     766             : 
     767           0 :         man = ttm_manager_type(bdev, place->mem_type);
     768           0 :         ticket = dma_resv_locking_ctx(bo->base.resv);
     769             :         do {
     770           0 :                 ret = ttm_resource_alloc(bo, place, mem);
     771           0 :                 if (likely(!ret))
     772             :                         break;
     773           0 :                 if (unlikely(ret != -ENOSPC))
     774             :                         return ret;
     775           0 :                 ret = ttm_mem_evict_first(bdev, man, place, ctx,
     776             :                                           ticket);
     777           0 :                 if (unlikely(ret != 0))
     778             :                         return ret;
     779             :         } while (1);
     780             : 
     781           0 :         return ttm_bo_add_move_fence(bo, man, *mem, ctx->no_wait_gpu);
     782             : }
     783             : 
     784             : /*
     785             :  * Creates space for memory region @mem according to its type.
     786             :  *
     787             :  * This function first searches for free space in compatible memory types in
     788             :  * the priority order defined by the driver.  If free space isn't found, then
     789             :  * ttm_bo_mem_force_space is attempted in priority order to evict and find
     790             :  * space.
     791             :  */
     792           0 : int ttm_bo_mem_space(struct ttm_buffer_object *bo,
     793             :                         struct ttm_placement *placement,
     794             :                         struct ttm_resource **mem,
     795             :                         struct ttm_operation_ctx *ctx)
     796             : {
     797           0 :         struct ttm_device *bdev = bo->bdev;
     798           0 :         bool type_found = false;
     799             :         int i, ret;
     800             : 
     801           0 :         ret = dma_resv_reserve_fences(bo->base.resv, 1);
     802           0 :         if (unlikely(ret))
     803             :                 return ret;
     804             : 
     805           0 :         for (i = 0; i < placement->num_placement; ++i) {
     806           0 :                 const struct ttm_place *place = &placement->placement[i];
     807             :                 struct ttm_resource_manager *man;
     808             : 
     809           0 :                 man = ttm_manager_type(bdev, place->mem_type);
     810           0 :                 if (!man || !ttm_resource_manager_used(man))
     811           0 :                         continue;
     812             : 
     813           0 :                 type_found = true;
     814           0 :                 ret = ttm_resource_alloc(bo, place, mem);
     815           0 :                 if (ret == -ENOSPC)
     816           0 :                         continue;
     817           0 :                 if (unlikely(ret))
     818             :                         goto error;
     819             : 
     820           0 :                 ret = ttm_bo_add_move_fence(bo, man, *mem, ctx->no_wait_gpu);
     821           0 :                 if (unlikely(ret)) {
     822           0 :                         ttm_resource_free(bo, mem);
     823           0 :                         if (ret == -EBUSY)
     824           0 :                                 continue;
     825             : 
     826             :                         goto error;
     827             :                 }
     828             :                 return 0;
     829             :         }
     830             : 
     831           0 :         for (i = 0; i < placement->num_busy_placement; ++i) {
     832           0 :                 const struct ttm_place *place = &placement->busy_placement[i];
     833             :                 struct ttm_resource_manager *man;
     834             : 
     835           0 :                 man = ttm_manager_type(bdev, place->mem_type);
     836           0 :                 if (!man || !ttm_resource_manager_used(man))
     837           0 :                         continue;
     838             : 
     839           0 :                 type_found = true;
     840           0 :                 ret = ttm_bo_mem_force_space(bo, place, mem, ctx);
     841           0 :                 if (likely(!ret))
     842             :                         return 0;
     843             : 
     844           0 :                 if (ret && ret != -EBUSY)
     845             :                         goto error;
     846             :         }
     847             : 
     848           0 :         ret = -ENOMEM;
     849           0 :         if (!type_found) {
     850           0 :                 pr_err(TTM_PFX "No compatible memory type found\n");
     851           0 :                 ret = -EINVAL;
     852             :         }
     853             : 
     854             : error:
     855             :         return ret;
     856             : }
     857             : EXPORT_SYMBOL(ttm_bo_mem_space);
     858             : 
     859           0 : static int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
     860             :                               struct ttm_placement *placement,
     861             :                               struct ttm_operation_ctx *ctx)
     862             : {
     863             :         struct ttm_resource *mem;
     864             :         struct ttm_place hop;
     865             :         int ret;
     866             : 
     867             :         dma_resv_assert_held(bo->base.resv);
     868             : 
     869             :         /*
     870             :          * Determine where to move the buffer.
     871             :          *
     872             :          * If driver determines move is going to need
     873             :          * an extra step then it will return -EMULTIHOP
     874             :          * and the buffer will be moved to the temporary
     875             :          * stop and the driver will be called to make
     876             :          * the second hop.
     877             :          */
     878           0 :         ret = ttm_bo_mem_space(bo, placement, &mem, ctx);
     879           0 :         if (ret)
     880             :                 return ret;
     881             : bounce:
     882           0 :         ret = ttm_bo_handle_move_mem(bo, mem, false, ctx, &hop);
     883           0 :         if (ret == -EMULTIHOP) {
     884           0 :                 ret = ttm_bo_bounce_temp_buffer(bo, &mem, ctx, &hop);
     885           0 :                 if (ret)
     886             :                         goto out;
     887             :                 /* try and move to final place now. */
     888             :                 goto bounce;
     889             :         }
     890             : out:
     891           0 :         if (ret)
     892           0 :                 ttm_resource_free(bo, &mem);
     893             :         return ret;
     894             : }
     895             : 
     896           0 : int ttm_bo_validate(struct ttm_buffer_object *bo,
     897             :                     struct ttm_placement *placement,
     898             :                     struct ttm_operation_ctx *ctx)
     899             : {
     900             :         int ret;
     901             : 
     902             :         dma_resv_assert_held(bo->base.resv);
     903             : 
     904             :         /*
     905             :          * Remove the backing store if no placement is given.
     906             :          */
     907           0 :         if (!placement->num_placement && !placement->num_busy_placement)
     908           0 :                 return ttm_bo_pipeline_gutting(bo);
     909             : 
     910             :         /*
     911             :          * Check whether we need to move buffer.
     912             :          */
     913           0 :         if (!ttm_resource_compat(bo->resource, placement)) {
     914           0 :                 ret = ttm_bo_move_buffer(bo, placement, ctx);
     915           0 :                 if (ret)
     916             :                         return ret;
     917             :         }
     918             :         /*
     919             :          * We might need to add a TTM.
     920             :          */
     921           0 :         if (bo->resource->mem_type == TTM_PL_SYSTEM) {
     922           0 :                 ret = ttm_tt_create(bo, true);
     923           0 :                 if (ret)
     924             :                         return ret;
     925             :         }
     926             :         return 0;
     927             : }
     928             : EXPORT_SYMBOL(ttm_bo_validate);
     929             : 
     930           0 : int ttm_bo_init_reserved(struct ttm_device *bdev,
     931             :                          struct ttm_buffer_object *bo,
     932             :                          size_t size,
     933             :                          enum ttm_bo_type type,
     934             :                          struct ttm_placement *placement,
     935             :                          uint32_t page_alignment,
     936             :                          struct ttm_operation_ctx *ctx,
     937             :                          struct sg_table *sg,
     938             :                          struct dma_resv *resv,
     939             :                          void (*destroy) (struct ttm_buffer_object *))
     940             : {
     941             :         static const struct ttm_place sys_mem = { .mem_type = TTM_PL_SYSTEM };
     942             :         bool locked;
     943             :         int ret;
     944             : 
     945           0 :         bo->destroy = destroy ? destroy : ttm_bo_default_destroy;
     946             : 
     947           0 :         kref_init(&bo->kref);
     948           0 :         INIT_LIST_HEAD(&bo->ddestroy);
     949           0 :         bo->bdev = bdev;
     950           0 :         bo->type = type;
     951           0 :         bo->page_alignment = page_alignment;
     952           0 :         bo->pin_count = 0;
     953           0 :         bo->sg = sg;
     954           0 :         bo->bulk_move = NULL;
     955           0 :         if (resv) {
     956           0 :                 bo->base.resv = resv;
     957             :                 dma_resv_assert_held(bo->base.resv);
     958             :         } else {
     959           0 :                 bo->base.resv = &bo->base._resv;
     960             :         }
     961           0 :         atomic_inc(&ttm_glob.bo_count);
     962             : 
     963           0 :         ret = ttm_resource_alloc(bo, &sys_mem, &bo->resource);
     964           0 :         if (unlikely(ret)) {
     965           0 :                 ttm_bo_put(bo);
     966           0 :                 return ret;
     967             :         }
     968             : 
     969             :         /*
     970             :          * For ttm_bo_type_device buffers, allocate
     971             :          * address space from the device.
     972             :          */
     973           0 :         if (bo->type == ttm_bo_type_device ||
     974             :             bo->type == ttm_bo_type_sg)
     975           0 :                 ret = drm_vma_offset_add(bdev->vma_manager, &bo->base.vma_node,
     976           0 :                                          bo->resource->num_pages);
     977             : 
     978             :         /* passed reservation objects should already be locked,
     979             :          * since otherwise lockdep will be angered in radeon.
     980             :          */
     981           0 :         if (!resv) {
     982           0 :                 locked = dma_resv_trylock(bo->base.resv);
     983           0 :                 WARN_ON(!locked);
     984             :         }
     985             : 
     986           0 :         if (likely(!ret))
     987           0 :                 ret = ttm_bo_validate(bo, placement, ctx);
     988             : 
     989           0 :         if (unlikely(ret)) {
     990           0 :                 if (!resv)
     991           0 :                         ttm_bo_unreserve(bo);
     992             : 
     993           0 :                 ttm_bo_put(bo);
     994           0 :                 return ret;
     995             :         }
     996             : 
     997             :         return ret;
     998             : }
     999             : EXPORT_SYMBOL(ttm_bo_init_reserved);
    1000             : 
    1001           0 : int ttm_bo_init(struct ttm_device *bdev,
    1002             :                 struct ttm_buffer_object *bo,
    1003             :                 size_t size,
    1004             :                 enum ttm_bo_type type,
    1005             :                 struct ttm_placement *placement,
    1006             :                 uint32_t page_alignment,
    1007             :                 bool interruptible,
    1008             :                 struct sg_table *sg,
    1009             :                 struct dma_resv *resv,
    1010             :                 void (*destroy) (struct ttm_buffer_object *))
    1011             : {
    1012           0 :         struct ttm_operation_ctx ctx = { interruptible, false };
    1013             :         int ret;
    1014             : 
    1015           0 :         ret = ttm_bo_init_reserved(bdev, bo, size, type, placement,
    1016             :                                    page_alignment, &ctx, sg, resv, destroy);
    1017           0 :         if (ret)
    1018             :                 return ret;
    1019             : 
    1020           0 :         if (!resv)
    1021           0 :                 ttm_bo_unreserve(bo);
    1022             : 
    1023             :         return 0;
    1024             : }
    1025             : EXPORT_SYMBOL(ttm_bo_init);
    1026             : 
    1027             : /*
    1028             :  * buffer object vm functions.
    1029             :  */
    1030             : 
    1031           0 : void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo)
    1032             : {
    1033           0 :         struct ttm_device *bdev = bo->bdev;
    1034             : 
    1035           0 :         drm_vma_node_unmap(&bo->base.vma_node, bdev->dev_mapping);
    1036           0 :         ttm_mem_io_free(bdev, bo->resource);
    1037           0 : }
    1038             : EXPORT_SYMBOL(ttm_bo_unmap_virtual);
    1039             : 
    1040           0 : int ttm_bo_wait(struct ttm_buffer_object *bo,
    1041             :                 bool interruptible, bool no_wait)
    1042             : {
    1043           0 :         long timeout = 15 * HZ;
    1044             : 
    1045           0 :         if (no_wait) {
    1046           0 :                 if (dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP))
    1047             :                         return 0;
    1048             :                 else
    1049           0 :                         return -EBUSY;
    1050             :         }
    1051             : 
    1052           0 :         timeout = dma_resv_wait_timeout(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP,
    1053             :                                         interruptible, timeout);
    1054           0 :         if (timeout < 0)
    1055           0 :                 return timeout;
    1056             : 
    1057           0 :         if (timeout == 0)
    1058             :                 return -EBUSY;
    1059             : 
    1060           0 :         return 0;
    1061             : }
    1062             : EXPORT_SYMBOL(ttm_bo_wait);
    1063             : 
    1064           0 : int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx,
    1065             :                    gfp_t gfp_flags)
    1066             : {
    1067             :         struct ttm_place place;
    1068             :         bool locked;
    1069             :         int ret;
    1070             : 
    1071             :         /*
    1072             :          * While the bo may already reside in SYSTEM placement, set
    1073             :          * SYSTEM as new placement to cover also the move further below.
    1074             :          * The driver may use the fact that we're moving from SYSTEM
    1075             :          * as an indication that we're about to swap out.
    1076             :          */
    1077           0 :         memset(&place, 0, sizeof(place));
    1078           0 :         place.mem_type = bo->resource->mem_type;
    1079           0 :         if (!ttm_bo_evict_swapout_allowable(bo, ctx, &place, &locked, NULL))
    1080             :                 return -EBUSY;
    1081             : 
    1082           0 :         if (!bo->ttm || !ttm_tt_is_populated(bo->ttm) ||
    1083           0 :             bo->ttm->page_flags & TTM_TT_FLAG_EXTERNAL ||
    1084           0 :             bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED ||
    1085           0 :             !ttm_bo_get_unless_zero(bo)) {
    1086           0 :                 if (locked)
    1087           0 :                         dma_resv_unlock(bo->base.resv);
    1088             :                 return -EBUSY;
    1089             :         }
    1090             : 
    1091           0 :         if (bo->deleted) {
    1092           0 :                 ret = ttm_bo_cleanup_refs(bo, false, false, locked);
    1093           0 :                 ttm_bo_put(bo);
    1094           0 :                 return ret == -EBUSY ? -ENOSPC : ret;
    1095             :         }
    1096             : 
    1097             :         /* TODO: Cleanup the locking */
    1098           0 :         spin_unlock(&bo->bdev->lru_lock);
    1099             : 
    1100             :         /*
    1101             :          * Move to system cached
    1102             :          */
    1103           0 :         if (bo->resource->mem_type != TTM_PL_SYSTEM) {
    1104           0 :                 struct ttm_operation_ctx ctx = { false, false };
    1105             :                 struct ttm_resource *evict_mem;
    1106             :                 struct ttm_place hop;
    1107             : 
    1108           0 :                 memset(&hop, 0, sizeof(hop));
    1109           0 :                 place.mem_type = TTM_PL_SYSTEM;
    1110           0 :                 ret = ttm_resource_alloc(bo, &place, &evict_mem);
    1111           0 :                 if (unlikely(ret))
    1112             :                         goto out;
    1113             : 
    1114           0 :                 ret = ttm_bo_handle_move_mem(bo, evict_mem, true, &ctx, &hop);
    1115           0 :                 if (unlikely(ret != 0)) {
    1116           0 :                         WARN(ret == -EMULTIHOP, "Unexpected multihop in swaput - likely driver bug.\n");
    1117             :                         goto out;
    1118             :                 }
    1119             :         }
    1120             : 
    1121             :         /*
    1122             :          * Make sure BO is idle.
    1123             :          */
    1124           0 :         ret = ttm_bo_wait(bo, false, false);
    1125           0 :         if (unlikely(ret != 0))
    1126             :                 goto out;
    1127             : 
    1128           0 :         ttm_bo_unmap_virtual(bo);
    1129             : 
    1130             :         /*
    1131             :          * Swap out. Buffer will be swapped in again as soon as
    1132             :          * anyone tries to access a ttm page.
    1133             :          */
    1134           0 :         if (bo->bdev->funcs->swap_notify)
    1135           0 :                 bo->bdev->funcs->swap_notify(bo);
    1136             : 
    1137           0 :         if (ttm_tt_is_populated(bo->ttm))
    1138           0 :                 ret = ttm_tt_swapout(bo->bdev, bo->ttm, gfp_flags);
    1139             : out:
    1140             : 
    1141             :         /*
    1142             :          * Unreserve without putting on LRU to avoid swapping out an
    1143             :          * already swapped buffer.
    1144             :          */
    1145           0 :         if (locked)
    1146           0 :                 dma_resv_unlock(bo->base.resv);
    1147           0 :         ttm_bo_put(bo);
    1148           0 :         return ret == -EBUSY ? -ENOSPC : ret;
    1149             : }
    1150             : 
    1151           0 : void ttm_bo_tt_destroy(struct ttm_buffer_object *bo)
    1152             : {
    1153           0 :         if (bo->ttm == NULL)
    1154             :                 return;
    1155             : 
    1156           0 :         ttm_tt_unpopulate(bo->bdev, bo->ttm);
    1157           0 :         ttm_tt_destroy(bo->bdev, bo->ttm);
    1158           0 :         bo->ttm = NULL;
    1159             : }

Generated by: LCOV version 1.14