drm/mgag200: Reserve video memory for cursor plane
authorThomas Zimmermann <tzimmermann@suse.de>
Fri, 27 Sep 2019 09:13:00 +0000 (11:13 +0200)
committerThomas Zimmermann <tzimmermann@suse.de>
Fri, 4 Oct 2019 08:01:05 +0000 (10:01 +0200)
The double-buffered cursor image is currently stored in video memory
by creating two BOs and pinning them to VRAM. The exact location is
chosen by VRAM helpers. The pinned cursor BOs can conflict with
framebuffer BOs and prevent the primary plane from displaying its
framebuffer.

As a first step to solving this problem, we reserve dedicated space at
the high end of the video memory for the cursor images. As the amount
of video memory now differs from the amount of available framebuffer
memory, size tests are adapted accordingly.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190927091301.10574-7-tzimmermann@suse.de
drivers/gpu/drm/mgag200/mgag200_cursor.c
drivers/gpu/drm/mgag200/mgag200_drv.h
drivers/gpu/drm/mgag200/mgag200_main.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/mgag200/mgag200_ttm.c

index ed69b396ac0266cd388b347f9d2104add7f5420b..318e434f2d40ebb5c704c9e5378e944707b1c215 100644 (file)
@@ -215,17 +215,20 @@ static void mgag200_move_cursor(struct mga_device *mdev, int x, int y)
 int mgag200_cursor_init(struct mga_device *mdev)
 {
        struct drm_device *dev = mdev->dev;
+       size_t size;
+
+       size = roundup(64 * 48, PAGE_SIZE);
+       if (size * 2 > mdev->vram_fb_available)
+               return -ENOMEM;
 
        /*
         * Make small buffers to store a hardware cursor (double
         * buffered icon updates)
         */
        mdev->cursor.pixels_1 = drm_gem_vram_create(dev, &dev->vram_mm->bdev,
-                                                   roundup(48*64, PAGE_SIZE),
-                                                   0, 0);
+                                                   size, 0, 0);
        mdev->cursor.pixels_2 = drm_gem_vram_create(dev, &dev->vram_mm->bdev,
-                                                   roundup(48*64, PAGE_SIZE),
-                                                   0, 0);
+                                                   size, 0, 0);
        if (IS_ERR(mdev->cursor.pixels_2) || IS_ERR(mdev->cursor.pixels_1)) {
                mdev->cursor.pixels_1 = NULL;
                mdev->cursor.pixels_2 = NULL;
@@ -234,6 +237,14 @@ int mgag200_cursor_init(struct mga_device *mdev)
        }
        mdev->cursor.pixels_current = NULL;
 
+       /*
+        * At the high end of video memory, we reserve space for
+        * buffer objects. The cursor plane uses this memory to store
+        * a double-buffered image of the current cursor. Hence, it's
+        * not available for framebuffers.
+        */
+       mdev->vram_fb_available -= 2 * size;
+
        return 0;
 }
 
index 01243fa6397c5e3922825a0b8cff6db49e5d259b..5d6cfc88697a4a10696c011bd2ee7097495a5e75 100644 (file)
@@ -173,6 +173,8 @@ struct mga_device {
 
        struct mga_cursor cursor;
 
+       size_t vram_fb_available;
+
        bool                            suspended;
        int                             num_crtc;
        enum mga_type                   type;
index 2b59280777a5b41d860145e1a3df1e1e0b8b5abd..5f74aabcd3dff5eaa89742eb569109fb28f797d9 100644 (file)
@@ -159,7 +159,7 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
 
        drm_mode_config_init(dev);
        dev->mode_config.funcs = (void *)&mga_mode_funcs;
-       if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024))
+       if (IS_G200_SE(mdev) && mdev->vram_fb_available < (2048*1024))
                dev->mode_config.preferred_depth = 16;
        else
                dev->mode_config.preferred_depth = 32;
index 0cf5608c3644e55fdffc7b8ade2ab0b010d54fff..5ec697148fc177de5868087b27cb1aa60412d11b 100644 (file)
@@ -1629,7 +1629,7 @@ static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector,
                        bpp = connector->cmdline_mode.bpp;
        }
 
-       if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) {
+       if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->vram_fb_available) {
                if (connector->cmdline_mode.specified)
                        connector->cmdline_mode.specified = false;
                return MODE_BAD;
index 69c81ebf37456445e82eed09969912f0fbbab7da..99997d73736225df671cfcc46d89a394b0d18353 100644 (file)
@@ -50,6 +50,8 @@ int mgag200_mm_init(struct mga_device *mdev)
        mdev->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
                                         pci_resource_len(dev->pdev, 0));
 
+       mdev->vram_fb_available = mdev->mc.vram_size;
+
        return 0;
 }
 
@@ -57,6 +59,8 @@ void mgag200_mm_fini(struct mga_device *mdev)
 {
        struct drm_device *dev = mdev->dev;
 
+       mdev->vram_fb_available = 0;
+
        drm_vram_helper_release_mm(dev);
 
        arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),