Index: /trunk/src/VBox/Additions/linux/drm/vbox_drv.c
===================================================================
--- /trunk/src/VBox/Additions/linux/drm/vbox_drv.c	(revision 74772)
+++ /trunk/src/VBox/Additions/linux/drm/vbox_drv.c	(revision 74773)
@@ -33,9 +33,4 @@
  *          Hans de Goede <hdegoede@redhat.com>
  */
-#include "vbox_drv.h"
-
-#include "version-generated.h"
-#include "revision-generated.h"
-
 #include <linux/module.h>
 #include <linux/console.h>
@@ -45,4 +40,9 @@
 #include <drm/drm_crtc_helper.h>
 
+#include "vbox_drv.h"
+
+#include "version-generated.h"
+#include "revision-generated.h"
+
 int vbox_modeset = -1;
 
@@ -70,13 +70,26 @@
 }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) && !defined(RHEL_74)
+static void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
+					bool suspend)
+{
+	if (!fb_helper || !fb_helper->fbdev)
+		return;
+
+	console_lock();
+	fb_set_suspend(fb_helper->fbdev, suspend);
+	console_unlock();
+}
+#endif
+
 static int vbox_drm_freeze(struct drm_device *dev)
 {
+	struct vbox_private *vbox = dev->dev_private;
+
 	drm_kms_helper_poll_disable(dev);
 
 	pci_save_state(dev->pdev);
 
-	console_lock();
-	vbox_fbdev_set_suspend(dev, 1);
-	console_unlock();
+	drm_fb_helper_set_suspend_unlocked(&vbox->fbdev->helper, true);
 
 	return 0;
@@ -85,10 +98,9 @@
 static int vbox_drm_thaw(struct drm_device *dev)
 {
+	struct vbox_private *vbox = dev->dev_private;
+
 	drm_mode_config_reset(dev);
 	drm_helper_resume_force_mode(dev);
-
-	console_lock();
-	vbox_fbdev_set_suspend(dev, 0);
-	console_unlock();
+	drm_fb_helper_set_suspend_unlocked(&vbox->fbdev->helper, false);
 
 	return 0;
Index: /trunk/src/VBox/Additions/linux/drm/vbox_drv.h
===================================================================
--- /trunk/src/VBox/Additions/linux/drm/vbox_drv.h	(revision 74772)
+++ /trunk/src/VBox/Additions/linux/drm/vbox_drv.h	(revision 74773)
@@ -36,8 +36,5 @@
 #define __VBOX_DRV_H__
 
-#define LOG_GROUP LOG_GROUP_DEV_VGA
-
 #include <linux/version.h>
-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
 # include <linux/types.h>
@@ -86,10 +83,10 @@
 
 #include <drm/drmP.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) || defined(RHEL_75)
+#include <drm/drm_encoder.h>
+#endif
+#include <drm/drm_fb_helper.h>
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) || defined(RHEL_72)
 #include <drm/drm_gem.h>
-#endif
-#include <drm/drm_fb_helper.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) || defined(RHEL_75)
-#include <drm/drm_encoder.h>
 #endif
 
@@ -133,4 +130,12 @@
 #define VBOX_REFRESH_PERIOD (HZ / 2)
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) && !defined(RHEL_72)
+static inline void *devm_kcalloc(struct device *dev, size_t n, size_t size,
+				 gfp_t flags)
+{
+    return devm_kzalloc(dev, n * size, flags);
+}
+#endif
+
 struct vbox_fbdev;
 
@@ -143,5 +148,5 @@
 	struct VBVABUFFERCONTEXT *vbva_info;
 	bool any_pitch;
-	unsigned int num_crtcs;
+	u32 num_crtcs;
 	/** Amount of available VRAM, including space used for buffers. */
 	u32 full_vram_size;
@@ -163,5 +168,4 @@
 
 	struct mutex hw_mutex; /* protects modeset and accel/vbva accesses */
-	bool isr_installed;
 	/**
 	 * We decide whether or not user-space supports display hot-plug
@@ -219,6 +223,6 @@
 	struct vbox_crtc *vbox_crtc;
 	struct {
-		u32 width;
-		u32 height;
+		u16 width;
+		u16 height;
 		bool disconnected;
 	} mode_hint;
@@ -285,12 +289,13 @@
 			  struct vbox_framebuffer *vbox_fb,
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) || defined(RHEL_73)
-			  const
-#endif
+			  const struct DRM_MODE_FB_CMD *mode_cmd,
+#else
 			  struct DRM_MODE_FB_CMD *mode_cmd,
+#endif
 			  struct drm_gem_object *obj);
 
 int vbox_fbdev_init(struct drm_device *dev);
 void vbox_fbdev_fini(struct drm_device *dev);
-void vbox_fbdev_set_suspend(struct drm_device *dev, int state);
+void vbox_fbdev_set_base(struct vbox_private *vbox, unsigned long gpu_addr);
 
 struct vbox_bo {
@@ -373,12 +378,12 @@
 void vbox_gem_prime_unpin(struct drm_gem_object *obj);
 struct sg_table *vbox_gem_prime_get_sg_table(struct drm_gem_object *obj);
-struct drm_gem_object *vbox_gem_prime_import_sg_table(struct drm_device *dev,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) && !defined(RHEL_72)
-						      size_t size,
-#else
-						      struct dma_buf_attachment
-						      *attach,
-#endif
-						      struct sg_table *table);
+struct drm_gem_object *vbox_gem_prime_import_sg_table(
+	struct drm_device *dev, size_t size, struct sg_table *table);
+#else
+struct drm_gem_object *vbox_gem_prime_import_sg_table(
+	struct drm_device *dev, struct dma_buf_attachment *attach,
+	struct sg_table *table);
+#endif
 void *vbox_gem_prime_vmap(struct drm_gem_object *obj);
 void vbox_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
@@ -394,5 +399,5 @@
 /* vbox_hgsmi.c */
 void *hgsmi_buffer_alloc(struct gen_pool *guest_pool, size_t size,
-                         u8 channel, u16 channel_info);
+			 u8 channel, u16 channel_info);
 void hgsmi_buffer_free(struct gen_pool *guest_pool, void *buf);
 int hgsmi_buffer_submit(struct gen_pool *guest_pool, void *buf);
@@ -400,6 +405,6 @@
 static inline void vbox_write_ioport(u16 index, u16 data)
 {
-        outw(index, VBE_DISPI_IOPORT_INDEX);
-        outw(data, VBE_DISPI_IOPORT_DATA);
+	outw(index, VBE_DISPI_IOPORT_INDEX);
+	outw(data, VBE_DISPI_IOPORT_DATA);
 }
 
Index: /trunk/src/VBox/Additions/linux/drm/vbox_fb.c
===================================================================
--- /trunk/src/VBox/Additions/linux/drm/vbox_fb.c	(revision 74772)
+++ /trunk/src/VBox/Additions/linux/drm/vbox_fb.c	(revision 74773)
@@ -32,8 +32,4 @@
  *          Michael Thayer <michael.thayer@oracle.com,
  */
