Also fixed PASID limit setting for dGPUs. Change-Id: If3bb8c0742019745bedf09077a271b1ed14deea1 Signed-off-by: Felix Kuehling <Felix.Kuehling at amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 11 ++--- drivers/gpu/drm/amd/amdkfd/kfd_module.c | 6 --- drivers/gpu/drm/amd/amdkfd/kfd_pasid.c | 84 +++++++++++++-------------------- 3 files changed, 39 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 378a9cf..1915e93 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -391,7 +391,6 @@ static bool device_iommu_pasid_init(struct kfd_dev *kfd) AMD_IOMMU_DEVICE_FLAG_PASID_SUP; struct amd_iommu_device_info iommu_info; - unsigned int pasid_limit; int err; err = amd_iommu_device_info(kfd->pdev, &iommu_info); @@ -410,11 +409,7 @@ static bool device_iommu_pasid_init(struct kfd_dev *kfd) return false; } - pasid_limit = min_t(unsigned int, - (unsigned int)(1 << kfd->device_info->max_pasid_bits), - iommu_info.max_pasids); - - if (!kfd_set_pasid_limit(pasid_limit)) { + if (!kfd_set_pasid_limit(iommu_info.max_pasids)) { dev_err(kfd_device, "error setting pasid limit\n"); return false; } @@ -605,6 +600,10 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, goto device_queue_manager_error; } + if (!kfd_set_pasid_limit(1U << kfd->device_info->max_pasid_bits)) { + dev_err(kfd_device, "Error setting pasid limit\n"); + goto device_iommu_pasid_error; + } #if defined(CONFIG_AMD_IOMMU_V2_MODULE) || defined(CONFIG_AMD_IOMMU_V2) if (kfd->device_info->is_need_iommu_device) { if (!device_iommu_pasid_init(kfd)) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_module.c b/drivers/gpu/drm/amd/amdkfd/kfd_module.c index aba3e9d..9846d58 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_module.c @@ -131,10 +131,6 @@ static int __init kfd_module_init(void) return -1; } - err = kfd_pasid_init(); - if (err < 0) - return err; - err = kfd_chardev_init(); if (err < 0) goto err_ioctl; @@ -162,7 +158,6 @@ static int __init kfd_module_init(void) err_topology: kfd_chardev_exit(); err_ioctl: - kfd_pasid_exit(); return err; } @@ -175,7 +170,6 @@ static void __exit kfd_module_exit(void) kfd_process_destroy_wq(); kfd_topology_shutdown(); kfd_chardev_exit(); - kfd_pasid_exit(); dev_info(kfd_device, "Removed module\n"); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c b/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c index 1e06de0..ed78937 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c @@ -20,78 +20,62 @@ * 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; + int r; + + /* Find the first best KFD device for calling KGD */ + if (!kfd2kgd) { + struct kfd_dev *dev = NULL; + unsigned int i; - mutex_lock(&pasid_mutex); + for (i = 0; kfd_topology_enum_kfd_devices(i, &dev) == 0; i++) + if (dev && dev->kfd2kgd) { + kfd2kgd = dev->kfd2kgd; + break; + } - found = find_first_zero_bit(pasid_bitmap, pasid_limit); - if (found == pasid_limit) - found = 0; - else - set_bit(found, pasid_bitmap); + 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); } -- 2.7.4