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 <hlieber...@debian.org>  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 <opensou...@hanno-stock.de>
-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 <71192298+simpilotad...@users.noreply.github.com>
+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)

Reply via email to