diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdkfd/kfd_pasid.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_pasid.c | 90 |
1 files changed, 38 insertions, 52 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c b/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c index 1e06de0bc673..d6a796144269 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c @@ -20,78 +20,64 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include <linux/slab.h> #include <linux/types.h> #include "kfd_priv.h" -static unsigned long *pasid_bitmap; -static unsigned int pasid_limit; -static DEFINE_MUTEX(pasid_mutex); - -int kfd_pasid_init(void) -{ - pasid_limit = KFD_MAX_NUM_OF_PROCESSES; - - pasid_bitmap = kcalloc(BITS_TO_LONGS(pasid_limit), sizeof(long), - GFP_KERNEL); - if (!pasid_bitmap) - return -ENOMEM; - - set_bit(0, pasid_bitmap); /* PASID 0 is reserved. */ - - return 0; -} - -void kfd_pasid_exit(void) -{ - kfree(pasid_bitmap); -} +static unsigned int pasid_bits = 16; +static const struct kfd2kgd_calls *kfd2kgd; bool kfd_set_pasid_limit(unsigned int new_limit) { - if (new_limit < pasid_limit) { - bool ok; - - mutex_lock(&pasid_mutex); - - /* ensure that no pasids >= new_limit are in-use */ - ok = (find_next_bit(pasid_bitmap, pasid_limit, new_limit) == - pasid_limit); - if (ok) - pasid_limit = new_limit; - - mutex_unlock(&pasid_mutex); - - return ok; + if (new_limit < 2) + return false; + + if (new_limit < (1U << pasid_bits)) { + if (kfd2kgd) + /* We've already allocated user PASIDs, too late to + * change the limit + */ + return false; + + while (new_limit < (1U << pasid_bits)) + pasid_bits--; } return true; } -inline unsigned int kfd_get_pasid_limit(void) +unsigned int kfd_get_pasid_limit(void) { - return pasid_limit; + return 1U << pasid_bits; } unsigned int kfd_pasid_alloc(void) { - unsigned int found; - - mutex_lock(&pasid_mutex); - - found = find_first_zero_bit(pasid_bitmap, pasid_limit); - if (found == pasid_limit) - found = 0; - else - set_bit(found, pasid_bitmap); + int r; + + /* Find the first best KFD device for calling KGD */ + if (!kfd2kgd) { + struct kfd_dev *dev = NULL; + unsigned int i = 0; + + while ((dev = kfd_topology_enum_kfd_devices(i)) != NULL) { + if (dev && dev->kfd2kgd) { + kfd2kgd = dev->kfd2kgd; + break; + } + i++; + } + + if (!kfd2kgd) + return false; + } - mutex_unlock(&pasid_mutex); + r = kfd2kgd->alloc_pasid(pasid_bits); - return found; + return r > 0 ? r : 0; } void kfd_pasid_free(unsigned int pasid) { - if (!WARN_ON(pasid == 0 || pasid >= pasid_limit)) - clear_bit(pasid, pasid_bitmap); + if (kfd2kgd) + kfd2kgd->free_pasid(pasid); } |