-/* Include from most specific to most general to be able to override things. */
-#include "vbox_drv.h"
-#include <VBoxVideo.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -51,5 +47,7 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
+
 #include "vbox_drv.h"
+#include <VBoxVideo.h>
 
 #define VBOX_DIRTY_DELAY (HZ / 30)
@@ -211,5 +209,5 @@
 #endif
 
-	int ret = 0;
+	int ret;
 
 	size = pitch * mode_cmd->height;
@@ -219,5 +217,6 @@
 
 	*gobj_p = gobj;
-	return ret;
+
+	return 0;
 }
 
@@ -232,6 +231,6 @@
 	struct fb_info *info;
 	struct device *device = &dev->pdev->dev;
-	struct drm_gem_object *gobj = NULL;
-	struct vbox_bo *bo = NULL;
+	struct drm_gem_object *gobj;
+	struct vbox_bo *bo;
 	int size, ret;
 	u32 pitch;
@@ -315,6 +314,4 @@
 	info->apertures->ranges[0].base = pci_resource_start(dev->pdev, 0);
 	info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0);
-	info->fix.smem_start = 0;
-	info->fix.smem_len = size;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) || defined(RHEL_75)
@@ -345,16 +342,19 @@
 };
 
-static void vbox_fbdev_destroy(struct drm_device *dev, struct vbox_fbdev *fbdev)
-{
-	struct fb_info *info;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) && !defined(RHEL_73)
+static void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
+{
+	if (fb_helper && fb_helper->fbdev)
+		unregister_framebuffer(fb_helper->fbdev);
+}
+#endif
+
+void vbox_fbdev_fini(struct drm_device *dev)
+{
+	struct vbox_private *vbox = dev->dev_private;
+	struct vbox_fbdev *fbdev = vbox->fbdev;
 	struct vbox_framebuffer *afb = &fbdev->afb;
 
-	if (fbdev->helper.fbdev) {
-		info = fbdev->helper.fbdev;
-		unregister_framebuffer(info);
-		if (info->cmap.len)
-			fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
+	drm_fb_helper_unregister_fbi(&fbdev->helper);
 
 	if (afb->obj) {
@@ -389,5 +389,5 @@
 	int ret;
 
-	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+	fbdev = devm_kzalloc(dev->dev, sizeof(*fbdev), GFP_KERNEL);
 	if (!fbdev)
 		return -ENOMEM;
@@ -409,9 +409,9 @@
 #endif
 	if (ret)
-		goto free;
+		return ret;
 
 	ret = drm_fb_helper_single_add_all_connectors(&fbdev->helper);
 	if (ret)
-		goto fini;
+		goto err_fini;
 
 	/* disable all the possible outputs/crtcs before entering KMS mode */
@@ -420,36 +420,18 @@
 	ret = drm_fb_helper_initial_config(&fbdev->helper, 32);
 	if (ret)
-		goto fini;
+		goto err_fini;
 
 	return 0;
 
-fini:
+err_fini:
 	drm_fb_helper_fini(&fbdev->helper);
-free:
-	kfree(fbdev);
-	vbox->fbdev = NULL;
-
 	return ret;
 }
 
-void vbox_fbdev_fini(struct drm_device *dev)
-{
-	struct vbox_private *vbox = dev->dev_private;
-
-	if (!vbox->fbdev)
-		return;
-
-	vbox_fbdev_destroy(dev, vbox->fbdev);
-	kfree(vbox->fbdev);
-	vbox->fbdev = NULL;
-}
-
-void vbox_fbdev_set_suspend(struct drm_device *dev, int state)
-{
-	struct vbox_private *vbox = dev->dev_private;
-
-	if (!vbox->fbdev)
-		return;
-
-	fb_set_suspend(vbox->fbdev->helper.fbdev, state);
-}
+void vbox_fbdev_set_base(struct vbox_private *vbox, unsigned long gpu_addr)
+{
+	struct fb_info *fbdev = vbox->fbdev->helper.fbdev;
+
+	fbdev->fix.smem_start = fbdev->apertures->ranges[0].base + gpu_addr;
+	fbdev->fix.smem_len = vbox->available_vram_size - gpu_addr;
+}
Index: /trunk/src/VBox/Additions/linux/drm/vbox_hgsmi.c
===================================================================
--- /trunk/src/VBox/Additions/linux/drm/vbox_hgsmi.c	(revision 74772)
+++ /trunk/src/VBox/Additions/linux/drm/vbox_hgsmi.c	(revision 74773)
@@ -88,10 +88,10 @@
 	dma_addr_t offset;
 
-	total_size = size + sizeof(HGSMIBUFFERHEADER) + sizeof(HGSMIBUFFERTAIL);
+	total_size = size + sizeof(*h) + sizeof(*t);
 	h = gen_pool_dma_alloc(guest_pool, total_size, &offset);
 	if (!h)
 		return NULL;
 
-	t = (HGSMIBUFFERTAIL *)((u8 *)h + sizeof(HGSMIBUFFERHEADER) + size);
+	t = (HGSMIBUFFERTAIL *)((u8 *)h + sizeof(*h) + size);
 
 	h->u8Flags = HGSMI_BUFFER_HEADER_F_SEQ_SINGLE;
@@ -104,5 +104,5 @@
 	t->u32Checksum = hgsmi_checksum(offset, h, t);
 
-	return (u8 *)h + sizeof(HGSMIBUFFERHEADER);
+	return (u8 *)h + sizeof(*h);
 }
 
@@ -110,6 +110,6 @@
 {
 	HGSMIBUFFERHEADER *h =
-		(HGSMIBUFFERHEADER *)((u8 *)buf - sizeof(HGSMIBUFFERHEADER));
-	size_t total_size = h->u32DataSize + sizeof(HGSMIBUFFERHEADER) +
+		(HGSMIBUFFERHEADER *)((u8 *)buf - sizeof(*h));
+	size_t total_size = h->u32DataSize + sizeof(*h) +
 					     sizeof(HGSMIBUFFERTAIL);
 
@@ -127,4 +127,4 @@
 	mb();
 
-	return VINF_SUCCESS;
+	return 0;
 }
Index: /trunk/src/VBox/Additions/linux/drm/vbox_irq.c
===================================================================
--- /trunk/src/VBox/Additions/linux/drm/vbox_irq.c	(revision 74772)
+++ /trunk/src/VBox/Additions/linux/drm/vbox_irq.c	(revision 74773)
@@ -32,10 +32,8 @@
  *          Hans de Goede <hdegoede@redhat.com>
  */
-
 #include "vbox_drv.h"
 
+#include <drm/drm_crtc_helper.h>
 #include <VBoxVideo.h>
-
-#include <drm/drm_crtc_helper.h>
 
 static void vbox_clear_irq(void)
@@ -87,12 +85,13 @@
 static void validate_or_set_position_hints(struct vbox_private *vbox)
 {
+	struct VBVAMODEHINT *hintsi, *hintsj;
+	bool valid = true;
+	u16 currentx = 0;
 	int i, j;
-	u16 currentx = 0;
-	bool valid = true;
 
 	for (i = 0; i < vbox->num_crtcs; ++i) {
 		for (j = 0; j < i; ++j) {
-			struct VBVAMODEHINT *hintsi = &vbox->last_mode_hints[i];
-			struct VBVAMODEHINT *hintsj = &vbox->last_mode_hints[j];
+			hintsi = &vbox->last_mode_hints[i];
+			hintsj = &vbox->last_mode_hints[j];
 
 			if (hintsi->fEnabled && hintsj->fEnabled) {
@@ -131,18 +130,18 @@
 	struct drm_device *dev = vbox->dev;
 	struct drm_connector *connector;
-	struct vbox_connector *vbox_connector;
+	struct vbox_connector *vbox_conn;
 	struct VBVAMODEHINT *hints;
 	u16 flags;
 	bool disconnected;
 	unsigned int crtc_id;
-	int rc;
-
-	rc = VBoxHGSMIGetModeHints(vbox->guest_pool, vbox->num_crtcs,
+	int ret;
+
+	ret = VBoxHGSMIGetModeHints(vbox->guest_pool, vbox->num_crtcs,
 				   vbox->last_mode_hints);
-	if (RT_FAILURE(rc)) {
-		DRM_ERROR("vboxvideo: VBoxHGSMIGetModeHints failed, rc=%i.\n",
-			  rc);
+	if (ret) {
+		DRM_ERROR("vboxvideo: hgsmi_get_mode_hints failed: %d\n", ret);
 		return;
 	}
+
 	validate_or_set_position_hints(vbox);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
@@ -152,30 +151,31 @@
 #endif
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		vbox_connector = to_vbox_connector(connector);
-		hints =
-		    &vbox->last_mode_hints[vbox_connector->vbox_crtc->crtc_id];
-		if (hints->magic == VBVAMODEHINT_MAGIC) {
-			disconnected = !(hints->fEnabled);
-			crtc_id = vbox_connector->vbox_crtc->crtc_id;
-			flags = VBVA_SCREEN_F_ACTIVE
-			    | (disconnected ? VBVA_SCREEN_F_DISABLED :
-			       VBVA_SCREEN_F_BLANK);
-			vbox_connector->mode_hint.width = hints->cx;
-			vbox_connector->mode_hint.height = hints->cy;
-			vbox_connector->vbox_crtc->x_hint = hints->dx;
-			vbox_connector->vbox_crtc->y_hint = hints->dy;
-			vbox_connector->mode_hint.disconnected = disconnected;
-			if (vbox_connector->vbox_crtc->disconnected !=
-			    disconnected) {
-				VBoxHGSMIProcessDisplayInfo(vbox->guest_pool,
-							    crtc_id, 0, 0, 0,
-							    hints->cx * 4,
-							    hints->cx,
-							    hints->cy, 0,
-							    flags);
-				vbox_connector->vbox_crtc->disconnected =
-				    disconnected;
-			}
-		}
+		vbox_conn = to_vbox_connector(connector);
+
+		hints = &vbox->last_mode_hints[vbox_conn->vbox_crtc->crtc_id];
+		if (hints->magic != VBVAMODEHINT_MAGIC)
+			continue;
+
+		disconnected = !(hints->fEnabled);
+		crtc_id = vbox_conn->vbox_crtc->crtc_id;
+		vbox_conn->mode_hint.width = hints->cx & 0x8fff;
+		vbox_conn->mode_hint.height = hints->cy & 0x8fff;
+		vbox_conn->vbox_crtc->x_hint = hints->dx;
+		vbox_conn->vbox_crtc->y_hint = hints->dy;
+		vbox_conn->mode_hint.disconnected = disconnected;
+
+		if (vbox_conn->vbox_crtc->disconnected == disconnected)
+			continue;
+
+		if (disconnected)
+			flags = VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_DISABLED;
+		else
+			flags = VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_BLANK;
+
+		VBoxHGSMIProcessDisplayInfo(vbox->guest_pool, crtc_id, 0, 0, 0,
+					   hints->cx * 4, hints->cx,
+					   hints->cy, 0, flags);
+
+		vbox_conn->vbox_crtc->disconnected = disconnected;
 	}
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
@@ -197,28 +197,16 @@
 int vbox_irq_init(struct vbox_private *vbox)
 {
-	int ret;
-
+	INIT_WORK(&vbox->hotplug_work, vbox_hotplug_worker);
 	vbox_update_mode_hints(vbox);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) || defined(RHEL_71)
-	ret = drm_irq_install(vbox->dev, vbox->dev->pdev->irq);
+	return drm_irq_install(vbox->dev, vbox->dev->pdev->irq);
 #else
-	ret = drm_irq_install(vbox->dev);
+	return drm_irq_install(vbox->dev);
 #endif
-	if (unlikely(ret != 0)) {
-		vbox_irq_fini(vbox);
-		DRM_ERROR("Failed installing irq: %d\n", ret);
-		return 1;
-	}
-	INIT_WORK(&vbox->hotplug_work, vbox_hotplug_worker);
-	vbox->isr_installed = true;
-	return 0;
 }
 
 void vbox_irq_fini(struct vbox_private *vbox)
 {
-	if (vbox->isr_installed) {
-		drm_irq_uninstall(vbox->dev);
-		flush_work(&vbox->hotplug_work);
-		vbox->isr_installed = false;
-	}
-}
+	drm_irq_uninstall(vbox->dev);
+	flush_work(&vbox->hotplug_work);
+}
Index: /trunk/src/VBox/Additions/linux/drm/vbox_main.c
===================================================================
--- /trunk/src/VBox/Additions/linux/drm/vbox_main.c	(revision 74772)
+++ /trunk/src/VBox/Additions/linux/drm/vbox_main.c	(revision 74773)
@@ -34,10 +34,9 @@
  */
 #include "vbox_drv.h"
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
 
 #include <VBoxVideoGuest.h>
 #include <VBoxVideoVBE.h>
-
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_crtc_helper.h>
 
 static void vbox_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -64,14 +63,13 @@
 
 	for (i = 0; i < vbox->num_crtcs; ++i) {
-		if (!vbox->vbva_info[i].pVBVA) {
-			vbva = (struct VBVABUFFER *)
-				((u8 *)vbox->vbva_buffers +
-						     i * VBVA_MIN_BUFFER_SIZE);
-			if (!VBoxVBVAEnable(&vbox->vbva_info[i],
-					    vbox->guest_pool, vbva, i)) {
-				/* very old host or driver error. */
-				DRM_ERROR("vboxvideo: VBoxVBVAEnable failed - heap allocation error.\n");
-				return;
-			}
+		if (vbox->vbva_info[i].pVBVA)
+			continue;
+
+		vbva = (void *)vbox->vbva_buffers + i * VBVA_MIN_BUFFER_SIZE;
+		if (!VBoxVBVAEnable(&vbox->vbva_info[i],
+				 vbox->guest_pool, vbva, i)) {
+			/* very old host or driver error. */
+			DRM_ERROR("vboxvideo: vbva_enable failed\n");
+			return;
 		}
 	}
@@ -88,8 +86,10 @@
 void vbox_report_caps(struct vbox_private *vbox)
 {
-	u32 caps = VBVACAPS_DISABLE_CURSOR_INTEGRATION
-	    | VBVACAPS_IRQ | VBVACAPS_USE_VBVA_ONLY;
+	u32 caps = VBVACAPS_DISABLE_CURSOR_INTEGRATION |
+		   VBVACAPS_IRQ | VBVACAPS_USE_VBVA_ONLY;
+
 	if (vbox->initial_mode_queried)
 		caps |= VBVACAPS_VIDEO_MODE_HINTS;
+
 	VBoxHGSMISendCapsInfo(vbox->guest_pool, caps);
 }
@@ -113,34 +113,29 @@
 	mutex_lock(&vbox->hw_mutex);
 	list_for_each_entry(crtc, &fb->dev->mode_config.crtc_list, head) {
-		if (CRTC_FB(crtc) == fb) {
-			for (i = 0; i < num_rects; ++i) {
-				VBVACMDHDR cmd_hdr;
-				unsigned int crtc_id =
-				    to_vbox_crtc(crtc)->crtc_id;
-
-				if ((rects[i].x1 >
-					 crtc->x + crtc->hwmode.hdisplay) ||
-				    (rects[i].y1 >
-					 crtc->y + crtc->hwmode.vdisplay) ||
-				    (rects[i].x2 < crtc->x) ||
-				    (rects[i].y2 < crtc->y))
-					continue;
-
-				cmd_hdr.x = (s16)rects[i].x1;
-				cmd_hdr.y = (s16)rects[i].y1;
-				cmd_hdr.w = (u16)rects[i].x2 - rects[i].x1;
-				cmd_hdr.h = (u16)rects[i].y2 - rects[i].y1;
-
-				if (VBoxVBVABufferBeginUpdate(
-						&vbox->vbva_info[crtc_id],
-						vbox->guest_pool)) {
-					VBoxVBVAWrite(&vbox->vbva_info[crtc_id],
-						      vbox->guest_pool,
-						      &cmd_hdr,
-						      sizeof(cmd_hdr));
-					VBoxVBVABufferEndUpdate(
-						&vbox->vbva_info[crtc_id]);
-				}
-			}
+		if (CRTC_FB(crtc) != fb)
+			continue;
+
+		for (i = 0; i < num_rects; ++i) {
+			VBVACMDHDR cmd_hdr;
+			unsigned int crtc_id = to_vbox_crtc(crtc)->crtc_id;
+
+			if ((rects[i].x1 > crtc->x + crtc->hwmode.hdisplay) ||
+			    (rects[i].y1 > crtc->y + crtc->hwmode.vdisplay) ||
+			    (rects[i].x2 < crtc->x) ||
+			    (rects[i].y2 < crtc->y))
+				continue;
+
+			cmd_hdr.x = (s16)rects[i].x1;
+			cmd_hdr.y = (s16)rects[i].y1;
+			cmd_hdr.w = (u16)rects[i].x2 - rects[i].x1;
+			cmd_hdr.h = (u16)rects[i].y2 - rects[i].y1;
+
+			if (!VBoxVBVABufferBeginUpdate(&vbox->vbva_info[crtc_id],
+						      vbox->guest_pool))
+				continue;
+
+			VBoxVBVAWrite(&vbox->vbva_info[crtc_id], vbox->guest_pool,
+				   &cmd_hdr, sizeof(cmd_hdr));
+			VBoxVBVABufferEndUpdate(&vbox->vbva_info[crtc_id]);
 		}
 	}
@@ -167,7 +162,8 @@
 			  struct vbox_framebuffer *vbox_fb,
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) || defined(RHEL_73)
-			  const
-#endif
+			  const struct DRM_MODE_FB_CMD *mode_cmd,
+#else
 			  struct DRM_MODE_FB_CMD *mode_cmd,
+#endif
 			  struct drm_gem_object *obj)
 {
@@ -200,5 +196,5 @@
 	struct drm_gem_object *obj;
 	struct vbox_framebuffer *vbox_fb;
-	int ret;
+	int ret = -ENOMEM;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) || defined(RHEL_74)
@@ -211,17 +207,18 @@
 
 	vbox_fb = kzalloc(sizeof(*vbox_fb), GFP_KERNEL);
-	if (!vbox_fb) {
-		drm_gem_object_unreference_unlocked(obj);
-		return ERR_PTR(-ENOMEM);
-	}
+	if (!vbox_fb)
+		goto err_unref_obj;
 
 	ret = vbox_framebuffer_init(dev, vbox_fb, mode_cmd, obj);
-	if (ret) {
-		drm_gem_object_unreference_unlocked(obj);
-		kfree(vbox_fb);
-		return ERR_PTR(ret);
-	}
+	if (ret)
+		goto err_free_vbox_fb;
 
 	return &vbox_fb->base;
+
+err_free_vbox_fb:
+	kfree(vbox_fb);
+err_unref_obj:
+	drm_gem_object_unreference_unlocked(obj);
+	return ERR_PTR(ret);
 }
 
@@ -230,17 +227,4 @@
 };
 
-static void vbox_accel_fini(struct vbox_private *vbox)
-{
-	if (vbox->vbva_info) {
-		vbox_disable_accel(vbox);
-		kfree(vbox->vbva_info);
-		vbox->vbva_info = NULL;
-	}
-	if (vbox->vbva_buffers) {
-		pci_iounmap(vbox->dev->pdev, vbox->vbva_buffers);
-		vbox->vbva_buffers = NULL;
-	}
-}
-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) && !defined(RHEL_73)
 #define pci_iomap_range(dev, bar, offset, maxlen) \
@@ -252,6 +236,6 @@
 	unsigned int i;
 
-	vbox->vbva_info = kcalloc(vbox->num_crtcs, sizeof(*vbox->vbva_info),
-				  GFP_KERNEL);
+	vbox->vbva_info = devm_kcalloc(vbox->dev->dev, vbox->num_crtcs,
+				       sizeof(*vbox->vbva_info), GFP_KERNEL);
 	if (!vbox->vbva_info)
 		return -ENOMEM;
@@ -269,11 +253,17 @@
 	for (i = 0; i < vbox->num_crtcs; ++i)
 		VBoxVBVASetupBufferContext(&vbox->vbva_info[i],
-					   vbox->available_vram_size +
-					   i * VBVA_MIN_BUFFER_SIZE,
-					   VBVA_MIN_BUFFER_SIZE);
+					  vbox->available_vram_size +
+					  i * VBVA_MIN_BUFFER_SIZE,
+					  VBVA_MIN_BUFFER_SIZE);
 
 	vbox_enable_accel(vbox);
 
 	return 0;
+}
+
+static void vbox_accel_fini(struct vbox_private *vbox)
+{
+	vbox_disable_accel(vbox);
+	pci_iounmap(vbox->dev->pdev, vbox->vbva_buffers);
 }
 
@@ -285,13 +275,13 @@
 
 	ret = VBoxQueryConfHGSMI(vbox->guest_pool,
-				 VBOX_VBVA_CONF32_MODE_HINT_REPORTING,
-				 &have_hints);
-	if (RT_FAILURE(ret))
+			       VBOX_VBVA_CONF32_MODE_HINT_REPORTING,
+			       &have_hints);
+	if (ret)
 		return false;
 
 	ret = VBoxQueryConfHGSMI(vbox->guest_pool,
-				 VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING,
-				 &have_cursor);
-	if (RT_FAILURE(ret))
+			       VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING,
+			       &have_cursor);
+	if (ret)
 		return false;
 
@@ -325,4 +315,14 @@
 }
 
+static bool vbox_check_supported(u16 id)
+{
+	u16 dispi_id;
+
+	vbox_write_ioport(VBE_DISPI_INDEX_ID, id);
+	dispi_id = inw(VBE_DISPI_IOPORT_DATA);
+
+	return dispi_id == id;
+}
+
 /**
  * Set up our heaps and data exchange buffers in VRAM before handing the rest
@@ -331,8 +331,8 @@
 static int vbox_hw_init(struct vbox_private *vbox)
 {
-	int ret;
-
-	vbox->full_vram_size = VBoxVideoGetVRAMSize();
-	vbox->any_pitch = VBoxVideoAnyWidthAllowed();
+	int ret = -ENOMEM;
+
+	vbox->full_vram_size = inl(VBE_DISPI_IOPORT_DATA);
+	vbox->any_pitch = vbox_check_supported(VBE_DISPI_ID_ANYX);
 
 	DRM_INFO("VRAM %08x\n", vbox->full_vram_size);
@@ -348,5 +348,5 @@
 	vbox->guest_pool = gen_pool_create(4, -1);
 	if (!vbox->guest_pool)
-		return -ENOMEM;
+		goto err_unmap_guest_heap;
 
 	ret = gen_pool_add_virt(vbox->guest_pool,
@@ -355,26 +355,40 @@
 				GUEST_HEAP_USABLE_SIZE, -1);
 	if (ret)
-		return ret;
+		goto err_destroy_guest_pool;
 
 	/* Reduce available VRAM size to reflect the guest heap. */
 	vbox->available_vram_size = GUEST_HEAP_OFFSET(vbox);
 	/* Linux drm represents monitors as a 32-bit array. */
-	vbox->num_crtcs = min_t(u32, VBoxHGSMIGetMonitorCount(vbox->guest_pool),
-				VBOX_MAX_SCREENS);
-
-	if (!have_hgsmi_mode_hints(vbox))
-		return -ENOTSUPP;
-
-	vbox->last_mode_hints =
-	    kcalloc(vbox->num_crtcs, sizeof(VBVAMODEHINT), GFP_KERNEL);
-	if (!vbox->last_mode_hints)
-		return -ENOMEM;
+	VBoxQueryConfHGSMI(vbox->guest_pool, VBOX_VBVA_CONF32_MONITOR_COUNT,
+			 &vbox->num_crtcs);
+	vbox->num_crtcs = clamp_t(u32, vbox->num_crtcs, 1, VBOX_MAX_SCREENS);
+
+	if (!have_hgsmi_mode_hints(vbox)) {
+		ret = -ENOTSUPP;
+		goto err_destroy_guest_pool;
+	}
+
+	vbox->last_mode_hints = devm_kcalloc(vbox->dev->dev, vbox->num_crtcs,
+					     sizeof(VBVAMODEHINT),
+					     GFP_KERNEL);
+	if (!vbox->last_mode_hints) {
+		ret = -ENOMEM;
+		goto err_destroy_guest_pool;
+	}
 
 	ret = vbox_accel_init(vbox);
 	if (ret)
