Commit 2c51a660 authored by Thomas Zimmermann's avatar Thomas Zimmermann

drm/mgag200: Reserve video memory for cursor plane

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: default avatarThomas Zimmermann <tzimmermann@suse.de>
Acked-by: default avatarGerd Hoffmann <kraxel@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190927091301.10574-7-tzimmermann@suse.de
parent 378c1838
...@@ -215,17 +215,20 @@ static void mgag200_move_cursor(struct mga_device *mdev, int x, int y) ...@@ -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) int mgag200_cursor_init(struct mga_device *mdev)
{ {
struct drm_device *dev = mdev->dev; 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 * Make small buffers to store a hardware cursor (double
* buffered icon updates) * buffered icon updates)
*/ */
mdev->cursor.pixels_1 = drm_gem_vram_create(dev, &dev->vram_mm->bdev, mdev->cursor.pixels_1 = drm_gem_vram_create(dev, &dev->vram_mm->bdev,
roundup(48*64, PAGE_SIZE), size, 0, 0);
0, 0);
mdev->cursor.pixels_2 = drm_gem_vram_create(dev, &dev->vram_mm->bdev, mdev->cursor.pixels_2 = drm_gem_vram_create(dev, &dev->vram_mm->bdev,
roundup(48*64, PAGE_SIZE), size, 0, 0);
0, 0);
if (IS_ERR(mdev->cursor.pixels_2) || IS_ERR(mdev->cursor.pixels_1)) { if (IS_ERR(mdev->cursor.pixels_2) || IS_ERR(mdev->cursor.pixels_1)) {
mdev->cursor.pixels_1 = NULL; mdev->cursor.pixels_1 = NULL;
mdev->cursor.pixels_2 = NULL; mdev->cursor.pixels_2 = NULL;
...@@ -234,6 +237,14 @@ int mgag200_cursor_init(struct mga_device *mdev) ...@@ -234,6 +237,14 @@ int mgag200_cursor_init(struct mga_device *mdev)
} }
mdev->cursor.pixels_current = NULL; 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; return 0;
} }
......
...@@ -173,6 +173,8 @@ struct mga_device { ...@@ -173,6 +173,8 @@ struct mga_device {
struct mga_cursor cursor; struct mga_cursor cursor;
size_t vram_fb_available;
bool suspended; bool suspended;
int num_crtc; int num_crtc;
enum mga_type type; enum mga_type type;
......
...@@ -159,7 +159,7 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -159,7 +159,7 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
drm_mode_config_init(dev); drm_mode_config_init(dev);
dev->mode_config.funcs = (void *)&mga_mode_funcs; 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; dev->mode_config.preferred_depth = 16;
else else
dev->mode_config.preferred_depth = 32; dev->mode_config.preferred_depth = 32;
......
...@@ -1629,7 +1629,7 @@ static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector, ...@@ -1629,7 +1629,7 @@ static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector,
bpp = connector->cmdline_mode.bpp; 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) if (connector->cmdline_mode.specified)
connector->cmdline_mode.specified = false; connector->cmdline_mode.specified = false;
return MODE_BAD; return MODE_BAD;
......
...@@ -50,6 +50,8 @@ int mgag200_mm_init(struct mga_device *mdev) ...@@ -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), mdev->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
pci_resource_len(dev->pdev, 0)); pci_resource_len(dev->pdev, 0));
mdev->vram_fb_available = mdev->mc.vram_size;
return 0; return 0;
} }
...@@ -57,6 +59,8 @@ void mgag200_mm_fini(struct mga_device *mdev) ...@@ -57,6 +59,8 @@ void mgag200_mm_fini(struct mga_device *mdev)
{ {
struct drm_device *dev = mdev->dev; struct drm_device *dev = mdev->dev;
mdev->vram_fb_available = 0;
drm_vram_helper_release_mm(dev); drm_vram_helper_release_mm(dev);
arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0), arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment