Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit df03ef93 authored by Harish Kasiviswanathan's avatar Harish Kasiviswanathan Committed by Oded Gabbay
Browse files

drm/amdkfd: Clean up KFD_MMAP_ offset handling



Use bit-rotate for better clarity and remove _MASK from the #defines as
these represent mmap types.

Centralize all the parsing of the mmap offset in kfd_mmap and add device
parameter to doorbell and reserved_mem map functions.

Encode gpu_id into upper bits of vm_pgoff. This frees up the lower bits
for encoding the the doorbell ID on Vega10.

Signed-off-by: default avatarHarish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
Signed-off-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
parent ada2b29c
Loading
Loading
Loading
Loading
+23 −12
Original line number Original line Diff line number Diff line
@@ -292,7 +292,8 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,




	/* Return gpu_id as doorbell offset for mmap usage */
	/* Return gpu_id as doorbell offset for mmap usage */
	args->doorbell_offset = (KFD_MMAP_DOORBELL_MASK | args->gpu_id);
	args->doorbell_offset = KFD_MMAP_TYPE_DOORBELL;
	args->doorbell_offset |= KFD_MMAP_GPU_ID(args->gpu_id);
	args->doorbell_offset <<= PAGE_SHIFT;
	args->doorbell_offset <<= PAGE_SHIFT;


	mutex_unlock(&p->mutex);
	mutex_unlock(&p->mutex);
@@ -1644,23 +1645,33 @@ static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
static int kfd_mmap(struct file *filp, struct vm_area_struct *vma)
static int kfd_mmap(struct file *filp, struct vm_area_struct *vma)
{
{
	struct kfd_process *process;
	struct kfd_process *process;
	struct kfd_dev *dev = NULL;
	unsigned long vm_pgoff;
	unsigned int gpu_id;


	process = kfd_get_process(current);
	process = kfd_get_process(current);
	if (IS_ERR(process))
	if (IS_ERR(process))
		return PTR_ERR(process);
		return PTR_ERR(process);


	if ((vma->vm_pgoff & KFD_MMAP_DOORBELL_MASK) ==
	vm_pgoff = vma->vm_pgoff;
			KFD_MMAP_DOORBELL_MASK) {
	vma->vm_pgoff = KFD_MMAP_OFFSET_VALUE_GET(vm_pgoff);
		vma->vm_pgoff = vma->vm_pgoff ^ KFD_MMAP_DOORBELL_MASK;
	gpu_id = KFD_MMAP_GPU_ID_GET(vm_pgoff);
		return kfd_doorbell_mmap(process, vma);
	if (gpu_id)
	} else if ((vma->vm_pgoff & KFD_MMAP_EVENTS_MASK) ==
		dev = kfd_device_by_id(gpu_id);
			KFD_MMAP_EVENTS_MASK) {

		vma->vm_pgoff = vma->vm_pgoff ^ KFD_MMAP_EVENTS_MASK;
	switch (vm_pgoff & KFD_MMAP_TYPE_MASK) {
	case KFD_MMAP_TYPE_DOORBELL:
		if (!dev)
			return -ENODEV;
		return kfd_doorbell_mmap(dev, process, vma);

	case KFD_MMAP_TYPE_EVENTS:
		return kfd_event_mmap(process, vma);
		return kfd_event_mmap(process, vma);
	} else if ((vma->vm_pgoff & KFD_MMAP_RESERVED_MEM_MASK) ==

			KFD_MMAP_RESERVED_MEM_MASK) {
	case KFD_MMAP_TYPE_RESERVED_MEM:
		vma->vm_pgoff = vma->vm_pgoff ^ KFD_MMAP_RESERVED_MEM_MASK;
		if (!dev)
		return kfd_reserved_mem_mmap(process, vma);
			return -ENODEV;
		return kfd_reserved_mem_mmap(dev, process, vma);
	}
	}


	return -EFAULT;
	return -EFAULT;
+2 −7
Original line number Original line Diff line number Diff line
@@ -126,15 +126,10 @@ void kfd_doorbell_fini(struct kfd_dev *kfd)
		iounmap(kfd->doorbell_kernel_ptr);
		iounmap(kfd->doorbell_kernel_ptr);
}
}


int kfd_doorbell_mmap(struct kfd_process *process, struct vm_area_struct *vma)
int kfd_doorbell_mmap(struct kfd_dev *dev, struct kfd_process *process,
		      struct vm_area_struct *vma)
{
{
	phys_addr_t address;
	phys_addr_t address;
	struct kfd_dev *dev;

	/* Find kfd device according to gpu id */
	dev = kfd_device_by_id(vma->vm_pgoff);
	if (!dev)
		return -EINVAL;


	/*
	/*
	 * For simplicitly we only allow mapping of the entire doorbell
	 * For simplicitly we only allow mapping of the entire doorbell
+1 −1
Original line number Original line Diff line number Diff line
@@ -345,7 +345,7 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p,
	case KFD_EVENT_TYPE_DEBUG:
	case KFD_EVENT_TYPE_DEBUG:
		ret = create_signal_event(devkfd, p, ev);
		ret = create_signal_event(devkfd, p, ev);
		if (!ret) {
		if (!ret) {
			*event_page_offset = KFD_MMAP_EVENTS_MASK;
			*event_page_offset = KFD_MMAP_TYPE_EVENTS;
			*event_page_offset <<= PAGE_SHIFT;
			*event_page_offset <<= PAGE_SHIFT;
			*event_slot_index = ev->event_id;
			*event_slot_index = ev->event_id;
		}
		}
+30 −8
Original line number Original line Diff line number Diff line
@@ -41,9 +41,33 @@


#define KFD_SYSFS_FILE_MODE 0444
#define KFD_SYSFS_FILE_MODE 0444


#define KFD_MMAP_DOORBELL_MASK 0x8000000000000ull
/* GPU ID hash width in bits */
#define KFD_MMAP_EVENTS_MASK 0x4000000000000ull
#define KFD_GPU_ID_HASH_WIDTH 16
#define KFD_MMAP_RESERVED_MEM_MASK 0x2000000000000ull

/* Use upper bits of mmap offset to store KFD driver specific information.
 * BITS[63:62] - Encode MMAP type
 * BITS[61:46] - Encode gpu_id. To identify to which GPU the offset belongs to
 * BITS[45:0]  - MMAP offset value
 *
 * NOTE: struct vm_area_struct.vm_pgoff uses offset in pages. Hence, these
 *  defines are w.r.t to PAGE_SIZE
 */
#define KFD_MMAP_TYPE_SHIFT	(62 - PAGE_SHIFT)
#define KFD_MMAP_TYPE_MASK	(0x3ULL << KFD_MMAP_TYPE_SHIFT)
#define KFD_MMAP_TYPE_DOORBELL	(0x3ULL << KFD_MMAP_TYPE_SHIFT)
#define KFD_MMAP_TYPE_EVENTS	(0x2ULL << KFD_MMAP_TYPE_SHIFT)
#define KFD_MMAP_TYPE_RESERVED_MEM	(0x1ULL << KFD_MMAP_TYPE_SHIFT)

#define KFD_MMAP_GPU_ID_SHIFT (46 - PAGE_SHIFT)
#define KFD_MMAP_GPU_ID_MASK (((1ULL << KFD_GPU_ID_HASH_WIDTH) - 1) \
				<< KFD_MMAP_GPU_ID_SHIFT)
#define KFD_MMAP_GPU_ID(gpu_id) ((((uint64_t)gpu_id) << KFD_MMAP_GPU_ID_SHIFT)\
				& KFD_MMAP_GPU_ID_MASK)
#define KFD_MMAP_GPU_ID_GET(offset)    ((offset & KFD_MMAP_GPU_ID_MASK) \
				>> KFD_MMAP_GPU_ID_SHIFT)

#define KFD_MMAP_OFFSET_VALUE_MASK	(0x3FFFFFFFFFFFULL >> PAGE_SHIFT)
#define KFD_MMAP_OFFSET_VALUE_GET(offset) (offset & KFD_MMAP_OFFSET_VALUE_MASK)


/*
/*
 * When working with cp scheduler we should assign the HIQ manually or via
 * When working with cp scheduler we should assign the HIQ manually or via
@@ -55,9 +79,6 @@
#define KFD_CIK_HIQ_PIPE 4
#define KFD_CIK_HIQ_PIPE 4
#define KFD_CIK_HIQ_QUEUE 0
#define KFD_CIK_HIQ_QUEUE 0


/* GPU ID hash width in bits */
#define KFD_GPU_ID_HASH_WIDTH 16

/* Macro for allocating structures */
/* Macro for allocating structures */
#define kfd_alloc_struct(ptr_to_struct)	\
#define kfd_alloc_struct(ptr_to_struct)	\
	((typeof(ptr_to_struct)) kzalloc(sizeof(*ptr_to_struct), GFP_KERNEL))
	((typeof(ptr_to_struct)) kzalloc(sizeof(*ptr_to_struct), GFP_KERNEL))
@@ -698,7 +719,7 @@ struct kfd_process_device *kfd_get_process_device_data(struct kfd_dev *dev,
struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev,
struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev,
							struct kfd_process *p);
							struct kfd_process *p);


int kfd_reserved_mem_mmap(struct kfd_process *process,
int kfd_reserved_mem_mmap(struct kfd_dev *dev, struct kfd_process *process,
			  struct vm_area_struct *vma);
			  struct vm_area_struct *vma);


/* KFD process API for creating and translating handles */
/* KFD process API for creating and translating handles */
@@ -728,7 +749,8 @@ void kfd_pasid_free(unsigned int pasid);
/* Doorbells */
/* Doorbells */
int kfd_doorbell_init(struct kfd_dev *kfd);
int kfd_doorbell_init(struct kfd_dev *kfd);
void kfd_doorbell_fini(struct kfd_dev *kfd);
void kfd_doorbell_fini(struct kfd_dev *kfd);
int kfd_doorbell_mmap(struct kfd_process *process, struct vm_area_struct *vma);
int kfd_doorbell_mmap(struct kfd_dev *dev, struct kfd_process *process,
		      struct vm_area_struct *vma);
void __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd,
void __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd,
					unsigned int *doorbell_off);
					unsigned int *doorbell_off);
void kfd_release_kernel_doorbell(struct kfd_dev *kfd, u32 __iomem *db_addr);
void kfd_release_kernel_doorbell(struct kfd_dev *kfd, u32 __iomem *db_addr);
+3 −5
Original line number Original line Diff line number Diff line
@@ -451,7 +451,8 @@ static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep)
		if (!dev->cwsr_enabled || qpd->cwsr_kaddr || qpd->cwsr_base)
		if (!dev->cwsr_enabled || qpd->cwsr_kaddr || qpd->cwsr_base)
			continue;
			continue;


		offset = (dev->id | KFD_MMAP_RESERVED_MEM_MASK) << PAGE_SHIFT;
		offset = (KFD_MMAP_TYPE_RESERVED_MEM | KFD_MMAP_GPU_ID(dev->id))
			<< PAGE_SHIFT;
		qpd->tba_addr = (int64_t)vm_mmap(filep, 0,
		qpd->tba_addr = (int64_t)vm_mmap(filep, 0,
			KFD_CWSR_TBA_TMA_SIZE, PROT_READ | PROT_EXEC,
			KFD_CWSR_TBA_TMA_SIZE, PROT_READ | PROT_EXEC,
			MAP_SHARED, offset);
			MAP_SHARED, offset);
@@ -989,15 +990,12 @@ int kfd_resume_all_processes(void)
	return ret;
	return ret;
}
}


int kfd_reserved_mem_mmap(struct kfd_process *process,
int kfd_reserved_mem_mmap(struct kfd_dev *dev, struct kfd_process *process,
			  struct vm_area_struct *vma)
			  struct vm_area_struct *vma)
{
{
	struct kfd_dev *dev = kfd_device_by_id(vma->vm_pgoff);
	struct kfd_process_device *pdd;
	struct kfd_process_device *pdd;
	struct qcm_process_device *qpd;
	struct qcm_process_device *qpd;


	if (!dev)
		return -EINVAL;
	if ((vma->vm_end - vma->vm_start) != KFD_CWSR_TBA_TMA_SIZE) {
	if ((vma->vm_end - vma->vm_start) != KFD_CWSR_TBA_TMA_SIZE) {
		pr_err("Incorrect CWSR mapping size.\n");
		pr_err("Incorrect CWSR mapping size.\n");
		return -EINVAL;
		return -EINVAL;