-		return ret;
+		goto err_destroy_guest_pool;
+
 	/* Set up the refresh timer for users which do not send dirty rectangles. */
 	INIT_DELAYED_WORK(&vbox->refresh_work, vbox_refresh_timer);
-	return 0;
+
+	return 0;
+
+err_destroy_guest_pool:
+	gen_pool_destroy(vbox->guest_pool);
+err_unmap_guest_heap:
+	pci_iounmap(vbox->dev->pdev, vbox->guest_heap);
+	return ret;
 }
 
@@ -384,6 +398,6 @@
 	cancel_delayed_work(&vbox->refresh_work);
 	vbox_accel_fini(vbox);
-	kfree(vbox->last_mode_hints);
-	vbox->last_mode_hints = NULL;
+	gen_pool_destroy(vbox->guest_pool);
+	pci_iounmap(vbox->dev->pdev, vbox->guest_heap);
 }
 
@@ -393,8 +407,8 @@
 	int ret = 0;
 
-	if (!VBoxHGSMIIsSupported())
+	if (!vbox_check_supported(VBE_DISPI_ID_HGSMI))
 		return -ENODEV;
 
-	vbox = kzalloc(sizeof(*vbox), GFP_KERNEL);
+	vbox = devm_kzalloc(dev->dev, sizeof(*vbox), GFP_KERNEL);
 	if (!vbox)
 		return -ENOMEM;
@@ -407,9 +421,9 @@
 	ret = vbox_hw_init(vbox);
 	if (ret)
-		goto out_free;
+		return ret;
 
 	ret = vbox_mm_init(vbox);
 	if (ret)
-		goto out_free;
+		goto err_hw_fini;
 
 	drm_mode_config_init(dev);
@@ -424,18 +438,25 @@
 	ret = vbox_mode_init(dev);
 	if (ret)
-		goto out_free;
+		goto err_drm_mode_cleanup;
 
 	ret = vbox_irq_init(vbox);
 	if (ret)
-		goto out_free;
+		goto err_mode_fini;
 
 	ret = vbox_fbdev_init(dev);
 	if (ret)
-		goto out_free;
-
-	return 0;
-
-out_free:
-	vbox_driver_unload(dev);
+		goto err_irq_fini;
+
+	return 0;
+
+err_irq_fini:
+	vbox_irq_fini(vbox);
+err_mode_fini:
+	vbox_mode_fini(dev);
+err_drm_mode_cleanup:
+	drm_mode_config_cleanup(dev);
+	vbox_mm_fini(vbox);
+err_hw_fini:
+	vbox_hw_fini(vbox);
 	return ret;
 }
@@ -452,15 +473,7 @@
 	vbox_irq_fini(vbox);
 	vbox_mode_fini(dev);
-	if (dev->mode_config.funcs)
-		drm_mode_config_cleanup(dev);
-
+	drm_mode_config_cleanup(dev);
+	vbox_mm_fini(vbox);
 	vbox_hw_fini(vbox);
-	vbox_mm_fini(vbox);
-	if (vbox->guest_pool)
-		gen_pool_destroy(vbox->guest_pool);
-	if (vbox->guest_heap)
-		pci_iounmap(dev->pdev, vbox->guest_heap);
-	kfree(vbox);
-	dev->dev_private = NULL;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) && !defined(RHEL_75)
 	return 0;
Index: /trunk/src/VBox/Additions/linux/drm/vbox_mode.c
===================================================================
--- /trunk/src/VBox/Additions/linux/drm/vbox_mode.c	(revision 74772)
+++ /trunk/src/VBox/Additions/linux/drm/vbox_mode.c	(revision 74773)
@@ -108,8 +108,8 @@
 	flags |= vbox_crtc->disconnected ? VBVA_SCREEN_F_DISABLED : 0;
 	VBoxHGSMIProcessDisplayInfo(vbox->guest_pool, vbox_crtc->crtc_id,
-				    x_offset, y_offset,
-				    crtc->x * bpp / 8 + crtc->y * pitch,
-				    pitch, width, height,
-				    vbox_crtc->blanked ? 0 : bpp, flags);
+				   x_offset, y_offset,
+				   crtc->x * bpp / 8 + crtc->y * pitch,
+				   pitch, width, height,
+				   vbox_crtc->blanked ? 0 : bpp, flags);
 }
 
@@ -118,5 +118,5 @@
 	struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
 	struct vbox_private *vbox = crtc->dev->dev_private;
-	void *p;
+	VBVAINFOVIEW *p;
 
 	/*
@@ -131,21 +131,17 @@
 	 * buffer and so on.
 	 */
-	p = VBoxHGSMIBufferAlloc(vbox->guest_pool, sizeof(VBVAINFOVIEW),
-				 HGSMI_CH_VBVA, VBVA_INFO_VIEW);
-	if (p) {
-		VBVAINFOVIEW *pInfo = (VBVAINFOVIEW *) p;
-
-		pInfo->u32ViewIndex = vbox_crtc->crtc_id;
-		pInfo->u32ViewOffset = vbox_crtc->fb_offset;
-		pInfo->u32ViewSize =
-		    vbox->available_vram_size - vbox_crtc->fb_offset +
-		    vbox_crtc->crtc_id * VBVA_MIN_BUFFER_SIZE;
-		pInfo->u32MaxScreenSize =
-		    vbox->available_vram_size - vbox_crtc->fb_offset;
-		VBoxHGSMIBufferSubmit(vbox->guest_pool, p);
-		VBoxHGSMIBufferFree(vbox->guest_pool, p);
-	} else {
+	p = VBoxHGSMIBufferAlloc(vbox->guest_pool, sizeof(*p),
+			       HGSMI_CH_VBVA, VBVA_INFO_VIEW);
+	if (!p)
 		return -ENOMEM;
-	}
+
+	p->u32ViewIndex = vbox_crtc->crtc_id;
+	p->u32ViewOffset = vbox_crtc->fb_offset;
+	p->u32ViewSize = vbox->available_vram_size - vbox_crtc->fb_offset +
+		       vbox_crtc->crtc_id * VBVA_MIN_BUFFER_SIZE;
+	p->u32MaxScreenSize = vbox->available_vram_size - vbox_crtc->fb_offset;
+
+	VBoxHGSMIBufferSubmit(vbox->guest_pool, p);
+	VBoxHGSMIBufferFree(vbox->guest_pool, p);
 
 	return 0;
@@ -213,13 +209,12 @@
 		list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list,
 				    head) {
-			if (to_vbox_crtc(crtci)->crtc_id == 0) {
-				vbox->single_framebuffer = true;
-				vbox->input_mapping_width =
-				    CRTC_FB(crtci)->width;
-				vbox->input_mapping_height =
-				    CRTC_FB(crtci)->height;
-				return old_single_framebuffer !=
-				    vbox->single_framebuffer;
-			}
+			if (to_vbox_crtc(crtci)->crtc_id != 0)
+				continue;
+
+			vbox->single_framebuffer = true;
+			vbox->input_mapping_width = CRTC_FB(crtci)->width;
+			vbox->input_mapping_height = CRTC_FB(crtci)->height;
+			return old_single_framebuffer !=
+			       vbox->single_framebuffer;
 		}
 	}
@@ -283,4 +278,7 @@
 	}
 
+	if (&vbox->fbdev->afb == vbox_fb)
+		vbox_fbdev_set_base(vbox, gpu_addr);
+
 	vbox_crtc->fb_offset = gpu_addr;
 	if (vbox_set_up_input_mapping(vbox)) {
@@ -303,17 +301,17 @@
 {
 	struct vbox_private *vbox = crtc->dev->dev_private;
-	int rc = vbox_crtc_set_base(crtc, old_fb, x, y);
-	if (rc)
-		return rc;
+	int ret = vbox_crtc_set_base(crtc, old_fb, x, y);
+	if (ret)
+		return ret;
 	mutex_lock(&vbox->hw_mutex);
-	rc = vbox_set_view(crtc);
-	if (!rc)
+	ret = vbox_set_view(crtc);
+	if (!ret)
 		vbox_do_modeset(crtc, mode);
 	VBoxHGSMIUpdateInputMapping(vbox->guest_pool, 0, 0,
-				    vbox->input_mapping_width,
-				    vbox->input_mapping_height);
+				   vbox->input_mapping_width,
+				   vbox->input_mapping_height);
 	mutex_unlock(&vbox->hw_mutex);
 
-	return rc;
+	return ret;
 }
 
@@ -455,9 +453,9 @@
 
 	drm_encoder_init(dev, &vbox_encoder->base, &vbox_enc_funcs,
-			 DRM_MODE_ENCODER_DAC
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) || defined(RHEL_73)
-			 , NULL
-#endif
-	    );
+			 DRM_MODE_ENCODER_DAC, NULL);
+#else
+			 DRM_MODE_ENCODER_DAC);
+#endif
 	drm_encoder_helper_add(&vbox_encoder->base, &vbox_enc_helper_funcs);
 
@@ -564,5 +562,5 @@
 	 */
 	VBoxHGSMIReportFlagsLocation(vbox->guest_pool, GUEST_HEAP_OFFSET(vbox) +
-				     HOST_FLAGS_OFFSET);
+				    HOST_FLAGS_OFFSET);
 	if (vbox_connector->vbox_crtc->crtc_id == 0)
 		vbox_report_caps(vbox);
@@ -621,5 +619,5 @@
 static void vbox_connector_destroy(struct drm_connector *connector)
 {
-	struct vbox_connector *vbox_connector = NULL;
+	struct vbox_connector *vbox_connector;
 
 	vbox_connector = to_vbox_connector(connector);
@@ -636,7 +634,6 @@
 vbox_connector_detect(struct drm_connector *connector, bool force)
 {
-	struct vbox_connector *vbox_connector = NULL;
-
-	(void)force;
+	struct vbox_connector *vbox_connector;
+
 	vbox_connector = to_vbox_connector(connector);
 
@@ -724,4 +721,5 @@
 	struct vbox_crtc *vbox_crtc;
 	unsigned int i;
+	int ret;
 
 	/* vbox_cursor_init(dev); */
@@ -733,5 +731,7 @@
 		if (!encoder)
 			return -ENOMEM;
-		vbox_connector_init(dev, vbox_crtc, encoder);
+		ret = vbox_connector_init(dev, vbox_crtc, encoder);
+		if (ret)
+			return ret;
 	}
 
@@ -768,13 +768,13 @@
 	struct vbox_private *vbox = crtc->dev->dev_private;
 	struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
+	struct ttm_bo_kmap_obj uobj_map;
+	size_t data_size, mask_size;
 	struct drm_gem_object *obj;
+	u32 flags, caps = 0;
 	struct vbox_bo *bo;
-	int ret, rc;
-	struct ttm_bo_kmap_obj uobj_map;
+	bool src_isiomem;
+	u8 *dst = NULL;
 	u8 *src;
-	u8 *dst = NULL;
-	u32 caps = 0;
-	size_t data_size, mask_size;
-	bool src_isiomem;
+	int ret;
 
 	if (!handle) {
@@ -785,24 +785,26 @@
 		vbox_crtc->cursor_enabled = false;
 		list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list,
-				    head)
+				    head) {
 			if (to_vbox_crtc(crtci)->cursor_enabled)
 				cursor_enabled = true;
+			}
 
 		if (!cursor_enabled)
 			VBoxHGSMIUpdatePointerShape(vbox->guest_pool, 0, 0, 0,
-						    0, 0, NULL, 0);
+						   0, 0, NULL, 0);
 		return 0;
 	}
+
 	vbox_crtc->cursor_enabled = true;
+
 	if (width > VBOX_MAX_CURSOR_WIDTH || height > VBOX_MAX_CURSOR_HEIGHT ||
 	    width == 0 || height == 0)
 		return -EINVAL;
-	rc = VBoxQueryConfHGSMI(vbox->guest_pool,
+	ret = VBoxQueryConfHGSMI(vbox->guest_pool,
 				VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &caps);
-	ret = rc == VINF_SUCCESS ? 0 : rc == VERR_NO_MEMORY ? -ENOMEM : -EINVAL;
 	if (ret)
-		return ret;
-
-	if (!(caps & VBOX_VBVA_CURSOR_CAPABILITY_HARDWARE))
+		return ret == VERR_NO_MEMORY ? -ENOMEM : -EINVAL;
+
+	if (!(caps & VBOX_VBVA_CURSOR_CAPABILITY_HARDWARE)) {
 		/*
 		 * -EINVAL means cursor_set2() not supported, -EAGAIN means
@@ -810,4 +812,5 @@
 		 */
 		return -EBUSY;
+	}
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) || defined(RHEL_74)
@@ -816,59 +819,57 @@
 	obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
 #endif
-	if (obj) {
-		bo = gem_to_vbox_bo(obj);
-		ret = vbox_bo_reserve(bo, false);
-		if (!ret) {
-			/*
-			 * The mask must be calculated based on the alpha
-			 * channel, one bit per ARGB word, and must be 32-bit
-			 * padded.
-			 */
-			mask_size = ((width + 7) / 8 * height + 3) & ~3;
-			data_size = width * height * 4 + mask_size;
-			vbox->cursor_hot_x = hot_x;
-			vbox->cursor_hot_y = hot_y;
-			vbox->cursor_width = width;
-			vbox->cursor_height = height;
-			vbox->cursor_data_size = data_size;
-			dst = vbox->cursor_data;
-			ret =
-			    ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages,
-					&uobj_map);
-			if (!ret) {
-				src =
-				    ttm_kmap_obj_virtual(&uobj_map,
-							 &src_isiomem);
-				if (!src_isiomem) {
-					u32 flags =
-					    VBOX_MOUSE_POINTER_VISIBLE |
-					    VBOX_MOUSE_POINTER_SHAPE |
-					    VBOX_MOUSE_POINTER_ALPHA;
-					copy_cursor_image(src, dst, width,
-							  height, mask_size);
-					rc = VBoxHGSMIUpdatePointerShape(
-						vbox->guest_pool, flags,
-						vbox->cursor_hot_x,
-						vbox->cursor_hot_y,
-						width, height, dst, data_size);
-					ret =
-					    rc == VINF_SUCCESS ? 0 : rc ==
-					    VERR_NO_MEMORY ? -ENOMEM : rc ==
-					    VERR_NOT_SUPPORTED ? -EBUSY :
-					    -EINVAL;
-				} else {
-					DRM_ERROR("src cursor bo should be in main memory\n");
-				}
-				ttm_bo_kunmap(&uobj_map);
-			} else {
-				vbox->cursor_data_size = 0;
-			}
-			vbox_bo_unreserve(bo);
-		}
-		drm_gem_object_unreference_unlocked(obj);
-	} else {
+	if (!obj) {
 		DRM_ERROR("Cannot find cursor object %x for crtc\n", handle);
-		ret = -ENOENT;
-	}
+		return -ENOENT;
+	}
+
+	bo = gem_to_vbox_bo(obj);
+	ret = vbox_bo_reserve(bo, false);
+	if (ret)
+		goto out_unref_obj;
+
+	/*
+	 * The mask must be calculated based on the alpha
+	 * channel, one bit per ARGB word, and must be 32-bit
+	 * padded.
+	 */
+	mask_size = ((width + 7) / 8 * height + 3) & ~3;
+	data_size = width * height * 4 + mask_size;
+	vbox->cursor_hot_x = hot_x;
+	vbox->cursor_hot_y = hot_y;
+	vbox->cursor_width = width;
+	vbox->cursor_height = height;
+	vbox->cursor_data_size = data_size;
+	dst = vbox->cursor_data;
+
+	ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &uobj_map);
+	if (ret) {
+		vbox->cursor_data_size = 0;
+		goto out_unreserve_bo;
+	}
+
+	src = ttm_kmap_obj_virtual(&uobj_map, &src_isiomem);
+	if (src_isiomem) {
+		DRM_ERROR("src cursor bo not in main memory\n");
+		ret = -EIO;
+		goto out_unmap_bo;
+	}
+
+	copy_cursor_image(src, dst, width, height, mask_size);
+
+	flags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE |
+		VBOX_MOUSE_POINTER_ALPHA;
+	ret = VBoxHGSMIUpdatePointerShape(vbox->guest_pool, flags,
+					 vbox->cursor_hot_x, vbox->cursor_hot_y,
+					 width, height, dst, data_size);
+	ret = ret == VINF_SUCCESS ? 0 : ret == VERR_NO_MEMORY ? -ENOMEM :
+		ret == VERR_NOT_SUPPORTED ? -EBUSY : -EINVAL;
+
+out_unmap_bo:
+	ttm_bo_kunmap(&uobj_map);
+out_unreserve_bo:
+	vbox_bo_unreserve(bo);
+out_unref_obj:
+	drm_gem_object_unreference_unlocked(obj);
 
 	return ret;
