]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/gpu/drm/udl/udl_fb.c
Merge branch 'udl-fixes' into drm-next
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / udl / udl_fb.c
index caa84f1de9c1d46b8d35dd218945ad504b084292..b9feec9d08d3dad033b1b5940fd56c815c6f853d 100644 (file)
@@ -22,9 +22,9 @@
 
 #include <drm/drm_fb_helper.h>
 
-#define DL_DEFIO_WRITE_DELAY    5 /* fb_deferred_io.delay in jiffies */
+#define DL_DEFIO_WRITE_DELAY    (HZ/20) /* fb_deferred_io.delay in jiffies */
 
-static int fb_defio = 1;  /* Optionally enable experimental fb_defio mmap support */
+static int fb_defio = 0;  /* Optionally enable experimental fb_defio mmap support */
 static int fb_bpp = 16;
 
 module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
@@ -153,6 +153,9 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
        struct urb *urb;
        int aligned_x;
        int bpp = (fb->base.bits_per_pixel / 8);
+       int x2, y2;
+       bool store_for_later = false;
+       unsigned long flags;
 
        if (!fb->active_16)
                return 0;
@@ -169,8 +172,6 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
                }
        }
 
-       start_cycles = get_cycles();
-
        aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
        width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long));
        x = aligned_x;
@@ -180,19 +181,53 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
            (y + height > fb->base.height))
                return -EINVAL;
 
+       /* if we are in atomic just store the info
+          can't test inside spin lock */
+       if (in_atomic())
+               store_for_later = true;
+
+       x2 = x + width - 1;
+       y2 = y + height - 1;
+
+       spin_lock_irqsave(&fb->dirty_lock, flags);
+
+       if (fb->y1 < y)
+               y = fb->y1;
+       if (fb->y2 > y2)
+               y2 = fb->y2;
+       if (fb->x1 < x)
+               x = fb->x1;
+       if (fb->x2 > x2)
+               x2 = fb->x2;
+
+       if (store_for_later) {
+               fb->x1 = x;
+               fb->x2 = x2;
+               fb->y1 = y;
+               fb->y2 = y2;
+               spin_unlock_irqrestore(&fb->dirty_lock, flags);
+               return 0;
+       }
+
+       fb->x1 = fb->y1 = INT_MAX;
+       fb->x2 = fb->y2 = 0;
+
+       spin_unlock_irqrestore(&fb->dirty_lock, flags);
+       start_cycles = get_cycles();
+
        urb = udl_get_urb(dev);
        if (!urb)
                return 0;
        cmd = urb->transfer_buffer;
 
-       for (i = y; i < y + height ; i++) {
+       for (i = y; i <= y2 ; i++) {
                const int line_offset = fb->base.pitches[0] * i;
                const int byte_offset = line_offset + (x * bpp);
                const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
                if (udl_render_hline(dev, bpp, &urb,
                                     (char *) fb->obj->vmapping,
                                     &cmd, byte_offset, dev_byte_offset,
-                                    width * bpp,
+                                    (x2 - x + 1) * bpp,
                                     &bytes_identical, &bytes_sent))
                        goto error;
        }
@@ -433,6 +468,7 @@ udl_framebuffer_init(struct drm_device *dev,
 {
        int ret;
 
+       spin_lock_init(&ufb->dirty_lock);
        ufb->obj = obj;
        drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd);
        ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs);