1/* $NetBSD: kfd_pasid.c,v 1.3 2021/12/18 23:44:59 riastradh Exp $ */ 2 3/* 4 * Copyright 2014 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25#include <sys/cdefs.h> 26__KERNEL_RCSID(0, "$NetBSD: kfd_pasid.c,v 1.3 2021/12/18 23:44:59 riastradh Exp $"); 27 28#include <linux/types.h> 29#include "kfd_priv.h" 30#include "amdgpu_ids.h" 31 32static unsigned int pasid_bits = 16; 33static const struct kfd2kgd_calls *kfd2kgd; 34 35bool kfd_set_pasid_limit(unsigned int new_limit) 36{ 37 if (new_limit < 2) 38 return false; 39 40 if (new_limit < (1U << pasid_bits)) { 41 if (kfd2kgd) 42 /* We've already allocated user PASIDs, too late to 43 * change the limit 44 */ 45 return false; 46 47 while (new_limit < (1U << pasid_bits)) 48 pasid_bits--; 49 } 50 51 return true; 52} 53 54unsigned int kfd_get_pasid_limit(void) 55{ 56 return 1U << pasid_bits; 57} 58 59unsigned int kfd_pasid_alloc(void) 60{ 61 int r; 62 63 /* Find the first best KFD device for calling KGD */ 64 if (!kfd2kgd) { 65 struct kfd_dev *dev = NULL; 66 unsigned int i = 0; 67 68 while ((kfd_topology_enum_kfd_devices(i, &dev)) == 0) { 69 if (dev && dev->kfd2kgd) { 70 kfd2kgd = dev->kfd2kgd; 71 break; 72 } 73 i++; 74 } 75 76 if (!kfd2kgd) 77 return false; 78 } 79 80 r = amdgpu_pasid_alloc(pasid_bits); 81 82 return r > 0 ? r : 0; 83} 84 85void kfd_pasid_free(unsigned int pasid) 86{ 87 if (kfd2kgd) 88 amdgpu_pasid_free(pasid); 89} 90