mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 13:26:27 +00:00
intel/display: check for mappable framebuffer
The driver code may allocate framebuffers which do not fit in the aperture. Trying to use such framebuffer may lead to only partial visible content on the screen and the rest either black or garbage. Instead check for this circumstance and deny to use such framebuffers and release them, since the user would get an unusable/hard to interpret state. Additionally, release the vma mappings earlier in order to reduce the likelihood of such un-mappable framebuffers. Issue #5377
This commit is contained in:
parent
7fe7ca1968
commit
6f5bcd4446
@ -385,6 +385,41 @@ static int kernel_register_fb(struct fb_info const * const fb_info,
|
||||
}
|
||||
|
||||
|
||||
static void destroy_fb_and_capture(struct drm_client_dev * const dev,
|
||||
struct drm_connector const * const connector,
|
||||
struct drm_framebuffer * const fb)
|
||||
{
|
||||
struct drm_mode_create_dumb * dumb_create = NULL;
|
||||
struct drm_mode_fb_cmd2 * fb_cmd = NULL;
|
||||
struct gem_dumb * gem_dumb = NULL;
|
||||
struct fb_info info = {};
|
||||
|
||||
if (!fb)
|
||||
return;
|
||||
|
||||
if (!dumb_meta(dev, fb, &dumb_create, &fb_cmd))
|
||||
return;
|
||||
|
||||
if (!dumb_gem(dev, fb, &gem_dumb))
|
||||
return;
|
||||
|
||||
info.var.bits_per_pixel = 32;
|
||||
info.node = connector->index;
|
||||
info.par = connector->name;
|
||||
|
||||
kernel_register_fb(&info, 0, 0);
|
||||
|
||||
if (gem_dumb->vma) {
|
||||
intel_unpin_fb_vma(gem_dumb->vma, gem_dumb->flags);
|
||||
|
||||
gem_dumb->vma = NULL;
|
||||
gem_dumb->flags = 0;
|
||||
}
|
||||
|
||||
destroy_fb(dev, dumb_create, fb_cmd);
|
||||
}
|
||||
|
||||
|
||||
struct drm_mode_fb_cmd2 fb_of_screen(struct drm_client_dev * const dev,
|
||||
struct genode_mode const * const conf_mode,
|
||||
struct fb_info * const fb_info,
|
||||
@ -413,15 +448,9 @@ struct drm_mode_fb_cmd2 fb_of_screen(struct drm_client_dev * const dev,
|
||||
|
||||
/* notify genode side about switch from connector specific fb to mirror fb */
|
||||
if (fb && conf_mode->mirror && fb != fb_mirror) {
|
||||
struct fb_info info = {};
|
||||
|
||||
info.var.bits_per_pixel = 32;
|
||||
info.node = connector->index;
|
||||
info.par = connector->name;
|
||||
destroy_fb_and_capture(dev, connector, fb);
|
||||
|
||||
kernel_register_fb(&info, mode->width_mm, mode->height_mm);
|
||||
|
||||
destroy_fb(dev, gem_dumb, fb_cmd);
|
||||
}
|
||||
|
||||
if (fb_mirror)
|
||||
@ -771,7 +800,18 @@ static bool reconfigure(struct drm_client_dev * const dev)
|
||||
unsigned width_mm = mode->width_mm ? : connector->display_info.width_mm;
|
||||
unsigned height_mm = mode->height_mm ? : connector->display_info.height_mm;
|
||||
|
||||
user_register_fb(dev, &fb_info, &fb_cmd, width_mm, height_mm);
|
||||
int err = user_register_fb(dev, &fb_info, &fb_cmd, width_mm, height_mm);
|
||||
|
||||
if (err == -ENOSPC) {
|
||||
|
||||
struct drm_framebuffer *fb = drm_framebuffer_lookup(dev->dev,
|
||||
dev->file,
|
||||
fb_cmd.fb_id);
|
||||
if (fb)
|
||||
drm_framebuffer_put(fb);
|
||||
|
||||
destroy_fb_and_capture(dev, connector, fb);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@ -1354,6 +1394,18 @@ static int user_register_fb(struct drm_client_dev const * const dev,
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!i915_vma_is_map_and_fenceable(gem_dumb->vma)) {
|
||||
printk("%s: framebuffer not mappable in aperture -> destroying framebuffer\n",
|
||||
(info && info->par) ? (char *)info->par : "unknown");
|
||||
|
||||
intel_unpin_fb_vma(gem_dumb->vma, gem_dumb->flags);
|
||||
|
||||
gem_dumb->vma = NULL;
|
||||
gem_dumb->flags = 0;
|
||||
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
vaddr = i915_vma_pin_iomap(gem_dumb->vma);
|
||||
if (IS_ERR(vaddr)) {
|
||||
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
|
||||
|
Loading…
Reference in New Issue
Block a user