]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/gpu/drm/udl/udl_fb.c
drm/udl: move to embedding drm device inside udl device.
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / udl / udl_fb.c
index b5b335c9b2bbe504fdddf47246820e1e64199d18..f41fd0684ce4a6913259ac81374fb12f6358d782 100644 (file)
@@ -82,7 +82,7 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
                      int width, int height)
 {
        struct drm_device *dev = fb->base.dev;
-       struct udl_device *udl = dev->dev_private;
+       struct udl_device *udl = to_udl(dev);
        int i, ret;
        char *cmd;
        cycles_t start_cycles, end_cycles;
@@ -90,7 +90,10 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
        int bytes_identical = 0;
        struct urb *urb;
        int aligned_x;
-       int bpp = fb->base.format->cpp[0];
+       int log_bpp;
+
+       BUG_ON(!is_power_of_2(fb->base.format->cpp[0]));
+       log_bpp = __ffs(fb->base.format->cpp[0]);
 
        if (!fb->active_16)
                return 0;
@@ -125,19 +128,22 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
 
        for (i = y; i < y + height ; 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,
+               const int byte_offset = line_offset + (x << log_bpp);
+               const int dev_byte_offset = (fb->base.width * i + x) << log_bpp;
+               if (udl_render_hline(dev, log_bpp, &urb,
                                     (char *) fb->obj->vmapping,
                                     &cmd, byte_offset, dev_byte_offset,
-                                    width bpp,
+                                    width << log_bpp,
                                     &bytes_identical, &bytes_sent))
                        goto error;
        }
 
        if (cmd > (char *) urb->transfer_buffer) {
                /* Send partial buffer remaining before exiting */
-               int len = cmd - (char *) urb->transfer_buffer;
+               int len;
+               if (cmd < (char *) urb->transfer_buffer + urb->transfer_buffer_length)
+                       *cmd++ = 0xAF;
+               len = cmd - (char *) urb->transfer_buffer;
                ret = udl_submit_urb(dev, urb, len);
                bytes_sent += len;
        } else
@@ -146,7 +152,7 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
 error:
        atomic_add(bytes_sent, &udl->bytes_sent);
        atomic_add(bytes_identical, &udl->bytes_identical);
-       atomic_add(width*height*bpp, &udl->bytes_rendered);
+       atomic_add((width * height) << log_bpp, &udl->bytes_rendered);
        end_cycles = get_cycles();
        atomic_add(((unsigned int) ((end_cycles - start_cycles)
                    >> 10)), /* Kcycles */
@@ -159,10 +165,15 @@ static int udl_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
        unsigned long start = vma->vm_start;
        unsigned long size = vma->vm_end - vma->vm_start;
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       unsigned long offset;
        unsigned long page, pos;
 
-       if (offset + size > info->fix.smem_len)
+       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+               return -EINVAL;
+
+       offset = vma->vm_pgoff << PAGE_SHIFT;
+
+       if (offset > info->fix.smem_len || size > info->fix.smem_len - offset)
                return -EINVAL;
 
        pos = (unsigned long)info->fix.smem_start + offset;
@@ -199,10 +210,10 @@ static int udl_fb_open(struct fb_info *info, int user)
 {
        struct udl_fbdev *ufbdev = info->par;
        struct drm_device *dev = ufbdev->ufb.base.dev;
-       struct udl_device *udl = dev->dev_private;
+       struct udl_device *udl = to_udl(dev);
 
        /* If the USB device is gone, we don't accept new opens */
-       if (drm_dev_is_unplugged(udl->ddev))
+       if (drm_dev_is_unplugged(&udl->drm))
                return -ENODEV;
 
        ufbdev->fb_count++;
@@ -213,7 +224,7 @@ static int udl_fb_open(struct fb_info *info, int user)
 
                struct fb_deferred_io *fbdefio;
 
-               fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
+               fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
 
                if (fbdefio) {
                        fbdefio->delay = DL_DEFIO_WRITE_DELAY;
@@ -421,14 +432,16 @@ static void udl_fbdev_destroy(struct drm_device *dev,
 {
        drm_fb_helper_unregister_fbi(&ufbdev->helper);
        drm_fb_helper_fini(&ufbdev->helper);
-       drm_framebuffer_unregister_private(&ufbdev->ufb.base);
-       drm_framebuffer_cleanup(&ufbdev->ufb.base);
-       drm_gem_object_put_unlocked(&ufbdev->ufb.obj->base);
+       if (ufbdev->ufb.obj) {
+               drm_framebuffer_unregister_private(&ufbdev->ufb.base);
+               drm_framebuffer_cleanup(&ufbdev->ufb.base);
+               drm_gem_object_put_unlocked(&ufbdev->ufb.obj->base);
+       }
 }
 
 int udl_fbdev_init(struct drm_device *dev)
 {
-       struct udl_device *udl = dev->dev_private;
+       struct udl_device *udl = to_udl(dev);
        int bpp_sel = fb_bpp;
        struct udl_fbdev *ufbdev;
        int ret;
@@ -467,7 +480,7 @@ free:
 
 void udl_fbdev_cleanup(struct drm_device *dev)
 {
-       struct udl_device *udl = dev->dev_private;
+       struct udl_device *udl = to_udl(dev);
        if (!udl->fbdev)
                return;
 
@@ -478,7 +491,7 @@ void udl_fbdev_cleanup(struct drm_device *dev)
 
 void udl_fbdev_unplug(struct drm_device *dev)
 {
-       struct udl_device *udl = dev->dev_private;
+       struct udl_device *udl = to_udl(dev);
        struct udl_fbdev *ufbdev;
        if (!udl->fbdev)
                return;