drm/amdkfd: Make event limit dependent on user mode mapping size
This allows increasing the KFD_SIGNAL_EVENT_LIMIT in kfd_ioctl.h without breaking processes built with older kfd_ioctl.h versions. Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
This commit is contained in:
committed by
Oded Gabbay
parent
3f04f96148
commit
b9a5d0a5db
@@ -97,9 +97,17 @@ static int allocate_event_notification_slot(struct kfd_process *p,
|
|||||||
p->signal_page = allocate_signal_page(p);
|
p->signal_page = allocate_signal_page(p);
|
||||||
if (!p->signal_page)
|
if (!p->signal_page)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
/* Oldest user mode expects 256 event slots */
|
||||||
|
p->signal_mapped_size = 256*8;
|
||||||
}
|
}
|
||||||
|
|
||||||
id = idr_alloc(&p->event_idr, ev, 0, KFD_SIGNAL_EVENT_LIMIT,
|
/*
|
||||||
|
* Compatibility with old user mode: Only use signal slots
|
||||||
|
* user mode has mapped, may be less than
|
||||||
|
* KFD_SIGNAL_EVENT_LIMIT. This also allows future increase
|
||||||
|
* of the event limit without breaking user mode.
|
||||||
|
*/
|
||||||
|
id = idr_alloc(&p->event_idr, ev, 0, p->signal_mapped_size / 8,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
return id;
|
return id;
|
||||||
@@ -173,7 +181,8 @@ static int create_signal_event(struct file *devkfd,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (p->signal_event_count == KFD_SIGNAL_EVENT_LIMIT) {
|
if (p->signal_mapped_size &&
|
||||||
|
p->signal_event_count == p->signal_mapped_size / 8) {
|
||||||
if (!p->signal_event_limit_reached) {
|
if (!p->signal_event_limit_reached) {
|
||||||
pr_warn("Signal event wasn't created because limit was reached\n");
|
pr_warn("Signal event wasn't created because limit was reached\n");
|
||||||
p->signal_event_limit_reached = true;
|
p->signal_event_limit_reached = true;
|
||||||
@@ -744,12 +753,12 @@ out:
|
|||||||
|
|
||||||
int kfd_event_mmap(struct kfd_process *p, struct vm_area_struct *vma)
|
int kfd_event_mmap(struct kfd_process *p, struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
|
|
||||||
unsigned long pfn;
|
unsigned long pfn;
|
||||||
struct kfd_signal_page *page;
|
struct kfd_signal_page *page;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* check required size is logical */
|
/* check required size doesn't exceed the allocated size */
|
||||||
if (get_order(KFD_SIGNAL_EVENT_LIMIT * 8) !=
|
if (get_order(KFD_SIGNAL_EVENT_LIMIT * 8) <
|
||||||
get_order(vma->vm_end - vma->vm_start)) {
|
get_order(vma->vm_end - vma->vm_start)) {
|
||||||
pr_err("Event page mmap requested illegal size\n");
|
pr_err("Event page mmap requested illegal size\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -779,8 +788,12 @@ int kfd_event_mmap(struct kfd_process *p, struct vm_area_struct *vma)
|
|||||||
page->user_address = (uint64_t __user *)vma->vm_start;
|
page->user_address = (uint64_t __user *)vma->vm_start;
|
||||||
|
|
||||||
/* mapping the page to user process */
|
/* mapping the page to user process */
|
||||||
return remap_pfn_range(vma, vma->vm_start, pfn,
|
ret = remap_pfn_range(vma, vma->vm_start, pfn,
|
||||||
vma->vm_end - vma->vm_start, vma->vm_page_prot);
|
vma->vm_end - vma->vm_start, vma->vm_page_prot);
|
||||||
|
if (!ret)
|
||||||
|
p->signal_mapped_size = vma->vm_end - vma->vm_start;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -543,6 +543,7 @@ struct kfd_process {
|
|||||||
struct idr event_idr;
|
struct idr event_idr;
|
||||||
/* Event page */
|
/* Event page */
|
||||||
struct kfd_signal_page *signal_page;
|
struct kfd_signal_page *signal_page;
|
||||||
|
size_t signal_mapped_size;
|
||||||
size_t signal_event_count;
|
size_t signal_event_count;
|
||||||
bool signal_event_limit_reached;
|
bool signal_event_limit_reached;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user