From patchwork Mon Mar 18 15:17:19 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 2293531 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id 8B8613FCF6 for ; Mon, 18 Mar 2013 15:17:44 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 46BF7E6232 for ; Mon, 18 Mar 2013 08:17:44 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from fireflyinternet.com (s16502780.onlinehome-server.info [87.106.93.118]) by gabe.freedesktop.org (Postfix) with ESMTP id 3A59CE5CEC; Mon, 18 Mar 2013 08:17:28 -0700 (PDT) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.73.22; Received: from arrandale.alporthouse.com (unverified [78.156.73.22]) by fireflyinternet.com (Firefly Internet (M2)) with ESMTP id 1869158-1500048 for multiple; Mon, 18 Mar 2013 15:17:29 +0000 From: Chris Wilson To: dri-devel@lists.freedesktop.org Subject: [PATCH] vesa: Prevent loading if we conflict with a previously loaded driver Date: Mon, 18 Mar 2013 15:17:19 +0000 Message-Id: <1363619839-18532-1-git-send-email-chris@chris-wilson.co.uk> X-Mailer: git-send-email 1.7.10.4 X-Originating-IP: 78.156.73.22 Cc: intel-gfx@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org vesa is presumed to be the generic hardware agnostic fallback framebuffer driver for standard VGA that conflicts with the real drivers. Those drivers already check and remove vesafb if it is previously loaded, but in the reverse case where vesafb is loaded afterwards, the VESA driver will proceed to clobber hardware state and corrupt the displays. References: https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-intel/+bug/1156077 Signed-off-by: Chris Wilson --- drivers/video/fbmem.c | 31 +++++++++++++++++++++++++++++++ drivers/video/vesafb.c | 22 ++++++++++++++++++++++ include/linux/fb.h | 2 ++ 3 files changed, 55 insertions(+) diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 7c25408..786cec8 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1722,6 +1722,37 @@ void remove_conflicting_framebuffers(struct apertures_struct *a, } EXPORT_SYMBOL(remove_conflicting_framebuffers); +bool has_conflicting_framebuffer(struct apertures_struct *a, bool primary) +{ + bool ret = false; + int i; + + mutex_lock(®istration_lock); + + for (i = 0 ; i < FB_MAX; i++) { + struct apertures_struct *gen_aper; + + if (!registered_fb[i]) + continue; + + if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE)) + continue; + + gen_aper = registered_fb[i]->apertures; + if (fb_do_apertures_overlap(gen_aper, a) || + (primary && gen_aper && gen_aper->count && + gen_aper->ranges[0].base == VGA_FB_PHYS)) { + ret = true; + break; + } + } + + mutex_unlock(®istration_lock); + + return ret; +} +EXPORT_SYMBOL(has_conflicting_framebuffer); + /** * register_framebuffer - registers a frame buffer device * @fb_info: frame buffer info structure diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 501b340..51adc4c1 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -226,6 +226,25 @@ static int __init vesafb_setup(char *options) return 0; } +static bool aperture_already_claimed(void) +{ + struct apertures_struct *ap; + bool ret; + + ap = alloc_apertures(1); + if (!ap) + return true; + + ap->ranges[0].base = screen_info.lfb_base; + ap->ranges[0].size = size_total; + + ret = has_conflicting_framebuffer(ap, true); + + kfree(ap); + + return ret; +} + static int __init vesafb_probe(struct platform_device *dev) { struct fb_info *info; @@ -237,6 +256,9 @@ static int __init vesafb_probe(struct platform_device *dev) if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return -ENODEV; + if (aperture_already_claimed()) + return -ENODEV; + vga_compat = (screen_info.capabilities & 2) ? 0 : 1; vesafb_fix.smem_start = screen_info.lfb_base; vesafb_defined.bits_per_pixel = screen_info.lfb_depth; diff --git a/include/linux/fb.h b/include/linux/fb.h index 58b9860..7dfd964 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -611,6 +611,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, extern int register_framebuffer(struct fb_info *fb_info); extern int unregister_framebuffer(struct fb_info *fb_info); extern int unlink_framebuffer(struct fb_info *fb_info); +extern bool has_conflicting_framebuffer(struct apertures_struct *a, + bool primary); extern void remove_conflicting_framebuffers(struct apertures_struct *a, const char *name, bool primary); extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);