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

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
...@@ -292,7 +292,8 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, ...@@ -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) ...@@ -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;
......
...@@ -126,15 +126,10 @@ void kfd_doorbell_fini(struct kfd_dev *kfd) ...@@ -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
......
...@@ -345,7 +345,7 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p, ...@@ -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;
} }
......
...@@ -41,9 +41,33 @@ ...@@ -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 @@ ...@@ -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, ...@@ -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); ...@@ -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);
......
...@@ -451,7 +451,8 @@ static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep) ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment