1 1.2 riastrad /* $NetBSD: vmwgfx_gmrid_manager.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $ */ 2 1.2 riastrad 3 1.3 riastrad // SPDX-License-Identifier: GPL-2.0 OR MIT 4 1.1 riastrad /************************************************************************** 5 1.1 riastrad * 6 1.3 riastrad * Copyright 2007-2010 VMware, Inc., Palo Alto, CA., USA 7 1.1 riastrad * 8 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 9 1.1 riastrad * copy of this software and associated documentation files (the 10 1.1 riastrad * "Software"), to deal in the Software without restriction, including 11 1.1 riastrad * without limitation the rights to use, copy, modify, merge, publish, 12 1.1 riastrad * distribute, sub license, and/or sell copies of the Software, and to 13 1.1 riastrad * permit persons to whom the Software is furnished to do so, subject to 14 1.1 riastrad * the following conditions: 15 1.1 riastrad * 16 1.1 riastrad * The above copyright notice and this permission notice (including the 17 1.1 riastrad * next paragraph) shall be included in all copies or substantial portions 18 1.1 riastrad * of the Software. 19 1.1 riastrad * 20 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 23 1.1 riastrad * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 24 1.1 riastrad * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 25 1.1 riastrad * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 26 1.1 riastrad * USE OR OTHER DEALINGS IN THE SOFTWARE. 27 1.1 riastrad * 28 1.1 riastrad **************************************************************************/ 29 1.1 riastrad /* 30 1.1 riastrad * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> 31 1.1 riastrad */ 32 1.1 riastrad 33 1.2 riastrad #include <sys/cdefs.h> 34 1.2 riastrad __KERNEL_RCSID(0, "$NetBSD: vmwgfx_gmrid_manager.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $"); 35 1.2 riastrad 36 1.1 riastrad #include "vmwgfx_drv.h" 37 1.1 riastrad #include <drm/ttm/ttm_module.h> 38 1.1 riastrad #include <drm/ttm/ttm_bo_driver.h> 39 1.1 riastrad #include <drm/ttm/ttm_placement.h> 40 1.1 riastrad #include <linux/idr.h> 41 1.1 riastrad #include <linux/spinlock.h> 42 1.1 riastrad #include <linux/kernel.h> 43 1.1 riastrad 44 1.1 riastrad struct vmwgfx_gmrid_man { 45 1.1 riastrad spinlock_t lock; 46 1.1 riastrad struct ida gmr_ida; 47 1.1 riastrad uint32_t max_gmr_ids; 48 1.1 riastrad uint32_t max_gmr_pages; 49 1.1 riastrad uint32_t used_gmr_pages; 50 1.1 riastrad }; 51 1.1 riastrad 52 1.1 riastrad static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man, 53 1.1 riastrad struct ttm_buffer_object *bo, 54 1.2 riastrad const struct ttm_place *place, 55 1.1 riastrad struct ttm_mem_reg *mem) 56 1.1 riastrad { 57 1.1 riastrad struct vmwgfx_gmrid_man *gman = 58 1.1 riastrad (struct vmwgfx_gmrid_man *)man->priv; 59 1.1 riastrad int id; 60 1.1 riastrad 61 1.1 riastrad mem->mm_node = NULL; 62 1.1 riastrad 63 1.3 riastrad id = ida_alloc_max(&gman->gmr_ida, gman->max_gmr_ids - 1, GFP_KERNEL); 64 1.3 riastrad if (id < 0) 65 1.3 riastrad return (id != -ENOMEM ? 0 : id); 66 1.3 riastrad 67 1.1 riastrad spin_lock(&gman->lock); 68 1.1 riastrad 69 1.1 riastrad if (gman->max_gmr_pages > 0) { 70 1.1 riastrad gman->used_gmr_pages += bo->num_pages; 71 1.1 riastrad if (unlikely(gman->used_gmr_pages > gman->max_gmr_pages)) 72 1.3 riastrad goto nospace; 73 1.1 riastrad } 74 1.1 riastrad 75 1.3 riastrad mem->mm_node = gman; 76 1.3 riastrad mem->start = id; 77 1.3 riastrad mem->num_pages = bo->num_pages; 78 1.1 riastrad 79 1.1 riastrad spin_unlock(&gman->lock); 80 1.1 riastrad return 0; 81 1.1 riastrad 82 1.3 riastrad nospace: 83 1.1 riastrad gman->used_gmr_pages -= bo->num_pages; 84 1.1 riastrad spin_unlock(&gman->lock); 85 1.3 riastrad ida_free(&gman->gmr_ida, id); 86 1.3 riastrad return 0; 87 1.1 riastrad } 88 1.1 riastrad 89 1.1 riastrad static void vmw_gmrid_man_put_node(struct ttm_mem_type_manager *man, 90 1.1 riastrad struct ttm_mem_reg *mem) 91 1.1 riastrad { 92 1.1 riastrad struct vmwgfx_gmrid_man *gman = 93 1.1 riastrad (struct vmwgfx_gmrid_man *)man->priv; 94 1.1 riastrad 95 1.1 riastrad if (mem->mm_node) { 96 1.3 riastrad ida_free(&gman->gmr_ida, mem->start); 97 1.1 riastrad spin_lock(&gman->lock); 98 1.1 riastrad gman->used_gmr_pages -= mem->num_pages; 99 1.1 riastrad spin_unlock(&gman->lock); 100 1.1 riastrad mem->mm_node = NULL; 101 1.1 riastrad } 102 1.1 riastrad } 103 1.1 riastrad 104 1.1 riastrad static int vmw_gmrid_man_init(struct ttm_mem_type_manager *man, 105 1.1 riastrad unsigned long p_size) 106 1.1 riastrad { 107 1.1 riastrad struct vmw_private *dev_priv = 108 1.1 riastrad container_of(man->bdev, struct vmw_private, bdev); 109 1.1 riastrad struct vmwgfx_gmrid_man *gman = 110 1.1 riastrad kzalloc(sizeof(*gman), GFP_KERNEL); 111 1.1 riastrad 112 1.3 riastrad if (unlikely(!gman)) 113 1.1 riastrad return -ENOMEM; 114 1.1 riastrad 115 1.1 riastrad spin_lock_init(&gman->lock); 116 1.1 riastrad gman->used_gmr_pages = 0; 117 1.1 riastrad ida_init(&gman->gmr_ida); 118 1.2 riastrad 119 1.2 riastrad switch (p_size) { 120 1.2 riastrad case VMW_PL_GMR: 121 1.2 riastrad gman->max_gmr_ids = dev_priv->max_gmr_ids; 122 1.2 riastrad gman->max_gmr_pages = dev_priv->max_gmr_pages; 123 1.2 riastrad break; 124 1.2 riastrad case VMW_PL_MOB: 125 1.2 riastrad gman->max_gmr_ids = VMWGFX_NUM_MOB; 126 1.2 riastrad gman->max_gmr_pages = dev_priv->max_mob_pages; 127 1.2 riastrad break; 128 1.2 riastrad default: 129 1.2 riastrad BUG(); 130 1.2 riastrad } 131 1.1 riastrad man->priv = (void *) gman; 132 1.1 riastrad return 0; 133 1.1 riastrad } 134 1.1 riastrad 135 1.1 riastrad static int vmw_gmrid_man_takedown(struct ttm_mem_type_manager *man) 136 1.1 riastrad { 137 1.1 riastrad struct vmwgfx_gmrid_man *gman = 138 1.1 riastrad (struct vmwgfx_gmrid_man *)man->priv; 139 1.1 riastrad 140 1.1 riastrad if (gman) { 141 1.1 riastrad ida_destroy(&gman->gmr_ida); 142 1.1 riastrad kfree(gman); 143 1.1 riastrad } 144 1.1 riastrad return 0; 145 1.1 riastrad } 146 1.1 riastrad 147 1.1 riastrad static void vmw_gmrid_man_debug(struct ttm_mem_type_manager *man, 148 1.3 riastrad struct drm_printer *printer) 149 1.1 riastrad { 150 1.3 riastrad drm_printf(printer, "No debug info available for the GMR id manager\n"); 151 1.1 riastrad } 152 1.1 riastrad 153 1.1 riastrad const struct ttm_mem_type_manager_func vmw_gmrid_manager_func = { 154 1.3 riastrad .init = vmw_gmrid_man_init, 155 1.3 riastrad .takedown = vmw_gmrid_man_takedown, 156 1.3 riastrad .get_node = vmw_gmrid_man_get_node, 157 1.3 riastrad .put_node = vmw_gmrid_man_put_node, 158 1.3 riastrad .debug = vmw_gmrid_man_debug 159 1.1 riastrad }; 160