Your message dated Sun, 23 Jul 2023 09:00:12 +0000
with message-id <[email protected]>
and subject line Bug#1023276: fixed in evdi 1.14.0+dfsg-1
has caused the Debian Bug report #1023276,
regarding evdi: diff for NMU version 1.12.0+dfsg-0.1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
1023276: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1023276
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: evdi
Version: 1.9.0+dfsg-1
Severity: normal
Tags: patch  pending

Dear maintainer,

I've prepared an NMU for evdi (versioned as 1.12.0+dfsg-0.1) and uploaded it to
DELAYED/0 as there has been no activity for some time and it has been dropped
from testing.

Regards.

diff -Nru evdi-1.9.0+dfsg/debian/changelog evdi-1.12.0+dfsg/debian/changelog
--- evdi-1.9.0+dfsg/debian/changelog    2021-01-26 10:32:36.000000000 -0500
+++ evdi-1.12.0+dfsg/debian/changelog   2022-11-01 11:56:26.000000000 -0400
@@ -1,3 +1,12 @@
+evdi (1.12.0+dfsg-0.1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * New upstream release (Closes: #994892, #1017058)
+  * Import patch to fix FTBFS in Linux >= 6.0 from upstream
+  * Add dh-dkms to build-depends
+
+ -- Harlan Lieberman-Berg <[email protected]>  Tue, 01 Nov 2022 11:56:26 
-0400
+
 evdi (1.9.0+dfsg-1) unstable; urgency=medium
 
   * new upstream release 1.9.0
diff -Nru evdi-1.9.0+dfsg/debian/control evdi-1.12.0+dfsg/debian/control
--- evdi-1.9.0+dfsg/debian/control      2021-01-26 10:32:36.000000000 -0500
+++ evdi-1.12.0+dfsg/debian/control     2022-11-01 11:56:26.000000000 -0400
@@ -2,7 +2,7 @@
 Section: misc
 Priority: optional
 Maintainer: Hanno Stock <[email protected]>
-Build-Depends: debhelper-compat (= 13), dkms, dh-exec, libdrm-dev
+Build-Depends: debhelper-compat (= 13), dh-dkms, dkms, dh-exec, libdrm-dev
 Standards-Version: 4.5.0
 Rules-Requires-Root: no
 Homepage: https://github.com/DisplayLink/evdi
diff -Nru evdi-1.9.0+dfsg/debian/patches/0001-fix-6.0-ftbfs.patch 
evdi-1.12.0+dfsg/debian/patches/0001-fix-6.0-ftbfs.patch
--- evdi-1.9.0+dfsg/debian/patches/0001-fix-6.0-ftbfs.patch     1969-12-31 
19:00:00.000000000 -0500
+++ evdi-1.12.0+dfsg/debian/patches/0001-fix-6.0-ftbfs.patch    2022-11-01 
11:56:26.000000000 -0400
@@ -0,0 +1,53 @@
+From bdc258b25df4d00f222fde0e3c5003bf88ef17b5 Mon Sep 17 00:00:00 2001
+From: Adam Tazul <[email protected]>
+Date: Thu, 13 Oct 2022 10:50:00 +0100
+Subject: [PATCH] Add support for kernel 6.0 + a minor fix (#381)
+
+* Add support for kernel 6.0
+
+Fixes #376 by implementing @Crashdummyy's fix as posted 
[here](https://github.com/DisplayLink/evdi/issues/376#issuecomment-1237450695)
+
+* Fixing the style used in evdi_painter.c
+
+* Update evdi_painter.c
+
+* drm_framebuffer is only included on 5.15 and later
+
+* drm_framebuffer is only included on 6.0.0 and later
+
+* drm_framebuffer is only included on 6.0.0 and later
+
+* drm_framebuffer is only included on 6.0.0 and later
+
+* drm_framebuffer is only included on 5.15.0 and later
+---
+ module/evdi_drm_drv.h | 2 +-
+ module/evdi_painter.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+Index: evdi/module/evdi_drm_drv.h
+===================================================================
+--- evdi.orig/module/evdi_drm_drv.h
++++ evdi/module/evdi_drm_drv.h
+@@ -26,7 +26,7 @@
+ #include <drm/drmP.h>
+ #endif
+ #if KERNEL_VERSION(5, 15, 0) <= LINUX_VERSION_CODE
+-#include <drm/drm_legacy.h>
++#include <drm/drm_framebuffer.h>
+ #else
+ #include <drm/drm_irq.h>
+ #endif
+Index: evdi/module/evdi_painter.c
+===================================================================
+--- evdi.orig/module/evdi_painter.c
++++ evdi/module/evdi_painter.c
+@@ -885,7 +885,7 @@ evdi_painter_connect(struct evdi_device
+ 
+       painter_lock(painter);
+ 
+-        evdi->pixel_area_limit = pixel_area_limit;
++      evdi->pixel_area_limit = pixel_area_limit;
+       evdi->pixel_per_second_limit = pixel_per_second_limit;
+       painter->drm_filp = file;
+       kfree(painter->edid);
diff -Nru evdi-1.9.0+dfsg/debian/patches/series 
evdi-1.12.0+dfsg/debian/patches/series
--- evdi-1.9.0+dfsg/debian/patches/series       1969-12-31 19:00:00.000000000 
-0500
+++ evdi-1.12.0+dfsg/debian/patches/series      2022-11-01 11:56:26.000000000 
-0400
@@ -0,0 +1 @@
+0001-fix-6.0-ftbfs.patch
diff -Nru evdi-1.9.0+dfsg/library/evdi_lib.c evdi-1.12.0+dfsg/library/evdi_lib.c
--- evdi-1.9.0+dfsg/library/evdi_lib.c  2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/library/evdi_lib.c 2022-07-13 09:58:06.000000000 -0400
@@ -29,7 +29,7 @@
 #define EVDI_INVALID_DEVICE_INDEX -1
 
 #define EVDI_MODULE_COMPATIBILITY_VERSION_MAJOR 1
-#define EVDI_MODULE_COMPATIBILITY_VERSION_MINOR 8
+#define EVDI_MODULE_COMPATIBILITY_VERSION_MINOR 9
 #define EVDI_MODULE_COMPATIBILITY_VERSION_PATCH 0
 
 #define evdi_log(...) do {                                             \
@@ -468,15 +468,45 @@
        return dev_index;
 }
 
-static int find_unused_card_for(const char *sysfs_parent_device_path)
+static bool is_correct_parent_device(const char *dirname, const char 
*parent_device)
 {
+       char link_path[PATH_MAX];
+
+       snprintf(link_path, PATH_MAX - 7, "%s/device", dirname);
+
+       if (parent_device == NULL)
+               return access(link_path, F_OK) != 0;
+
+       char link_resolution[PATH_MAX];
+       const ssize_t link_resolution_len = readlink(link_path, 
link_resolution, PATH_MAX);
+
+       if (link_resolution_len == -1 || link_resolution_len == PATH_MAX)
+               return false;
+
+       link_resolution[link_resolution_len] = '\0';
+       char *parent_device_token = strrchr(link_resolution, '/');
+
+       if (strlen(parent_device) < 2)
+               return false;
+
+       parent_device_token++;
+       size_t len = strlen(parent_device_token);
+
+       bool is_same_device = strlen(parent_device) == len && 
strncmp(parent_device_token, parent_device, len) == 0;
+
+       return is_same_device;
+}
+
+static int find_unused_card_for(const char *parent_device)
+{
+       char evdi_platform_root[] = "/sys/bus/platform/devices";
        struct dirent *fd_entry;
        DIR *fd_dir;
        int device_index = EVDI_INVALID_DEVICE_INDEX;
 
-       fd_dir = opendir(sysfs_parent_device_path);
+       fd_dir = opendir(evdi_platform_root);
        if (fd_dir == NULL) {
-               evdi_log("Failed to open dir %s", sysfs_parent_device_path);
+               evdi_log("Failed to open dir %s", evdi_platform_root);
                return device_index;
        }
 
@@ -484,9 +514,16 @@
                if (strncmp(fd_entry->d_name, "evdi", 4) != 0)
                        continue;
 
+               char evdi_path[PATH_MAX];
+
+               snprintf(evdi_path, PATH_MAX, "%s/%s", evdi_platform_root, 
fd_entry->d_name);
+
+               if (!is_correct_parent_device(evdi_path, parent_device))
+                       continue;
+
                char evdi_drm_path[PATH_MAX];
 
-               snprintf(evdi_drm_path, PATH_MAX, "%s/%s/drm", 
sysfs_parent_device_path, fd_entry->d_name);
+               snprintf(evdi_drm_path, PATH_MAX - strlen(evdi_path), "%s/drm", 
evdi_path);
                int dev_index = get_drm_device_index(evdi_drm_path);
 
                assert(dev_index < EVDI_USAGE_LEN && dev_index >= 0);
@@ -503,37 +540,30 @@
 
 static int get_generic_device(void)
 {
-       char evdi_platform_root[] = "/sys/devices/platform";
        int device_index = EVDI_INVALID_DEVICE_INDEX;
 
-       device_index = find_unused_card_for(evdi_platform_root);
+       device_index = find_unused_card_for(NULL);
        if (device_index == EVDI_INVALID_DEVICE_INDEX) {
-               evdi_log("Creating card in %s", evdi_platform_root);
+               evdi_log("Creating card in /sys/devices/platform");
                write_add_device("1", 1);
-               device_index = find_unused_card_for(evdi_platform_root);
+               device_index = find_unused_card_for(NULL);
        }
 
        return device_index;
 }
 
-static int get_device_attached_to_usb(const char *bus_ident)
+static int get_device_attached_to_usb(const char *sysfs_parent_device)
 {
        int device_index = EVDI_INVALID_DEVICE_INDEX;
-       char evdi_usb_parent_path[PATH_MAX] = "/sys/bus/usb/devices/";
-
-       strncat(evdi_usb_parent_path, bus_ident, PATH_MAX - 
strlen(evdi_usb_parent_path));
+       const char *parent_device = &sysfs_parent_device[4];
 
-       device_index = find_unused_card_for(evdi_usb_parent_path);
+       device_index = find_unused_card_for(parent_device);
        if (device_index == EVDI_INVALID_DEVICE_INDEX) {
-               evdi_log("Creating card for %s", bus_ident);
-               char usb_dev_path[PATH_MAX] = "usb:";
-               const size_t current_len = strlen(usb_dev_path);
+               evdi_log("Creating card for usb device %s in 
/sys/bus/platform/devices", parent_device);
+               const size_t len = strlen(sysfs_parent_device);
 
-               strncat(usb_dev_path, bus_ident, PATH_MAX - current_len);
-               const size_t len = strlen(usb_dev_path);
-
-               write_add_device(usb_dev_path, len);
-               device_index = find_unused_card_for(evdi_usb_parent_path);
+               write_add_device(sysfs_parent_device, len);
+               device_index = find_unused_card_for(parent_device);
        }
 
        return device_index;
@@ -616,14 +646,8 @@
        if (sysfs_parent_device == NULL)
                device_index = get_generic_device();
 
-       if (sysfs_parent_device != NULL && strncmp(sysfs_parent_device, "usb:", 
4) == 0 && strlen(sysfs_parent_device) > 4) {
-               char bus_ident[PATH_MAX];
-               const size_t len = strlen(sysfs_parent_device) - 4;
-
-               strncpy(bus_ident, &sysfs_parent_device[4], len);
-               bus_ident[len] = 0;
-               device_index = get_device_attached_to_usb(bus_ident);
-       }
+       if (sysfs_parent_device != NULL && strncmp(sysfs_parent_device, "usb:", 
4) == 0 && strlen(sysfs_parent_device) > 4)
+               device_index = get_device_attached_to_usb(sysfs_parent_device);
 
        if (device_index >= 0 && device_index < EVDI_USAGE_LEN)  {
                evdi_handle handle = evdi_open(device_index);
@@ -651,14 +675,16 @@
 void evdi_connect(evdi_handle handle,
                  const unsigned char *edid,
                  const unsigned int edid_length,
-                 const uint32_t sku_area_limit)
+                 const uint32_t pixel_area_limit,
+                 const uint32_t pixel_per_second_limit)
 {
        struct drm_evdi_connect cmd = {
                .connected = 1,
                .dev_index = handle->device_index,
                .edid = edid,
                .edid_length = edid_length,
-               .sku_area_limit = sku_area_limit,
+               .pixel_area_limit = pixel_area_limit,
+               .pixel_per_second_limit = pixel_per_second_limit,
        };
 
        do_ioctl(handle->fd, DRM_IOCTL_EVDI_CONNECT, &cmd, "connect");
@@ -666,44 +692,22 @@
 
 void evdi_disconnect(evdi_handle handle)
 {
-       struct drm_evdi_connect cmd = { 0, 0, 0, 0, 0 };
+       struct drm_evdi_connect cmd = { 0, 0, 0, 0, 0, 0 };
 
        do_ioctl(handle->fd, DRM_IOCTL_EVDI_CONNECT, &cmd, "disconnect");
 }
 
-void evdi_enable_cursor_events(evdi_handle handle)
+void evdi_enable_cursor_events(evdi_handle handle, bool enable)
 {
-       char path[PATH_MAX] = {0};
-       static const char enable[] = "Y";
-       int path_len = 0;
-       FILE *cursor_evs = NULL;
-       size_t written = 0;
-       const size_t elem_bytes = 1;
-       int errcode = 0;
-
-       if (evdi_device_to_platform(handle->device_index, path) !=
-           AVAILABLE) {
-               evdi_log("Failed to enable cursor events");
-               evdi_log("Device /dev/dri/card%d, device is not available.",
-                       handle->device_index);
-               return;
-       }
+       struct drm_evdi_enable_cursor_events cmd = {
+               .enable = enable,
+       };
 
-       path_len = strlen(path);
-       snprintf(path+path_len, PATH_MAX-path_len, "/cursor_events");
-       cursor_evs = fopen(path, "w");
-       if (cursor_evs == NULL) {
-               evdi_log("Failed to open %s, err: %s", path, strerror(errno));
-               return;
-       }
+       evdi_log("%s cursor events on /dev/dri/card%d",
+               (enable ? "Enabling" : "Disabling"),
+               handle->device_index);
 
-       written = fwrite(enable, elem_bytes, sizeof(enable), cursor_evs);
-       errcode = errno;
-       fclose(cursor_evs);
-       evdi_log("Enabling cursor events on /dev/dri/card%d %s %s",
-               handle->device_index,
-               written < sizeof(enable) ? "failed: " : "succeeded",
-               written < sizeof(enable) ? strerror(errcode) : "");
+       do_ioctl(handle->fd, DRM_IOCTL_EVDI_ENABLE_CURSOR_EVENTS, &cmd, "enable 
cursor events");
 }
 
 void evdi_grab_pixels(evdi_handle handle,
@@ -861,6 +865,8 @@
                        cursor_set.buffer = malloc(size);
                        memcpy(cursor_set.buffer, ptr, size);
                        munmap(ptr, size);
+               } else {
+                       evdi_log("Error: mmap failed with error: %s", 
strerror(errno));
                }
        }
 
@@ -936,10 +942,13 @@
                if (evtctx->cursor_set_handler) {
                        struct drm_evdi_event_cursor_set *event =
                                (struct drm_evdi_event_cursor_set *) e;
+                       struct evdi_cursor_set cursor_set = 
to_evdi_cursor_set(handle, event);
 
-                       evtctx->cursor_set_handler(to_evdi_cursor_set(handle,
-                                                                     event),
-                                                  evtctx->user_data);
+                       if (cursor_set.enabled && cursor_set.buffer == NULL)
+                               evdi_log("Error: Cursor buffer is null!");
+                       else
+                               evtctx->cursor_set_handler(cursor_set,
+                                                          evtctx->user_data);
                }
                break;
 
diff -Nru evdi-1.9.0+dfsg/library/evdi_lib.h evdi-1.12.0+dfsg/library/evdi_lib.h
--- evdi-1.9.0+dfsg/library/evdi_lib.h  2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/library/evdi_lib.h 2022-07-13 09:58:06.000000000 -0400
@@ -12,7 +12,7 @@
 #endif
 
 #define LIBEVDI_VERSION_MAJOR 1
-#define LIBEVDI_VERSION_MINOR 9
+#define LIBEVDI_VERSION_MINOR 12
 #define LIBEVDI_VERSION_PATCH 0
 
 struct evdi_lib_version {
@@ -107,9 +107,10 @@
 void evdi_close(evdi_handle handle);
 void evdi_connect(evdi_handle handle, const unsigned char *edid,
                  const unsigned int edid_length,
-                 const uint32_t sku_area_limit);
+                 const uint32_t pixel_area_limit,
+                 const uint32_t pixel_per_second_limit);
 void evdi_disconnect(evdi_handle handle);
-void evdi_enable_cursor_events(evdi_handle handle);
+void evdi_enable_cursor_events(evdi_handle handle, bool enable);
 
 void evdi_grab_pixels(evdi_handle handle,
                      struct evdi_rect *rects,
diff -Nru evdi-1.9.0+dfsg/library/Makefile evdi-1.12.0+dfsg/library/Makefile
--- evdi-1.9.0+dfsg/library/Makefile    2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/library/Makefile   2022-07-13 09:58:06.000000000 -0400
@@ -8,9 +8,9 @@
 RM ?= rm
 
 DEPS = evdi_ioctl.h
-CFLAGS := -I../module -std=gnu99 -fPIC $(CFLAGS)
+CFLAGS := -I../module -std=gnu99 -fPIC -D_FILE_OFFSET_BITS=64 $(CFLAGS)
 
-LIBVER := 1.9.0
+LIBVER := 1.12.0
 LIBABI := 0
 
 PREFIX ?= /usr/local
diff -Nru evdi-1.9.0+dfsg/module/dkms.conf evdi-1.12.0+dfsg/module/dkms.conf
--- evdi-1.9.0+dfsg/module/dkms.conf    2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/module/dkms.conf   2022-07-13 09:58:06.000000000 -0400
@@ -7,7 +7,7 @@
 #
 
 PACKAGE_NAME="evdi"
-PACKAGE_VERSION=1.9.0
+PACKAGE_VERSION=1.12.0
 AUTOINSTALL=yes
 
 MAKE[0]="make all INCLUDEDIR=/lib/modules/$kernelver/build/include 
KVERSION=$kernelver DKMS_BUILD=1"
diff -Nru evdi-1.9.0+dfsg/module/evdi_connector.c 
evdi-1.12.0+dfsg/module/evdi_connector.c
--- evdi-1.9.0+dfsg/module/evdi_connector.c     2021-01-26 09:31:59.000000000 
-0500
+++ evdi-1.12.0+dfsg/module/evdi_connector.c    2022-07-13 09:58:06.000000000 
-0400
@@ -50,11 +50,14 @@
        ret = drm_mode_connector_update_edid_property(connector, edid);
 #endif
 
-       if (!ret)
-               ret = drm_add_edid_modes(connector, edid);
-       else
-               EVDI_ERROR("Failed to set edid modes! error: %d", ret);
+       if (ret) {
+               EVDI_ERROR("Failed to set edid property! error: %d", ret);
+               goto err;
+       }
 
+       ret = drm_add_edid_modes(connector, edid);
+       EVDI_INFO("(card%d) Edid property set", evdi->dev_index);
+err:
        kfree(edid);
        return ret;
 }
@@ -63,13 +66,15 @@
                                            struct drm_display_mode *mode)
 {
        struct evdi_device *evdi = connector->dev->dev_private;
-       uint32_t mode_area = mode->hdisplay * mode->vdisplay;
+       uint32_t area_limit = mode->hdisplay * mode->vdisplay;
+       uint32_t mode_limit = area_limit * drm_mode_vrefresh(mode);
 
-       if (evdi->sku_area_limit == 0)
+       if (evdi->pixel_per_second_limit == 0)
                return MODE_OK;
 
-       if (mode_area > evdi->sku_area_limit) {
-               EVDI_WARN("(dev=%d) Mode %dx%d@%d rejected\n",
+       if (area_limit > evdi->pixel_area_limit ||
+           mode_limit > evdi->pixel_per_second_limit) {
+               EVDI_WARN("(card%d) Mode %dx%d@%d rejected\n",
                        evdi->dev_index,
                        mode->hdisplay,
                        mode->vdisplay,
@@ -87,11 +92,11 @@
 
        EVDI_CHECKPT();
        if (evdi_painter_is_connected(evdi->painter)) {
-               EVDI_DEBUG("(dev=%d) poll connector state: connected\n",
+               EVDI_INFO("(card%d) Connector state: connected\n",
                           evdi->dev_index);
                return connector_status_connected;
        }
-       EVDI_DEBUG("(dev=%d) poll connector state: disconnected\n",
+       EVDI_VERBOSE("(card%d) Connector state: disconnected\n",
                   evdi->dev_index);
        return connector_status_disconnected;
 }
diff -Nru evdi-1.9.0+dfsg/module/evdi_cursor.c 
evdi-1.12.0+dfsg/module/evdi_cursor.c
--- evdi-1.9.0+dfsg/module/evdi_cursor.c        2021-01-26 09:31:59.000000000 
-0500
+++ evdi-1.12.0+dfsg/module/evdi_cursor.c       2022-07-13 09:58:06.000000000 
-0400
@@ -55,7 +55,7 @@
        if (obj)
                drm_gem_object_get(&obj->base);
        if (cursor->obj)
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
                drm_gem_object_put(&cursor->obj->base);
 #else
                drm_gem_object_put_unlocked(&cursor->obj->base);
@@ -232,8 +232,8 @@
                        bool const is_pix_sane =
                                mouse_pix_x >= 0 &&
                                mouse_pix_y >= 0 &&
-                               mouse_pix_x < fb->width &&
-                               mouse_pix_y < fb->height;
+                               mouse_pix_x < (int)fb->width &&
+                               mouse_pix_y < (int)fb->height;
 
                        if (!is_pix_sane)
                                continue;
diff -Nru evdi-1.9.0+dfsg/module/evdi_debug.c 
evdi-1.12.0+dfsg/module/evdi_debug.c
--- evdi-1.9.0+dfsg/module/evdi_debug.c 2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/module/evdi_debug.c        2022-07-13 09:58:06.000000000 
-0400
@@ -10,7 +10,7 @@
 
 #include "evdi_debug.h"
 
-void evdi_log_process(void)
+void evdi_log_process(char *buf, size_t size)
 {
        int task_pid = (int)task_pid_nr(current);
        char task_comm[TASK_COMM_LEN] = { 0 };
@@ -21,13 +21,13 @@
                char process_comm[TASK_COMM_LEN] = { 0 };
 
                get_task_comm(process_comm, current->group_leader);
-               EVDI_INFO("Task %d (%s) of process %d (%s)\n",
+               snprintf(buf, size, "Task %d (%s) of process %d (%s)",
                          task_pid,
                          task_comm,
                          (int)task_pid_nr(current->group_leader),
                          process_comm);
        } else {
-               EVDI_INFO("Task %d (%s)\n",
+               snprintf(buf, size, "Task %d (%s)",
                          task_pid,
                          task_comm);
        }
diff -Nru evdi-1.9.0+dfsg/module/evdi_debug.h 
evdi-1.12.0+dfsg/module/evdi_debug.h
--- evdi-1.9.0+dfsg/module/evdi_debug.h 2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/module/evdi_debug.h        2022-07-13 09:58:06.000000000 
-0400
@@ -11,7 +11,6 @@
 
 #include "evdi_params.h"
 
-#define EVDI_LOGLEVEL_ALWAYS  0
 #define EVDI_LOGLEVEL_FATAL   1
 #define EVDI_LOGLEVEL_ERROR   2
 #define EVDI_LOGLEVEL_WARN    3
@@ -53,6 +52,6 @@
 #define EVDI_ENTER() EVDI_VERBOSE("enter\n")
 #define EVDI_EXIT() EVDI_VERBOSE("exit\n")
 
-void evdi_log_process(void);
+void evdi_log_process(char *buf, size_t size);
 
 #endif /* EVDI_DEBUG_H */
diff -Nru evdi-1.9.0+dfsg/module/evdi_drm_drv.c 
evdi-1.12.0+dfsg/module/evdi_drm_drv.c
--- evdi-1.9.0+dfsg/module/evdi_drm_drv.c       2021-01-26 09:31:59.000000000 
-0500
+++ evdi-1.12.0+dfsg/module/evdi_drm_drv.c      2022-07-13 09:58:06.000000000 
-0400
@@ -12,14 +12,22 @@
  */
 
 #include <linux/version.h>
-#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_ioctl.h>
+#include <drm/drm_file.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_vblank.h>
+#elif KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #else
 #include <drm/drmP.h>
 #endif
 #if KERNEL_VERSION(5, 1, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #include <drm/drm_probe_helper.h>
 #endif
-
+#if KERNEL_VERSION(5, 8, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_managed.h>
+#endif
+#include <drm/drm_atomic_helper.h>
 #include "evdi_drm_drv.h"
 #include "evdi_platform_drv.h"
 #include "evdi_cursor.h"
@@ -37,13 +45,18 @@
                          DRM_UNLOCKED),
        DRM_IOCTL_DEF_DRV(EVDI_DDCCI_RESPONSE, 
evdi_painter_ddcci_response_ioctl,
                          DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(EVDI_ENABLE_CURSOR_EVENTS, 
evdi_painter_enable_cursor_events_ioctl,
+                         DRM_UNLOCKED),
 };
 
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
 static const struct vm_operations_struct evdi_gem_vm_ops = {
        .fault = evdi_gem_fault,
        .open = drm_gem_vm_open,
        .close = drm_gem_vm_close,
 };
+#endif
 
 static const struct file_operations evdi_driver_fops = {
        .owner = THIS_MODULE,
@@ -53,12 +66,16 @@
        .read = drm_read,
        .unlocked_ioctl = drm_ioctl,
        .release = drm_release,
+
 #ifdef CONFIG_COMPAT
        .compat_ioctl = evdi_compat_ioctl,
 #endif
+
        .llseek = noop_llseek,
 };
 
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
 static int evdi_enable_vblank(__always_unused struct drm_device *dev,
                              __always_unused unsigned int pipe)
 {
@@ -69,30 +86,39 @@
                                __always_unused unsigned int pipe)
 {
 }
+#endif
 
 static struct drm_driver driver = {
-#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE || defined(EL8)
        .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
 #else
        .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
                         | DRIVER_ATOMIC,
 #endif
-       .unload = evdi_driver_unload,
-       .preclose = evdi_driver_preclose,
+       .unload = evdi_drm_device_unload,
 
+       .open = evdi_driver_open,
        .postclose = evdi_driver_postclose,
 
        /* gem hooks */
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#elif KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
        .gem_free_object_unlocked = evdi_gem_free_object,
 #else
        .gem_free_object = evdi_gem_free_object,
 #endif
+
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
        .gem_vm_ops = &evdi_gem_vm_ops,
+#endif
 
        .dumb_create = evdi_dumb_create,
        .dumb_map_offset = evdi_gem_mmap,
+#if KERNEL_VERSION(5, 12, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
        .dumb_destroy = drm_gem_dumb_destroy,
+#endif
 
        .ioctls = evdi_painter_ioctls,
        .num_ioctls = ARRAY_SIZE(evdi_painter_ioctls),
@@ -102,12 +128,15 @@
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_import = drm_gem_prime_import,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
+       .preclose = evdi_driver_preclose,
        .gem_prime_export = drm_gem_prime_export,
        .gem_prime_get_sg_table = evdi_prime_get_sg_table,
-       .gem_prime_import_sg_table = evdi_prime_import_sg_table,
-
        .enable_vblank = evdi_enable_vblank,
        .disable_vblank = evdi_disable_vblank,
+#endif
+       .gem_prime_import_sg_table = evdi_prime_import_sg_table,
 
        .name = DRIVER_NAME,
        .desc = DRIVER_DESC,
@@ -117,7 +146,15 @@
        .patchlevel = DRIVER_PATCH,
 };
 
-static int evdi_driver_setup(struct drm_device *dev)
+#if KERNEL_VERSION(5, 8, 0) <= LINUX_VERSION_CODE
+static void evdi_drm_device_release_cb(__always_unused struct drm_device *dev,
+                                      __always_unused void *ptr)
+{
+       EVDI_INFO("Evdi drm_device removed.\n");
+}
+#endif
+
+static int evdi_drm_device_setup(struct drm_device *dev)
 {
        struct evdi_device *evdi;
        int ret;
@@ -129,19 +166,12 @@
 
        evdi->ddev = dev;
        dev->dev_private = evdi;
+       evdi->dev_index = dev->primary->index;
 
+       evdi->cursor_events_enabled = false;
        ret =  evdi_cursor_init(&evdi->cursor);
        if (ret)
-               goto err;
-
-       evdi->cursor_attr = (struct dev_ext_attribute) {
-           __ATTR(cursor_events, 0644, device_show_bool, device_store_bool),
-           &evdi->cursor_events_enabled
-       };
-       ret = device_create_file(dev->dev, &evdi->cursor_attr.attr);
-       if (ret)
-               goto err_fb;
-
+               goto err_free;
 
        EVDI_CHECKPT();
        evdi_modeset_init(dev);
@@ -149,7 +179,7 @@
 #ifdef CONFIG_FB
        ret = evdi_fbdev_init(dev);
        if (ret)
-               goto err;
+               goto err_cursor;
 #endif /* CONFIG_FB */
 
        ret = drm_vblank_init(dev, 1);
@@ -162,21 +192,26 @@
 
        drm_kms_helper_poll_init(dev);
 
+#if KERNEL_VERSION(5, 8, 0) <= LINUX_VERSION_CODE
+       ret = drmm_add_action_or_reset(dev, evdi_drm_device_release_cb, NULL);
+       if (ret)
+               goto err_fb;
+#endif
        return 0;
 
 err_fb:
 #ifdef CONFIG_FB
        evdi_fbdev_cleanup(dev);
+err_cursor:
 #endif /* CONFIG_FB */
-err:
-       EVDI_ERROR("%d\n", ret);
-       if (evdi->cursor)
-               evdi_cursor_free(evdi->cursor);
+       evdi_cursor_free(evdi->cursor);
+err_free:
+       EVDI_ERROR("Failed to setup drm device %d\n", ret);
        kfree(evdi);
        return ret;
 }
 
-void evdi_driver_unload(struct drm_device *dev)
+void evdi_drm_device_unload(struct drm_device *dev)
 {
        struct evdi_device *evdi = dev->dev_private;
 
@@ -190,7 +225,6 @@
        if (evdi->cursor)
                evdi_cursor_free(evdi->cursor);
 
-       device_remove_file(dev->dev, &evdi->cursor_attr.attr);
        evdi_painter_cleanup(evdi->painter);
 #ifdef CONFIG_FB
        evdi_fbdev_cleanup(dev);
@@ -200,6 +234,16 @@
        kfree(evdi);
 }
 
+int evdi_driver_open(struct drm_device *drm_dev, __always_unused struct 
drm_file *file)
+{
+       struct evdi_device *evdi = drm_dev->dev_private;
+       char buf[100];
+
+       evdi_log_process(buf, sizeof(buf));
+       EVDI_INFO("(card%d) Opened by %s\n", evdi->dev_index, buf);
+       return 0;
+}
+
 static void evdi_driver_close(struct drm_device *drm_dev, struct drm_file 
*file)
 {
        struct evdi_device *evdi = drm_dev->dev_private;
@@ -217,10 +261,11 @@
 void evdi_driver_postclose(struct drm_device *drm_dev, struct drm_file *file)
 {
        struct evdi_device *evdi = drm_dev->dev_private;
+       char buf[100];
 
-       EVDI_DEBUG("(dev=%d) Process tries to close us, postclose\n",
-                  evdi ? evdi->dev_index : -1);
-       evdi_log_process();
+       evdi_log_process(buf, sizeof(buf));
+       EVDI_INFO("(card%d) Closed by %s\n",
+                  evdi->dev_index, buf);
 
        evdi_driver_close(drm_dev, file);
 }
@@ -234,7 +279,7 @@
        if (IS_ERR(dev))
                return dev;
 
-       ret = evdi_driver_setup(dev);
+       ret = evdi_drm_device_setup(dev);
        if (ret)
                goto err_free;
 
@@ -252,6 +297,8 @@
 int evdi_drm_device_remove(struct drm_device *dev)
 {
        drm_dev_unplug(dev);
+       drm_atomic_helper_shutdown(dev);
+       drm_dev_put(dev);
        return 0;
 }
 
diff -Nru evdi-1.9.0+dfsg/module/evdi_drm_drv.h 
evdi-1.12.0+dfsg/module/evdi_drm_drv.h
--- evdi-1.9.0+dfsg/module/evdi_drm_drv.h       2021-01-26 09:31:59.000000000 
-0500
+++ evdi-1.12.0+dfsg/module/evdi_drm_drv.h      2022-07-13 09:58:06.000000000 
-0400
@@ -15,16 +15,21 @@
 
 #include <linux/module.h>
 #include <linux/version.h>
+#include <linux/mutex.h>
 #include <linux/device.h>
 #if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #include <drm/drm_drv.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_ioctl.h>
-#include <drm/drm_irq.h>
 #include <drm/drm_vblank.h>
 #else
 #include <drm/drmP.h>
 #endif
+#if KERNEL_VERSION(5, 15, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_legacy.h>
+#else
+#include <drm/drm_irq.h>
+#endif
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_rect.h>
@@ -44,10 +49,10 @@
        struct drm_device *ddev;
        struct drm_connector *conn;
        struct evdi_cursor *cursor;
-       struct dev_ext_attribute cursor_attr;
        bool cursor_events_enabled;
 
-       uint32_t sku_area_limit;
+       uint32_t pixel_area_limit;
+       uint32_t pixel_per_second_limit;
 
        struct evdi_fbdev *fbdev;
        struct evdi_painter *painter;
@@ -59,7 +64,12 @@
 struct evdi_gem_object {
        struct drm_gem_object base;
        struct page **pages;
+       unsigned int pages_pin_count;
+       struct mutex pages_lock;
        void *vmapping;
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+       bool vmap_is_iomem;
+#endif
        struct sg_table *sg;
 #if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE || defined(EL8)
        struct dma_resv *resv;
@@ -68,6 +78,7 @@
        struct reservation_object *resv;
        struct reservation_object _resv;
 #endif
+       bool allow_sw_cursor_rect_updates;
 };
 
 #define to_evdi_bo(x) container_of(x, struct evdi_gem_object, base)
@@ -87,8 +98,8 @@
 
 struct drm_encoder *evdi_encoder_init(struct drm_device *dev);
 
-int evdi_driver_load(struct drm_device *dev, unsigned long flags);
-void evdi_driver_unload(struct drm_device *dev);
+void evdi_drm_device_unload(struct drm_device *dev);
+int evdi_driver_open(struct drm_device *drm_dev, struct drm_file *file);
 void evdi_driver_preclose(struct drm_device *dev, struct drm_file *file_priv);
 void evdi_driver_postclose(struct drm_device *dev, struct drm_file *file_priv);
 
@@ -96,6 +107,7 @@
 long evdi_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 #endif
 
+
 #ifdef CONFIG_FB
 int evdi_fbdev_init(struct drm_device *dev);
 void evdi_fbdev_cleanup(struct drm_device *dev);
@@ -146,7 +158,6 @@
 void evdi_painter_dpms_notify(struct evdi_device *evdi, int mode);
 void evdi_painter_mode_changed_notify(struct evdi_device *evdi,
                                      struct drm_display_mode *mode);
-void evdi_painter_crtc_state_notify(struct evdi_device *evdi, int state);
 unsigned int evdi_painter_poll(struct file *filp,
                               struct poll_table_struct *wait);
 
@@ -160,6 +171,8 @@
                                      struct drm_file *file);
 int evdi_painter_ddcci_response_ioctl(struct drm_device *drm_dev, void *data,
                                      struct drm_file *file);
+int evdi_painter_enable_cursor_events_ioctl(struct drm_device *drm_dev, void 
*data,
+                                         struct drm_file *file);
 
 int evdi_painter_init(struct evdi_device *evdi);
 void evdi_painter_cleanup(struct evdi_painter *painter);
diff -Nru evdi-1.9.0+dfsg/module/evdi_drm.h evdi-1.12.0+dfsg/module/evdi_drm.h
--- evdi-1.9.0+dfsg/module/evdi_drm.h   2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/module/evdi_drm.h  2022-07-13 09:58:06.000000000 -0400
@@ -47,7 +47,8 @@
        int32_t dev_index;
        const unsigned char * __user edid;
        uint32_t edid_length;
-       uint32_t sku_area_limit;
+       uint32_t pixel_area_limit;
+       uint32_t pixel_per_second_limit;
 };
 
 struct drm_evdi_request_update {
@@ -94,6 +95,11 @@
        uint8_t result;
 };
 
+struct drm_evdi_enable_cursor_events {
+       struct drm_event base;
+       uint8_t enable;
+};
+
 #define DDCCI_BUFFER_SIZE 64
 
 struct drm_evdi_event_ddcci_data {
@@ -109,6 +115,7 @@
 #define DRM_EVDI_REQUEST_UPDATE   0x01
 #define DRM_EVDI_GRABPIX          0x02
 #define DRM_EVDI_DDCCI_RESPONSE   0x03
+#define DRM_EVDI_ENABLE_CURSOR_EVENTS 0x04
 /* LAST_IOCTL 0x5F -- 96 driver specific ioctls to use */
 
 #define DRM_IOCTL_EVDI_CONNECT DRM_IOWR(DRM_COMMAND_BASE +  \
@@ -119,5 +126,7 @@
        DRM_EVDI_GRABPIX, struct drm_evdi_grabpix)
 #define DRM_IOCTL_EVDI_DDCCI_RESPONSE DRM_IOWR(DRM_COMMAND_BASE +  \
        DRM_EVDI_DDCCI_RESPONSE, struct drm_evdi_ddcci_response)
+#define DRM_IOCTL_EVDI_ENABLE_CURSOR_EVENTS DRM_IOWR(DRM_COMMAND_BASE +  \
+       DRM_EVDI_ENABLE_CURSOR_EVENTS, struct drm_evdi_enable_cursor_events)
 
 #endif /* __EVDI_UAPI_DRM_H__ */
diff -Nru evdi-1.9.0+dfsg/module/evdi_fb.c evdi-1.12.0+dfsg/module/evdi_fb.c
--- evdi-1.9.0+dfsg/module/evdi_fb.c    2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/module/evdi_fb.c   2022-07-13 09:58:06.000000000 -0400
@@ -25,7 +25,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_atomic.h>
-#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #include <drm/drm_damage_helper.h>
 #endif
 #include "evdi_drm_drv.h"
@@ -63,28 +63,29 @@
 
 
        if (rect.x1 > fb->base.width) {
-               EVDI_WARN("Wrong clip rect: x1 > fb.width\n");
+               EVDI_DEBUG("Wrong clip rect: x1 > fb.width\n");
                rect.x1 = fb->base.width;
        }
 
        if (rect.y1 > fb->base.height) {
-               EVDI_WARN("Wrong clip rect: y1 > fb.height\n");
+               EVDI_DEBUG("Wrong clip rect: y1 > fb.height\n");
                rect.y1 = fb->base.height;
        }
 
        if (rect.x2 > fb->base.width) {
-               EVDI_WARN("Wrong clip rect: x2 > fb.width\n");
+               EVDI_DEBUG("Wrong clip rect: x2 > fb.width\n");
                rect.x2 = fb->base.width;
        }
 
        if (rect.y2 > fb->base.height) {
-               EVDI_WARN("Wrong clip rect: y2 > fb.height\n");
+               EVDI_DEBUG("Wrong clip rect: y2 > fb.height\n");
                rect.y2 = fb->base.height;
        }
 
        return rect;
 }
 
+#ifdef CONFIG_FB
 static int evdi_handle_damage(struct evdi_framebuffer *fb,
                       int x, int y, int width, int height)
 {
@@ -104,7 +105,6 @@
        return 0;
 }
 
-#ifdef CONFIG_FB
 static int evdi_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
        unsigned long start = vma->vm_start;
@@ -221,7 +221,7 @@
 };
 #endif /* CONFIG_FB */
 
-#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #else
 /*
  * Function taken from
@@ -243,7 +243,7 @@
        struct drm_atomic_state *state;
        struct drm_plane *plane;
        int ret = 0;
-       int i;
+       unsigned int i;
 
        EVDI_CHECKPT();
 
@@ -319,7 +319,7 @@
 
        EVDI_CHECKPT();
        if (efb->obj)
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
                drm_gem_object_put(&efb->obj->base);
 #else
                drm_gem_object_put_unlocked(&efb->obj->base);
@@ -331,7 +331,7 @@
 static const struct drm_framebuffer_funcs evdifb_funcs = {
        .create_handle = evdi_user_framebuffer_create_handle,
        .destroy = evdi_user_framebuffer_destroy,
-#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
        .dirty = drm_atomic_helper_dirtyfb,
 #else
        .dirty = evdi_user_framebuffer_dirty,
@@ -441,7 +441,7 @@
 
        return ret;
  out_gfree:
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
        drm_gem_object_put(&efbdev->efb.obj->base);
 #else
        drm_gem_object_put_unlocked(&efbdev->efb.obj->base);
@@ -471,7 +471,7 @@
        if (efbdev->efb.obj) {
                drm_framebuffer_unregister_private(&efbdev->efb.base);
                drm_framebuffer_cleanup(&efbdev->efb.base);
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
                drm_gem_object_put(&efbdev->efb.obj->base);
 #else
                drm_gem_object_put_unlocked(&efbdev->efb.obj->base);
@@ -493,7 +493,7 @@
        evdi->fbdev = efbdev;
        drm_fb_helper_prepare(dev, &efbdev->helper, &evdi_fb_helper_funcs);
 
-#if KERNEL_VERSION(5, 7, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 7, 0) <= LINUX_VERSION_CODE || defined(EL8)
        ret = drm_fb_helper_init(dev, &efbdev->helper);
 #else
        ret = drm_fb_helper_init(dev, &efbdev->helper, 1);
@@ -503,7 +503,7 @@
                return ret;
        }
 
-#if KERNEL_VERSION(5, 7, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 7, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #else
        drm_fb_helper_single_add_all_connectors(&efbdev->helper);
 #endif
@@ -541,7 +541,7 @@
                struct fb_info *info;
 
                info = efbdev->helper.fbdev;
-#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE || defined(EL8)
                unregister_framebuffer(info);
 #else
                unlink_framebuffer(info);
diff -Nru evdi-1.9.0+dfsg/module/evdi_gem.c evdi-1.12.0+dfsg/module/evdi_gem.c
--- evdi-1.9.0+dfsg/module/evdi_gem.c   2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/module/evdi_gem.c  2022-07-13 09:58:06.000000000 -0400
@@ -8,16 +8,66 @@
  * more details.
  */
 
+#include <linux/sched.h>
 #include <linux/version.h>
-#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#if KERNEL_VERSION(5, 18, 0) <= LINUX_VERSION_CODE
+#elif KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE
+#include <linux/dma-buf-map.h>
+#endif
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_prime.h>
+#include <drm/drm_file.h>
+#elif KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #else
 #include <drm/drmP.h>
 #endif
 #include "evdi_drm_drv.h"
+#include "evdi_params.h"
 #include <linux/shmem_fs.h>
 #include <linux/dma-buf.h>
 #include <drm/drm_cache.h>
 
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+MODULE_IMPORT_NS(DMA_BUF);
+#endif
+
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+static int evdi_prime_pin(struct drm_gem_object *obj);
+static void evdi_prime_unpin(struct drm_gem_object *obj);
+
+static const struct vm_operations_struct evdi_gem_vm_ops = {
+       .fault = evdi_gem_fault,
+       .open = drm_gem_vm_open,
+       .close = drm_gem_vm_close,
+};
+
+static struct drm_gem_object_funcs gem_obj_funcs = {
+       .free = evdi_gem_free_object,
+       .pin = evdi_prime_pin,
+       .unpin = evdi_prime_unpin,
+       .vm_ops = &evdi_gem_vm_ops,
+       .export = drm_gem_prime_export,
+       .get_sg_table = evdi_prime_get_sg_table,
+};
+#endif
+
+static bool evdi_was_called_by_mutter(void)
+{
+       char task_comm[TASK_COMM_LEN] = { 0 };
+
+       get_task_comm(task_comm, current);
+
+       return strcmp(task_comm, "gnome-shell") == 0;
+}
+
+static bool evdi_drm_gem_object_use_import_attach(struct drm_gem_object *obj)
+{
+       if (!obj || !obj->import_attach)
+               return false;
+
+       return obj->import_attach && 
strcmp(obj->import_attach->dmabuf->owner->name, "amdgpu") != 0;
+}
+
 uint32_t evdi_gem_object_handle_lookup(struct drm_file *filp,
                                       struct drm_gem_object *obj)
 {
@@ -58,6 +108,14 @@
 #endif
        obj->resv = &obj->_resv;
 
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+       obj->base.funcs = &gem_obj_funcs;
+#endif
+
+       obj->allow_sw_cursor_rect_updates = false;
+
+       mutex_init(&obj->pages_lock);
+
        return obj;
 }
 
@@ -81,11 +139,12 @@
                kfree(obj);
                return ret;
        }
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
        drm_gem_object_put(&obj->base);
 #else
        drm_gem_object_put_unlocked(&obj->base);
 #endif
+       obj->allow_sw_cursor_rect_updates = evdi_was_called_by_mutter();
        *handle_p = handle;
        return 0;
 }
@@ -186,7 +245,7 @@
        obj->pages = pages;
 
 #if defined(CONFIG_X86)
-       drm_clflush_pages(obj->pages, obj->base.size / PAGE_SIZE);
+       drm_clflush_pages(obj->pages, DIV_ROUND_UP(obj->base.size, PAGE_SIZE));
 #endif
 
        return 0;
@@ -204,19 +263,55 @@
        obj->pages = NULL;
 }
 
+static int evdi_pin_pages(struct evdi_gem_object *obj)
+{
+       int ret = 0;
+
+       mutex_lock(&obj->pages_lock);
+       if (obj->pages_pin_count++ == 0) {
+               ret = evdi_gem_get_pages(obj, GFP_KERNEL);
+               if (ret)
+                       obj->pages_pin_count--;
+       }
+       mutex_unlock(&obj->pages_lock);
+       return ret;
+}
+
+static void evdi_unpin_pages(struct evdi_gem_object *obj)
+{
+       mutex_lock(&obj->pages_lock);
+       if (--obj->pages_pin_count == 0)
+               evdi_gem_put_pages(obj);
+       mutex_unlock(&obj->pages_lock);
+}
+
 int evdi_gem_vmap(struct evdi_gem_object *obj)
 {
-       int page_count = obj->base.size / PAGE_SIZE;
+       int page_count = DIV_ROUND_UP(obj->base.size, PAGE_SIZE);
        int ret;
 
-       if (obj->base.import_attach) {
+       if (evdi_drm_gem_object_use_import_attach(&obj->base)) {
+#if KERNEL_VERSION(5, 18, 0) <= LINUX_VERSION_CODE
+               struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
+#elif KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+               struct dma_buf_map map = DMA_BUF_MAP_INIT_VADDR(NULL);
+#endif
+
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+               ret = dma_buf_vmap(obj->base.import_attach->dmabuf, &map);
+               if (ret)
+                       return -ENOMEM;
+               obj->vmapping = map.vaddr;
+               obj->vmap_is_iomem = map.is_iomem;
+#else
                obj->vmapping = dma_buf_vmap(obj->base.import_attach->dmabuf);
                if (!obj->vmapping)
                        return -ENOMEM;
+#endif
                return 0;
        }
 
-       ret = evdi_gem_get_pages(obj, GFP_KERNEL);
+       ret = evdi_pin_pages(obj);
        if (ret)
                return ret;
 
@@ -228,8 +323,29 @@
 
 void evdi_gem_vunmap(struct evdi_gem_object *obj)
 {
-       if (obj->base.import_attach) {
+       if (evdi_drm_gem_object_use_import_attach(&obj->base)) {
+#if KERNEL_VERSION(5, 18, 0) <= LINUX_VERSION_CODE
+               struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
+
+               if (obj->vmap_is_iomem)
+                       iosys_map_set_vaddr_iomem(&map, obj->vmapping);
+               else
+                       iosys_map_set_vaddr(&map, obj->vmapping);
+
+               dma_buf_vunmap(obj->base.import_attach->dmabuf, &map);
+
+#elif KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+               struct dma_buf_map map;
+
+               if (obj->vmap_is_iomem)
+                       dma_buf_map_set_vaddr_iomem(&map, obj->vmapping);
+               else
+                       dma_buf_map_set_vaddr(&map, obj->vmapping);
+
+               dma_buf_vunmap(obj->base.import_attach->dmabuf, &map);
+#else
                dma_buf_vunmap(obj->base.import_attach->dmabuf, obj->vmapping);
+#endif
                obj->vmapping = NULL;
                return;
        }
@@ -239,7 +355,7 @@
                obj->vmapping = NULL;
        }
 
-       evdi_gem_put_pages(obj);
+       evdi_unpin_pages(obj);
 }
 
 void evdi_gem_free_object(struct drm_gem_object *gem_obj)
@@ -263,6 +379,7 @@
        reservation_object_fini(&obj->_resv);
 #endif
        obj->resv = NULL;
+       mutex_destroy(&obj->pages_lock);
 }
 
 /*
@@ -284,7 +401,7 @@
        }
        gobj = to_evdi_bo(obj);
 
-       ret = evdi_gem_get_pages(gobj, GFP_KERNEL);
+       ret = evdi_pin_pages(gobj);
        if (ret)
                goto out;
 
@@ -308,12 +425,15 @@
 {
        struct evdi_gem_object *obj;
        int npages;
+       bool called_by_mutter;
+
+       called_by_mutter = evdi_was_called_by_mutter();
 
        obj = evdi_gem_alloc_object(dev, attach->dmabuf->size);
        if (IS_ERR(obj))
                return ERR_CAST(obj);
 
-       npages = PAGE_ALIGN(attach->dmabuf->size) / PAGE_SIZE;
+       npages = DIV_ROUND_UP(attach->dmabuf->size, PAGE_SIZE);
        DRM_DEBUG_PRIME("Importing %d pages\n", npages);
        obj->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
        if (!obj->pages) {
@@ -321,15 +441,36 @@
                return ERR_PTR(-ENOMEM);
        }
 
+#if KERNEL_VERSION(5, 12, 0) <= LINUX_VERSION_CODE || defined(EL8)
+       drm_prime_sg_to_page_array(sg, obj->pages, npages);
+#else
        drm_prime_sg_to_page_addr_arrays(sg, obj->pages, NULL, npages);
+#endif
        obj->sg = sg;
+       obj->allow_sw_cursor_rect_updates = called_by_mutter;
        return &obj->base;
 }
 
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+static int evdi_prime_pin(struct drm_gem_object *obj)
+{
+       struct evdi_gem_object *bo = to_evdi_bo(obj);
+
+       return evdi_pin_pages(bo);
+}
+
+static void evdi_prime_unpin(struct drm_gem_object *obj)
+{
+       struct evdi_gem_object *bo = to_evdi_bo(obj);
+
+       evdi_unpin_pages(bo);
+}
+#endif
+
 struct sg_table *evdi_prime_get_sg_table(struct drm_gem_object *obj)
 {
        struct evdi_gem_object *bo = to_evdi_bo(obj);
-       #if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
+       #if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE || defined(EL8)
                return drm_prime_pages_to_sg(obj->dev, bo->pages, bo->base.size 
>> PAGE_SHIFT);
        #else
                return drm_prime_pages_to_sg(bo->pages, bo->base.size >> 
PAGE_SHIFT);
diff -Nru evdi-1.9.0+dfsg/module/evdi_ioc32.c 
evdi-1.12.0+dfsg/module/evdi_ioc32.c
--- evdi-1.9.0+dfsg/module/evdi_ioc32.c 2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/module/evdi_ioc32.c        2022-07-13 09:58:06.000000000 
-0400
@@ -22,7 +22,9 @@
 #include <linux/compat.h>
 
 #include <linux/version.h>
-#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_ioctl.h>
+#elif KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #else
 #include <drm/drmP.h>
 #endif
@@ -36,7 +38,8 @@
        int32_t dev_index;
        uint32_t edid_ptr32;
        uint32_t edid_length;
-       uint32_t sku_area_limit;
+       uint32_t pixel_area_limit;
+       uint32_t pixel_per_second_limit;
 };
 
 struct drm_evdi_grabpix32 {
@@ -59,7 +62,11 @@
        if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
                return -EFAULT;
 
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE && KERNEL_VERSION(5, 14, 0) 
>= LINUX_VERSION_CODE || defined(EL8)
        request = compat_alloc_user_space(sizeof(*request));
+#else
+       request = kmalloc(sizeof(*request), GFP_USER);
+#endif
 #if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
        if (!access_ok(request, sizeof(*request))
 #else
@@ -70,7 +77,8 @@
                || __put_user((void __user *)(unsigned long)req32.edid_ptr32,
                          &request->edid)
                || __put_user(req32.edid_length, &request->edid_length)
-               || __put_user(req32.sku_area_limit, &request->sku_area_limit))
+               || __put_user(req32.pixel_area_limit, 
&request->pixel_area_limit)
+               || __put_user(req32.pixel_per_second_limit, 
&request->pixel_per_second_limit))
                return -EFAULT;
 
        return drm_ioctl(file, DRM_IOCTL_EVDI_CONNECT,
@@ -87,7 +95,11 @@
        if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
                return -EFAULT;
 
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE && KERNEL_VERSION(5, 14, 0) 
>= LINUX_VERSION_CODE || defined(EL8)
        request = compat_alloc_user_space(sizeof(*request));
+#else
+       request = kmalloc(sizeof(*request), GFP_USER);
+#endif
 #if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
        if (!access_ok(request, sizeof(*request))
 #else
diff -Nru evdi-1.9.0+dfsg/module/evdi_modeset.c 
evdi-1.12.0+dfsg/module/evdi_modeset.c
--- evdi-1.9.0+dfsg/module/evdi_modeset.c       2021-01-26 09:31:59.000000000 
-0500
+++ evdi-1.12.0+dfsg/module/evdi_modeset.c      2022-07-13 09:58:06.000000000 
-0400
@@ -12,7 +12,11 @@
  */
 
 #include <linux/version.h>
-#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_vblank.h>
+#include <drm/drm_damage_helper.h>
+#elif KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#include <drm/drm_damage_helper.h>
 #else
 #include <drm/drmP.h>
 #endif
@@ -25,7 +29,11 @@
 #include "evdi_drm_drv.h"
 #include "evdi_cursor.h"
 #include "evdi_params.h"
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_gem_atomic_helper.h>
+#else
 #include <drm/drm_gem_framebuffer_helper.h>
+#endif
 
 static void evdi_crtc_dpms(__always_unused struct drm_crtc *crtc,
                           __always_unused int mode)
@@ -36,6 +44,7 @@
 static void evdi_crtc_disable(__always_unused struct drm_crtc *crtc)
 {
        EVDI_CHECKPT();
+       drm_crtc_vblank_off(crtc);
 }
 
 static void evdi_crtc_destroy(struct drm_crtc *crtc)
@@ -56,25 +65,37 @@
 
 static void evdi_crtc_atomic_flush(
        struct drm_crtc *crtc
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(RPI) || 
defined(EL8)
+       , struct drm_atomic_state *state
+#else
        , __always_unused struct drm_crtc_state *old_state
+#endif
        )
 {
-       struct drm_crtc_state *state = crtc->state;
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(RPI) || 
defined(EL8)
+       struct drm_crtc_state *crtc_state = 
drm_atomic_get_new_crtc_state(state, crtc);
+#else
+       struct drm_crtc_state *crtc_state = crtc->state;
+#endif
        struct evdi_device *evdi = crtc->dev->dev_private;
+       bool notify_mode_changed = crtc_state->active &&
+                                  (crtc_state->mode_changed || 
evdi_painter_needs_full_modeset(evdi->painter));
+       bool notify_dpms = crtc_state->active_changed || 
evdi_painter_needs_full_modeset(evdi->painter);
 
+       if (notify_mode_changed)
+               evdi_painter_mode_changed_notify(evdi, 
&crtc_state->adjusted_mode);
 
-       if (state->mode_changed && state->active)
-               evdi_painter_mode_changed_notify(evdi, &state->adjusted_mode);
-
-       if (state->active_changed)
+       if (notify_dpms)
                evdi_painter_dpms_notify(evdi,
-                       state->active ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF);
+                       crtc_state->active ? DRM_MODE_DPMS_ON : 
DRM_MODE_DPMS_OFF);
 
-       evdi_painter_set_vblank(evdi->painter, crtc, state->event);
+       evdi_painter_set_vblank(evdi->painter, crtc, crtc_state->event);
        evdi_painter_send_update_ready_if_needed(evdi->painter);
-       state->event = NULL;
+       crtc_state->event = NULL;
 }
 
+#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
 static void evdi_mark_full_screen_dirty(struct evdi_device *evdi)
 {
        const struct drm_clip_rect rect =
@@ -125,7 +146,7 @@
        evdi_cursor_set(evdi->cursor,
                        eobj, width, height, hot_x, hot_y,
                        format, stride);
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
        drm_gem_object_put(obj);
 #else
        drm_gem_object_put_unlocked(obj);
@@ -157,6 +178,7 @@
 
        return 0;
 }
+#endif
 
 static struct drm_crtc_helper_funcs evdi_helper_funcs = {
        .mode_set_nofb  = evdi_crtc_set_nofb,
@@ -167,6 +189,17 @@
        .disable        = evdi_crtc_disable
 };
 
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(RPI) || 
defined(EL8)
+static int evdi_enable_vblank(__always_unused struct drm_crtc *crtc)
+{
+       return 1;
+}
+
+static void evdi_disable_vblank(__always_unused struct drm_crtc *crtc)
+{
+}
+#endif
+
 static const struct drm_crtc_funcs evdi_crtc_funcs = {
        .reset                  = drm_atomic_helper_crtc_reset,
        .destroy                = evdi_crtc_destroy,
@@ -175,18 +208,40 @@
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
        .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
 
+#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
        .cursor_set2            = evdi_crtc_cursor_set,
-       .cursor_move            = evdi_crtc_cursor_move
+       .cursor_move            = evdi_crtc_cursor_move,
+#endif
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(RPI) || 
defined(EL8)
+       .enable_vblank          = evdi_enable_vblank,
+       .disable_vblank         = evdi_disable_vblank,
+#endif
 };
 
 static void evdi_plane_atomic_update(struct drm_plane *plane,
-                                    struct drm_plane_state *old_state)
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+                                    struct drm_atomic_state *atom_state
+#else
+                                    struct drm_plane_state *old_state
+#endif
+               )
 {
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+       struct drm_plane_state *old_state = 
drm_atomic_get_old_plane_state(atom_state, plane);
+#else
+#endif
        struct drm_plane_state *state;
        struct evdi_device *evdi;
        struct evdi_painter *painter;
        struct drm_crtc *crtc;
 
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_rect rect;
+       struct drm_clip_rect clip_rect;
+#endif
+
        if (!plane || !plane->state) {
                EVDI_WARN("Plane state is null\n");
                return;
@@ -228,10 +283,28 @@
                    evdi_painter_needs_full_modeset(painter)) {
 
                        evdi_painter_set_scanout_buffer(painter, efb);
+
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
+                       state->visible = true;
+                       state->src.x1 = 0;
+                       state->src.y1 = 0;
+                       state->src.x2 = fb->width << 16;
+                       state->src.y2 = fb->height << 16;
+
+                       drm_atomic_helper_damage_iter_init(&iter, old_state, 
state);
+                       while (drm_atomic_helper_damage_iter_next(&iter, 
&rect)) {
+                               clip_rect.x1 = rect.x1;
+                               clip_rect.y1 = rect.y1;
+                               clip_rect.x2 = rect.x2;
+                               clip_rect.y2 = rect.y2;
+                               evdi_painter_mark_dirty(evdi, &clip_rect);
+                       }
+#endif
+
+               };
+
+               if (evdi_painter_get_num_dirts(painter) == 0)
                        evdi_painter_mark_dirty(evdi, &fullscreen_rect);
-               } else if (evdi_painter_get_num_dirts(painter) == 0) {
-                       evdi_painter_mark_dirty(evdi, &fullscreen_rect);
-               }
        }
 }
 
@@ -245,8 +318,17 @@
 }
 
 static void evdi_cursor_atomic_update(struct drm_plane *plane,
-                                     struct drm_plane_state *old_state)
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+                                    struct drm_atomic_state *atom_state
+#else
+                                    struct drm_plane_state *old_state
+#endif
+               )
 {
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+       struct drm_plane_state *old_state = 
drm_atomic_get_old_plane_state(atom_state, plane);
+#else
+#endif
        if (plane && plane->state && plane->dev && plane->dev->dev_private) {
                struct drm_plane_state *state = plane->state;
                struct evdi_device *evdi = plane->dev->dev_private;
@@ -288,13 +370,20 @@
 
                mutex_unlock(&plane->dev->struct_mutex);
                if (!evdi->cursor_events_enabled) {
-                       evdi_cursor_atomic_get_rect(&old_rect, old_state);
-                       evdi_cursor_atomic_get_rect(&rect, state);
-
-                       evdi_painter_mark_dirty(evdi, &old_rect);
-                       evdi_painter_mark_dirty(evdi, &rect);
+                       if (fb != NULL) {
+                               if (efb->obj->allow_sw_cursor_rect_updates) {
+                                       evdi_cursor_atomic_get_rect(&old_rect, 
old_state);
+                                       evdi_cursor_atomic_get_rect(&rect, 
state);
+
+                                       evdi_painter_mark_dirty(evdi, 
&old_rect);
+                               } else {
+                                       rect = 
evdi_painter_framebuffer_size(evdi->painter);
+                               }
+                               evdi_painter_mark_dirty(evdi, &rect);
+                       }
                        return;
                }
+
                if (cursor_changed)
                        evdi_painter_send_cursor_set(evdi->painter,
                                                     evdi->cursor);
@@ -306,12 +395,20 @@
 
 static const struct drm_plane_helper_funcs evdi_plane_helper_funcs = {
        .atomic_update = evdi_plane_atomic_update,
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+       .prepare_fb = drm_gem_plane_helper_prepare_fb
+#else
        .prepare_fb = drm_gem_fb_prepare_fb
+#endif
 };
 
 static const struct drm_plane_helper_funcs evdi_cursor_helper_funcs = {
        .atomic_update = evdi_cursor_atomic_update,
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+       .prepare_fb = drm_gem_plane_helper_prepare_fb
+#else
        .prepare_fb = drm_gem_fb_prepare_fb
+#endif
 };
 
 static const struct drm_plane_funcs evdi_plane_funcs = {
@@ -337,10 +434,11 @@
 {
        struct drm_plane *plane;
        int ret;
+       char *plane_type = (type == DRM_PLANE_TYPE_CURSOR) ? "cursor" : 
"primary";
 
        plane = kzalloc(sizeof(*plane), GFP_KERNEL);
        if (plane == NULL) {
-               EVDI_ERROR("Failed to allocate primary plane\n");
+               EVDI_ERROR("Failed to allocate %s plane\n", plane_type);
                return NULL;
        }
        plane->format_default = true;
@@ -357,7 +455,7 @@
                                       );
 
        if (ret) {
-               EVDI_ERROR("Failed to initialize primary plane\n");
+               EVDI_ERROR("Failed to initialize %s plane\n", plane_type);
                kfree(plane);
                return NULL;
        }
@@ -381,6 +479,16 @@
 
        primary_plane = evdi_create_plane(dev, DRM_PLANE_TYPE_PRIMARY,
                                          &evdi_plane_helper_funcs);
+
+#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE || defined(EL8)
+       cursor_plane = evdi_create_plane(dev, DRM_PLANE_TYPE_CURSOR,
+                                               &evdi_cursor_helper_funcs);
+#endif
+
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
+       drm_plane_enable_fb_damage_clips(primary_plane);
+#endif
+
        status = drm_crtc_init_with_planes(dev, crtc,
                                           primary_plane, cursor_plane,
                                           &evdi_crtc_funcs,
@@ -393,29 +501,11 @@
        return 0;
 }
 
-static int evdi_atomic_check(struct drm_device *dev,
-                            struct drm_atomic_state *state)
-{
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
-       int i;
-       struct evdi_device *evdi = dev->dev_private;
-
-       if (evdi_painter_needs_full_modeset(evdi->painter)) {
-               for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
-                       crtc_state->active_changed = true;
-                       crtc_state->mode_changed = true;
-               }
-       }
-
-       return drm_atomic_helper_check(dev, state);
-}
-
 static const struct drm_mode_config_funcs evdi_mode_funcs = {
        .fb_create = evdi_fb_user_fb_create,
        .output_poll_changed = NULL,
        .atomic_commit = drm_atomic_helper_commit,
-       .atomic_check = evdi_atomic_check
+       .atomic_check = drm_atomic_helper_check
 };
 
 void evdi_modeset_init(struct drm_device *dev)
@@ -429,8 +519,8 @@
        dev->mode_config.min_width = 64;
        dev->mode_config.min_height = 64;
 
-       dev->mode_config.max_width = 3840;
-       dev->mode_config.max_height = 2160;
+       dev->mode_config.max_width = 7680;
+       dev->mode_config.max_height = 4320;
 
        dev->mode_config.prefer_shadow = 0;
        dev->mode_config.preferred_depth = 24;
@@ -446,8 +536,10 @@
        drm_mode_config_reset(dev);
 }
 
-void evdi_modeset_cleanup(struct drm_device *dev)
+void evdi_modeset_cleanup(__maybe_unused struct drm_device *dev)
 {
-       EVDI_CHECKPT();
+#if KERNEL_VERSION(5, 8, 0) <= LINUX_VERSION_CODE
+#else
        drm_mode_config_cleanup(dev);
+#endif
 }
diff -Nru evdi-1.9.0+dfsg/module/evdi_painter.c 
evdi-1.12.0+dfsg/module/evdi_painter.c
--- evdi-1.9.0+dfsg/module/evdi_painter.c       2021-01-26 09:31:59.000000000 
-0500
+++ evdi-1.12.0+dfsg/module/evdi_painter.c      2022-07-13 09:58:06.000000000 
-0400
@@ -10,7 +10,11 @@
 #include "linux/thread_info.h"
 #include "linux/mm.h"
 #include <linux/version.h>
-#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_file.h>
+#include <drm/drm_vblank.h>
+#include <drm/drm_ioctl.h>
+#elif KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #else
 #include <drm/drmP.h>
 #endif
@@ -27,6 +31,10 @@
 
 #include <linux/dma-buf.h>
 
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+MODULE_IMPORT_NS(DMA_BUF);
+#endif
+
 #if KERNEL_VERSION(5, 1, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #include <drm/drm_probe_helper.h>
 #endif
@@ -239,7 +247,6 @@
                        memcpy(block,
                               evdi->painter->edid,
                               evdi->painter->edid_length);
-                       EVDI_DEBUG("(dev=%d) EDID valid\n", evdi->dev_index);
                }
        }
        painter_unlock(evdi->painter);