@@ -882,5 +883,5 @@
 	s32 crtc_y =
 	    vbox->single_framebuffer ? crtc->y : to_vbox_crtc(crtc)->y_hint;
-	int rc;
+	int ret;
 
 	x += vbox->cursor_hot_x;
@@ -891,7 +892,7 @@
 		vbox->cursor_data_size == 0)
 		return 0;
-	rc = VBoxHGSMICursorPosition(vbox->guest_pool, true, x + crtc_x,
+	ret = VBoxHGSMICursorPosition(vbox->guest_pool, true, x + crtc_x,
 					 y + crtc_y, NULL, NULL);
-	return rc == VINF_SUCCESS ? 0 : rc == VERR_NO_MEMORY ? -ENOMEM : rc ==
+	return ret == VINF_SUCCESS ? 0 : ret == VERR_NO_MEMORY ? -ENOMEM : ret ==
 		VERR_NOT_SUPPORTED ? -EBUSY : -EINVAL;
 }
Index: /trunk/src/VBox/Additions/linux/drm/vbox_prime.c
===================================================================
--- /trunk/src/VBox/Additions/linux/drm/vbox_prime.c	(revision 74772)
+++ /trunk/src/VBox/Additions/linux/drm/vbox_prime.c	(revision 74773)
@@ -1,5 +1,4 @@
 /*
  * Copyright (C) 2017 Oracle Corporation
- * This file is based on ????.c?
  * Copyright 2017 Canonical
  *
@@ -50,12 +49,12 @@
 }
 
-struct drm_gem_object *vbox_gem_prime_import_sg_table(struct drm_device *dev,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) && !defined(RHEL_72)
-						      size_t size,
+struct drm_gem_object *vbox_gem_prime_import_sg_table(
+	struct drm_device *dev, size_t size, struct sg_table *table)
 #else
-						      struct dma_buf_attachment
-						      *attach,
+struct drm_gem_object *vbox_gem_prime_import_sg_table(
+	struct drm_device *dev, struct dma_buf_attachment *attach,
+	struct sg_table *table)
 #endif
-						      struct sg_table *table)
 {
 	WARN_ONCE(1, "not implemented");
Index: /trunk/src/VBox/Additions/linux/drm/vbox_ttm.c
===================================================================
--- /trunk/src/VBox/Additions/linux/drm/vbox_ttm.c	(revision 74772)
+++ /trunk/src/VBox/Additions/linux/drm/vbox_ttm.c	(revision 74773)
@@ -63,5 +63,5 @@
 {
 	struct drm_global_reference *global_ref;
-	int r;
+	int ret;
 
 	global_ref = &vbox->ttm.mem_global_ref;
@@ -70,8 +70,8 @@
 	global_ref->init = &vbox_ttm_mem_global_init;
 	global_ref->release = &vbox_ttm_mem_global_release;
-	r = drm_global_item_ref(global_ref);
-	if (r != 0) {
-		DRM_ERROR("Failed setting up TTM memory accounting subsystem.\n");
-		return r;
+	ret = drm_global_item_ref(global_ref);
+	if (ret) {
+		DRM_ERROR("Failed setting up TTM memory subsystem.\n");
+		return ret;
 	}
 
@@ -83,9 +83,9 @@
 	global_ref->release = &ttm_bo_global_release;
 
-	r = drm_global_item_ref(global_ref);
-	if (r != 0) {
+	ret = drm_global_item_ref(global_ref);
+	if (ret) {
 		DRM_ERROR("Failed setting up TTM BO subsystem.\n");
 		drm_global_item_unref(&vbox->ttm.mem_global_ref);
-		return r;
+		return ret;
 	}
 
@@ -98,10 +98,6 @@
 static void vbox_ttm_global_release(struct vbox_private *vbox)
 {
-	if (!vbox->ttm.mem_global_ref.release)
-		return;
-
 	drm_global_item_unref(&vbox->ttm.bo_global_ref.ref);
 	drm_global_item_unref(&vbox->ttm.mem_global_ref);
-	vbox->ttm.mem_global_ref.release = NULL;
 }
 
@@ -305,5 +301,5 @@
 	if (ret) {
 		DRM_ERROR("Error initialising bo driver; %d\n", ret);
-		return ret;
+		goto err_ttm_global_release;
 	}
 
@@ -312,6 +308,7 @@
 	if (ret) {
 		DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
-		return ret;
-	}
+		goto err_device_release;
+	}
+
 #ifdef DRM_MTRR_WC
 	vbox->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
@@ -322,28 +319,24 @@
 					 pci_resource_len(dev->pdev, 0));
 #endif
-
-	vbox->ttm.mm_initialised = true;
-
-	return 0;
+	return 0;
+
+err_device_release:
+	ttm_bo_device_release(&vbox->ttm.bdev);
+err_ttm_global_release:
+	vbox_ttm_global_release(vbox);
+	return ret;
 }
 
 void vbox_mm_fini(struct vbox_private *vbox)
 {
-#ifdef DRM_MTRR_WC
-	struct drm_device *dev = vbox->dev;
-#endif
-	if (!vbox->ttm.mm_initialised)
-		return;
-	ttm_bo_device_release(&vbox->ttm.bdev);
-
-	vbox_ttm_global_release(vbox);
-
 #ifdef DRM_MTRR_WC
 	drm_mtrr_del(vbox->fb_mtrr,
-		     pci_resource_start(dev->pdev, 0),
-		     pci_resource_len(dev->pdev, 0), DRM_MTRR_WC);
+		     pci_resource_start(vbox->dev->pdev, 0),
+		     pci_resource_len(vbox->dev->pdev, 0), DRM_MTRR_WC);
 #else
 	arch_phys_wc_del(vbox->fb_mtrr);
 #endif
+	ttm_bo_device_release(&vbox->ttm.bdev);
+	vbox_ttm_global_release(vbox);
 }
 
@@ -373,4 +366,5 @@
 	bo->placement.num_placement = c;
 	bo->placement.num_busy_placement = c;
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) || defined(RHEL_72)
 	for (i = 0; i < c; ++i) {
@@ -394,8 +388,6 @@
 
 	ret = drm_gem_object_init(dev, &vboxbo->gem, size);
-	if (ret) {
-		kfree(vboxbo);
-		return ret;
-	}
+	if (ret)
+		goto err_free_vboxbo;
 
 	vboxbo->bo.bdev = &vbox->ttm.bdev;
@@ -417,13 +409,18 @@
 #endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) || defined(RHEL_72)
-			  NULL,
-#endif
+			  NULL, NULL, vbox_bo_ttm_destroy);
+#else
 			  NULL, vbox_bo_ttm_destroy);
+#endif
 	if (ret)
-		return ret;
+		goto err_free_vboxbo;
 
 	*pvboxbo = vboxbo;
 
 	return 0;
+
+err_free_vboxbo:
+	kfree(vboxbo);
+	return ret;
 }
 
