From patchwork Fri May 9 20:20:41 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 4145011 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7BDCBBFF02 for ; Fri, 9 May 2014 20:20:49 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 719772034E for ; Fri, 9 May 2014 20:20:48 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 3ED5120328 for ; Fri, 9 May 2014 20:20:47 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 5191C6E0E9; Fri, 9 May 2014 13:20:46 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by gabe.freedesktop.org (Postfix) with ESMTP id 8668B6E0E9 for ; Fri, 9 May 2014 13:20:45 -0700 (PDT) Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s49KKgPN028224 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 9 May 2014 16:20:42 -0400 Received: from bling.home (ovpn-113-93.phx2.redhat.com [10.3.113.93]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s49KKfgb031167; Fri, 9 May 2014 16:20:41 -0400 From: Alex Williamson To: intel-gfx@lists.freedesktop.org Date: Fri, 09 May 2014 14:20:41 -0600 Message-ID: <20140509201655.2849.97478.stgit@bling.home> User-Agent: StGit/0.17-dirty MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Cc: Daniel Vetter , linux-kernel@vger.kernel.org, Dave Airlie Subject: [Intel-gfx] [PATCH] i915: Add module option to support VGA arbiter on HD devices X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Commit 81b5c7bc found that the current VGA arbiter support in i915 only works for ancient GMCH-based IGD devices and attempted to update support for newer HD devices. Unfortunately newer devices cannot completely opt-out of VGA arbitration like the old devices could. The VGA I/O space cannot be disabled internally. The only way to route VGA I/O elsewhere is by disabling I/O at the device PCI command register. This means that with commit 81b5c7bc and multiple VGA adapters, the VGA arbiter will report that multiple VGA devices are participating in arbitration, Xorg will notice this and disable DRI. Therefore, 81b5c7bc was reverted because DRI is more important than being correct. There is however an actual need for i915 to correctly participate in VGA arbitration; VGA device assignment. If we want to use VFIO to assign a VGA device to a virtual machine, we need to be able to access the VGA resources of that device. By adding an i915 module option we can allow i915 to continue with its charade by default, but also allow an easy path for users who require working VGA arbitration. Hopefully Xorg can someday be taught to behave better with multiple VGA devices. This also rolls in reverted commit 6e1b4fda, which corrected an ordering issue with 81b5c7bc by delaying the disabling of VGA memory until after vgacon->fbcon handoff. Signed-off-by: Alex Williamson Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Dave Airlie --- This should be a nop with the default module setting, so if there's any opportunity to get this into v3.15, it would be appreciated. drivers/gpu/drm/i915/i915_dma.c | 22 +++++++++++++++++++--- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_params.c | 5 +++++ drivers/gpu/drm/i915/intel_display.c | 30 ++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 2 ++ include/linux/vgaarb.h | 7 +++++++ 6 files changed, 64 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 96177ee..c0d0c03 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1306,10 +1306,20 @@ static int i915_load_modeset_init(struct drm_device *dev) * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA), * then we do not take part in VGA arbitration and the * vga_client_register() fails with -ENODEV. + * + * NB. The set_decode callback here actually only works on GMCH + * devices, on newer HD devices we can only disable VGA MMIO space. + * Disabling VGA I/O space requires disabling I/O in the PCI command + * register. Nonetheless, we like to pretend that we participate in + * VGA arbitration and can dynamically disable VGA I/O space because + * this makes X happy, even though it's a complete lie. */ - ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode); - if (ret && ret != -ENODEV) - goto out; + if (!i915.enable_hd_vgaarb || !HAS_PCH_SPLIT(dev)) { + ret = vga_client_register(dev->pdev, dev, NULL, + i915_vga_set_decode); + if (ret && ret != -ENODEV) + goto out; + } intel_register_dsm_handler(); @@ -1369,6 +1379,12 @@ static int i915_load_modeset_init(struct drm_device *dev) */ intel_fbdev_initial_config(dev); + /* + * Must do this after fbcon init so that + * vgacon_save_screen() works during the handover. + */ + i915_disable_vga_mem(dev); + /* Only enable hotplug handling once the fbdev is fully set up. */ dev_priv->enable_hotplug_processing = true; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ec82f6b..f3908f6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2080,6 +2080,7 @@ struct i915_params { bool prefault_disable; bool reset; bool disable_display; + bool enable_hd_vgaarb; }; extern struct i915_params i915 __read_mostly; diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index d1d7980..64d96c6 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -47,6 +47,7 @@ struct i915_params i915 __read_mostly = { .invert_brightness = 0, .disable_display = 0, .enable_cmd_parser = 0, + .enable_hd_vgaarb = false, }; module_param_named(modeset, i915.modeset, int, 0400); @@ -152,3 +153,7 @@ MODULE_PARM_DESC(disable_display, "Disable display (default: false)"); module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600); MODULE_PARM_DESC(enable_cmd_parser, "Enable command parsing (1=enabled, 0=disabled [default])"); + +module_param_named(enable_hd_vgaarb, i915.enable_hd_vgaarb, bool, 0444); +MODULE_PARM_DESC(enable_hd_vgaarb, + "Enable support for VGA arbitration on Intel HD IGD. (default: false)"); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 69bcc42..2cd35ba 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11284,6 +11284,33 @@ static void i915_disable_vga(struct drm_device *dev) POSTING_READ(vga_reg); } +static void i915_enable_vga_mem(struct drm_device *dev) +{ + /* Enable VGA memory on Intel HD */ + if (i915.enable_hd_vgaarb && HAS_PCH_SPLIT(dev)) { + vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO); + outb(inb(VGA_MSR_READ) | VGA_MSR_MEM_EN, VGA_MSR_WRITE); + vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO | + VGA_RSRC_LEGACY_MEM | + VGA_RSRC_NORMAL_IO | + VGA_RSRC_NORMAL_MEM); + vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); + } +} + +void i915_disable_vga_mem(struct drm_device *dev) +{ + /* Disable VGA memory on Intel HD */ + if (i915.enable_hd_vgaarb && HAS_PCH_SPLIT(dev)) { + vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO); + outb(inb(VGA_MSR_READ) & ~VGA_MSR_MEM_EN, VGA_MSR_WRITE); + vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO | + VGA_RSRC_NORMAL_IO | + VGA_RSRC_NORMAL_MEM); + vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); + } +} + void intel_modeset_init_hw(struct drm_device *dev) { intel_prepare_ddi(dev); @@ -11594,6 +11621,7 @@ void i915_redisable_vga_power_on(struct drm_device *dev) if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) { DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); i915_disable_vga(dev); + i915_disable_vga_mem(dev); } } @@ -11848,6 +11876,8 @@ void intel_modeset_cleanup(struct drm_device *dev) intel_disable_fbc(dev); + i915_enable_vga_mem(dev); + intel_disable_gt_powersave(dev); ironlake_teardown_rc6(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 328b1a7..fbe5d360 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -934,4 +934,6 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data, /* intel_tv.c */ void intel_tv_init(struct drm_device *dev); +extern void i915_disable_vga_mem(struct drm_device *dev); + #endif /* __INTEL_DRV_H__ */ diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h index 2c02f3a..80cf817 100644 --- a/include/linux/vgaarb.h +++ b/include/linux/vgaarb.h @@ -65,8 +65,15 @@ struct pci_dev; * out of the arbitration process (and can be safe to take * interrupts at any time. */ +#if defined(CONFIG_VGA_ARB) extern void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes); +#else +static inline void vga_set_legacy_decoding(struct pci_dev *pdev, + unsigned int decodes) +{ +} +#endif /** * vga_get - acquire & locks VGA resources