@@ -318,7 +325,7 @@
        }
 
        if (!painter->drm_filp) {
-               EVDI_WARN("Painter is not connected!");
+               EVDI_VERBOSE("Painter is not connected!");
                drm_event_cancel_free(painter->drm_device, event);
                return;
        }
@@ -496,31 +503,6 @@
        evdi_painter_send_event(painter, event);
 }
 
-static struct drm_pending_event *create_crtc_state_event(int state)
-{
-       struct evdi_event_crtc_state_pending *event;
-
-       event = kzalloc(sizeof(*event), GFP_KERNEL);
-       if (!event) {
-               EVDI_ERROR("Failed to create crtc state event");
-               return NULL;
-       }
-
-       event->crtc_state.base.type = DRM_EVDI_EVENT_CRTC_STATE;
-       event->crtc_state.base.length = sizeof(event->crtc_state);
-       event->crtc_state.state = state;
-       event->base.event = &event->crtc_state.base;
-       return &event->base;
-}
-
-static void evdi_painter_send_crtc_state(struct evdi_painter *painter,
-                                        int state)
-{
-       struct drm_pending_event *event = create_crtc_state_event(state);
-
-       evdi_painter_send_event(painter, event);
-}
-
 static struct drm_pending_event *create_mode_changed_event(
        struct drm_display_mode *current_mode,
        int32_t bits_per_pixel,
@@ -591,7 +573,8 @@
        painter_lock(painter);
        efb = painter->scanout_fb;
        if (!efb) {
-               EVDI_DEBUG("Scanout buffer not set.");
+               if (painter->is_connected)
+                       EVDI_WARN("Scanout buffer not set.");
                goto unlock;
        }
        rect.x1 = 0;
@@ -618,14 +601,15 @@
        painter_lock(painter);
        efb = painter->scanout_fb;
        if (!efb) {
-               EVDI_DEBUG("(dev=%d) Skip clip rect. Scanout buffer not set.\n",
+               if (painter->is_connected)
+                       EVDI_WARN("(card%d) Skip clip rect. Scanout buffer not 
set.\n",
                           evdi->dev_index);
                goto unlock;
        }
 
        rect = evdi_framebuffer_sanitize_rect(efb, dirty_rect);
 
-       EVDI_VERBOSE("(dev=%d) %d,%d-%d,%d\n", evdi->dev_index, rect.x1,
+       EVDI_VERBOSE("(card%d) %d,%d-%d,%d\n", evdi->dev_index, rect.x1,
                     rect.y1, rect.x2, rect.y2);
 
        if (painter->num_dirts == MAX_DIRTS)
@@ -695,8 +679,11 @@
        EVDI_CHECKPT();
        if (painter) {
                painter_lock(painter);
-
+#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE || defined(EL8)
+               if (painter->was_update_requested && painter->num_dirts) {
+#else
                if (painter->was_update_requested) {
+#endif
                        evdi_painter_send_update_ready(painter);
                        painter->was_update_requested = false;
                }
@@ -707,38 +694,47 @@
        }
 }
 
+static const char * const dpms_str[] = { "on", "standby", "suspend", "off" };
+
 void evdi_painter_dpms_notify(struct evdi_device *evdi, int mode)
 {
        struct evdi_painter *painter = evdi->painter;
+       const char *mode_str;
 
-       if (painter) {
-               EVDI_DEBUG("(dev=%d) Notifying dpms mode: %d\n",
-                          evdi->dev_index, mode);
-               evdi_painter_send_dpms(painter, mode);
-       } else {
-               EVDI_WARN("Painter does not exist!");
+       if (!painter) {
+               EVDI_WARN("(card%d) Painter does not exist!", evdi->dev_index);
+               return;
        }
-}
 
-void evdi_painter_crtc_state_notify(struct evdi_device *evdi, int state)
-{
-       struct evdi_painter *painter = evdi->painter;
+       if (!painter->is_connected)
+               return;
 
-       if (painter) {
-               EVDI_DEBUG("(dev=%d) Notifying crtc state: %d\n",
-                          evdi->dev_index, state);
-               evdi_painter_send_crtc_state(painter, state);
-       } else {
-               EVDI_WARN("Painter does not exist!");
-       }
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               mode_str = dpms_str[mode];
+               break;
+       default:
+               mode_str = "unknown";
+       };
+       EVDI_INFO("(card%d) Notifying display power state: %s",
+                  evdi->dev_index, mode_str);
+       evdi_painter_send_dpms(painter, mode);
 }
 
-static void evdi_log_pixel_format(uint32_t pixel_format)
+static void evdi_log_pixel_format(uint32_t pixel_format,
+               char *buf, size_t size)
 {
+#if KERNEL_VERSION(5, 14, 0) <= LINUX_VERSION_CODE
+       snprintf(buf, size, "pixel format %p4cc", &pixel_format);
+#else
        struct drm_format_name_buf format_name;
 
        drm_get_format_name(pixel_format, &format_name);
-       EVDI_DEBUG("pixel format %s\n", format_name.str);
+       snprintf(buf, size, "pixel format %s", format_name.str);
+#endif
 }
 
 void evdi_painter_mode_changed_notify(struct evdi_device *evdi,
@@ -748,6 +744,7 @@
        struct drm_framebuffer *fb;
        int bits_per_pixel;
        uint32_t pixel_format;
+       char buf[100];
 
        if (painter == NULL)
                return;
@@ -759,10 +756,11 @@
        bits_per_pixel = fb->format->cpp[0] * 8;
        pixel_format = fb->format->format;
 
-       EVDI_DEBUG("(dev=%d) Notifying mode changed: %dx%d@%d; bpp %d; ",
+
+       evdi_log_pixel_format(pixel_format, buf, sizeof(buf));
+       EVDI_INFO("(card%d) Notifying mode changed: %dx%d@%d; bpp %d; %s",
                   evdi->dev_index, new_mode->hdisplay, new_mode->vdisplay,
-                  drm_mode_vrefresh(new_mode), bits_per_pixel);
-       evdi_log_pixel_format(pixel_format);
+                  drm_mode_vrefresh(new_mode), bits_per_pixel, buf);
 
        evdi_painter_send_mode_changed(painter,
                                       new_mode,
@@ -795,7 +793,7 @@
        evdi->i2c_adapter = kzalloc(sizeof(*evdi->i2c_adapter), GFP_KERNEL);
 
        if (!evdi->i2c_adapter) {
-               EVDI_ERROR("(dev=%d) Failed to allocate for i2c adapter",
+               EVDI_ERROR("(card%d) Failed to allocate for i2c adapter",
                        evdi->dev_index);
                return;
        }
@@ -805,19 +803,19 @@
        if (result) {
                kfree(evdi->i2c_adapter);
                evdi->i2c_adapter = NULL;
-               EVDI_ERROR("(dev=%d) Failed to add i2c adapter, error %d",
+               EVDI_ERROR("(card%d) Failed to add i2c adapter, error %d",
                        evdi->dev_index, result);
                return;
        }
 
-       EVDI_DEBUG("(dev=%d) Added i2c adapter bus number %d",
+       EVDI_INFO("(card%d) Added i2c adapter bus number %d",
                evdi->dev_index, evdi->i2c_adapter->nr);
 
        result = sysfs_create_link(&evdi->conn->kdev->kobj,
                        &evdi->i2c_adapter->dev.kobj, "ddc");
 
        if (result) {
-               EVDI_ERROR("(dev=%d) Failed to create sysfs link, error %d",
+               EVDI_ERROR("(card%d) Failed to create sysfs link, error %d",
                        evdi->dev_index, result);
                return;
        }
@@ -826,7 +824,7 @@
 static void evdi_remove_i2c_adapter(struct evdi_device *evdi)
 {
        if (evdi->i2c_adapter) {
-               EVDI_DEBUG("(dev=%d) Removing i2c adapter bus number %d",
+               EVDI_INFO("(card%d) Removing i2c adapter bus number %d",
                        evdi->dev_index, evdi->i2c_adapter->nr);
 
                sysfs_remove_link(&evdi->conn->kdev->kobj, "ddc");
@@ -841,16 +839,16 @@
 static int
 evdi_painter_connect(struct evdi_device *evdi,
                     void const __user *edid_data, unsigned int edid_length,
-                    uint32_t sku_area_limit,
-                    struct drm_file *file, int dev_index)
+                    uint32_t pixel_area_limit,
+                    uint32_t pixel_per_second_limit,
+                    struct drm_file *file, __always_unused int dev_index)
 {
        struct evdi_painter *painter = evdi->painter;
        struct edid *new_edid = NULL;
-       int expected_edid_size = 0;
+       unsigned int expected_edid_size = 0;
+       char buf[100];
 
-       EVDI_DEBUG("(dev=%d) Process is trying to connect\n",
-                  evdi->dev_index);
-       evdi_log_process();
+       evdi_log_process(buf, sizeof(buf));
 
        if (edid_length < sizeof(struct edid)) {
                EVDI_ERROR("Edid length too small\n");
@@ -867,7 +865,7 @@
                return -ENOMEM;
 
        if (copy_from_user(new_edid, edid_data, edid_length)) {
-               EVDI_ERROR("(dev=%d) Failed to read edid\n", dev_index);
+               EVDI_ERROR("(card%d) Failed to read edid\n", evdi->dev_index);
                kfree(new_edid);
                return -EFAULT;
        }
@@ -882,13 +880,13 @@
        }
 
        if (painter->drm_filp)
-               EVDI_WARN("(dev=%d) Double connect - replacing %p with %p\n",
-                         dev_index, painter->drm_filp, file);
+               EVDI_WARN("(card%d) Double connect - replacing %p with %p\n",
+                         evdi->dev_index, painter->drm_filp, file);
 
        painter_lock(painter);
 
-       evdi->dev_index = dev_index;
-       evdi->sku_area_limit = sku_area_limit;
+        evdi->pixel_area_limit = pixel_area_limit;
+       evdi->pixel_per_second_limit = pixel_per_second_limit;
        painter->drm_filp = file;
        kfree(painter->edid);
        painter->edid_length = edid_length;
@@ -896,12 +894,12 @@
        painter->is_connected = true;
        painter->needs_full_modeset = true;
 
-       evdi_add_i2c_adapter(evdi);
+       if (!evdi->i2c_adapter)
+               evdi_add_i2c_adapter(evdi);
 
        painter_unlock(painter);
 
-       EVDI_DEBUG("(dev=%d) Connected with %p\n", evdi->dev_index,
-                  painter->drm_filp);
+       EVDI_INFO("(card%d) Connected with %s\n", evdi->dev_index, buf);
 
        drm_helper_hpd_irq_event(evdi->ddev);
 
@@ -912,6 +910,7 @@
        struct drm_file *file)
 {
        struct evdi_painter *painter = evdi->painter;
+       char buf[100];
 
        EVDI_CHECKPT();
 
@@ -929,8 +928,8 @@
 
        painter->is_connected = false;
 
-       EVDI_DEBUG("(dev=%d) Disconnected from %p\n", evdi->dev_index,
-                  painter->drm_filp);
+       evdi_log_process(buf, sizeof(buf));
+       EVDI_INFO("(card%d) Disconnected from %s\n", evdi->dev_index, buf);
        evdi_painter_events_cleanup(painter);
 
        evdi_painter_send_vblank(painter);
@@ -944,7 +943,6 @@
        evdi_remove_i2c_adapter(evdi);
 
        painter->drm_filp = NULL;
-       evdi->dev_index = -1;
 
        painter->was_update_requested = false;
        evdi->cursor_events_enabled = false;
@@ -962,10 +960,8 @@
 {
        EVDI_CHECKPT();
 
-       if (evdi->painter)
+       if (evdi->painter && file == evdi->painter->drm_filp)
                evdi_painter_disconnect(evdi, file);
-       else
-               EVDI_WARN("Painter does not exist!");
 }
 
 int evdi_painter_connect_ioctl(struct drm_device *drm_dev, void *data,
@@ -982,19 +978,20 @@
                        ret = evdi_painter_connect(evdi,
                                             cmd->edid,
                                             cmd->edid_length,
-                                            cmd->sku_area_limit,
+                                            cmd->pixel_area_limit,
+                                            cmd->pixel_per_second_limit,
                                             file,
                                             cmd->dev_index);
                else
                        ret = evdi_painter_disconnect(evdi, file);
 
                if (ret) {
-                       EVDI_WARN("(dev=%d)(pid=%d) disconnect failed\n",
+                       EVDI_WARN("(card%d)(pid=%d) disconnect failed\n",
                                  evdi->dev_index, (int)task_pid_nr(current));
                }
                return ret;
        }
-       EVDI_WARN("Painter does not exist!");
+       EVDI_WARN("(card%d) Painter does not exist!", evdi->dev_index);
        return -ENODEV;
 }
 
@@ -1030,7 +1027,7 @@
        painter_lock(painter);
 
        if (painter->was_update_requested) {
-               EVDI_WARN("(dev=%d) Update ready not sent,",
+               EVDI_WARN("(card%d) Update ready not sent,",
                          evdi->dev_index);
                EVDI_WARN(" but pixels are grabbed.\n");
        }
@@ -1084,9 +1081,9 @@
                }
        }
 
-       if (cmd->buf_width != efb->base.width ||
-               cmd->buf_height != efb->base.height) {
-               EVDI_ERROR("Invalid buffer dimension\n");
+       if ((unsigned int)cmd->buf_width != efb->base.width ||
+               (unsigned int)cmd->buf_height != efb->base.height) {
+               EVDI_DEBUG("Invalid buffer dimension\n");
                err = -EINVAL;
                goto err_fb;
        }
@@ -1149,7 +1146,7 @@
 
                if (painter->was_update_requested) {
                        EVDI_WARN
-                         ("(dev=%d) Update was already requested - ignoring\n",
+                         ("(card%d) Update was already requested - ignoring\n",
                           evdi->dev_index);
                } else {
                        if (painter->num_dirts > 0)
@@ -1210,6 +1207,9 @@
        kfree(painter->edid);
        painter->edid_length = 0;
        painter->edid = NULL;
+       if (painter->scanout_fb)
+               drm_framebuffer_put(&painter->scanout_fb->base);
+       painter->scanout_fb = NULL;
 
        evdi_painter_send_vblank(painter);
 
@@ -1318,7 +1318,7 @@
        }
 
        if (msg->addr != I2C_ADDRESS_DDCCI) {
-               EVDI_DEBUG("Ignored ddc/ci data for address 0x%x\n", msg->addr);
+               EVDI_WARN("Ignored ddc/ci data for address 0x%x\n", msg->addr);
                return false;
        }
 
@@ -1363,3 +1363,14 @@
        painter_unlock(painter);
        return result;
 }
+
+int evdi_painter_enable_cursor_events_ioctl(struct drm_device *drm_dev, void 
*data,
+                                       __always_unused struct drm_file *file)
+{
+       struct evdi_device *evdi = drm_dev->dev_private;
+       struct drm_evdi_enable_cursor_events *cmd = data;
+
+       evdi->cursor_events_enabled = cmd->enable;
+
+       return 0;
+}
diff -Nru evdi-1.9.0+dfsg/module/evdi_params.c 
evdi-1.12.0+dfsg/module/evdi_params.c
--- evdi-1.9.0+dfsg/module/evdi_params.c        2021-01-26 09:31:59.000000000 
-0500
+++ evdi-1.12.0+dfsg/module/evdi_params.c       2022-07-13 09:58:06.000000000 
-0400
@@ -13,7 +13,7 @@
 #include "evdi_params.h"
 #include "evdi_debug.h"
 
-unsigned int evdi_loglevel __read_mostly = EVDI_LOGLEVEL_DEBUG;
+unsigned int evdi_loglevel __read_mostly = EVDI_LOGLEVEL_INFO;
 unsigned short int evdi_initial_device_count __read_mostly;
 
 module_param_named(initial_loglevel, evdi_loglevel, int, 0400);
@@ -22,3 +22,4 @@
 module_param_named(initial_device_count,
                   evdi_initial_device_count, ushort, 0644);
 MODULE_PARM_DESC(initial_device_count, "Initial DRM device count (default: 
0)");
+
diff -Nru evdi-1.9.0+dfsg/module/evdi_platform_dev.c 
evdi-1.12.0+dfsg/module/evdi_platform_dev.c
--- evdi-1.9.0+dfsg/module/evdi_platform_dev.c  2021-01-26 09:31:59.000000000 
-0500
+++ evdi-1.12.0+dfsg/module/evdi_platform_dev.c 2022-07-13 09:58:06.000000000 
-0400
@@ -21,7 +21,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #include <linux/iommu.h>
 #endif
 
@@ -41,8 +41,8 @@
 
        platform_dev = platform_device_register_full(info);
        if (dma_set_mask(&platform_dev->dev, DMA_BIT_MASK(64))) {
-               EVDI_DEBUG("Unable to change dma mask to 64 bit. ");
-               EVDI_DEBUG("Sticking with 32 bit\n");
+               EVDI_WARN("Unable to change dma mask to 64 bit. ");
+               EVDI_WARN("Sticking with 32 bit\n");
        }
 
        EVDI_INFO("Evdi platform_device create\n");
@@ -58,20 +58,22 @@
 
 int evdi_platform_device_probe(struct platform_device *pdev)
 {
-       struct drm_device *dev = NULL;
-       struct evdi_platform_device_data *data =
-               kzalloc(sizeof(struct evdi_platform_device_data), GFP_KERNEL);
+       struct drm_device *dev;
+       struct evdi_platform_device_data *data;
 
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU)
        struct dev_iommu iommu;
 #endif
 #endif
        EVDI_CHECKPT();
 
+       data = kzalloc(sizeof(struct evdi_platform_device_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
 /* Intel-IOMMU workaround: platform-bus unsupported, force ID-mapping */
 #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU)
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
        memset(&iommu, 0, sizeof(iommu));
        iommu.priv = (void *)-1;
        pdev->dev.iommu = &iommu;
@@ -83,20 +85,21 @@
 
        dev = evdi_drm_device_create(&pdev->dev);
        if (IS_ERR_OR_NULL(dev))
-               kfree(data);
-       else {
-               data->drm_dev = dev;
-               data->symlinked = false;
-               platform_set_drvdata(pdev, data);
-       }
+               goto err_free;
 
+       data->drm_dev = dev;
+       data->symlinked = false;
+       platform_set_drvdata(pdev, data);
+       return PTR_ERR_OR_ZERO(dev);
+
+err_free:
+       kfree(data);
        return PTR_ERR_OR_ZERO(dev);
 }
 
 int evdi_platform_device_remove(struct platform_device *pdev)
 {
-       struct evdi_platform_device_data *data =
-               (struct evdi_platform_device_data *)platform_get_drvdata(pdev);
+       struct evdi_platform_device_data *data = platform_get_drvdata(pdev);
 
        EVDI_CHECKPT();
 
@@ -107,8 +110,7 @@
 
 bool evdi_platform_device_is_free(struct platform_device *pdev)
 {
-       struct evdi_platform_device_data *data =
-               (struct evdi_platform_device_data *)platform_get_drvdata(pdev);
+       struct evdi_platform_device_data *data = platform_get_drvdata(pdev);
        struct evdi_device *evdi = data->drm_dev->dev_private;
 
        if (evdi && !evdi_painter_is_connected(evdi->painter) &&
@@ -121,23 +123,21 @@
                                      struct device *parent)
 {
        struct evdi_platform_device_data *data = NULL;
-       char evdi_name[10] = { 0 };
        int ret = 0;
 
        if (!parent || !pdev)
                return;
 
-       data = (struct evdi_platform_device_data *)platform_get_drvdata(pdev);
+       data = platform_get_drvdata(pdev);
        if (!evdi_platform_device_is_free(pdev)) {
                EVDI_FATAL("Device is already attached can't symlink again\n");
                return;
        }
 
-       snprintf(evdi_name, sizeof(evdi_name), "evdi.%d", pdev->id);
-       ret = sysfs_create_link(&parent->kobj, &pdev->dev.kobj, evdi_name);
-       if (ret)
-               EVDI_FATAL("Failed to create sysfs link to parent device\n");
-       else {
+       ret = sysfs_create_link(&pdev->dev.kobj, &parent->kobj, "device");
+       if (ret) {
+               EVDI_FATAL("Failed to create sysfs link from evdi to parent 
device\n");
+       } else {
                data->symlinked = true;
                data->parent = parent;
        }
@@ -146,10 +146,10 @@
 void evdi_platform_device_unlink_if_linked_with(struct platform_device *pdev,
                                struct device *parent)
 {
-       struct evdi_platform_device_data *data =
-               (struct evdi_platform_device_data *)platform_get_drvdata(pdev);
+       struct evdi_platform_device_data *data = platform_get_drvdata(pdev);
 
-       if (data->parent == parent) {
+       if (parent && data->parent == parent) {
+               sysfs_remove_link(&pdev->dev.kobj, "device");
                data->symlinked = false;
                data->parent = NULL;
                EVDI_INFO("Detached from parent device\n");
diff -Nru evdi-1.9.0+dfsg/module/evdi_platform_drv.c 
evdi-1.12.0+dfsg/module/evdi_platform_drv.c
--- evdi-1.9.0+dfsg/module/evdi_platform_drv.c  2021-01-26 09:31:59.000000000 
-0500
+++ evdi-1.12.0+dfsg/module/evdi_platform_drv.c 2022-07-13 09:58:06.000000000 
-0400
@@ -31,8 +31,15 @@
        unsigned int dev_count;
        struct platform_device *devices[EVDI_DEVICE_COUNT_MAX];
        struct notifier_block usb_notifier;
+       struct mutex lock;
 } g_ctx;
 
+#define evdi_platform_drv_context_lock(ctx) \
+               mutex_lock(&ctx->lock)
+
+#define evdi_platform_drv_context_unlock(ctx) \
+               mutex_unlock(&ctx->lock)
+
 static int evdi_platform_drv_usb(__always_unused struct notifier_block *nb,
                unsigned long action,
                void *data)
@@ -54,8 +61,10 @@
                if (pdev->dev.parent == &usb_dev->dev) {
                        EVDI_INFO("Parent USB removed. Removing evdi.%d\n", i);
                        evdi_platform_dev_destroy(pdev);
+                       evdi_platform_drv_context_lock((&g_ctx));
                        g_ctx.dev_count--;
                        g_ctx.devices[i] = NULL;
+                       evdi_platform_drv_context_unlock((&g_ctx));
                }
        }
        return 0;
@@ -116,10 +125,15 @@
 {
        struct evdi_platform_drv_context *ctx =
                (struct evdi_platform_drv_context *)dev_get_drvdata(device);
-       struct platform_device *pdev = evdi_platform_drv_get_free_device(ctx);
+       struct platform_device *pdev = NULL;
+
+       evdi_platform_drv_context_lock(ctx);
+       if (parent)
+               pdev = evdi_platform_drv_get_free_device(ctx);
 
        if (IS_ERR_OR_NULL(pdev))
                pdev = evdi_platform_drv_create_new_device(ctx);
+       evdi_platform_drv_context_unlock(ctx);
 
        if (IS_ERR_OR_NULL(pdev))
                return -EINVAL;
@@ -130,19 +144,18 @@
 
 int evdi_platform_add_devices(struct device *device, unsigned int val)
 {
-       struct evdi_platform_drv_context *ctx =
-               (struct evdi_platform_drv_context *)dev_get_drvdata(device);
+       unsigned int dev_count = evdi_platform_device_count(device);
 
        if (val == 0) {
                EVDI_WARN("Adding 0 devices has no effect\n");
                return 0;
        }
-       if (val > EVDI_DEVICE_COUNT_MAX - ctx->dev_count) {
+       if (val > EVDI_DEVICE_COUNT_MAX - dev_count) {
                EVDI_ERROR("Evdi device add failed. Too many devices.\n");
                return -EINVAL;
        }
 
-       EVDI_DEBUG("Increasing device count to %u\n", ctx->dev_count + val);
+       EVDI_INFO("Increasing device count to %u\n", dev_count + val);
        while (val-- && evdi_platform_device_add(device, NULL) == 0)
                ;
        return 0;
@@ -154,6 +167,7 @@
        struct evdi_platform_drv_context *ctx =
                (struct evdi_platform_drv_context *)dev_get_drvdata(device);
 
+       evdi_platform_drv_context_lock(ctx);
        for (i = 0; i < EVDI_DEVICE_COUNT_MAX; ++i) {
                if (ctx->devices[i]) {
                        EVDI_INFO("Removing evdi %d\n", i);
@@ -163,14 +177,21 @@
                }
        }
        ctx->dev_count = 0;
+       evdi_platform_drv_context_unlock(ctx);
 }
 
-int evdi_platform_device_count(struct device *device)
+unsigned int evdi_platform_device_count(struct device *device)
 {
-       struct evdi_platform_drv_context *ctx =
-               (struct evdi_platform_drv_context *)dev_get_drvdata(device);
+       unsigned int count = 0;
+       struct evdi_platform_drv_context *ctx = NULL;
+
+       ctx = (struct evdi_platform_drv_context *)dev_get_drvdata(device);
+       evdi_platform_drv_context_lock(ctx);
+       count = ctx->dev_count;
+       evdi_platform_drv_context_unlock(ctx);
+
+       return count;
 
-       return ctx->dev_count;
 }
 
 static struct platform_driver evdi_platform_driver = {
@@ -193,6 +214,7 @@
        memset(&g_ctx, 0, sizeof(g_ctx));
        g_ctx.root_dev = root_device_register(DRIVER_NAME);
        g_ctx.usb_notifier.notifier_call = evdi_platform_drv_usb;
+       mutex_init(&g_ctx.lock);
        dev_set_drvdata(g_ctx.root_dev, &g_ctx);
 
        usb_register_notify(&g_ctx.usb_notifier);
diff -Nru evdi-1.9.0+dfsg/module/evdi_platform_drv.h 
evdi-1.12.0+dfsg/module/evdi_platform_drv.h
--- evdi-1.9.0+dfsg/module/evdi_platform_drv.h  2021-01-26 09:31:59.000000000 
-0500
+++ evdi-1.12.0+dfsg/module/evdi_platform_drv.h 2022-07-13 09:58:06.000000000 
-0400
@@ -25,14 +25,14 @@
 
 #define DRIVER_NAME   "evdi"
 #define DRIVER_DESC   "Extensible Virtual Display Interface"
-#define DRIVER_DATE   "20201210"
+#define DRIVER_DATE   "20220713"
 
 #define DRIVER_MAJOR 1
-#define DRIVER_MINOR 9
+#define DRIVER_MINOR 12
 #define DRIVER_PATCH 0
 
 void evdi_platform_remove_all_devices(struct device *device);
-int evdi_platform_device_count(struct device *device);
+unsigned int evdi_platform_device_count(struct device *device);
 int evdi_platform_add_devices(struct device *device, unsigned int val);
 int evdi_platform_device_add(struct device *device, struct device *parent);
 
diff -Nru evdi-1.9.0+dfsg/module/evdi_sysfs.c 
evdi-1.12.0+dfsg/module/evdi_sysfs.c
--- evdi-1.9.0+dfsg/module/evdi_sysfs.c 2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/module/evdi_sysfs.c        2022-07-13 09:58:06.000000000 
-0400
@@ -28,6 +28,8 @@
 #include "evdi_debug.h"
 #include "evdi_platform_drv.h"
 
+#define MAX_EVDI_USB_ADDR 10
+
 static ssize_t version_show(__always_unused struct device *dev,
                            __always_unused struct device_attribute *attr,
                            char *buf)
@@ -44,7 +46,6 @@
 }
 
 struct evdi_usb_addr {
-       #define MAX_EVDI_USB_ADDR 10
        int addr[MAX_EVDI_USB_ADDR];
        int len;
        struct usb_device *usb;
@@ -58,15 +59,17 @@
 {
        char *usb_path = kstrdup(buf, GFP_KERNEL);
        char *temp_path = usb_path;
-       char *bus_token = NULL;
-       char *usb_token = NULL;
+       char *bus_token;
+       char *usb_token;
        char *usb_token_copy = NULL;
-       char *itf_token = NULL;
-       char *token = NULL;
-       char *bus = NULL;
-       char *port = NULL;
+       char *token;
+       char *bus;
+       char *port;
        struct evdi_usb_addr usb_addr;
 
+       if (!usb_path)
+               return -ENOMEM;
+
        memset(&usb_addr, 0, sizeof(usb_addr));
        temp_path = strnstr(temp_path, "usb:", count);
        if (!temp_path)
@@ -83,7 +86,8 @@
        if (!usb_token)
                goto err_parse_usb_path;
 
-       itf_token = strsep(&temp_path, ":");
+       /* Separate trailing ':*' from usb_token */
+       strsep(&temp_path, ":");
 
        token = usb_token_copy = kstrdup(usb_token, GFP_KERNEL);
        bus = strsep(&token, "-");
@@ -231,7 +235,7 @@
 
 void evdi_sysfs_init(struct device *root)
 {
-       int i;
+       unsigned int i;
 
        if (!PTR_ERR_OR_ZERO(root))
                for (i = 0; i < ARRAY_SIZE(evdi_device_attributes); i++)
@@ -240,7 +244,7 @@
 
 void evdi_sysfs_exit(struct device *root)
 {
-       int i;
+       unsigned int i;
 
        if (PTR_ERR_OR_ZERO(root)) {
                EVDI_ERROR("root device is null");
diff -Nru evdi-1.9.0+dfsg/module/Kconfig evdi-1.12.0+dfsg/module/Kconfig
--- evdi-1.9.0+dfsg/module/Kconfig      2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/module/Kconfig     2022-07-13 09:58:06.000000000 -0400
@@ -9,6 +9,9 @@
 config DRM_EVDI
        tristate "Extensible Virtual Display Interface"
        depends on DRM
+       depends on USB_SUPPORT
+       depends on USB_ARCH_HAS_HCD
+       select USB
        select DRM_KMS_HELPER
        help
                This is a KMS interface driver allowing user-space programs to
diff -Nru evdi-1.9.0+dfsg/module/Makefile evdi-1.12.0+dfsg/module/Makefile
--- evdi-1.9.0+dfsg/module/Makefile     2021-01-26 09:31:59.000000000 -0500
+++ evdi-1.12.0+dfsg/module/Makefile    2022-07-13 09:58:06.000000000 -0400
@@ -11,13 +11,18 @@
 EL8FLAG := -DEL8
 endif
 
+Raspbian := $(shell grep -Eic 'raspb(erry|ian)' /proc/cpuinfo /etc/os-release 
2>/dev/null )
+ifeq (,$(findstring 0, $(Raspbian)))
+RPIFLAG := -DRPI
+endif
+
 ifneq ($(DKMS_BUILD),)
 
 # DKMS
 
 KERN_DIR := /lib/modules/$(KERNELRELEASE)/build
 
-ccflags-y := -Iinclude/drm $(EL8FLAG)
+ccflags-y := -Iinclude/drm $(EL8FLAG) $(RPIFLAG)
 evdi-y := evdi_platform_drv.o evdi_platform_dev.o evdi_sysfs.o evdi_modeset.o 
evdi_connector.o evdi_encoder.o evdi_drm_drv.o evdi_fb.o evdi_gem.o 
evdi_painter.o evdi_params.o evdi_cursor.o evdi_debug.o evdi_i2c.o
 evdi-$(CONFIG_COMPAT) += evdi_ioc32.o
 obj-m := evdi.o
@@ -40,8 +45,7 @@
 # inside kbuild
 # Note: this can be removed once it is in kernel tree and Kconfig is properly 
used
 CONFIG_DRM_EVDI := m
-LINUXINCLUDE := $(subst -I,-isystem,$(LINUXINCLUDE))
-ccflags-y := -isystem include/drm $(CFLAGS) $(EL8FLAG)
+ccflags-y := -isystem include/drm $(CFLAGS) $(EL8FLAG) $(RPIFLAG)
 evdi-y := evdi_platform_drv.o evdi_platform_dev.o evdi_sysfs.o evdi_modeset.o 
evdi_connector.o evdi_encoder.o evdi_drm_drv.o evdi_fb.o evdi_gem.o 
evdi_painter.o evdi_params.o evdi_cursor.o evdi_debug.o evdi_i2c.o
 evdi-$(CONFIG_COMPAT) += evdi_ioc32.o
 obj-$(CONFIG_DRM_EVDI) := evdi.o
@@ -53,7 +57,7 @@
 DKMS ?= dkms
 RM ?= rm
 
-MODVER=1.9.0
+MODVER=1.12.0
 
 ifeq ($(KVER),)
        KVER := $(shell uname -r)

--- End Message ---
--- Begin Message ---
Source: evdi
Source-Version: 1.14.0+dfsg-1
Done: Harlan Lieberman-Berg <[email protected]>

We believe that the bug you reported is fixed in the latest version of
evdi, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Harlan Lieberman-Berg <[email protected]> (supplier of updated evdi package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Format: 1.8
Date: Fri, 21 Jul 2023 23:52:40 -0400
Source: evdi
Binary: evdi-dkms libevdi-dev libevdi0-dev libevdi1 libevdi1-dbgsym
Architecture: source all amd64
Version: 1.14.0+dfsg-1
Distribution: unstable
Urgency: medium
Maintainer: Harlan Lieberman-Berg <[email protected]>
Changed-By: Harlan Lieberman-Berg <[email protected]>
Description:
 evdi-dkms  - Extensible Virtual Display Interface driver kernel module
 libevdi-dev - EVDI driver client library dev package
 libevdi0-dev - transitional package
 libevdi1   - Extensible Virtual Display Interface driver client library
Closes: 1023276 1027871 1039520
Changes:
 evdi (1.14.0+dfsg-1) unstable; urgency=medium
 .
   * Take maintainer, update salsa links (Closes: #1023276, #1039520)
   * Bump SOVERSION to .1; rename dev package
   * Restore changes accidentally removed (Closes: #1027871)
   * Run wrap-and-sort
   * Bump S-V; no changes needed
Checksums-Sha1:
 0c17ed3b182383417e3c41f95c0b82ce4c989da4 2241 evdi_1.14.0+dfsg-1.dsc
 cb9228adbd857cd95b7d12ffc3da7ab8a38658ff 5388 evdi_1.14.0+dfsg-1.debian.tar.xz
 81404dac8f521c166c2b23a773fe2f09b155ced9 31316 evdi-dkms_1.14.0+dfsg-1_all.deb
 37df2fe8ddeea37d0815a9bcb9b1e63c9f44a86f 7484 
evdi_1.14.0+dfsg-1_amd64.buildinfo
 00c30bef756a605ef8cffc76a0fe9ad31f20d863 5392 libevdi-dev_1.14.0+dfsg-1_all.deb
 16692735b0a192f44e94da855d3327de410dc3e0 3872 
libevdi0-dev_1.14.0+dfsg-1_all.deb
 46b5bd33fa8cb37939be2e78ba3ecc917ec3ed21 26732 
libevdi1-dbgsym_1.14.0+dfsg-1_amd64.deb
 b88d79a745274b0803d2d477278db1fe8365d621 12256 libevdi1_1.14.0+dfsg-1_amd64.deb
Checksums-Sha256:
 d86f56e9352bd3913993640f3064680875857ca60ef3321355028b8f4827aa61 2241 
evdi_1.14.0+dfsg-1.dsc
 58659d0511d63b3a148fa2e42d65e4b6afcbe8be972405f215148f9ecd10ca16 5388 
evdi_1.14.0+dfsg-1.debian.tar.xz
 39184495ea3fb8b1fce16a0e06058c83ae1d2cee75c21ad86b45666c1e53c52b 31316 
evdi-dkms_1.14.0+dfsg-1_all.deb
 4ddb3150665f5ed11006f5b01d95c1dbeefc0adb85422f4cb959de69491184ed 7484 
evdi_1.14.0+dfsg-1_amd64.buildinfo
 0c2b5a824b80413d87721ed5aeed6f23c3792354c04b184410ab92f64cf508c4 5392 
libevdi-dev_1.14.0+dfsg-1_all.deb
 37bff554f96cb32e91b43119ed698672f40339f3c23f274dd520780dfe8e1cb3 3872 
libevdi0-dev_1.14.0+dfsg-1_all.deb
 eb616db241057aa7c89b7b33682621cf0d8fe2ecce639abcfa7ec2dfdf2ffe4c 26732 
libevdi1-dbgsym_1.14.0+dfsg-1_amd64.deb
 cc7cb3167aae39ab839e3d378dc0b64149e92c6a00ab0a5f5ab4e235041a4be0 12256 
libevdi1_1.14.0+dfsg-1_amd64.deb
Files:
 e8536b79a5e582eca8cbd21333366523 2241 misc optional evdi_1.14.0+dfsg-1.dsc
 ebcf80d9fa82a7066fc348a6c4ea91fd 5388 misc optional 
evdi_1.14.0+dfsg-1.debian.tar.xz
 4313e22b7d96ceea976883edcb698280 31316 kernel optional 
evdi-dkms_1.14.0+dfsg-1_all.deb
 25ba593245619dbafd5afd5ac7b1ae65 7484 misc optional 
evdi_1.14.0+dfsg-1_amd64.buildinfo
 f2c73763f8250be39893d373d74cf144 5392 libdevel optional 
libevdi-dev_1.14.0+dfsg-1_all.deb
 d4b6cb92be8c6e3cd1b0e7ae4e0d0092 3872 oldlibs optional 
libevdi0-dev_1.14.0+dfsg-1_all.deb
 57353d722aff3cdc509f9f3ce200b870 26732 debug optional 
libevdi1-dbgsym_1.14.0+dfsg-1_amd64.deb
 a17b6e0ebaee2f7529f19000bf7db489 12256 libs optional 
libevdi1_1.14.0+dfsg-1_amd64.deb

-----BEGIN PGP SIGNATURE-----

iQKqBAEBCgCUFiEE9zr8PqWxFLiOwkJPHjOjduLt8U4FAmS8HeZfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEY3
M0FGQzNFQTVCMTE0Qjg4RUMyNDI0RjFFMzNBMzc2RTJFREYxNEUWHGhsaWViZXJt
YW5AZGViaWFuLm9yZwAKCRAeM6N24u3xTkDoD/9c9y/PwRh+i7EY5KQqfkHxKFdr
Q0d2ynabZfMnOEXGyMdk3YrgAWksfHSD6ebklodSLYnEaFn32ZAGcToEOQaqmjex
zpohcc02VilyVZEhIXTL2t65ppN79t+g58IoEfgBWpXit7daMrFGvyykYsKdDY44
eCwcExKURMIruyOQxswCpohp8lA50Uql8Cb0ppZA2aF42FXUNQbfdwtAx0XuEdcx
mH+qVL71A0GEzgifHG+WrTuoZX8lkyig/2hvfu/ZjZfFkLzZTMHRY0GA7gA87Wck
rmZzWDvj03pIYTifk+n7cKN/1sskC2pdUUTDyP8B1/WforzsKCrn34sO9/ILkNXc
QB1E7ztNTqYSNZyqTXJEYE8jqRiJkOZiCgjt/xGxtYRdCVaURpRYG6zZiVKJiaQx
FopI9fPgDQGoS9Bk8RcZQXvxgb4LFOufQoprG1mGebrS5Coki1IwcwMX5aL+vjoH
M0yEew2SmumDI5U/wTPbUoGPjmerp/5I8BMjjusUo/e2+osm2wPp7Cxkgq6c0K40
hy8zk79N1rG7X/FHPz7uQ7B6DNRdlwvfaVKaOHr98rTyYEL1ICEURuUivXWRezhz
7xBYl/IxlEEhkeqWN16CRwBY8gCIbWjE4hHIwH6m0DER4oI922AnJ/eP/uUduqAK
3oKxdWPU9pHF89xXoQ==
=AplZ
-----END PGP SIGNATURE-----

--- End Message ---

Reply via email to