]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amdkfd: Make event limit dependent on user mode mapping size
authorFelix Kuehling <Felix.Kuehling@amd.com>
Fri, 27 Oct 2017 23:35:29 +0000 (19:35 -0400)
committerOded Gabbay <oded.gabbay@gmail.com>
Fri, 27 Oct 2017 23:35:29 +0000 (19:35 -0400)
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>
drivers/gpu/drm/amd/amdkfd/kfd_events.c
drivers/gpu/drm/amd/amdkfd/kfd_priv.h

index 26e8045aa760b2bb45f1dc8ad1c45ec4af403b3c..cb92d4b72400953c453f92357b82fbd6ad4ef1fc 100644 (file)
@@ -97,9 +97,17 @@ static int allocate_event_notification_slot(struct kfd_process *p,
                p->signal_page = allocate_signal_page(p);
                if (!p->signal_page)
                        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);
        if (id < 0)
                return id;
@@ -173,7 +181,8 @@ static int create_signal_event(struct file *devkfd,
 {
        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) {
                        pr_warn("Signal event wasn't created because limit was reached\n");
                        p->signal_event_limit_reached = true;
@@ -744,12 +753,12 @@ out:
 
 int kfd_event_mmap(struct kfd_process *p, struct vm_area_struct *vma)
 {
-
        unsigned long pfn;
        struct kfd_signal_page *page;
+       int ret;
 
-       /* check required size is logical */
-       if (get_order(KFD_SIGNAL_EVENT_LIMIT * 8) !=
+       /* check required size doesn't exceed the allocated size */
+       if (get_order(KFD_SIGNAL_EVENT_LIMIT * 8) <
                        get_order(vma->vm_end - vma->vm_start)) {
                pr_err("Event page mmap requested illegal size\n");
                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;
 
        /* 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);
+       if (!ret)
+               p->signal_mapped_size = vma->vm_end - vma->vm_start;
+
+       return ret;
 }
 
 /*
index ebae8e1891d27d294329451a6cc0c151aca4a2b0..ba26da81d8ec5079acf1c7d3cb52502dfcc4e672 100644 (file)
@@ -543,6 +543,7 @@ struct kfd_process {
        struct idr event_idr;
        /* Event page */
        struct kfd_signal_page *signal_page;
+       size_t signal_mapped_size;
        size_t signal_event_count;
        bool signal_event_limit_reached;
 };