Commit d2791c45 authored by Felix Kuehling's avatar Felix Kuehling Committed by Alex Deucher
Browse files

drm/amdkfd: Use PASID manager from KGD

parent a91e70e3
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -103,10 +103,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;
@@ -126,7 +122,6 @@ static int __init kfd_module_init(void)
err_topology:
	kfd_chardev_exit();
err_ioctl:
	kfd_pasid_exit();
	return err;
}

@@ -137,7 +132,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");
}

+38 −52
Original line number Diff line number Diff line
@@ -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);
	if (new_limit < 2)
		return false;

		/* 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);
	if (new_limit < (1U << pasid_bits)) {
		if (kfd2kgd)
			/* We've already allocated user PASIDs, too late to
			 * change the limit
			 */
			return false;

		return ok;
		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;

	mutex_lock(&pasid_mutex);
	/* Find the first best KFD device for calling KGD */
	if (!kfd2kgd) {
		struct kfd_dev *dev = NULL;
		unsigned int i = 0;

	found = find_first_zero_bit(pasid_bitmap, pasid_limit);
	if (found == pasid_limit)
		found = 0;
	else
		set_bit(found, pasid_bitmap);
		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);
}