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

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 OR MIT */
       2             : /**************************************************************************
       3             :  *
       4             :  * Copyright (c) 2007-2010 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             : #include <drm/ttm/ttm_device.h>
      33             : #include <drm/ttm/ttm_placement.h>
      34             : #include <drm/ttm/ttm_range_manager.h>
      35             : #include <drm/ttm/ttm_bo_api.h>
      36             : #include <drm/drm_mm.h>
      37             : #include <linux/slab.h>
      38             : #include <linux/spinlock.h>
      39             : 
      40             : /*
      41             :  * Currently we use a spinlock for the lock, but a mutex *may* be
      42             :  * more appropriate to reduce scheduling latency if the range manager
      43             :  * ends up with very fragmented allocation patterns.
      44             :  */
      45             : 
      46             : struct ttm_range_manager {
      47             :         struct ttm_resource_manager manager;
      48             :         struct drm_mm mm;
      49             :         spinlock_t lock;
      50             : };
      51             : 
      52             : static inline struct ttm_range_manager *
      53             : to_range_manager(struct ttm_resource_manager *man)
      54             : {
      55           0 :         return container_of(man, struct ttm_range_manager, manager);
      56             : }
      57             : 
      58           0 : static int ttm_range_man_alloc(struct ttm_resource_manager *man,
      59             :                                struct ttm_buffer_object *bo,
      60             :                                const struct ttm_place *place,
      61             :                                struct ttm_resource **res)
      62             : {
      63           0 :         struct ttm_range_manager *rman = to_range_manager(man);
      64             :         struct ttm_range_mgr_node *node;
      65           0 :         struct drm_mm *mm = &rman->mm;
      66             :         enum drm_mm_insert_mode mode;
      67             :         unsigned long lpfn;
      68             :         int ret;
      69             : 
      70           0 :         lpfn = place->lpfn;
      71           0 :         if (!lpfn)
      72           0 :                 lpfn = man->size;
      73             : 
      74           0 :         node = kzalloc(struct_size(node, mm_nodes, 1), GFP_KERNEL);
      75           0 :         if (!node)
      76             :                 return -ENOMEM;
      77             : 
      78           0 :         mode = DRM_MM_INSERT_BEST;
      79           0 :         if (place->flags & TTM_PL_FLAG_TOPDOWN)
      80           0 :                 mode = DRM_MM_INSERT_HIGH;
      81             : 
      82           0 :         ttm_resource_init(bo, place, &node->base);
      83             : 
      84           0 :         spin_lock(&rman->lock);
      85           0 :         ret = drm_mm_insert_node_in_range(mm, &node->mm_nodes[0],
      86           0 :                                           node->base.num_pages,
      87           0 :                                           bo->page_alignment, 0,
      88           0 :                                           place->fpfn, lpfn, mode);
      89           0 :         spin_unlock(&rman->lock);
      90             : 
      91           0 :         if (unlikely(ret)) {
      92           0 :                 ttm_resource_fini(man, &node->base);
      93           0 :                 kfree(node);
      94           0 :                 return ret;
      95             :         }
      96             : 
      97           0 :         node->base.start = node->mm_nodes[0].start;
      98           0 :         *res = &node->base;
      99           0 :         return 0;
     100             : }
     101             : 
     102           0 : static void ttm_range_man_free(struct ttm_resource_manager *man,
     103             :                                struct ttm_resource *res)
     104             : {
     105           0 :         struct ttm_range_mgr_node *node = to_ttm_range_mgr_node(res);
     106           0 :         struct ttm_range_manager *rman = to_range_manager(man);
     107             : 
     108           0 :         spin_lock(&rman->lock);
     109           0 :         drm_mm_remove_node(&node->mm_nodes[0]);
     110           0 :         spin_unlock(&rman->lock);
     111             : 
     112           0 :         ttm_resource_fini(man, res);
     113           0 :         kfree(node);
     114           0 : }
     115             : 
     116           0 : static void ttm_range_man_debug(struct ttm_resource_manager *man,
     117             :                                 struct drm_printer *printer)
     118             : {
     119           0 :         struct ttm_range_manager *rman = to_range_manager(man);
     120             : 
     121           0 :         spin_lock(&rman->lock);
     122           0 :         drm_mm_print(&rman->mm, printer);
     123           0 :         spin_unlock(&rman->lock);
     124           0 : }
     125             : 
     126             : static const struct ttm_resource_manager_func ttm_range_manager_func = {
     127             :         .alloc = ttm_range_man_alloc,
     128             :         .free = ttm_range_man_free,
     129             :         .debug = ttm_range_man_debug
     130             : };
     131             : 
     132             : /**
     133             :  * ttm_range_man_init_nocheck - Initialise a generic range manager for the
     134             :  * selected memory type.
     135             :  *
     136             :  * @bdev: ttm device
     137             :  * @type: memory manager type
     138             :  * @use_tt: if the memory manager uses tt
     139             :  * @p_size: size of area to be managed in pages.
     140             :  *
     141             :  * The range manager is installed for this device in the type slot.
     142             :  *
     143             :  * Return: %0 on success or a negative error code on failure
     144             :  */
     145           0 : int ttm_range_man_init_nocheck(struct ttm_device *bdev,
     146             :                        unsigned type, bool use_tt,
     147             :                        unsigned long p_size)
     148             : {
     149             :         struct ttm_resource_manager *man;
     150             :         struct ttm_range_manager *rman;
     151             : 
     152           0 :         rman = kzalloc(sizeof(*rman), GFP_KERNEL);
     153           0 :         if (!rman)
     154             :                 return -ENOMEM;
     155             : 
     156           0 :         man = &rman->manager;
     157           0 :         man->use_tt = use_tt;
     158             : 
     159           0 :         man->func = &ttm_range_manager_func;
     160             : 
     161           0 :         ttm_resource_manager_init(man, bdev, p_size);
     162             : 
     163           0 :         drm_mm_init(&rman->mm, 0, p_size);
     164           0 :         spin_lock_init(&rman->lock);
     165             : 
     166           0 :         ttm_set_driver_manager(bdev, type, &rman->manager);
     167           0 :         ttm_resource_manager_set_used(man, true);
     168           0 :         return 0;
     169             : }
     170             : EXPORT_SYMBOL(ttm_range_man_init_nocheck);
     171             : 
     172             : /**
     173             :  * ttm_range_man_fini_nocheck - Remove the generic range manager from a slot
     174             :  * and tear it down.
     175             :  *
     176             :  * @bdev: ttm device
     177             :  * @type: memory manager type
     178             :  *
     179             :  * Return: %0 on success or a negative error code on failure
     180             :  */
     181           0 : int ttm_range_man_fini_nocheck(struct ttm_device *bdev,
     182             :                        unsigned type)
     183             : {
     184           0 :         struct ttm_resource_manager *man = ttm_manager_type(bdev, type);
     185           0 :         struct ttm_range_manager *rman = to_range_manager(man);
     186           0 :         struct drm_mm *mm = &rman->mm;
     187             :         int ret;
     188             : 
     189           0 :         if (!man)
     190             :                 return 0;
     191             : 
     192           0 :         ttm_resource_manager_set_used(man, false);
     193             : 
     194           0 :         ret = ttm_resource_manager_evict_all(bdev, man);
     195           0 :         if (ret)
     196             :                 return ret;
     197             : 
     198           0 :         spin_lock(&rman->lock);
     199           0 :         drm_mm_clean(mm);
     200           0 :         drm_mm_takedown(mm);
     201           0 :         spin_unlock(&rman->lock);
     202             : 
     203             :         ttm_resource_manager_cleanup(man);
     204           0 :         ttm_set_driver_manager(bdev, type, NULL);
     205           0 :         kfree(rman);
     206           0 :         return 0;
     207             : }
     208             : EXPORT_SYMBOL(ttm_range_man_fini_nocheck);

Generated by: LCOV version 1.14