[Intel-gfx] [PATCH 09/11] drm/i915: Merge i915_dma.c into i915_drv.c
Joonas Lahtinen
joonas.lahtinen at linux.intel.com
Mon May 30 06:30:12 UTC 2016
On pe, 2016-05-27 at 15:00 +0100, Chris Wilson wrote:
> i915_dma.c used to contain the DRI1/UMS horror show, but now all that
> remains are the out-of-place driver level interfaces (such as
> allocating, initialising and registering the driver). These should be in
> i915_drv.c alongside similar routines for suspend/resume.
>
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Assuming this was NOP change,
Reviewed-by: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter at ffwll.ch>
> ---
> drivers/gpu/drm/i915/Makefile | 3 -
> drivers/gpu/drm/i915/i915_dma.c | 1680 --------------------------------
> drivers/gpu/drm/i915/i915_drv.c | 2014 +++++++++++++++++++++++++++++++++++----
> drivers/gpu/drm/i915/i915_drv.h | 16 +-
> 4 files changed, 1825 insertions(+), 1888 deletions(-)
> delete mode 100644 drivers/gpu/drm/i915/i915_dma.c
>
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 7e2944406b8f..2ea7c245923e 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -101,9 +101,6 @@ i915-y += dvo_ch7017.o \
> # virtual gpu code
> i915-y += i915_vgpu.o
>
> -# legacy horrors
> -i915-y += i915_dma.o
> -
> obj-$(CONFIG_DRM_I915) += i915.o
>
> CFLAGS_i915_trace_points.o := -I$(src)
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> deleted file mode 100644
> index 0ec785d4505e..000000000000
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ /dev/null
> @@ -1,1680 +0,0 @@
> -/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
> - */
> -/*
> - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
> - * All Rights Reserved.
> - *
> - * Permission is hereby granted, free of charge, to any person obtaining a
> - * copy of this software and associated documentation files (the
> - * "Software"), to deal in the Software without restriction, including
> - * without limitation the rights to use, copy, modify, merge, publish,
> - * distribute, sub license, and/or sell copies of the Software, and to
> - * permit persons to whom the Software is furnished to do so, subject to
> - * the following conditions:
> - *
> - * The above copyright notice and this permission notice (including the
> - * next paragraph) shall be included in all copies or substantial portions
> - * of the Software.
> - *
> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
> - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> - *
> - */
> -
> -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> -
> -#include
> -#include
> -#include
> -#include
> -#include "intel_drv.h"
> -#include
> -#include "i915_drv.h"
> -#include "i915_vgpu.h"
> -#include "i915_trace.h"
> -#include
> -#include
> -#include
> -#include
> -#include
> -#include
> -#include
> -#include
> -#include
> -#include
> -#include
> -#include
> -
> -static unsigned int i915_load_fail_count;
> -
> -bool __i915_inject_load_failure(const char *func, int line)
> -{
> - if (i915_load_fail_count >= i915.inject_load_failure)
> - return false;
> -
> - if (++i915_load_fail_count == i915.inject_load_failure) {
> - DRM_INFO("Injecting failure at checkpoint %u [%s:%d]\n",
> - i915.inject_load_failure, func, line);
> - return true;
> - }
> -
> - return false;
> -}
> -
> -#define FDO_BUG_URL "https://bugs.freedesktop.org/enter_bug.cgi?product=DRI"
> -#define FDO_BUG_MSG "Please file a bug at " FDO_BUG_URL " against DRM/Intel " \
> - "providing the dmesg log by booting with drm.debug=0xf"
> -
> -void
> -__i915_printk(struct drm_i915_private *dev_priv, const char *level,
> - const char *fmt, ...)
> -{
> - static bool shown_bug_once;
> - struct device *dev = dev_priv->dev->dev;
> - bool is_error = level[1] <= KERN_ERR[1];
> - bool is_debug = level[1] == KERN_DEBUG[1];
> - struct va_format vaf;
> - va_list args;
> -
> - if (is_debug && !(drm_debug & DRM_UT_DRIVER))
> - return;
> -
> - va_start(args, fmt);
> -
> - vaf.fmt = fmt;
> - vaf.va = &args;
> -
> - dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV",
> - __builtin_return_address(0), &vaf);
> -
> - if (is_error && !shown_bug_once) {
> - dev_notice(dev, "%s", FDO_BUG_MSG);
> - shown_bug_once = true;
> - }
> -
> - va_end(args);
> -}
> -
> -static bool i915_error_injected(struct drm_i915_private *dev_priv)
> -{
> - return i915.inject_load_failure &&
> - i915_load_fail_count == i915.inject_load_failure;
> -}
> -
> -#define i915_load_error(dev_priv, fmt, ...) \
> - __i915_printk(dev_priv, \
> - i915_error_injected(dev_priv) ? KERN_DEBUG : KERN_ERR, \
> - fmt, ##__VA_ARGS__)
> -
> -static int i915_getparam(struct drm_device *dev, void *data,
> - struct drm_file *file_priv)
> -{
> - struct drm_i915_private *dev_priv = dev->dev_private;
> - drm_i915_getparam_t *param = data;
> - int value;
> -
> - switch (param->param) {
> - case I915_PARAM_IRQ_ACTIVE:
> - case I915_PARAM_ALLOW_BATCHBUFFER:
> - case I915_PARAM_LAST_DISPATCH:
> - /* Reject all old ums/dri params. */
> - return -ENODEV;
> - case I915_PARAM_CHIPSET_ID:
> - value = dev->pdev->device;
> - break;
> - case I915_PARAM_REVISION:
> - value = dev->pdev->revision;
> - break;
> - case I915_PARAM_HAS_GEM:
> - value = 1;
> - break;
> - case I915_PARAM_NUM_FENCES_AVAIL:
> - value = dev_priv->num_fence_regs;
> - break;
> - case I915_PARAM_HAS_OVERLAY:
> - value = dev_priv->overlay ? 1 : 0;
> - break;
> - case I915_PARAM_HAS_PAGEFLIPPING:
> - value = 1;
> - break;
> - case I915_PARAM_HAS_EXECBUF2:
> - /* depends on GEM */
> - value = 1;
> - break;
> - case I915_PARAM_HAS_BSD:
> - value = intel_engine_initialized(&dev_priv->engine[VCS]);
> - break;
> - case I915_PARAM_HAS_BLT:
> - value = intel_engine_initialized(&dev_priv->engine[BCS]);
> - break;
> - case I915_PARAM_HAS_VEBOX:
> - value = intel_engine_initialized(&dev_priv->engine[VECS]);
> - break;
> - case I915_PARAM_HAS_BSD2:
> - value = intel_engine_initialized(&dev_priv->engine[VCS2]);
> - break;
> - case I915_PARAM_HAS_RELAXED_FENCING:
> - value = 1;
> - break;
> - case I915_PARAM_HAS_COHERENT_RINGS:
> - value = 1;
> - break;
> - case I915_PARAM_HAS_EXEC_CONSTANTS:
> - value = INTEL_INFO(dev)->gen >= 4;
> - break;
> - case I915_PARAM_HAS_RELAXED_DELTA:
> - value = 1;
> - break;
> - case I915_PARAM_HAS_GEN7_SOL_RESET:
> - value = 1;
> - break;
> - case I915_PARAM_HAS_LLC:
> - value = HAS_LLC(dev);
> - break;
> - case I915_PARAM_HAS_WT:
> - value = HAS_WT(dev);
> - break;
> - case I915_PARAM_HAS_ALIASING_PPGTT:
> - value = USES_PPGTT(dev);
> - break;
> - case I915_PARAM_HAS_WAIT_TIMEOUT:
> - value = 1;
> - break;
> - case I915_PARAM_HAS_SEMAPHORES:
> - value = i915_semaphore_is_enabled(dev_priv);
> - break;
> - case I915_PARAM_HAS_PRIME_VMAP_FLUSH:
> - value = 1;
> - break;
> - case I915_PARAM_HAS_SECURE_BATCHES:
> - value = capable(CAP_SYS_ADMIN);
> - break;
> - case I915_PARAM_HAS_PINNED_BATCHES:
> - value = 1;
> - break;
> - case I915_PARAM_HAS_EXEC_NO_RELOC:
> - value = 1;
> - break;
> - case I915_PARAM_HAS_EXEC_HANDLE_LUT:
> - value = 1;
> - break;
> - case I915_PARAM_CMD_PARSER_VERSION:
> - value = i915_cmd_parser_get_version(dev_priv);
> - break;
> - case I915_PARAM_HAS_COHERENT_PHYS_GTT:
> - value = 1;
> - break;
> - case I915_PARAM_MMAP_VERSION:
> - value = 1;
> - break;
> - case I915_PARAM_SUBSLICE_TOTAL:
> - value = INTEL_INFO(dev)->subslice_total;
> - if (!value)
> - return -ENODEV;
> - break;
> - case I915_PARAM_EU_TOTAL:
> - value = INTEL_INFO(dev)->eu_total;
> - if (!value)
> - return -ENODEV;
> - break;
> - case I915_PARAM_HAS_GPU_RESET:
> - value = i915.enable_hangcheck && intel_has_gpu_reset(dev_priv);
> - break;
> - case I915_PARAM_HAS_RESOURCE_STREAMER:
> - value = HAS_RESOURCE_STREAMER(dev);
> - break;
> - case I915_PARAM_HAS_EXEC_SOFTPIN:
> - value = 1;
> - break;
> - default:
> - DRM_DEBUG("Unknown parameter %d\n", param->param);
> - return -EINVAL;
> - }
> -
> - if (copy_to_user(param->value, &value, sizeof(int))) {
> - DRM_ERROR("copy_to_user failed\n");
> - return -EFAULT;
> - }
> -
> - return 0;
> -}
> -
> -static int i915_get_bridge_dev(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = dev->dev_private;
> -
> - dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
> - if (!dev_priv->bridge_dev) {
> - DRM_ERROR("bridge device not found\n");
> - return -1;
> - }
> - return 0;
> -}
> -
> -/* Allocate space for the MCH regs if needed, return nonzero on error */
> -static int
> -intel_alloc_mchbar_resource(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = dev->dev_private;
> - int reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
> - u32 temp_lo, temp_hi = 0;
> - u64 mchbar_addr;
> - int ret;
> -
> - if (INTEL_INFO(dev)->gen >= 4)
> - pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
> - pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
> - mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
> -
> - /* If ACPI doesn't have it, assume we need to allocate it ourselves */
> -#ifdef CONFIG_PNP
> - if (mchbar_addr &&
> - pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE))
> - return 0;
> -#endif
> -
> - /* Get some space for it */
> - dev_priv->mch_res.name = "i915 MCHBAR";
> - dev_priv->mch_res.flags = IORESOURCE_MEM;
> - ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus,
> - &dev_priv->mch_res,
> - MCHBAR_SIZE, MCHBAR_SIZE,
> - PCIBIOS_MIN_MEM,
> - 0, pcibios_align_resource,
> - dev_priv->bridge_dev);
> - if (ret) {
> - DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
> - dev_priv->mch_res.start = 0;
> - return ret;
> - }
> -
> - if (INTEL_INFO(dev)->gen >= 4)
> - pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
> - upper_32_bits(dev_priv->mch_res.start));
> -
> - pci_write_config_dword(dev_priv->bridge_dev, reg,
> - lower_32_bits(dev_priv->mch_res.start));
> - return 0;
> -}
> -
> -/* Setup MCHBAR if possible, return true if we should disable it again */
> -static void
> -intel_setup_mchbar(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = dev->dev_private;
> - int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
> - u32 temp;
> - bool enabled;
> -
> - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
> - return;
> -
> - dev_priv->mchbar_need_disable = false;
> -
> - if (IS_I915G(dev) || IS_I915GM(dev)) {
> - pci_read_config_dword(dev_priv->bridge_dev, DEVEN, &temp);
> - enabled = !!(temp & DEVEN_MCHBAR_EN);
> - } else {
> - pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
> - enabled = temp & 1;
> - }
> -
> - /* If it's already enabled, don't have to do anything */
> - if (enabled)
> - return;
> -
> - if (intel_alloc_mchbar_resource(dev))
> - return;
> -
> - dev_priv->mchbar_need_disable = true;
> -
> - /* Space is allocated or reserved, so enable it. */
> - if (IS_I915G(dev) || IS_I915GM(dev)) {
> - pci_write_config_dword(dev_priv->bridge_dev, DEVEN,
> - temp | DEVEN_MCHBAR_EN);
> - } else {
> - pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
> - pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
> - }
> -}
> -
> -static void
> -intel_teardown_mchbar(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = dev->dev_private;
> - int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
> -
> - if (dev_priv->mchbar_need_disable) {
> - if (IS_I915G(dev) || IS_I915GM(dev)) {
> - u32 deven_val;
> -
> - pci_read_config_dword(dev_priv->bridge_dev, DEVEN,
> - &deven_val);
> - deven_val &= ~DEVEN_MCHBAR_EN;
> - pci_write_config_dword(dev_priv->bridge_dev, DEVEN,
> - deven_val);
> - } else {
> - u32 mchbar_val;
> -
> - pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg,
> - &mchbar_val);
> - mchbar_val &= ~1;
> - pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg,
> - mchbar_val);
> - }
> - }
> -
> - if (dev_priv->mch_res.start)
> - release_resource(&dev_priv->mch_res);
> -}
> -
> -/* true = enable decode, false = disable decoder */
> -static unsigned int i915_vga_set_decode(void *cookie, bool state)
> -{
> - struct drm_device *dev = cookie;
> -
> - intel_modeset_vga_set_state(dev, state);
> - if (state)
> - return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
> - VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
> - else
> - return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
> -}
> -
> -static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
> -{
> - struct drm_device *dev = pci_get_drvdata(pdev);
> - pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
> -
> - if (state == VGA_SWITCHEROO_ON) {
> - pr_info("switched on\n");
> - dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
> - /* i915 resume handler doesn't set to D0 */
> - pci_set_power_state(dev->pdev, PCI_D0);
> - i915_resume_switcheroo(dev);
> - dev->switch_power_state = DRM_SWITCH_POWER_ON;
> - } else {
> - pr_info("switched off\n");
> - dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
> - i915_suspend_switcheroo(dev, pmm);
> - dev->switch_power_state = DRM_SWITCH_POWER_OFF;
> - }
> -}
> -
> -static bool i915_switcheroo_can_switch(struct pci_dev *pdev)
> -{
> - struct drm_device *dev = pci_get_drvdata(pdev);
> -
> - /*
> - * FIXME: open_count is protected by drm_global_mutex but that would lead to
> - * locking inversion with the driver load path. And the access here is
> - * completely racy anyway. So don't bother with locking for now.
> - */
> - return dev->open_count == 0;
> -}
> -
> -static const struct vga_switcheroo_client_ops i915_switcheroo_ops = {
> - .set_gpu_state = i915_switcheroo_set_state,
> - .reprobe = NULL,
> - .can_switch = i915_switcheroo_can_switch,
> -};
> -
> -static void i915_gem_fini(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = to_i915(dev);
> -
> - /*
> - * Neither the BIOS, ourselves or any other kernel
> - * expects the system to be in execlists mode on startup,
> - * so we need to reset the GPU back to legacy mode. And the only
> - * known way to disable logical contexts is through a GPU reset.
> - *
> - * So in order to leave the system in a known default configuration,
> - * always reset the GPU upon unload. Afterwards we then clean up the
> - * GEM state tracking, flushing off the requests and leaving the
> - * system in a known idle state.
> - *
> - * Note that is of the upmost importance that the GPU is idle and
> - * all stray writes are flushed *before* we dismantle the backing
> - * storage for the pinned objects.
> - *
> - * However, since we are uncertain that reseting the GPU on older
> - * machines is a good idea, we don't - just in case it leaves the
> - * machine in an unusable condition.
> - */
> - if (HAS_HW_CONTEXTS(dev)) {
> - int reset = intel_gpu_reset(dev_priv, ALL_ENGINES);
> - WARN_ON(reset && reset != -ENODEV);
> - }
> -
> - mutex_lock(&dev->struct_mutex);
> - i915_gem_reset(dev);
> - i915_gem_cleanup_engines(dev);
> - i915_gem_context_fini(dev);
> - mutex_unlock(&dev->struct_mutex);
> -
> - WARN_ON(!list_empty(&to_i915(dev)->context_list));
> -}
> -
> -static int i915_load_modeset_init(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = dev->dev_private;
> - int ret;
> -
> - if (i915_inject_load_failure())
> - return -ENODEV;
> -
> - ret = intel_bios_init(dev_priv);
> - if (ret)
> - DRM_INFO("failed to find VBIOS tables\n");
> -
> - /* If we have > 1 VGA cards, then we need to arbitrate access
> - * to the common VGA resources.
> - *
> - * 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.
> - */
> - ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
> - if (ret && ret != -ENODEV)
> - goto out;
> -
> - intel_register_dsm_handler();
> -
> - ret = vga_switcheroo_register_client(dev->pdev, &i915_switcheroo_ops, false);
> - if (ret)
> - goto cleanup_vga_client;
> -
> - /* must happen before intel_power_domains_init_hw() on VLV/CHV */
> - intel_update_rawclk(dev_priv);
> -
> - intel_power_domains_init_hw(dev_priv, false);
> -
> - intel_csr_ucode_init(dev_priv);
> -
> - ret = intel_irq_install(dev_priv);
> - if (ret)
> - goto cleanup_csr;
> -
> - intel_setup_gmbus(dev);
> -
> - /* Important: The output setup functions called by modeset_init need
> - * working irqs for e.g. gmbus and dp aux transfers. */
> - intel_modeset_init(dev);
> -
> - intel_guc_init(dev);
> -
> - ret = i915_gem_init(dev);
> - if (ret)
> - goto cleanup_irq;
> -
> - intel_modeset_gem_init(dev);
> -
> - if (INTEL_INFO(dev)->num_pipes == 0)
> - return 0;
> -
> - ret = intel_fbdev_init(dev);
> - if (ret)
> - goto cleanup_gem;
> -
> - /* Only enable hotplug handling once the fbdev is fully set up. */
> - intel_hpd_init(dev_priv);
> -
> - drm_kms_helper_poll_init(dev);
> -
> - return 0;
> -
> -cleanup_gem:
> - i915_gem_fini(dev);
> -cleanup_irq:
> - intel_guc_fini(dev);
> - drm_irq_uninstall(dev);
> - intel_teardown_gmbus(dev);
> -cleanup_csr:
> - intel_csr_ucode_fini(dev_priv);
> - intel_power_domains_fini(dev_priv);
> - vga_switcheroo_unregister_client(dev->pdev);
> -cleanup_vga_client:
> - vga_client_register(dev->pdev, NULL, NULL, NULL);
> -out:
> - return ret;
> -}
> -
> -#if IS_ENABLED(CONFIG_FB)
> -static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
> -{
> - struct apertures_struct *ap;
> - struct pci_dev *pdev = dev_priv->dev->pdev;
> - struct i915_ggtt *ggtt = &dev_priv->ggtt;
> - bool primary;
> - int ret;
> -
> - ap = alloc_apertures(1);
> - if (!ap)
> - return -ENOMEM;
> -
> - ap->ranges[0].base = ggtt->mappable_base;
> - ap->ranges[0].size = ggtt->mappable_end;
> -
> - primary =
> - pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
> -
> - ret = remove_conflicting_framebuffers(ap, "inteldrmfb", primary);
> -
> - kfree(ap);
> -
> - return ret;
> -}
> -#else
> -static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
> -{
> - return 0;
> -}
> -#endif
> -
> -#if !defined(CONFIG_VGA_CONSOLE)
> -static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> -{
> - return 0;
> -}
> -#elif !defined(CONFIG_DUMMY_CONSOLE)
> -static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> -{
> - return -ENODEV;
> -}
> -#else
> -static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> -{
> - int ret = 0;
> -
> - DRM_INFO("Replacing VGA console driver\n");
> -
> - console_lock();
> - if (con_is_bound(&vga_con))
> - ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);
> - if (ret == 0) {
> - ret = do_unregister_con_driver(&vga_con);
> -
> - /* Ignore "already unregistered". */
> - if (ret == -ENODEV)
> - ret = 0;
> - }
> - console_unlock();
> -
> - return ret;
> -}
> -#endif
> -
> -static void i915_dump_device_info(struct drm_i915_private *dev_priv)
> -{
> - const struct intel_device_info *info = &dev_priv->info;
> -
> -#define PRINT_S(name) "%s"
> -#define SEP_EMPTY
> -#define PRINT_FLAG(name) info->name ? #name "," : ""
> -#define SEP_COMMA ,
> - DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags="
> - DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
> - info->gen,
> - dev_priv->dev->pdev->device,
> - dev_priv->dev->pdev->revision,
> - DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
> -#undef PRINT_S
> -#undef SEP_EMPTY
> -#undef PRINT_FLAG
> -#undef SEP_COMMA
> -}
> -
> -static void cherryview_sseu_info_init(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = dev->dev_private;
> - struct intel_device_info *info;
> - u32 fuse, eu_dis;
> -
> - info = (struct intel_device_info *)&dev_priv->info;
> - fuse = I915_READ(CHV_FUSE_GT);
> -
> - info->slice_total = 1;
> -
> - if (!(fuse & CHV_FGT_DISABLE_SS0)) {
> - info->subslice_per_slice++;
> - eu_dis = fuse & (CHV_FGT_EU_DIS_SS0_R0_MASK |
> - CHV_FGT_EU_DIS_SS0_R1_MASK);
> - info->eu_total += 8 - hweight32(eu_dis);
> - }
> -
> - if (!(fuse & CHV_FGT_DISABLE_SS1)) {
> - info->subslice_per_slice++;
> - eu_dis = fuse & (CHV_FGT_EU_DIS_SS1_R0_MASK |
> - CHV_FGT_EU_DIS_SS1_R1_MASK);
> - info->eu_total += 8 - hweight32(eu_dis);
> - }
> -
> - info->subslice_total = info->subslice_per_slice;
> - /*
> - * CHV expected to always have a uniform distribution of EU
> - * across subslices.
> - */
> - info->eu_per_subslice = info->subslice_total ?
> - info->eu_total / info->subslice_total :
> - 0;
> - /*
> - * CHV supports subslice power gating on devices with more than
> - * one subslice, and supports EU power gating on devices with
> - * more than one EU pair per subslice.
> - */
> - info->has_slice_pg = 0;
> - info->has_subslice_pg = (info->subslice_total > 1);
> - info->has_eu_pg = (info->eu_per_subslice > 2);
> -}
> -
> -static void gen9_sseu_info_init(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = dev->dev_private;
> - struct intel_device_info *info;
> - int s_max = 3, ss_max = 4, eu_max = 8;
> - int s, ss;
> - u32 fuse2, s_enable, ss_disable, eu_disable;
> - u8 eu_mask = 0xff;
> -
> - info = (struct intel_device_info *)&dev_priv->info;
> - fuse2 = I915_READ(GEN8_FUSE2);
> - s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >>
> - GEN8_F2_S_ENA_SHIFT;
> - ss_disable = (fuse2 & GEN9_F2_SS_DIS_MASK) >>
> - GEN9_F2_SS_DIS_SHIFT;
> -
> - info->slice_total = hweight32(s_enable);
> - /*
> - * The subslice disable field is global, i.e. it applies
> - * to each of the enabled slices.
> - */
> - info->subslice_per_slice = ss_max - hweight32(ss_disable);
> - info->subslice_total = info->slice_total *
> - info->subslice_per_slice;
> -
> - /*
> - * Iterate through enabled slices and subslices to
> - * count the total enabled EU.
> - */
> - for (s = 0; s < s_max; s++) {
> - if (!(s_enable & (0x1 << s)))
> - /* skip disabled slice */
> - continue;
> -
> - eu_disable = I915_READ(GEN9_EU_DISABLE(s));
> - for (ss = 0; ss < ss_max; ss++) {
> - int eu_per_ss;
> -
> - if (ss_disable & (0x1 << ss))
> - /* skip disabled subslice */
> - continue;
> -
> - eu_per_ss = eu_max - hweight8((eu_disable >> (ss*8)) &
> - eu_mask);
> -
> - /*
> - * Record which subslice(s) has(have) 7 EUs. we
> - * can tune the hash used to spread work among
> - * subslices if they are unbalanced.
> - */
> - if (eu_per_ss == 7)
> - info->subslice_7eu[s] |= 1 << ss;
> -
> - info->eu_total += eu_per_ss;
> - }
> - }
> -
> - /*
> - * SKL is expected to always have a uniform distribution
> - * of EU across subslices with the exception that any one
> - * EU in any one subslice may be fused off for die
> - * recovery. BXT is expected to be perfectly uniform in EU
> - * distribution.
> - */
> - info->eu_per_subslice = info->subslice_total ?
> - DIV_ROUND_UP(info->eu_total,
> - info->subslice_total) : 0;
> - /*
> - * SKL supports slice power gating on devices with more than
> - * one slice, and supports EU power gating on devices with
> - * more than one EU pair per subslice. BXT supports subslice
> - * power gating on devices with more than one subslice, and
> - * supports EU power gating on devices with more than one EU
> - * pair per subslice.
> - */
> - info->has_slice_pg = ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
> - (info->slice_total > 1));
> - info->has_subslice_pg = (IS_BROXTON(dev) && (info->subslice_total > 1));
> - info->has_eu_pg = (info->eu_per_subslice > 2);
> -}
> -
> -static void broadwell_sseu_info_init(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = dev->dev_private;
> - struct intel_device_info *info;
> - const int s_max = 3, ss_max = 3, eu_max = 8;
> - int s, ss;
> - u32 fuse2, eu_disable[s_max], s_enable, ss_disable;
> -
> - fuse2 = I915_READ(GEN8_FUSE2);
> - s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT;
> - ss_disable = (fuse2 & GEN8_F2_SS_DIS_MASK) >> GEN8_F2_SS_DIS_SHIFT;
> -
> - eu_disable[0] = I915_READ(GEN8_EU_DISABLE0) & GEN8_EU_DIS0_S0_MASK;
> - eu_disable[1] = (I915_READ(GEN8_EU_DISABLE0) >> GEN8_EU_DIS0_S1_SHIFT) |
> - ((I915_READ(GEN8_EU_DISABLE1) & GEN8_EU_DIS1_S1_MASK) <<
> - (32 - GEN8_EU_DIS0_S1_SHIFT));
> - eu_disable[2] = (I915_READ(GEN8_EU_DISABLE1) >> GEN8_EU_DIS1_S2_SHIFT) |
> - ((I915_READ(GEN8_EU_DISABLE2) & GEN8_EU_DIS2_S2_MASK) <<
> - (32 - GEN8_EU_DIS1_S2_SHIFT));
> -
> -
> - info = (struct intel_device_info *)&dev_priv->info;
> - info->slice_total = hweight32(s_enable);
> -
> - /*
> - * The subslice disable field is global, i.e. it applies
> - * to each of the enabled slices.
> - */
> - info->subslice_per_slice = ss_max - hweight32(ss_disable);
> - info->subslice_total = info->slice_total * info->subslice_per_slice;
> -
> - /*
> - * Iterate through enabled slices and subslices to
> - * count the total enabled EU.
> - */
> - for (s = 0; s < s_max; s++) {
> - if (!(s_enable & (0x1 << s)))
> - /* skip disabled slice */
> - continue;
> -
> - for (ss = 0; ss < ss_max; ss++) {
> - u32 n_disabled;
> -
> - if (ss_disable & (0x1 << ss))
> - /* skip disabled subslice */
> - continue;
> -
> - n_disabled = hweight8(eu_disable[s] >> (ss * eu_max));
> -
> - /*
> - * Record which subslices have 7 EUs.
> - */
> - if (eu_max - n_disabled == 7)
> - info->subslice_7eu[s] |= 1 << ss;
> -
> - info->eu_total += eu_max - n_disabled;
> - }
> - }
> -
> - /*
> - * BDW is expected to always have a uniform distribution of EU across
> - * subslices with the exception that any one EU in any one subslice may
> - * be fused off for die recovery.
> - */
> - info->eu_per_subslice = info->subslice_total ?
> - DIV_ROUND_UP(info->eu_total, info->subslice_total) : 0;
> -
> - /*
> - * BDW supports slice power gating on devices with more than
> - * one slice.
> - */
> - info->has_slice_pg = (info->slice_total > 1);
> - info->has_subslice_pg = 0;
> - info->has_eu_pg = 0;
> -}
> -
> -/*
> - * Determine various intel_device_info fields at runtime.
> - *
> - * Use it when either:
> - * - it's judged too laborious to fill n static structures with the limit
> - * when a simple if statement does the job,
> - * - run-time checks (eg read fuse/strap registers) are needed.
> - *
> - * This function needs to be called:
> - * - after the MMIO has been setup as we are reading registers,
> - * - after the PCH has been detected,
> - * - before the first usage of the fields it can tweak.
> - */
> -static void intel_device_info_runtime_init(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = dev->dev_private;
> - struct intel_device_info *info;
> - enum pipe pipe;
> -
> - info = (struct intel_device_info *)&dev_priv->info;
> -
> - /*
> - * Skylake and Broxton currently don't expose the topmost plane as its
> - * use is exclusive with the legacy cursor and we only want to expose
> - * one of those, not both. Until we can safely expose the topmost plane
> - * as a DRM_PLANE_TYPE_CURSOR with all the features exposed/supported,
> - * we don't expose the topmost plane at all to prevent ABI breakage
> - * down the line.
> - */
> - if (IS_BROXTON(dev)) {
> - info->num_sprites[PIPE_A] = 2;
> - info->num_sprites[PIPE_B] = 2;
> - info->num_sprites[PIPE_C] = 1;
> - } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
> - for_each_pipe(dev_priv, pipe)
> - info->num_sprites[pipe] = 2;
> - else
> - for_each_pipe(dev_priv, pipe)
> - info->num_sprites[pipe] = 1;
> -
> - if (i915.disable_display) {
> - DRM_INFO("Display disabled (module parameter)\n");
> - info->num_pipes = 0;
> - } else if (info->num_pipes > 0 &&
> - (IS_GEN7(dev_priv) || IS_GEN8(dev_priv)) &&
> - HAS_PCH_SPLIT(dev)) {
> - u32 fuse_strap = I915_READ(FUSE_STRAP);
> - u32 sfuse_strap = I915_READ(SFUSE_STRAP);
> -
> - /*
> - * SFUSE_STRAP is supposed to have a bit signalling the display
> - * is fused off. Unfortunately it seems that, at least in
> - * certain cases, fused off display means that PCH display
> - * reads don't land anywhere. In that case, we read 0s.
> - *
> - * On CPT/PPT, we can detect this case as SFUSE_STRAP_FUSE_LOCK
> - * should be set when taking over after the firmware.
> - */
> - if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE ||
> - sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED ||
> - (dev_priv->pch_type == PCH_CPT &&
> - !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) {
> - DRM_INFO("Display fused off, disabling\n");
> - info->num_pipes = 0;
> - } else if (fuse_strap & IVB_PIPE_C_DISABLE) {
> - DRM_INFO("PipeC fused off\n");
> - info->num_pipes -= 1;
> - }
> - } else if (info->num_pipes > 0 && IS_GEN9(dev_priv)) {
> - u32 dfsm = I915_READ(SKL_DFSM);
> - u8 disabled_mask = 0;
> - bool invalid;
> - int num_bits;
> -
> - if (dfsm & SKL_DFSM_PIPE_A_DISABLE)
> - disabled_mask |= BIT(PIPE_A);
> - if (dfsm & SKL_DFSM_PIPE_B_DISABLE)
> - disabled_mask |= BIT(PIPE_B);
> - if (dfsm & SKL_DFSM_PIPE_C_DISABLE)
> - disabled_mask |= BIT(PIPE_C);
> -
> - num_bits = hweight8(disabled_mask);
> -
> - switch (disabled_mask) {
> - case BIT(PIPE_A):
> - case BIT(PIPE_B):
> - case BIT(PIPE_A) | BIT(PIPE_B):
> - case BIT(PIPE_A) | BIT(PIPE_C):
> - invalid = true;
> - break;
> - default:
> - invalid = false;
> - }
> -
> - if (num_bits > info->num_pipes || invalid)
> - DRM_ERROR("invalid pipe fuse configuration: 0x%x\n",
> - disabled_mask);
> - else
> - info->num_pipes -= num_bits;
> - }
> -
> - /* Initialize slice/subslice/EU info */
> - if (IS_CHERRYVIEW(dev))
> - cherryview_sseu_info_init(dev);
> - else if (IS_BROADWELL(dev))
> - broadwell_sseu_info_init(dev);
> - else if (INTEL_INFO(dev)->gen >= 9)
> - gen9_sseu_info_init(dev);
> -
> - info->has_snoop = !info->has_llc;
> -
> - /* Snooping is broken on BXT A stepping. */
> - if (IS_BXT_REVID(dev, 0, BXT_REVID_A1))
> - info->has_snoop = false;
> -
> - DRM_DEBUG_DRIVER("slice total: %u\n", info->slice_total);
> - DRM_DEBUG_DRIVER("subslice total: %u\n", info->subslice_total);
> - DRM_DEBUG_DRIVER("subslice per slice: %u\n", info->subslice_per_slice);
> - DRM_DEBUG_DRIVER("EU total: %u\n", info->eu_total);
> - DRM_DEBUG_DRIVER("EU per subslice: %u\n", info->eu_per_subslice);
> - DRM_DEBUG_DRIVER("has slice power gating: %s\n",
> - info->has_slice_pg ? "y" : "n");
> - DRM_DEBUG_DRIVER("has subslice power gating: %s\n",
> - info->has_subslice_pg ? "y" : "n");
> - DRM_DEBUG_DRIVER("has EU power gating: %s\n",
> - info->has_eu_pg ? "y" : "n");
> -
> - i915.enable_execlists =
> - intel_sanitize_enable_execlists(dev_priv,
> - i915.enable_execlists);
> -
> - /*
> - * i915.enable_ppgtt is read-only, so do an early pass to validate the
> - * user's requested state against the hardware/driver capabilities. We
> - * do this now so that we can print out any log messages once rather
> - * than every time we check intel_enable_ppgtt().
> - */
> - i915.enable_ppgtt =
> - intel_sanitize_enable_ppgtt(dev_priv, i915.enable_ppgtt);
> - DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915.enable_ppgtt);
> -}
> -
> -static void intel_init_dpio(struct drm_i915_private *dev_priv)
> -{
> - /*
> - * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
> - * CHV x1 PHY (DP/HDMI D)
> - * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C)
> - */
> - if (IS_CHERRYVIEW(dev_priv)) {
> - DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
> - DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
> - } else if (IS_VALLEYVIEW(dev_priv)) {
> - DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
> - }
> -}
> -
> -static int i915_workqueues_init(struct drm_i915_private *dev_priv)
> -{
> - /*
> - * The i915 workqueue is primarily used for batched retirement of
> - * requests (and thus managing bo) once the task has been completed
> - * by the GPU. i915_gem_retire_requests() is called directly when we
> - * need high-priority retirement, such as waiting for an explicit
> - * bo.
> - *
> - * It is also used for periodic low-priority events, such as
> - * idle-timers and recording error state.
> - *
> - * All tasks on the workqueue are expected to acquire the dev mutex
> - * so there is no point in running more than one instance of the
> - * workqueue at any time. Use an ordered one.
> - */
> - dev_priv->wq = alloc_ordered_workqueue("i915", 0);
> - if (dev_priv->wq == NULL)
> - goto out_err;
> -
> - dev_priv->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0);
> - if (dev_priv->hotplug.dp_wq == NULL)
> - goto out_free_wq;
> -
> - dev_priv->gpu_error.hangcheck_wq =
> - alloc_ordered_workqueue("i915-hangcheck", 0);
> - if (dev_priv->gpu_error.hangcheck_wq == NULL)
> - goto out_free_dp_wq;
> -
> - return 0;
> -
> -out_free_dp_wq:
> - destroy_workqueue(dev_priv->hotplug.dp_wq);
> -out_free_wq:
> - destroy_workqueue(dev_priv->wq);
> -out_err:
> - DRM_ERROR("Failed to allocate workqueues.\n");
> -
> - return -ENOMEM;
> -}
> -
> -static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
> -{
> - destroy_workqueue(dev_priv->gpu_error.hangcheck_wq);
> - destroy_workqueue(dev_priv->hotplug.dp_wq);
> - destroy_workqueue(dev_priv->wq);
> -}
> -
> -/**
> - * i915_driver_init_early - setup state not requiring device access
> - * @dev_priv: device private
> - *
> - * Initialize everything that is a "SW-only" state, that is state not
> - * requiring accessing the device or exposing the driver via kernel internal
> - * or userspace interfaces. Example steps belonging here: lock initialization,
> - * system memory allocation, setting up device specific attributes and
> - * function hooks not requiring accessing the device.
> - */
> -static int i915_driver_init_early(struct drm_i915_private *dev_priv,
> - const struct pci_device_id *ent)
> -{
> - const struct intel_device_info *match_info =
> - (struct intel_device_info *)ent->driver_data;
> - struct intel_device_info *device_info;
> - int ret = 0;
> -
> - if (i915_inject_load_failure())
> - return -ENODEV;
> -
> - /* Setup the write-once "constant" device info */
> - device_info = (struct intel_device_info *)&dev_priv->info;
> - memcpy(device_info, match_info, sizeof(*device_info));
> - device_info->device_id = dev_priv->drm.pdev->device;
> -
> - BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE);
> - device_info->gen_mask = BIT(device_info->gen - 1);
> -
> - spin_lock_init(&dev_priv->irq_lock);
> - spin_lock_init(&dev_priv->gpu_error.lock);
> - mutex_init(&dev_priv->backlight_lock);
> - spin_lock_init(&dev_priv->uncore.lock);
> - spin_lock_init(&dev_priv->mm.object_stat_lock);
> - spin_lock_init(&dev_priv->mmio_flip_lock);
> - mutex_init(&dev_priv->sb_lock);
> - mutex_init(&dev_priv->modeset_restore_lock);
> - mutex_init(&dev_priv->av_mutex);
> - mutex_init(&dev_priv->wm.wm_mutex);
> - mutex_init(&dev_priv->pps_mutex);
> -
> - ret = i915_workqueues_init(dev_priv);
> - if (ret < 0)
> - return ret;
> -
> - /* This must be called before any calls to HAS_PCH_* */
> - intel_detect_pch(&dev_priv->drm);
> -
> - intel_pm_setup(&dev_priv->drm);
> - intel_init_dpio(dev_priv);
> - intel_power_domains_init(dev_priv);
> - intel_irq_init(dev_priv);
> - intel_init_display_hooks(dev_priv);
> - intel_init_clock_gating_hooks(dev_priv);
> - intel_init_audio_hooks(dev_priv);
> - i915_gem_load_init(&dev_priv->drm);
> -
> - intel_display_crc_init(&dev_priv->drm);
> -
> - i915_dump_device_info(dev_priv);
> -
> - /* Not all pre-production machines fall into this category, only the
> - * very first ones. Almost everything should work, except for maybe
> - * suspend/resume. And we don't implement workarounds that affect only
> - * pre-production machines. */
> - if (IS_HSW_EARLY_SDV(dev_priv))
> - DRM_INFO("This is an early pre-production Haswell machine. "
> - "It may not be fully functional.\n");
> -
> - return 0;
> -}
> -
> -/**
> - * i915_driver_cleanup_early - cleanup the setup done in i915_driver_init_early()
> - * @dev_priv: device private
> - */
> -static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
> -{
> - i915_gem_load_cleanup(dev_priv->dev);
> - i915_workqueues_cleanup(dev_priv);
> -}
> -
> -static int i915_mmio_setup(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = to_i915(dev);
> - int mmio_bar;
> - int mmio_size;
> -
> - mmio_bar = IS_GEN2(dev) ? 1 : 0;
> - /*
> - * Before gen4, the registers and the GTT are behind different BARs.
> - * However, from gen4 onwards, the registers and the GTT are shared
> - * in the same BAR, so we want to restrict this ioremap from
> - * clobbering the GTT which we want ioremap_wc instead. Fortunately,
> - * the register BAR remains the same size for all the earlier
> - * generations up to Ironlake.
> - */
> - if (INTEL_INFO(dev)->gen < 5)
> - mmio_size = 512 * 1024;
> - else
> - mmio_size = 2 * 1024 * 1024;
> - dev_priv->regs = pci_iomap(dev->pdev, mmio_bar, mmio_size);
> - if (dev_priv->regs == NULL) {
> - DRM_ERROR("failed to map registers\n");
> -
> - return -EIO;
> - }
> -
> - /* Try to make sure MCHBAR is enabled before poking at it */
> - intel_setup_mchbar(dev);
> -
> - return 0;
> -}
> -
> -static void i915_mmio_cleanup(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = to_i915(dev);
> -
> - intel_teardown_mchbar(dev);
> - pci_iounmap(dev->pdev, dev_priv->regs);
> -}
> -
> -/**
> - * i915_driver_init_mmio - setup device MMIO
> - * @dev_priv: device private
> - *
> - * Setup minimal device state necessary for MMIO accesses later in the
> - * initialization sequence. The setup here should avoid any other device-wide
> - * side effects or exposing the driver via kernel internal or user space
> - * interfaces.
> - */
> -static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
> -{
> - struct drm_device *dev = dev_priv->dev;
> - int ret;
> -
> - if (i915_inject_load_failure())
> - return -ENODEV;
> -
> - if (i915_get_bridge_dev(dev))
> - return -EIO;
> -
> - ret = i915_mmio_setup(dev);
> - if (ret < 0)
> - goto put_bridge;
> -
> - intel_uncore_init(dev_priv);
> -
> - return 0;
> -
> -put_bridge:
> - pci_dev_put(dev_priv->bridge_dev);
> -
> - return ret;
> -}
> -
> -/**
> - * i915_driver_cleanup_mmio - cleanup the setup done in i915_driver_init_mmio()
> - * @dev_priv: device private
> - */
> -static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv)
> -{
> - struct drm_device *dev = dev_priv->dev;
> -
> - intel_uncore_fini(dev_priv);
> - i915_mmio_cleanup(dev);
> - pci_dev_put(dev_priv->bridge_dev);
> -}
> -
> -/**
> - * i915_driver_init_hw - setup state requiring device access
> - * @dev_priv: device private
> - *
> - * Setup state that requires accessing the device, but doesn't require
> - * exposing the driver via kernel internal or userspace interfaces.
> - */
> -static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
> -{
> - struct drm_device *dev = dev_priv->dev;
> - struct i915_ggtt *ggtt = &dev_priv->ggtt;
> - uint32_t aperture_size;
> - int ret;
> -
> - if (i915_inject_load_failure())
> - return -ENODEV;
> -
> - intel_device_info_runtime_init(dev);
> -
> - ret = i915_ggtt_init_hw(dev);
> - if (ret)
> - return ret;
> -
> - ret = i915_ggtt_enable_hw(dev);
> - if (ret) {
> - DRM_ERROR("failed to enable GGTT\n");
> - goto out_ggtt;
> - }
> -
> - /* WARNING: Apparently we must kick fbdev drivers before vgacon,
> - * otherwise the vga fbdev driver falls over. */
> - ret = i915_kick_out_firmware_fb(dev_priv);
> - if (ret) {
> - DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
> - goto out_ggtt;
> - }
> -
> - ret = i915_kick_out_vgacon(dev_priv);
> - if (ret) {
> - DRM_ERROR("failed to remove conflicting VGA console\n");
> - goto out_ggtt;
> - }
> -
> - pci_set_master(dev->pdev);
> -
> - /* overlay on gen2 is broken and can't address above 1G */
> - if (IS_GEN2(dev)) {
> - ret = dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30));
> - if (ret) {
> - DRM_ERROR("failed to set DMA mask\n");
> -
> - goto out_ggtt;
> - }
> - }
> -
> -
> - /* 965GM sometimes incorrectly writes to hardware status page (HWS)
> - * using 32bit addressing, overwriting memory if HWS is located
> - * above 4GB.
> - *
> - * The documentation also mentions an issue with undefined
> - * behaviour if any general state is accessed within a page above 4GB,
> - * which also needs to be handled carefully.
> - */
> - if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) {
> - ret = dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32));
> -
> - if (ret) {
> - DRM_ERROR("failed to set DMA mask\n");
> -
> - goto out_ggtt;
> - }
> - }
> -
> - aperture_size = ggtt->mappable_end;
> -
> - ggtt->mappable =
> - io_mapping_create_wc(ggtt->mappable_base,
> - aperture_size);
> - if (!ggtt->mappable) {
> - ret = -EIO;
> - goto out_ggtt;
> - }
> -
> - ggtt->mtrr = arch_phys_wc_add(ggtt->mappable_base,
> - aperture_size);
> -
> - pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY,
> - PM_QOS_DEFAULT_VALUE);
> -
> - intel_uncore_sanitize(dev_priv);
> -
> - intel_opregion_setup(dev_priv);
> -
> - i915_gem_load_init_fences(dev_priv);
> -
> - /* On the 945G/GM, the chipset reports the MSI capability on the
> - * integrated graphics even though the support isn't actually there
> - * according to the published specs. It doesn't appear to function
> - * correctly in testing on 945G.
> - * This may be a side effect of MSI having been made available for PEG
> - * and the registers being closely associated.
> - *
> - * According to chipset errata, on the 965GM, MSI interrupts may
> - * be lost or delayed, but we use them anyways to avoid
> - * stuck interrupts on some machines.
> - */
> - if (!IS_I945G(dev) && !IS_I945GM(dev)) {
> - if (pci_enable_msi(dev->pdev) < 0)
> - DRM_DEBUG_DRIVER("can't enable MSI");
> - }
> -
> - return 0;
> -
> -out_ggtt:
> - i915_ggtt_cleanup_hw(dev);
> -
> - return ret;
> -}
> -
> -/**
> - * i915_driver_cleanup_hw - cleanup the setup done in i915_driver_init_hw()
> - * @dev_priv: device private
> - */
> -static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv)
> -{
> - struct drm_device *dev = dev_priv->dev;
> - struct i915_ggtt *ggtt = &dev_priv->ggtt;
> -
> - if (dev->pdev->msi_enabled)
> - pci_disable_msi(dev->pdev);
> -
> - pm_qos_remove_request(&dev_priv->pm_qos);
> - arch_phys_wc_del(ggtt->mtrr);
> - io_mapping_free(ggtt->mappable);
> - i915_ggtt_cleanup_hw(dev);
> -}
> -
> -/**
> - * i915_driver_register - register the driver with the rest of the system
> - * @dev_priv: device private
> - *
> - * Perform any steps necessary to make the driver available via kernel
> - * internal or userspace interfaces.
> - */
> -static void i915_driver_register(struct drm_i915_private *dev_priv)
> -{
> - struct drm_device *dev = dev_priv->dev;
> -
> - i915_gem_shrinker_init(dev_priv);
> -
> - /*
> - * Notify a valid surface after modesetting,
> - * when running inside a VM.
> - */
> - if (intel_vgpu_active(dev_priv))
> - I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY);
> -
> - /* Reveal our presence to userspace */
> - if (drm_dev_register(dev, 0) == 0) {
> - i915_debugfs_register(dev_priv);
> - i915_setup_sysfs(dev);
> - intel_modeset_register(dev_priv);
> - } else
> - DRM_ERROR("Failed to register driver for userspace access!\n");
> -
> - if (INTEL_INFO(dev_priv)->num_pipes) {
> - /* Must be done after probing outputs */
> - intel_opregion_register(dev_priv);
> - acpi_video_register();
> - }
> -
> - if (IS_GEN5(dev_priv))
> - intel_gpu_ips_init(dev_priv);
> -
> - i915_audio_component_init(dev_priv);
> -
> - /*
> - * Some ports require correctly set-up hpd registers for detection to
> - * work properly (leading to ghost connected connector status), e.g. VGA
> - * on gm45. Hence we can only set up the initial fbdev config after hpd
> - * irqs are fully enabled. Now we should scan for the initial config
> - * only once hotplug handling is enabled, but due to screwed-up locking
> - * around kms/fbdev init we can't protect the fdbev initial config
> - * scanning against hotplug events. Hence do this first and ignore the
> - * tiny window where we will loose hotplug notifactions.
> - */
> - intel_fbdev_initial_config_async(dev);
> -}
> -
> -/**
> - * i915_driver_unregister - cleanup the registration done in i915_driver_regiser()
> - * @dev_priv: device private
> - */
> -static void i915_driver_unregister(struct drm_i915_private *dev_priv)
> -{
> - i915_audio_component_cleanup(dev_priv);
> -
> - intel_gpu_ips_teardown();
> - acpi_video_unregister();
> - intel_opregion_unregister(dev_priv);
> -
> - intel_modeset_unregister(dev_priv);
> - i915_teardown_sysfs(dev_priv->dev);
> - i915_debugfs_unregister(dev_priv);
> - drm_dev_unregister(dev_priv->dev);
> -
> - i915_gem_shrinker_cleanup(dev_priv);
> -}
> -
> -/**
> - * i915_driver_load - setup chip and create an initial config
> - * @dev: DRM device
> - * @flags: startup flags
> - *
> - * The driver load routine has to do several things:
> - * - drive output discovery via intel_modeset_init()
> - * - initialize the memory manager
> - * - allocate initial config memory
> - * - setup the DRM framebuffer with the allocated memory
> - */
> -int i915_driver_load(struct pci_dev *pdev,
> - const struct pci_device_id *ent,
> - struct drm_driver *driver)
> -{
> - struct drm_i915_private *dev_priv;
> - int ret;
> -
> - dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
> - if (dev_priv == NULL)
> - return -ENOMEM;
> -
> - ret = drm_dev_init(&dev_priv->drm, driver, &pdev->dev);
> - if (ret)
> - goto out_free_priv;
> -
> - /* Must be set before calling __i915_printk */
> - dev_priv->drm.pdev = pdev;
> - dev_priv->drm.dev_private = dev_priv;
> - dev_priv->dev = &dev_priv->drm;
> -
> - ret = i915_driver_init_early(dev_priv, ent);
> - if (ret < 0)
> - goto out_free_priv;
> -
> - ret = pci_enable_device(pdev);
> - if (ret)
> - goto out_cleanup_early;
> -
> - pci_set_drvdata(pdev, &dev_priv->drm);
> -
> - intel_runtime_pm_get(dev_priv);
> -
> - ret = i915_driver_init_mmio(dev_priv);
> - if (ret < 0)
> - goto out_runtime_pm_put;
> -
> - ret = i915_driver_init_hw(dev_priv);
> - if (ret < 0)
> - goto out_cleanup_mmio;
> -
> - /*
> - * TODO: move the vblank init and parts of modeset init steps into one
> - * of the i915_driver_init_/i915_driver_register functions according
> - * to the role/effect of the given init step.
> - */
> - if (INTEL_INFO(dev_priv)->num_pipes) {
> - ret = drm_vblank_init(dev_priv->dev,
> - INTEL_INFO(dev_priv)->num_pipes);
> - if (ret)
> - goto out_cleanup_hw;
> - }
> -
> - ret = i915_load_modeset_init(dev_priv->dev);
> - if (ret < 0)
> - goto out_cleanup_vblank;
> -
> - i915_driver_register(dev_priv);
> -
> - intel_runtime_pm_enable(dev_priv);
> -
> - intel_runtime_pm_put(dev_priv);
> -
> - return 0;
> -
> -out_cleanup_vblank:
> - drm_vblank_cleanup(dev_priv->dev);
> -out_cleanup_hw:
> - i915_driver_cleanup_hw(dev_priv);
> -out_cleanup_mmio:
> - i915_driver_cleanup_mmio(dev_priv);
> -out_runtime_pm_put:
> - intel_runtime_pm_put(dev_priv);
> - pci_disable_device(pdev);
> -out_cleanup_early:
> - i915_driver_cleanup_early(dev_priv);
> -out_free_priv:
> - i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret);
> -
> - kfree(dev_priv);
> -
> - return ret;
> -}
> -
> -int i915_driver_unload(struct drm_device *dev)
> -{
> - struct drm_i915_private *dev_priv = dev->dev_private;
> - int ret;
> -
> - intel_fbdev_fini(dev);
> -
> - ret = i915_gem_suspend(dev);
> - if (ret) {
> - DRM_ERROR("failed to idle hardware: %d\n", ret);
> - return ret;
> - }
> -
> - intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> -
> - i915_driver_unregister(dev_priv);
> -
> - drm_vblank_cleanup(dev);
> -
> - intel_modeset_cleanup(dev);
> -
> - /*
> - * free the memory space allocated for the child device
> - * config parsed from VBT
> - */
> - if (dev_priv->vbt.child_dev && dev_priv->vbt.child_dev_num) {
> - kfree(dev_priv->vbt.child_dev);
> - dev_priv->vbt.child_dev = NULL;
> - dev_priv->vbt.child_dev_num = 0;
> - }
> - kfree(dev_priv->vbt.sdvo_lvds_vbt_mode);
> - dev_priv->vbt.sdvo_lvds_vbt_mode = NULL;
> - kfree(dev_priv->vbt.lfp_lvds_vbt_mode);
> - dev_priv->vbt.lfp_lvds_vbt_mode = NULL;
> -
> - vga_switcheroo_unregister_client(dev->pdev);
> - vga_client_register(dev->pdev, NULL, NULL, NULL);
> -
> - intel_csr_ucode_fini(dev_priv);
> -
> - /* Free error state after interrupts are fully disabled. */
> - cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
> - i915_destroy_error_state(dev);
> -
> - /* Flush any outstanding unpin_work. */
> - flush_workqueue(dev_priv->wq);
> -
> - intel_guc_fini(dev);
> - i915_gem_fini(dev);
> - intel_fbc_cleanup_cfb(dev_priv);
> -
> - intel_power_domains_fini(dev_priv);
> -
> - i915_driver_cleanup_hw(dev_priv);
> - i915_driver_cleanup_mmio(dev_priv);
> -
> - intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> -
> - i915_driver_cleanup_early(dev_priv);
> -
> - return 0;
> -}
> -
> -int i915_driver_open(struct drm_device *dev, struct drm_file *file)
> -{
> - int ret;
> -
> - ret = i915_gem_open(dev, file);
> - if (ret)
> - return ret;
> -
> - return 0;
> -}
> -
> -/**
> - * i915_driver_lastclose - clean up after all DRM clients have exited
> - * @dev: DRM device
> - *
> - * Take care of cleaning up after all DRM clients have exited. In the
> - * mode setting case, we want to restore the kernel's initial mode (just
> - * in case the last client left us in a bad state).
> - *
> - * Additionally, in the non-mode setting case, we'll tear down the GTT
> - * and DMA structures, since the kernel won't be using them, and clea
> - * up any GEM state.
> - */
> -void i915_driver_lastclose(struct drm_device *dev)
> -{
> - intel_fbdev_restore_mode(dev);
> - vga_switcheroo_process_delayed_switch();
> -}
> -
> -void i915_driver_preclose(struct drm_device *dev, struct drm_file *file)
> -{
> - mutex_lock(&dev->struct_mutex);
> - i915_gem_context_close(dev, file);
> - i915_gem_release(dev, file);
> - mutex_unlock(&dev->struct_mutex);
> -}
> -
> -void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
> -{
> - struct drm_i915_file_private *file_priv = file->driver_priv;
> -
> - kfree(file_priv);
> -}
> -
> -static int
> -i915_gem_reject_pin_ioctl(struct drm_device *dev, void *data,
> - struct drm_file *file)
> -{
> - return -ENODEV;
> -}
> -
> -const struct drm_ioctl_desc i915_ioctls[] = {
> - DRM_IOCTL_DEF_DRV(I915_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> - DRM_IOCTL_DEF_DRV(I915_FLUSH, drm_noop, DRM_AUTH),
> - DRM_IOCTL_DEF_DRV(I915_FLIP, drm_noop, DRM_AUTH),
> - DRM_IOCTL_DEF_DRV(I915_BATCHBUFFER, drm_noop, DRM_AUTH),
> - DRM_IOCTL_DEF_DRV(I915_IRQ_EMIT, drm_noop, DRM_AUTH),
> - DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, drm_noop, DRM_AUTH),
> - DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH|DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_SETPARAM, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> - DRM_IOCTL_DEF_DRV(I915_ALLOC, drm_noop, DRM_AUTH),
> - DRM_IOCTL_DEF_DRV(I915_FREE, drm_noop, DRM_AUTH),
> - DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> - DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, drm_noop, DRM_AUTH),
> - DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> - DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> - DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE, drm_noop, DRM_AUTH),
> - DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, drm_noop, DRM_AUTH),
> - DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> - DRM_IOCTL_DEF_DRV(I915_GEM_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> - DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
> - DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
> - DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
> - DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_SET_CACHING, i915_gem_set_caching_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_GET_CACHING, i915_gem_get_caching_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_ENTERVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> - DRM_IOCTL_DEF_DRV(I915_GEM_LEAVEVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> - DRM_IOCTL_DEF_DRV(I915_GEM_CREATE, i915_gem_create_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
> - DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_gem_context_reset_stats_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW),
> - DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_RENDER_ALLOW),
> -};
> -
> -int i915_max_ioctl = ARRAY_SIZE(i915_ioctls);
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index b13d6751ebe4..e20f63ac73d3 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -27,21 +27,30 @@
> *
> */
>
> -#include
> #include
> -#include
> -#include
> -#include "i915_drv.h"
> -#include "i915_trace.h"
> -#include "intel_drv.h"
> -
> #include
> #include
> +#include
> +#include
> #include
> +#include
> +#include
> #include
> +#include
> +#include
> #include
> #include
> +#include
> +#include
> +
> +#include
> #include
> +#include
> +
> +#include "i915_drv.h"
> +#include "i915_trace.h"
> +#include "i915_vgpu.h"
> +#include "intel_drv.h"
>
> static struct drm_driver driver;
>
> @@ -340,219 +349,1783 @@ static const struct intel_device_info intel_skylake_info = {
> .gen = 9,
> };
>
> -static const struct intel_device_info intel_skylake_gt3_info = {
> - BDW_FEATURES,
> - .is_skylake = 1,
> - .gen = 9,
> - .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
> -};
> +static const struct intel_device_info intel_skylake_gt3_info = {
> + BDW_FEATURES,
> + .is_skylake = 1,
> + .gen = 9,
> + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
> +};
> +
> +static const struct intel_device_info intel_broxton_info = {
> + .is_preliminary = 1,
> + .is_broxton = 1,
> + .gen = 9,
> + .need_gfx_hws = 1, .has_hotplug = 1,
> + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
> + .num_pipes = 3,
> + .has_ddi = 1,
> + .has_fpga_dbg = 1,
> + .has_fbc = 1,
> + GEN_DEFAULT_PIPEOFFSETS,
> + IVB_CURSOR_OFFSETS,
> + BDW_COLORS,
> +};
> +
> +static const struct intel_device_info intel_kabylake_info = {
> + BDW_FEATURES,
> + .is_kabylake = 1,
> + .gen = 9,
> +};
> +
> +static const struct intel_device_info intel_kabylake_gt3_info = {
> + BDW_FEATURES,
> + .is_kabylake = 1,
> + .gen = 9,
> + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
> +};
> +
> +/*
> + * Make sure any device matches here are from most specific to most
> + * general. For example, since the Quanta match is based on the subsystem
> + * and subvendor IDs, we need it to come before the more general IVB
> + * PCI ID matches, otherwise we'll use the wrong info struct above.
> + */
> +static const struct pci_device_id pciidlist[] = {
> + INTEL_I830_IDS(&intel_i830_info),
> + INTEL_I845G_IDS(&intel_845g_info),
> + INTEL_I85X_IDS(&intel_i85x_info),
> + INTEL_I865G_IDS(&intel_i865g_info),
> + INTEL_I915G_IDS(&intel_i915g_info),
> + INTEL_I915GM_IDS(&intel_i915gm_info),
> + INTEL_I945G_IDS(&intel_i945g_info),
> + INTEL_I945GM_IDS(&intel_i945gm_info),
> + INTEL_I965G_IDS(&intel_i965g_info),
> + INTEL_G33_IDS(&intel_g33_info),
> + INTEL_I965GM_IDS(&intel_i965gm_info),
> + INTEL_GM45_IDS(&intel_gm45_info),
> + INTEL_G45_IDS(&intel_g45_info),
> + INTEL_PINEVIEW_IDS(&intel_pineview_info),
> + INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info),
> + INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info),
> + INTEL_SNB_D_IDS(&intel_sandybridge_d_info),
> + INTEL_SNB_M_IDS(&intel_sandybridge_m_info),
> + INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */
> + INTEL_IVB_M_IDS(&intel_ivybridge_m_info),
> + INTEL_IVB_D_IDS(&intel_ivybridge_d_info),
> + INTEL_HSW_D_IDS(&intel_haswell_d_info),
> + INTEL_HSW_M_IDS(&intel_haswell_m_info),
> + INTEL_VLV_M_IDS(&intel_valleyview_m_info),
> + INTEL_VLV_D_IDS(&intel_valleyview_d_info),
> + INTEL_BDW_GT12M_IDS(&intel_broadwell_m_info),
> + INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info),
> + INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info),
> + INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info),
> + INTEL_CHV_IDS(&intel_cherryview_info),
> + INTEL_SKL_GT1_IDS(&intel_skylake_info),
> + INTEL_SKL_GT2_IDS(&intel_skylake_info),
> + INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info),
> + INTEL_SKL_GT4_IDS(&intel_skylake_gt3_info),
> + INTEL_BXT_IDS(&intel_broxton_info),
> + INTEL_KBL_GT1_IDS(&intel_kabylake_info),
> + INTEL_KBL_GT2_IDS(&intel_kabylake_info),
> + INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info),
> + INTEL_KBL_GT4_IDS(&intel_kabylake_gt3_info),
> + {0, 0, 0}
> +};
> +MODULE_DEVICE_TABLE(pci, pciidlist);
> +
> +static unsigned int i915_load_fail_count;
> +
> +bool __i915_inject_load_failure(const char *func, int line)
> +{
> + if (i915_load_fail_count >= i915.inject_load_failure)
> + return false;
> +
> + if (++i915_load_fail_count == i915.inject_load_failure) {
> + DRM_INFO("Injecting failure at checkpoint %u [%s:%d]\n",
> + i915.inject_load_failure, func, line);
> + return true;
> + }
> +
> + return false;
> +}
> +
> +#define FDO_BUG_URL "https://bugs.freedesktop.org/enter_bug.cgi?product=DRI"
> +#define FDO_BUG_MSG "Please file a bug at " FDO_BUG_URL " against DRM/Intel " \
> + "providing the dmesg log by booting with drm.debug=0xf"
> +
> +void
> +__i915_printk(struct drm_i915_private *dev_priv, const char *level,
> + const char *fmt, ...)
> +{
> + static bool shown_bug_once;
> + struct device *dev = dev_priv->dev->dev;
> + bool is_error = level[1] <= KERN_ERR[1];
> + bool is_debug = level[1] == KERN_DEBUG[1];
> + struct va_format vaf;
> + va_list args;
> +
> + if (is_debug && !(drm_debug & DRM_UT_DRIVER))
> + return;
> +
> + va_start(args, fmt);
> +
> + vaf.fmt = fmt;
> + vaf.va = &args;
> +
> + dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV",
> + __builtin_return_address(0), &vaf);
> +
> + if (is_error && !shown_bug_once) {
> + dev_notice(dev, "%s", FDO_BUG_MSG);
> + shown_bug_once = true;
> + }
> +
> + va_end(args);
> +}
> +
> +static bool i915_error_injected(struct drm_i915_private *dev_priv)
> +{
> + return i915.inject_load_failure &&
> + i915_load_fail_count == i915.inject_load_failure;
> +}
> +
> +#define i915_load_error(dev_priv, fmt, ...) \
> + __i915_printk(dev_priv, \
> + i915_error_injected(dev_priv) ? KERN_DEBUG : KERN_ERR, \
> + fmt, ##__VA_ARGS__)
> +
> +
> +static enum intel_pch intel_virt_detect_pch(struct drm_device *dev)
> +{
> + enum intel_pch ret = PCH_NOP;
> +
> + /*
> + * In a virtualized passthrough environment we can be in a
> + * setup where the ISA bridge is not able to be passed through.
> + * In this case, a south bridge can be emulated and we have to
> + * make an educated guess as to which PCH is really there.
> + */
> +
> + if (IS_GEN5(dev)) {
> + ret = PCH_IBX;
> + DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n");
> + } else if (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) {
> + ret = PCH_CPT;
> + DRM_DEBUG_KMS("Assuming CouarPoint PCH\n");
> + } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> + ret = PCH_LPT;
> + DRM_DEBUG_KMS("Assuming LynxPoint PCH\n");
> + } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
> + ret = PCH_SPT;
> + DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n");
> + }
> +
> + return ret;
> +}
> +
> +static void intel_detect_pch(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct pci_dev *pch = NULL;
> +
> + /* In all current cases, num_pipes is equivalent to the PCH_NOP setting
> + * (which really amounts to a PCH but no South Display).
> + */
> + if (INTEL_INFO(dev)->num_pipes == 0) {
> + dev_priv->pch_type = PCH_NOP;
> + return;
> + }
> +
> + /*
> + * The reason to probe ISA bridge instead of Dev31:Fun0 is to
> + * make graphics device passthrough work easy for VMM, that only
> + * need to expose ISA bridge to let driver know the real hardware
> + * underneath. This is a requirement from virtualization team.
> + *
> + * In some virtualized environments (e.g. XEN), there is irrelevant
> + * ISA bridge in the system. To work reliably, we should scan trhough
> + * all the ISA bridge devices and check for the first match, instead
> + * of only checking the first one.
> + */
> + while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) {
> + if (pch->vendor == PCI_VENDOR_ID_INTEL) {
> + unsigned short id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
> + dev_priv->pch_id = id;
> +
> + if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
> + dev_priv->pch_type = PCH_IBX;
> + DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
> + WARN_ON(!IS_GEN5(dev));
> + } else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
> + dev_priv->pch_type = PCH_CPT;
> + DRM_DEBUG_KMS("Found CougarPoint PCH\n");
> + WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
> + } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
> + /* PantherPoint is CPT compatible */
> + dev_priv->pch_type = PCH_CPT;
> + DRM_DEBUG_KMS("Found PantherPoint PCH\n");
> + WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
> + } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
> + dev_priv->pch_type = PCH_LPT;
> + DRM_DEBUG_KMS("Found LynxPoint PCH\n");
> + WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev));
> + WARN_ON(IS_HSW_ULT(dev) || IS_BDW_ULT(dev));
> + } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
> + dev_priv->pch_type = PCH_LPT;
> + DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
> + WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev));
> + WARN_ON(!IS_HSW_ULT(dev) && !IS_BDW_ULT(dev));
> + } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) {
> + dev_priv->pch_type = PCH_SPT;
> + DRM_DEBUG_KMS("Found SunrisePoint PCH\n");
> + WARN_ON(!IS_SKYLAKE(dev) &&
> + !IS_KABYLAKE(dev));
> + } else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) {
> + dev_priv->pch_type = PCH_SPT;
> + DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
> + WARN_ON(!IS_SKYLAKE(dev) &&
> + !IS_KABYLAKE(dev));
> + } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) ||
> + (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) ||
> + ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) &&
> + pch->subsystem_vendor == 0x1af4 &&
> + pch->subsystem_device == 0x1100)) {
> + dev_priv->pch_type = intel_virt_detect_pch(dev);
> + } else
> + continue;
> +
> + break;
> + }
> + }
> + if (!pch)
> + DRM_DEBUG_KMS("No PCH found.\n");
> +
> + pci_dev_put(pch);
> +}
> +
> +bool i915_semaphore_is_enabled(struct drm_i915_private *dev_priv)
> +{
> + if (INTEL_GEN(dev_priv) < 6)
> + return false;
> +
> + if (i915.semaphores >= 0)
> + return i915.semaphores;
> +
> + /* TODO: make semaphores and Execlists play nicely together */
> + if (i915.enable_execlists)
> + return false;
> +
> +#ifdef CONFIG_INTEL_IOMMU
> + /* Enable semaphores on SNB when IO remapping is off */
> + if (IS_GEN6(dev_priv) && intel_iommu_gfx_mapped)
> + return false;
> +#endif
> +
> + return true;
> +}
> +
> +static int i915_getparam(struct drm_device *dev, void *data,
> + struct drm_file *file_priv)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + drm_i915_getparam_t *param = data;
> + int value;
> +
> + switch (param->param) {
> + case I915_PARAM_IRQ_ACTIVE:
> + case I915_PARAM_ALLOW_BATCHBUFFER:
> + case I915_PARAM_LAST_DISPATCH:
> + /* Reject all old ums/dri params. */
> + return -ENODEV;
> + case I915_PARAM_CHIPSET_ID:
> + value = dev->pdev->device;
> + break;
> + case I915_PARAM_REVISION:
> + value = dev->pdev->revision;
> + break;
> + case I915_PARAM_HAS_GEM:
> + value = 1;
> + break;
> + case I915_PARAM_NUM_FENCES_AVAIL:
> + value = dev_priv->num_fence_regs;
> + break;
> + case I915_PARAM_HAS_OVERLAY:
> + value = dev_priv->overlay ? 1 : 0;
> + break;
> + case I915_PARAM_HAS_PAGEFLIPPING:
> + value = 1;
> + break;
> + case I915_PARAM_HAS_EXECBUF2:
> + /* depends on GEM */
> + value = 1;
> + break;
> + case I915_PARAM_HAS_BSD:
> + value = intel_engine_initialized(&dev_priv->engine[VCS]);
> + break;
> + case I915_PARAM_HAS_BLT:
> + value = intel_engine_initialized(&dev_priv->engine[BCS]);
> + break;
> + case I915_PARAM_HAS_VEBOX:
> + value = intel_engine_initialized(&dev_priv->engine[VECS]);
> + break;
> + case I915_PARAM_HAS_BSD2:
> + value = intel_engine_initialized(&dev_priv->engine[VCS2]);
> + break;
> + case I915_PARAM_HAS_RELAXED_FENCING:
> + value = 1;
> + break;
> + case I915_PARAM_HAS_COHERENT_RINGS:
> + value = 1;
> + break;
> + case I915_PARAM_HAS_EXEC_CONSTANTS:
> + value = INTEL_INFO(dev)->gen >= 4;
> + break;
> + case I915_PARAM_HAS_RELAXED_DELTA:
> + value = 1;
> + break;
> + case I915_PARAM_HAS_GEN7_SOL_RESET:
> + value = 1;
> + break;
> + case I915_PARAM_HAS_LLC:
> + value = HAS_LLC(dev);
> + break;
> + case I915_PARAM_HAS_WT:
> + value = HAS_WT(dev);
> + break;
> + case I915_PARAM_HAS_ALIASING_PPGTT:
> + value = USES_PPGTT(dev);
> + break;
> + case I915_PARAM_HAS_WAIT_TIMEOUT:
> + value = 1;
> + break;
> + case I915_PARAM_HAS_SEMAPHORES:
> + value = i915_semaphore_is_enabled(dev_priv);
> + break;
> + case I915_PARAM_HAS_PRIME_VMAP_FLUSH:
> + value = 1;
> + break;
> + case I915_PARAM_HAS_SECURE_BATCHES:
> + value = capable(CAP_SYS_ADMIN);
> + break;
> + case I915_PARAM_HAS_PINNED_BATCHES:
> + value = 1;
> + break;
> + case I915_PARAM_HAS_EXEC_NO_RELOC:
> + value = 1;
> + break;
> + case I915_PARAM_HAS_EXEC_HANDLE_LUT:
> + value = 1;
> + break;
> + case I915_PARAM_CMD_PARSER_VERSION:
> + value = i915_cmd_parser_get_version(dev_priv);
> + break;
> + case I915_PARAM_HAS_COHERENT_PHYS_GTT:
> + value = 1;
> + break;
> + case I915_PARAM_MMAP_VERSION:
> + value = 1;
> + break;
> + case I915_PARAM_SUBSLICE_TOTAL:
> + value = INTEL_INFO(dev)->subslice_total;
> + if (!value)
> + return -ENODEV;
> + break;
> + case I915_PARAM_EU_TOTAL:
> + value = INTEL_INFO(dev)->eu_total;
> + if (!value)
> + return -ENODEV;
> + break;
> + case I915_PARAM_HAS_GPU_RESET:
> + value = i915.enable_hangcheck && intel_has_gpu_reset(dev_priv);
> + break;
> + case I915_PARAM_HAS_RESOURCE_STREAMER:
> + value = HAS_RESOURCE_STREAMER(dev);
> + break;
> + case I915_PARAM_HAS_EXEC_SOFTPIN:
> + value = 1;
> + break;
> + default:
> + DRM_DEBUG("Unknown parameter %d\n", param->param);
> + return -EINVAL;
> + }
> +
> + if (copy_to_user(param->value, &value, sizeof(int))) {
> + DRM_ERROR("copy_to_user failed\n");
> + return -EFAULT;
> + }
> +
> + return 0;
> +}
> +
> +static int i915_get_bridge_dev(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
> + if (!dev_priv->bridge_dev) {
> + DRM_ERROR("bridge device not found\n");
> + return -1;
> + }
> + return 0;
> +}
> +
> +/* Allocate space for the MCH regs if needed, return nonzero on error */
> +static int
> +intel_alloc_mchbar_resource(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + int reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
> + u32 temp_lo, temp_hi = 0;
> + u64 mchbar_addr;
> + int ret;
> +
> + if (INTEL_INFO(dev)->gen >= 4)
> + pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
> + pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
> + mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
> +
> + /* If ACPI doesn't have it, assume we need to allocate it ourselves */
> +#ifdef CONFIG_PNP
> + if (mchbar_addr &&
> + pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE))
> + return 0;
> +#endif
> +
> + /* Get some space for it */
> + dev_priv->mch_res.name = "i915 MCHBAR";
> + dev_priv->mch_res.flags = IORESOURCE_MEM;
> + ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus,
> + &dev_priv->mch_res,
> + MCHBAR_SIZE, MCHBAR_SIZE,
> + PCIBIOS_MIN_MEM,
> + 0, pcibios_align_resource,
> + dev_priv->bridge_dev);
> + if (ret) {
> + DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
> + dev_priv->mch_res.start = 0;
> + return ret;
> + }
> +
> + if (INTEL_INFO(dev)->gen >= 4)
> + pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
> + upper_32_bits(dev_priv->mch_res.start));
> +
> + pci_write_config_dword(dev_priv->bridge_dev, reg,
> + lower_32_bits(dev_priv->mch_res.start));
> + return 0;
> +}
> +
> +/* Setup MCHBAR if possible, return true if we should disable it again */
> +static void
> +intel_setup_mchbar(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
> + u32 temp;
> + bool enabled;
> +
> + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
> + return;
> +
> + dev_priv->mchbar_need_disable = false;
> +
> + if (IS_I915G(dev) || IS_I915GM(dev)) {
> + pci_read_config_dword(dev_priv->bridge_dev, DEVEN, &temp);
> + enabled = !!(temp & DEVEN_MCHBAR_EN);
> + } else {
> + pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
> + enabled = temp & 1;
> + }
> +
> + /* If it's already enabled, don't have to do anything */
> + if (enabled)
> + return;
> +
> + if (intel_alloc_mchbar_resource(dev))
> + return;
> +
> + dev_priv->mchbar_need_disable = true;
> +
> + /* Space is allocated or reserved, so enable it. */
> + if (IS_I915G(dev) || IS_I915GM(dev)) {
> + pci_write_config_dword(dev_priv->bridge_dev, DEVEN,
> + temp | DEVEN_MCHBAR_EN);
> + } else {
> + pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
> + pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
> + }
> +}
> +
> +static void
> +intel_teardown_mchbar(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
> +
> + if (dev_priv->mchbar_need_disable) {
> + if (IS_I915G(dev) || IS_I915GM(dev)) {
> + u32 deven_val;
> +
> + pci_read_config_dword(dev_priv->bridge_dev, DEVEN,
> + &deven_val);
> + deven_val &= ~DEVEN_MCHBAR_EN;
> + pci_write_config_dword(dev_priv->bridge_dev, DEVEN,
> + deven_val);
> + } else {
> + u32 mchbar_val;
> +
> + pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg,
> + &mchbar_val);
> + mchbar_val &= ~1;
> + pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg,
> + mchbar_val);
> + }
> + }
> +
> + if (dev_priv->mch_res.start)
> + release_resource(&dev_priv->mch_res);
> +}
> +
> +/* true = enable decode, false = disable decoder */
> +static unsigned int i915_vga_set_decode(void *cookie, bool state)
> +{
> + struct drm_device *dev = cookie;
> +
> + intel_modeset_vga_set_state(dev, state);
> + if (state)
> + return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
> + VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
> + else
> + return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
> +}
> +
> +static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
> +{
> + struct drm_device *dev = pci_get_drvdata(pdev);
> + pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
> +
> + if (state == VGA_SWITCHEROO_ON) {
> + pr_info("switched on\n");
> + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
> + /* i915 resume handler doesn't set to D0 */
> + pci_set_power_state(dev->pdev, PCI_D0);
> + i915_resume_switcheroo(dev);
> + dev->switch_power_state = DRM_SWITCH_POWER_ON;
> + } else {
> + pr_info("switched off\n");
> + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
> + i915_suspend_switcheroo(dev, pmm);
> + dev->switch_power_state = DRM_SWITCH_POWER_OFF;
> + }
> +}
> +
> +static bool i915_switcheroo_can_switch(struct pci_dev *pdev)
> +{
> + struct drm_device *dev = pci_get_drvdata(pdev);
> +
> + /*
> + * FIXME: open_count is protected by drm_global_mutex but that would lead to
> + * locking inversion with the driver load path. And the access here is
> + * completely racy anyway. So don't bother with locking for now.
> + */
> + return dev->open_count == 0;
> +}
> +
> +static const struct vga_switcheroo_client_ops i915_switcheroo_ops = {
> + .set_gpu_state = i915_switcheroo_set_state,
> + .reprobe = NULL,
> + .can_switch = i915_switcheroo_can_switch,
> +};
> +
> +static void i915_gem_fini(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = to_i915(dev);
> +
> + /*
> + * Neither the BIOS, ourselves or any other kernel
> + * expects the system to be in execlists mode on startup,
> + * so we need to reset the GPU back to legacy mode. And the only
> + * known way to disable logical contexts is through a GPU reset.
> + *
> + * So in order to leave the system in a known default configuration,
> + * always reset the GPU upon unload. Afterwards we then clean up the
> + * GEM state tracking, flushing off the requests and leaving the
> + * system in a known idle state.
> + *
> + * Note that is of the upmost importance that the GPU is idle and
> + * all stray writes are flushed *before* we dismantle the backing
> + * storage for the pinned objects.
> + *
> + * However, since we are uncertain that reseting the GPU on older
> + * machines is a good idea, we don't - just in case it leaves the
> + * machine in an unusable condition.
> + */
> + if (HAS_HW_CONTEXTS(dev)) {
> + int reset = intel_gpu_reset(dev_priv, ALL_ENGINES);
> + WARN_ON(reset && reset != -ENODEV);
> + }
> +
> + mutex_lock(&dev->struct_mutex);
> + i915_gem_reset(dev);
> + i915_gem_cleanup_engines(dev);
> + i915_gem_context_fini(dev);
> + mutex_unlock(&dev->struct_mutex);
> +
> + WARN_ON(!list_empty(&to_i915(dev)->context_list));
> +}
> +
> +static int i915_load_modeset_init(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + int ret;
> +
> + if (i915_inject_load_failure())
> + return -ENODEV;
> +
> + ret = intel_bios_init(dev_priv);
> + if (ret)
> + DRM_INFO("failed to find VBIOS tables\n");
> +
> + /* If we have > 1 VGA cards, then we need to arbitrate access
> + * to the common VGA resources.
> + *
> + * 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.
> + */
> + ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
> + if (ret && ret != -ENODEV)
> + goto out;
> +
> + intel_register_dsm_handler();
> +
> + ret = vga_switcheroo_register_client(dev->pdev, &i915_switcheroo_ops, false);
> + if (ret)
> + goto cleanup_vga_client;
> +
> + /* must happen before intel_power_domains_init_hw() on VLV/CHV */
> + intel_update_rawclk(dev_priv);
> +
> + intel_power_domains_init_hw(dev_priv, false);
> +
> + intel_csr_ucode_init(dev_priv);
> +
> + ret = intel_irq_install(dev_priv);
> + if (ret)
> + goto cleanup_csr;
> +
> + intel_setup_gmbus(dev);
> +
> + /* Important: The output setup functions called by modeset_init need
> + * working irqs for e.g. gmbus and dp aux transfers. */
> + intel_modeset_init(dev);
> +
> + intel_guc_init(dev);
> +
> + ret = i915_gem_init(dev);
> + if (ret)
> + goto cleanup_irq;
> +
> + intel_modeset_gem_init(dev);
> +
> + if (INTEL_INFO(dev)->num_pipes == 0)
> + return 0;
> +
> + ret = intel_fbdev_init(dev);
> + if (ret)
> + goto cleanup_gem;
> +
> + /* Only enable hotplug handling once the fbdev is fully set up. */
> + intel_hpd_init(dev_priv);
> +
> + drm_kms_helper_poll_init(dev);
> +
> + return 0;
> +
> +cleanup_gem:
> + i915_gem_fini(dev);
> +cleanup_irq:
> + intel_guc_fini(dev);
> + drm_irq_uninstall(dev);
> + intel_teardown_gmbus(dev);
> +cleanup_csr:
> + intel_csr_ucode_fini(dev_priv);
> + intel_power_domains_fini(dev_priv);
> + vga_switcheroo_unregister_client(dev->pdev);
> +cleanup_vga_client:
> + vga_client_register(dev->pdev, NULL, NULL, NULL);
> +out:
> + return ret;
> +}
> +
> +#if IS_ENABLED(CONFIG_FB)
> +static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
> +{
> + struct apertures_struct *ap;
> + struct pci_dev *pdev = dev_priv->dev->pdev;
> + struct i915_ggtt *ggtt = &dev_priv->ggtt;
> + bool primary;
> + int ret;
> +
> + ap = alloc_apertures(1);
> + if (!ap)
> + return -ENOMEM;
> +
> + ap->ranges[0].base = ggtt->mappable_base;
> + ap->ranges[0].size = ggtt->mappable_end;
> +
> + primary =
> + pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
> +
> + ret = remove_conflicting_framebuffers(ap, "inteldrmfb", primary);
> +
> + kfree(ap);
> +
> + return ret;
> +}
> +#else
> +static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
> +{
> + return 0;
> +}
> +#endif
> +
> +#if !defined(CONFIG_VGA_CONSOLE)
> +static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> +{
> + return 0;
> +}
> +#elif !defined(CONFIG_DUMMY_CONSOLE)
> +static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> +{
> + return -ENODEV;
> +}
> +#else
> +static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
> +{
> + int ret = 0;
> +
> + DRM_INFO("Replacing VGA console driver\n");
> +
> + console_lock();
> + if (con_is_bound(&vga_con))
> + ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);
> + if (ret == 0) {
> + ret = do_unregister_con_driver(&vga_con);
> +
> + /* Ignore "already unregistered". */
> + if (ret == -ENODEV)
> + ret = 0;
> + }
> + console_unlock();
> +
> + return ret;
> +}
> +#endif
> +
> +static void i915_dump_device_info(struct drm_i915_private *dev_priv)
> +{
> + const struct intel_device_info *info = &dev_priv->info;
> +
> +#define PRINT_S(name) "%s"
> +#define SEP_EMPTY
> +#define PRINT_FLAG(name) info->name ? #name "," : ""
> +#define SEP_COMMA ,
> + DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags="
> + DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
> + info->gen,
> + dev_priv->dev->pdev->device,
> + dev_priv->dev->pdev->revision,
> + DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
> +#undef PRINT_S
> +#undef SEP_EMPTY
> +#undef PRINT_FLAG
> +#undef SEP_COMMA
> +}
> +
> +static void cherryview_sseu_info_init(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_device_info *info;
> + u32 fuse, eu_dis;
> +
> + info = (struct intel_device_info *)&dev_priv->info;
> + fuse = I915_READ(CHV_FUSE_GT);
> +
> + info->slice_total = 1;
> +
> + if (!(fuse & CHV_FGT_DISABLE_SS0)) {
> + info->subslice_per_slice++;
> + eu_dis = fuse & (CHV_FGT_EU_DIS_SS0_R0_MASK |
> + CHV_FGT_EU_DIS_SS0_R1_MASK);
> + info->eu_total += 8 - hweight32(eu_dis);
> + }
> +
> + if (!(fuse & CHV_FGT_DISABLE_SS1)) {
> + info->subslice_per_slice++;
> + eu_dis = fuse & (CHV_FGT_EU_DIS_SS1_R0_MASK |
> + CHV_FGT_EU_DIS_SS1_R1_MASK);
> + info->eu_total += 8 - hweight32(eu_dis);
> + }
> +
> + info->subslice_total = info->subslice_per_slice;
> + /*
> + * CHV expected to always have a uniform distribution of EU
> + * across subslices.
> + */
> + info->eu_per_subslice = info->subslice_total ?
> + info->eu_total / info->subslice_total :
> + 0;
> + /*
> + * CHV supports subslice power gating on devices with more than
> + * one subslice, and supports EU power gating on devices with
> + * more than one EU pair per subslice.
> + */
> + info->has_slice_pg = 0;
> + info->has_subslice_pg = (info->subslice_total > 1);
> + info->has_eu_pg = (info->eu_per_subslice > 2);
> +}
> +
> +static void gen9_sseu_info_init(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_device_info *info;
> + int s_max = 3, ss_max = 4, eu_max = 8;
> + int s, ss;
> + u32 fuse2, s_enable, ss_disable, eu_disable;
> + u8 eu_mask = 0xff;
> +
> + info = (struct intel_device_info *)&dev_priv->info;
> + fuse2 = I915_READ(GEN8_FUSE2);
> + s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >>
> + GEN8_F2_S_ENA_SHIFT;
> + ss_disable = (fuse2 & GEN9_F2_SS_DIS_MASK) >>
> + GEN9_F2_SS_DIS_SHIFT;
> +
> + info->slice_total = hweight32(s_enable);
> + /*
> + * The subslice disable field is global, i.e. it applies
> + * to each of the enabled slices.
> + */
> + info->subslice_per_slice = ss_max - hweight32(ss_disable);
> + info->subslice_total = info->slice_total *
> + info->subslice_per_slice;
> +
> + /*
> + * Iterate through enabled slices and subslices to
> + * count the total enabled EU.
> + */
> + for (s = 0; s < s_max; s++) {
> + if (!(s_enable & (0x1 << s)))
> + /* skip disabled slice */
> + continue;
> +
> + eu_disable = I915_READ(GEN9_EU_DISABLE(s));
> + for (ss = 0; ss < ss_max; ss++) {
> + int eu_per_ss;
> +
> + if (ss_disable & (0x1 << ss))
> + /* skip disabled subslice */
> + continue;
> +
> + eu_per_ss = eu_max - hweight8((eu_disable >> (ss*8)) &
> + eu_mask);
> +
> + /*
> + * Record which subslice(s) has(have) 7 EUs. we
> + * can tune the hash used to spread work among
> + * subslices if they are unbalanced.
> + */
> + if (eu_per_ss == 7)
> + info->subslice_7eu[s] |= 1 << ss;
> +
> + info->eu_total += eu_per_ss;
> + }
> + }
> +
> + /*
> + * SKL is expected to always have a uniform distribution
> + * of EU across subslices with the exception that any one
> + * EU in any one subslice may be fused off for die
> + * recovery. BXT is expected to be perfectly uniform in EU
> + * distribution.
> + */
> + info->eu_per_subslice = info->subslice_total ?
> + DIV_ROUND_UP(info->eu_total,
> + info->subslice_total) : 0;
> + /*
> + * SKL supports slice power gating on devices with more than
> + * one slice, and supports EU power gating on devices with
> + * more than one EU pair per subslice. BXT supports subslice
> + * power gating on devices with more than one subslice, and
> + * supports EU power gating on devices with more than one EU
> + * pair per subslice.
> + */
> + info->has_slice_pg = ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
> + (info->slice_total > 1));
> + info->has_subslice_pg = (IS_BROXTON(dev) && (info->subslice_total > 1));
> + info->has_eu_pg = (info->eu_per_subslice > 2);
> +}
> +
> +static void broadwell_sseu_info_init(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_device_info *info;
> + const int s_max = 3, ss_max = 3, eu_max = 8;
> + int s, ss;
> + u32 fuse2, eu_disable[s_max], s_enable, ss_disable;
> +
> + fuse2 = I915_READ(GEN8_FUSE2);
> + s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT;
> + ss_disable = (fuse2 & GEN8_F2_SS_DIS_MASK) >> GEN8_F2_SS_DIS_SHIFT;
> +
> + eu_disable[0] = I915_READ(GEN8_EU_DISABLE0) & GEN8_EU_DIS0_S0_MASK;
> + eu_disable[1] = (I915_READ(GEN8_EU_DISABLE0) >> GEN8_EU_DIS0_S1_SHIFT) |
> + ((I915_READ(GEN8_EU_DISABLE1) & GEN8_EU_DIS1_S1_MASK) <<
> + (32 - GEN8_EU_DIS0_S1_SHIFT));
> + eu_disable[2] = (I915_READ(GEN8_EU_DISABLE1) >> GEN8_EU_DIS1_S2_SHIFT) |
> + ((I915_READ(GEN8_EU_DISABLE2) & GEN8_EU_DIS2_S2_MASK) <<
> + (32 - GEN8_EU_DIS1_S2_SHIFT));
> +
> +
> + info = (struct intel_device_info *)&dev_priv->info;
> + info->slice_total = hweight32(s_enable);
> +
> + /*
> + * The subslice disable field is global, i.e. it applies
> + * to each of the enabled slices.
> + */
> + info->subslice_per_slice = ss_max - hweight32(ss_disable);
> + info->subslice_total = info->slice_total * info->subslice_per_slice;
> +
> + /*
> + * Iterate through enabled slices and subslices to
> + * count the total enabled EU.
> + */
> + for (s = 0; s < s_max; s++) {
> + if (!(s_enable & (0x1 << s)))
> + /* skip disabled slice */
> + continue;
> +
> + for (ss = 0; ss < ss_max; ss++) {
> + u32 n_disabled;
> +
> + if (ss_disable & (0x1 << ss))
> + /* skip disabled subslice */
> + continue;
> +
> + n_disabled = hweight8(eu_disable[s] >> (ss * eu_max));
> +
> + /*
> + * Record which subslices have 7 EUs.
> + */
> + if (eu_max - n_disabled == 7)
> + info->subslice_7eu[s] |= 1 << ss;
> +
> + info->eu_total += eu_max - n_disabled;
> + }
> + }
> +
> + /*
> + * BDW is expected to always have a uniform distribution of EU across
> + * subslices with the exception that any one EU in any one subslice may
> + * be fused off for die recovery.
> + */
> + info->eu_per_subslice = info->subslice_total ?
> + DIV_ROUND_UP(info->eu_total, info->subslice_total) : 0;
> +
> + /*
> + * BDW supports slice power gating on devices with more than
> + * one slice.
> + */
> + info->has_slice_pg = (info->slice_total > 1);
> + info->has_subslice_pg = 0;
> + info->has_eu_pg = 0;
> +}
> +
> +/*
> + * Determine various intel_device_info fields at runtime.
> + *
> + * Use it when either:
> + * - it's judged too laborious to fill n static structures with the limit
> + * when a simple if statement does the job,
> + * - run-time checks (eg read fuse/strap registers) are needed.
> + *
> + * This function needs to be called:
> + * - after the MMIO has been setup as we are reading registers,
> + * - after the PCH has been detected,
> + * - before the first usage of the fields it can tweak.
> + */
> +static void intel_device_info_runtime_init(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_device_info *info;
> + enum pipe pipe;
> +
> + info = (struct intel_device_info *)&dev_priv->info;
> +
> + /*
> + * Skylake and Broxton currently don't expose the topmost plane as its
> + * use is exclusive with the legacy cursor and we only want to expose
> + * one of those, not both. Until we can safely expose the topmost plane
> + * as a DRM_PLANE_TYPE_CURSOR with all the features exposed/supported,
> + * we don't expose the topmost plane at all to prevent ABI breakage
> + * down the line.
> + */
> + if (IS_BROXTON(dev)) {
> + info->num_sprites[PIPE_A] = 2;
> + info->num_sprites[PIPE_B] = 2;
> + info->num_sprites[PIPE_C] = 1;
> + } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
> + for_each_pipe(dev_priv, pipe)
> + info->num_sprites[pipe] = 2;
> + else
> + for_each_pipe(dev_priv, pipe)
> + info->num_sprites[pipe] = 1;
> +
> + if (i915.disable_display) {
> + DRM_INFO("Display disabled (module parameter)\n");
> + info->num_pipes = 0;
> + } else if (info->num_pipes > 0 &&
> + (IS_GEN7(dev_priv) || IS_GEN8(dev_priv)) &&
> + HAS_PCH_SPLIT(dev)) {
> + u32 fuse_strap = I915_READ(FUSE_STRAP);
> + u32 sfuse_strap = I915_READ(SFUSE_STRAP);
> +
> + /*
> + * SFUSE_STRAP is supposed to have a bit signalling the display
> + * is fused off. Unfortunately it seems that, at least in
> + * certain cases, fused off display means that PCH display
> + * reads don't land anywhere. In that case, we read 0s.
> + *
> + * On CPT/PPT, we can detect this case as SFUSE_STRAP_FUSE_LOCK
> + * should be set when taking over after the firmware.
> + */
> + if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE ||
> + sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED ||
> + (dev_priv->pch_type == PCH_CPT &&
> + !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) {
> + DRM_INFO("Display fused off, disabling\n");
> + info->num_pipes = 0;
> + } else if (fuse_strap & IVB_PIPE_C_DISABLE) {
> + DRM_INFO("PipeC fused off\n");
> + info->num_pipes -= 1;
> + }
> + } else if (info->num_pipes > 0 && IS_GEN9(dev_priv)) {
> + u32 dfsm = I915_READ(SKL_DFSM);
> + u8 disabled_mask = 0;
> + bool invalid;
> + int num_bits;
> +
> + if (dfsm & SKL_DFSM_PIPE_A_DISABLE)
> + disabled_mask |= BIT(PIPE_A);
> + if (dfsm & SKL_DFSM_PIPE_B_DISABLE)
> + disabled_mask |= BIT(PIPE_B);
> + if (dfsm & SKL_DFSM_PIPE_C_DISABLE)
> + disabled_mask |= BIT(PIPE_C);
> +
> + num_bits = hweight8(disabled_mask);
> +
> + switch (disabled_mask) {
> + case BIT(PIPE_A):
> + case BIT(PIPE_B):
> + case BIT(PIPE_A) | BIT(PIPE_B):
> + case BIT(PIPE_A) | BIT(PIPE_C):
> + invalid = true;
> + break;
> + default:
> + invalid = false;
> + }
> +
> + if (num_bits > info->num_pipes || invalid)
> + DRM_ERROR("invalid pipe fuse configuration: 0x%x\n",
> + disabled_mask);
> + else
> + info->num_pipes -= num_bits;
> + }
> +
> + /* Initialize slice/subslice/EU info */
> + if (IS_CHERRYVIEW(dev))
> + cherryview_sseu_info_init(dev);
> + else if (IS_BROADWELL(dev))
> + broadwell_sseu_info_init(dev);
> + else if (INTEL_INFO(dev)->gen >= 9)
> + gen9_sseu_info_init(dev);
> +
> + info->has_snoop = !info->has_llc;
> +
> + /* Snooping is broken on BXT A stepping. */
> + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1))
> + info->has_snoop = false;
> +
> + DRM_DEBUG_DRIVER("slice total: %u\n", info->slice_total);
> + DRM_DEBUG_DRIVER("subslice total: %u\n", info->subslice_total);
> + DRM_DEBUG_DRIVER("subslice per slice: %u\n", info->subslice_per_slice);
> + DRM_DEBUG_DRIVER("EU total: %u\n", info->eu_total);
> + DRM_DEBUG_DRIVER("EU per subslice: %u\n", info->eu_per_subslice);
> + DRM_DEBUG_DRIVER("has slice power gating: %s\n",
> + info->has_slice_pg ? "y" : "n");
> + DRM_DEBUG_DRIVER("has subslice power gating: %s\n",
> + info->has_subslice_pg ? "y" : "n");
> + DRM_DEBUG_DRIVER("has EU power gating: %s\n",
> + info->has_eu_pg ? "y" : "n");
> +
> + i915.enable_execlists =
> + intel_sanitize_enable_execlists(dev_priv,
> + i915.enable_execlists);
> +
> + /*
> + * i915.enable_ppgtt is read-only, so do an early pass to validate the
> + * user's requested state against the hardware/driver capabilities. We
> + * do this now so that we can print out any log messages once rather
> + * than every time we check intel_enable_ppgtt().
> + */
> + i915.enable_ppgtt =
> + intel_sanitize_enable_ppgtt(dev_priv, i915.enable_ppgtt);
> + DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915.enable_ppgtt);
> +}
> +
> +static void intel_init_dpio(struct drm_i915_private *dev_priv)
> +{
> + /*
> + * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
> + * CHV x1 PHY (DP/HDMI D)
> + * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C)
> + */
> + if (IS_CHERRYVIEW(dev_priv)) {
> + DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
> + DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
> + } else if (IS_VALLEYVIEW(dev_priv)) {
> + DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
> + }
> +}
> +
> +static int i915_workqueues_init(struct drm_i915_private *dev_priv)
> +{
> + /*
> + * The i915 workqueue is primarily used for batched retirement of
> + * requests (and thus managing bo) once the task has been completed
> + * by the GPU. i915_gem_retire_requests() is called directly when we
> + * need high-priority retirement, such as waiting for an explicit
> + * bo.
> + *
> + * It is also used for periodic low-priority events, such as
> + * idle-timers and recording error state.
> + *
> + * All tasks on the workqueue are expected to acquire the dev mutex
> + * so there is no point in running more than one instance of the
> + * workqueue at any time. Use an ordered one.
> + */
> + dev_priv->wq = alloc_ordered_workqueue("i915", 0);
> + if (dev_priv->wq == NULL)
> + goto out_err;
> +
> + dev_priv->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0);
> + if (dev_priv->hotplug.dp_wq == NULL)
> + goto out_free_wq;
> +
> + dev_priv->gpu_error.hangcheck_wq =
> + alloc_ordered_workqueue("i915-hangcheck", 0);
> + if (dev_priv->gpu_error.hangcheck_wq == NULL)
> + goto out_free_dp_wq;
> +
> + return 0;
> +
> +out_free_dp_wq:
> + destroy_workqueue(dev_priv->hotplug.dp_wq);
> +out_free_wq:
> + destroy_workqueue(dev_priv->wq);
> +out_err:
> + DRM_ERROR("Failed to allocate workqueues.\n");
> +
> + return -ENOMEM;
> +}
> +
> +static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
> +{
> + destroy_workqueue(dev_priv->gpu_error.hangcheck_wq);
> + destroy_workqueue(dev_priv->hotplug.dp_wq);
> + destroy_workqueue(dev_priv->wq);
> +}
> +
> +/**
> + * i915_driver_init_early - setup state not requiring device access
> + * @dev_priv: device private
> + *
> + * Initialize everything that is a "SW-only" state, that is state not
> + * requiring accessing the device or exposing the driver via kernel internal
> + * or userspace interfaces. Example steps belonging here: lock initialization,
> + * system memory allocation, setting up device specific attributes and
> + * function hooks not requiring accessing the device.
> + */
> +static int i915_driver_init_early(struct drm_i915_private *dev_priv,
> + const struct pci_device_id *ent)
> +{
> + const struct intel_device_info *match_info =
> + (struct intel_device_info *)ent->driver_data;
> + struct intel_device_info *device_info;
> + int ret = 0;
> +
> + if (i915_inject_load_failure())
> + return -ENODEV;
> +
> + /* Setup the write-once "constant" device info */
> + device_info = (struct intel_device_info *)&dev_priv->info;
> + memcpy(device_info, match_info, sizeof(*device_info));
> + device_info->device_id = dev_priv->drm.pdev->device;
> +
> + BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE);
> + device_info->gen_mask = BIT(device_info->gen - 1);
> +
> + spin_lock_init(&dev_priv->irq_lock);
> + spin_lock_init(&dev_priv->gpu_error.lock);
> + mutex_init(&dev_priv->backlight_lock);
> + spin_lock_init(&dev_priv->uncore.lock);
> + spin_lock_init(&dev_priv->mm.object_stat_lock);
> + spin_lock_init(&dev_priv->mmio_flip_lock);
> + mutex_init(&dev_priv->sb_lock);
> + mutex_init(&dev_priv->modeset_restore_lock);
> + mutex_init(&dev_priv->av_mutex);
> + mutex_init(&dev_priv->wm.wm_mutex);
> + mutex_init(&dev_priv->pps_mutex);
> +
> + ret = i915_workqueues_init(dev_priv);
> + if (ret < 0)
> + return ret;
> +
> + /* This must be called before any calls to HAS_PCH_* */
> + intel_detect_pch(&dev_priv->drm);
> +
> + intel_pm_setup(&dev_priv->drm);
> + intel_init_dpio(dev_priv);
> + intel_power_domains_init(dev_priv);
> + intel_irq_init(dev_priv);
> + intel_init_display_hooks(dev_priv);
> + intel_init_clock_gating_hooks(dev_priv);
> + intel_init_audio_hooks(dev_priv);
> + i915_gem_load_init(&dev_priv->drm);
> +
> + intel_display_crc_init(&dev_priv->drm);
> +
> + i915_dump_device_info(dev_priv);
> +
> + /* Not all pre-production machines fall into this category, only the
> + * very first ones. Almost everything should work, except for maybe
> + * suspend/resume. And we don't implement workarounds that affect only
> + * pre-production machines. */
> + if (IS_HSW_EARLY_SDV(dev_priv))
> + DRM_INFO("This is an early pre-production Haswell machine. "
> + "It may not be fully functional.\n");
> +
> + return 0;
> +}
> +
> +/**
> + * i915_driver_cleanup_early - cleanup the setup done in i915_driver_init_early()
> + * @dev_priv: device private
> + */
> +static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
> +{
> + i915_gem_load_cleanup(dev_priv->dev);
> + i915_workqueues_cleanup(dev_priv);
> +}
> +
> +static int i915_mmio_setup(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = to_i915(dev);
> + int mmio_bar;
> + int mmio_size;
> +
> + mmio_bar = IS_GEN2(dev) ? 1 : 0;
> + /*
> + * Before gen4, the registers and the GTT are behind different BARs.
> + * However, from gen4 onwards, the registers and the GTT are shared
> + * in the same BAR, so we want to restrict this ioremap from
> + * clobbering the GTT which we want ioremap_wc instead. Fortunately,
> + * the register BAR remains the same size for all the earlier
> + * generations up to Ironlake.
> + */
> + if (INTEL_INFO(dev)->gen < 5)
> + mmio_size = 512 * 1024;
> + else
> + mmio_size = 2 * 1024 * 1024;
> + dev_priv->regs = pci_iomap(dev->pdev, mmio_bar, mmio_size);
> + if (dev_priv->regs == NULL) {
> + DRM_ERROR("failed to map registers\n");
> +
> + return -EIO;
> + }
> +
> + /* Try to make sure MCHBAR is enabled before poking at it */
> + intel_setup_mchbar(dev);
> +
> + return 0;
> +}
> +
> +static void i915_mmio_cleanup(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = to_i915(dev);
> +
> + intel_teardown_mchbar(dev);
> + pci_iounmap(dev->pdev, dev_priv->regs);
> +}
> +
> +/**
> + * i915_driver_init_mmio - setup device MMIO
> + * @dev_priv: device private
> + *
> + * Setup minimal device state necessary for MMIO accesses later in the
> + * initialization sequence. The setup here should avoid any other device-wide
> + * side effects or exposing the driver via kernel internal or user space
> + * interfaces.
> + */
> +static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
> +{
> + struct drm_device *dev = dev_priv->dev;
> + int ret;
> +
> + if (i915_inject_load_failure())
> + return -ENODEV;
> +
> + if (i915_get_bridge_dev(dev))
> + return -EIO;
> +
> + ret = i915_mmio_setup(dev);
> + if (ret < 0)
> + goto put_bridge;
> +
> + intel_uncore_init(dev_priv);
> +
> + return 0;
> +
> +put_bridge:
> + pci_dev_put(dev_priv->bridge_dev);
> +
> + return ret;
> +}
> +
> +/**
> + * i915_driver_cleanup_mmio - cleanup the setup done in i915_driver_init_mmio()
> + * @dev_priv: device private
> + */
> +static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv)
> +{
> + struct drm_device *dev = dev_priv->dev;
> +
> + intel_uncore_fini(dev_priv);
> + i915_mmio_cleanup(dev);
> + pci_dev_put(dev_priv->bridge_dev);
> +}
> +
> +/**
> + * i915_driver_init_hw - setup state requiring device access
> + * @dev_priv: device private
> + *
> + * Setup state that requires accessing the device, but doesn't require
> + * exposing the driver via kernel internal or userspace interfaces.
> + */
> +static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
> +{
> + struct drm_device *dev = dev_priv->dev;
> + struct i915_ggtt *ggtt = &dev_priv->ggtt;
> + uint32_t aperture_size;
> + int ret;
> +
> + if (i915_inject_load_failure())
> + return -ENODEV;
> +
> + intel_device_info_runtime_init(dev);
> +
> + ret = i915_ggtt_init_hw(dev);
> + if (ret)
> + return ret;
> +
> + ret = i915_ggtt_enable_hw(dev);
> + if (ret) {
> + DRM_ERROR("failed to enable GGTT\n");
> + goto out_ggtt;
> + }
> +
> + /* WARNING: Apparently we must kick fbdev drivers before vgacon,
> + * otherwise the vga fbdev driver falls over. */
> + ret = i915_kick_out_firmware_fb(dev_priv);
> + if (ret) {
> + DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
> + goto out_ggtt;
> + }
> +
> + ret = i915_kick_out_vgacon(dev_priv);
> + if (ret) {
> + DRM_ERROR("failed to remove conflicting VGA console\n");
> + goto out_ggtt;
> + }
> +
> + pci_set_master(dev->pdev);
> +
> + /* overlay on gen2 is broken and can't address above 1G */
> + if (IS_GEN2(dev)) {
> + ret = dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30));
> + if (ret) {
> + DRM_ERROR("failed to set DMA mask\n");
> +
> + goto out_ggtt;
> + }
> + }
> +
> +
> + /* 965GM sometimes incorrectly writes to hardware status page (HWS)
> + * using 32bit addressing, overwriting memory if HWS is located
> + * above 4GB.
> + *
> + * The documentation also mentions an issue with undefined
> + * behaviour if any general state is accessed within a page above 4GB,
> + * which also needs to be handled carefully.
> + */
> + if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) {
> + ret = dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32));
> +
> + if (ret) {
> + DRM_ERROR("failed to set DMA mask\n");
> +
> + goto out_ggtt;
> + }
> + }
> +
> + aperture_size = ggtt->mappable_end;
> +
> + ggtt->mappable =
> + io_mapping_create_wc(ggtt->mappable_base,
> + aperture_size);
> + if (!ggtt->mappable) {
> + ret = -EIO;
> + goto out_ggtt;
> + }
> +
> + ggtt->mtrr = arch_phys_wc_add(ggtt->mappable_base,
> + aperture_size);
> +
> + pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY,
> + PM_QOS_DEFAULT_VALUE);
> +
> + intel_uncore_sanitize(dev_priv);
> +
> + intel_opregion_setup(dev_priv);
> +
> + i915_gem_load_init_fences(dev_priv);
> +
> + /* On the 945G/GM, the chipset reports the MSI capability on the
> + * integrated graphics even though the support isn't actually there
> + * according to the published specs. It doesn't appear to function
> + * correctly in testing on 945G.
> + * This may be a side effect of MSI having been made available for PEG
> + * and the registers being closely associated.
> + *
> + * According to chipset errata, on the 965GM, MSI interrupts may
> + * be lost or delayed, but we use them anyways to avoid
> + * stuck interrupts on some machines.
> + */
> + if (!IS_I945G(dev) && !IS_I945GM(dev)) {
> + if (pci_enable_msi(dev->pdev) < 0)
> + DRM_DEBUG_DRIVER("can't enable MSI");
> + }
> +
> + return 0;
> +
> +out_ggtt:
> + i915_ggtt_cleanup_hw(dev);
> +
> + return ret;
> +}
> +
> +/**
> + * i915_driver_cleanup_hw - cleanup the setup done in i915_driver_init_hw()
> + * @dev_priv: device private
> + */
> +static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv)
> +{
> + struct drm_device *dev = dev_priv->dev;
> + struct i915_ggtt *ggtt = &dev_priv->ggtt;
> +
> + if (dev->pdev->msi_enabled)
> + pci_disable_msi(dev->pdev);
> +
> + pm_qos_remove_request(&dev_priv->pm_qos);
> + arch_phys_wc_del(ggtt->mtrr);
> + io_mapping_free(ggtt->mappable);
> + i915_ggtt_cleanup_hw(dev);
> +}
> +
> +/**
> + * i915_driver_register - register the driver with the rest of the system
> + * @dev_priv: device private
> + *
> + * Perform any steps necessary to make the driver available via kernel
> + * internal or userspace interfaces.
> + */
> +static void i915_driver_register(struct drm_i915_private *dev_priv)
> +{
> + struct drm_device *dev = dev_priv->dev;
> +
> + i915_gem_shrinker_init(dev_priv);
>
> -static const struct intel_device_info intel_broxton_info = {
> - .is_preliminary = 1,
> - .is_broxton = 1,
> - .gen = 9,
> - .need_gfx_hws = 1, .has_hotplug = 1,
> - .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
> - .num_pipes = 3,
> - .has_ddi = 1,
> - .has_fpga_dbg = 1,
> - .has_fbc = 1,
> - GEN_DEFAULT_PIPEOFFSETS,
> - IVB_CURSOR_OFFSETS,
> - BDW_COLORS,
> -};
> + /*
> + * Notify a valid surface after modesetting,
> + * when running inside a VM.
> + */
> + if (intel_vgpu_active(dev_priv))
> + I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY);
> +
> + /* Reveal our presence to userspace */
> + if (drm_dev_register(dev, 0) == 0) {
> + i915_debugfs_register(dev_priv);
> + i915_setup_sysfs(dev);
> + intel_modeset_register(dev_priv);
> + } else
> + DRM_ERROR("Failed to register driver for userspace access!\n");
> +
> + if (INTEL_INFO(dev_priv)->num_pipes) {
> + /* Must be done after probing outputs */
> + intel_opregion_register(dev_priv);
> + acpi_video_register();
> + }
>
> -static const struct intel_device_info intel_kabylake_info = {
> - BDW_FEATURES,
> - .is_kabylake = 1,
> - .gen = 9,
> -};
> + if (IS_GEN5(dev_priv))
> + intel_gpu_ips_init(dev_priv);
>
> -static const struct intel_device_info intel_kabylake_gt3_info = {
> - BDW_FEATURES,
> - .is_kabylake = 1,
> - .gen = 9,
> - .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
> -};
> + i915_audio_component_init(dev_priv);
>
> -/*
> - * Make sure any device matches here are from most specific to most
> - * general. For example, since the Quanta match is based on the subsystem
> - * and subvendor IDs, we need it to come before the more general IVB
> - * PCI ID matches, otherwise we'll use the wrong info struct above.
> + /*
> + * Some ports require correctly set-up hpd registers for detection to
> + * work properly (leading to ghost connected connector status), e.g. VGA
> + * on gm45. Hence we can only set up the initial fbdev config after hpd
> + * irqs are fully enabled. Now we should scan for the initial config
> + * only once hotplug handling is enabled, but due to screwed-up locking
> + * around kms/fbdev init we can't protect the fdbev initial config
> + * scanning against hotplug events. Hence do this first and ignore the
> + * tiny window where we will loose hotplug notifactions.
> + */
> + intel_fbdev_initial_config_async(dev);
> +}
> +
> +/**
> + * i915_driver_unregister - cleanup the registration done in i915_driver_regiser()
> + * @dev_priv: device private
> */
> -static const struct pci_device_id pciidlist[] = {
> - INTEL_I830_IDS(&intel_i830_info),
> - INTEL_I845G_IDS(&intel_845g_info),
> - INTEL_I85X_IDS(&intel_i85x_info),
> - INTEL_I865G_IDS(&intel_i865g_info),
> - INTEL_I915G_IDS(&intel_i915g_info),
> - INTEL_I915GM_IDS(&intel_i915gm_info),
> - INTEL_I945G_IDS(&intel_i945g_info),
> - INTEL_I945GM_IDS(&intel_i945gm_info),
> - INTEL_I965G_IDS(&intel_i965g_info),
> - INTEL_G33_IDS(&intel_g33_info),
> - INTEL_I965GM_IDS(&intel_i965gm_info),
> - INTEL_GM45_IDS(&intel_gm45_info),
> - INTEL_G45_IDS(&intel_g45_info),
> - INTEL_PINEVIEW_IDS(&intel_pineview_info),
> - INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info),
> - INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info),
> - INTEL_SNB_D_IDS(&intel_sandybridge_d_info),
> - INTEL_SNB_M_IDS(&intel_sandybridge_m_info),
> - INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */
> - INTEL_IVB_M_IDS(&intel_ivybridge_m_info),
> - INTEL_IVB_D_IDS(&intel_ivybridge_d_info),
> - INTEL_HSW_D_IDS(&intel_haswell_d_info),
> - INTEL_HSW_M_IDS(&intel_haswell_m_info),
> - INTEL_VLV_M_IDS(&intel_valleyview_m_info),
> - INTEL_VLV_D_IDS(&intel_valleyview_d_info),
> - INTEL_BDW_GT12M_IDS(&intel_broadwell_m_info),
> - INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info),
> - INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info),
> - INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info),
> - INTEL_CHV_IDS(&intel_cherryview_info),
> - INTEL_SKL_GT1_IDS(&intel_skylake_info),
> - INTEL_SKL_GT2_IDS(&intel_skylake_info),
> - INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info),
> - INTEL_SKL_GT4_IDS(&intel_skylake_gt3_info),
> - INTEL_BXT_IDS(&intel_broxton_info),
> - INTEL_KBL_GT1_IDS(&intel_kabylake_info),
> - INTEL_KBL_GT2_IDS(&intel_kabylake_info),
> - INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info),
> - INTEL_KBL_GT4_IDS(&intel_kabylake_gt3_info),
> - {0, 0, 0}
> -};
> +static void i915_driver_unregister(struct drm_i915_private *dev_priv)
> +{
> + i915_audio_component_cleanup(dev_priv);
>
> -MODULE_DEVICE_TABLE(pci, pciidlist);
> + intel_gpu_ips_teardown();
> + acpi_video_unregister();
> + intel_opregion_unregister(dev_priv);
>
> -static enum intel_pch intel_virt_detect_pch(struct drm_device *dev)
> + intel_modeset_unregister(dev_priv);
> + i915_teardown_sysfs(dev_priv->dev);
> + i915_debugfs_unregister(dev_priv);
> + drm_dev_unregister(dev_priv->dev);
> +
> + i915_gem_shrinker_cleanup(dev_priv);
> +}
> +
> +/**
> + * i915_driver_load - setup chip and create an initial config
> + * @dev: DRM device
> + * @flags: startup flags
> + *
> + * The driver load routine has to do several things:
> + * - drive output discovery via intel_modeset_init()
> + * - initialize the memory manager
> + * - allocate initial config memory
> + * - setup the DRM framebuffer with the allocated memory
> + */
> +static int i915_driver_load(struct pci_dev *pdev,
> + const struct pci_device_id *ent)
> {
> - enum intel_pch ret = PCH_NOP;
> + struct drm_i915_private *dev_priv;
> + int ret;
> +
> + dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
> + if (dev_priv == NULL)
> + return -ENOMEM;
> +
> + ret = drm_dev_init(&dev_priv->drm, &driver, &pdev->dev);
> + if (ret)
> + goto out_free_priv;
> +
> + /* Must be set before calling __i915_printk */
> + dev_priv->drm.pdev = pdev;
> + dev_priv->drm.dev_private = dev_priv;
> + dev_priv->dev = &dev_priv->drm;
> +
> + ret = i915_driver_init_early(dev_priv, ent);
> + if (ret < 0)
> + goto out_free_priv;
> +
> + ret = pci_enable_device(pdev);
> + if (ret)
> + goto out_cleanup_early;
> +
> + pci_set_drvdata(pdev, &dev_priv->drm);
> +
> + intel_runtime_pm_get(dev_priv);
> +
> + ret = i915_driver_init_mmio(dev_priv);
> + if (ret < 0)
> + goto out_runtime_pm_put;
> +
> + ret = i915_driver_init_hw(dev_priv);
> + if (ret < 0)
> + goto out_cleanup_mmio;
>
> /*
> - * In a virtualized passthrough environment we can be in a
> - * setup where the ISA bridge is not able to be passed through.
> - * In this case, a south bridge can be emulated and we have to
> - * make an educated guess as to which PCH is really there.
> + * TODO: move the vblank init and parts of modeset init steps into one
> + * of the i915_driver_init_/i915_driver_register functions according
> + * to the role/effect of the given init step.
> */
> -
> - if (IS_GEN5(dev)) {
> - ret = PCH_IBX;
> - DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n");
> - } else if (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) {
> - ret = PCH_CPT;
> - DRM_DEBUG_KMS("Assuming CouarPoint PCH\n");
> - } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> - ret = PCH_LPT;
> - DRM_DEBUG_KMS("Assuming LynxPoint PCH\n");
> - } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
> - ret = PCH_SPT;
> - DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n");
> + if (INTEL_INFO(dev_priv)->num_pipes) {
> + ret = drm_vblank_init(dev_priv->dev,
> + INTEL_INFO(dev_priv)->num_pipes);
> + if (ret)
> + goto out_cleanup_hw;
> }
>
> + ret = i915_load_modeset_init(dev_priv->dev);
> + if (ret < 0)
> + goto out_cleanup_vblank;
> +
> + i915_driver_register(dev_priv);
> +
> + intel_runtime_pm_enable(dev_priv);
> +
> + intel_runtime_pm_put(dev_priv);
> +
> + return 0;
> +
> +out_cleanup_vblank:
> + drm_vblank_cleanup(dev_priv->dev);
> +out_cleanup_hw:
> + i915_driver_cleanup_hw(dev_priv);
> +out_cleanup_mmio:
> + i915_driver_cleanup_mmio(dev_priv);
> +out_runtime_pm_put:
> + intel_runtime_pm_put(dev_priv);
> + pci_disable_device(pdev);
> +out_cleanup_early:
> + i915_driver_cleanup_early(dev_priv);
> +out_free_priv:
> + i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret);
> +
> + kfree(dev_priv);
> +
> return ret;
> }
>
> -void intel_detect_pch(struct drm_device *dev)
> +static int i915_driver_unload(struct drm_device *dev)
> {
> struct drm_i915_private *dev_priv = dev->dev_private;
> - struct pci_dev *pch = NULL;
> + int ret;
>
> - /* In all current cases, num_pipes is equivalent to the PCH_NOP setting
> - * (which really amounts to a PCH but no South Display).
> - */
> - if (INTEL_INFO(dev)->num_pipes == 0) {
> - dev_priv->pch_type = PCH_NOP;
> - return;
> + intel_fbdev_fini(dev);
> +
> + ret = i915_gem_suspend(dev);
> + if (ret) {
> + DRM_ERROR("failed to idle hardware: %d\n", ret);
> + return ret;
> }
>
> + intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +
> + i915_driver_unregister(dev_priv);
> +
> + drm_vblank_cleanup(dev);
> +
> + intel_modeset_cleanup(dev);
> +
> /*
> - * The reason to probe ISA bridge instead of Dev31:Fun0 is to
> - * make graphics device passthrough work easy for VMM, that only
> - * need to expose ISA bridge to let driver know the real hardware
> - * underneath. This is a requirement from virtualization team.
> - *
> - * In some virtualized environments (e.g. XEN), there is irrelevant
> - * ISA bridge in the system. To work reliably, we should scan trhough
> - * all the ISA bridge devices and check for the first match, instead
> - * of only checking the first one.
> + * free the memory space allocated for the child device
> + * config parsed from VBT
> */
> - while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) {
> - if (pch->vendor == PCI_VENDOR_ID_INTEL) {
> - unsigned short id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
> - dev_priv->pch_id = id;
> + if (dev_priv->vbt.child_dev && dev_priv->vbt.child_dev_num) {
> + kfree(dev_priv->vbt.child_dev);
> + dev_priv->vbt.child_dev = NULL;
> + dev_priv->vbt.child_dev_num = 0;
> + }
> + kfree(dev_priv->vbt.sdvo_lvds_vbt_mode);
> + dev_priv->vbt.sdvo_lvds_vbt_mode = NULL;
> + kfree(dev_priv->vbt.lfp_lvds_vbt_mode);
> + dev_priv->vbt.lfp_lvds_vbt_mode = NULL;
>
> - if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
> - dev_priv->pch_type = PCH_IBX;
> - DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
> - WARN_ON(!IS_GEN5(dev));
> - } else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
> - dev_priv->pch_type = PCH_CPT;
> - DRM_DEBUG_KMS("Found CougarPoint PCH\n");
> - WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
> - } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
> - /* PantherPoint is CPT compatible */
> - dev_priv->pch_type = PCH_CPT;
> - DRM_DEBUG_KMS("Found PantherPoint PCH\n");
> - WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
> - } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
> - dev_priv->pch_type = PCH_LPT;
> - DRM_DEBUG_KMS("Found LynxPoint PCH\n");
> - WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev));
> - WARN_ON(IS_HSW_ULT(dev) || IS_BDW_ULT(dev));
> - } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
> - dev_priv->pch_type = PCH_LPT;
> - DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
> - WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev));
> - WARN_ON(!IS_HSW_ULT(dev) && !IS_BDW_ULT(dev));
> - } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) {
> - dev_priv->pch_type = PCH_SPT;
> - DRM_DEBUG_KMS("Found SunrisePoint PCH\n");
> - WARN_ON(!IS_SKYLAKE(dev) &&
> - !IS_KABYLAKE(dev));
> - } else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) {
> - dev_priv->pch_type = PCH_SPT;
> - DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
> - WARN_ON(!IS_SKYLAKE(dev) &&
> - !IS_KABYLAKE(dev));
> - } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) ||
> - (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) ||
> - ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) &&
> - pch->subsystem_vendor == 0x1af4 &&
> - pch->subsystem_device == 0x1100)) {
> - dev_priv->pch_type = intel_virt_detect_pch(dev);
> - } else
> - continue;
> + vga_switcheroo_unregister_client(dev->pdev);
> + vga_client_register(dev->pdev, NULL, NULL, NULL);
>
> - break;
> - }
> - }
> - if (!pch)
> - DRM_DEBUG_KMS("No PCH found.\n");
> + intel_csr_ucode_fini(dev_priv);
>
> - pci_dev_put(pch);
> + /* Free error state after interrupts are fully disabled. */
> + cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
> + i915_destroy_error_state(dev);
> +
> + /* Flush any outstanding unpin_work. */
> + flush_workqueue(dev_priv->wq);
> +
> + intel_guc_fini(dev);
> + i915_gem_fini(dev);
> + intel_fbc_cleanup_cfb(dev_priv);
> +
> + intel_power_domains_fini(dev_priv);
> +
> + i915_driver_cleanup_hw(dev_priv);
> + i915_driver_cleanup_mmio(dev_priv);
> +
> + intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +
> + i915_driver_cleanup_early(dev_priv);
> +
> + return 0;
> }
>
> -bool i915_semaphore_is_enabled(struct drm_i915_private *dev_priv)
> +static int i915_driver_open(struct drm_device *dev, struct drm_file *file)
> {
> - if (INTEL_GEN(dev_priv) < 6)
> - return false;
> + int ret;
>
> - if (i915.semaphores >= 0)
> - return i915.semaphores;
> + ret = i915_gem_open(dev, file);
> + if (ret)
> + return ret;
>
> - /* TODO: make semaphores and Execlists play nicely together */
> - if (i915.enable_execlists)
> - return false;
> + return 0;
> +}
>
> -#ifdef CONFIG_INTEL_IOMMU
> - /* Enable semaphores on SNB when IO remapping is off */
> - if (IS_GEN6(dev_priv) && intel_iommu_gfx_mapped)
> - return false;
> -#endif
> +/**
> + * i915_driver_lastclose - clean up after all DRM clients have exited
> + * @dev: DRM device
> + *
> + * Take care of cleaning up after all DRM clients have exited. In the
> + * mode setting case, we want to restore the kernel's initial mode (just
> + * in case the last client left us in a bad state).
> + *
> + * Additionally, in the non-mode setting case, we'll tear down the GTT
> + * and DMA structures, since the kernel won't be using them, and clea
> + * up any GEM state.
> + */
> +static void i915_driver_lastclose(struct drm_device *dev)
> +{
> + intel_fbdev_restore_mode(dev);
> + vga_switcheroo_process_delayed_switch();
> +}
>
> - return true;
> +static void i915_driver_preclose(struct drm_device *dev, struct drm_file *file)
> +{
> + mutex_lock(&dev->struct_mutex);
> + i915_gem_context_close(dev, file);
> + i915_gem_release(dev, file);
> + mutex_unlock(&dev->struct_mutex);
> +}
> +
> +static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
> +{
> + struct drm_i915_file_private *file_priv = file->driver_priv;
> +
> + kfree(file_priv);
> }
>
> static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
> @@ -1039,7 +2612,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> !vga_switcheroo_handler_flags())
> return -EPROBE_DEFER;
>
> - return i915_driver_load(pdev, ent, &driver);
> + return i915_driver_load(pdev, ent);
> }
>
> static void
> @@ -1747,6 +3320,68 @@ static const struct file_operations i915_driver_fops = {
> .llseek = noop_llseek,
> };
>
> +static int
> +i915_gem_reject_pin_ioctl(struct drm_device *dev, void *data,
> + struct drm_file *file)
> +{
> + return -ENODEV;
> +}
> +
> +static const struct drm_ioctl_desc i915_ioctls[] = {
> + DRM_IOCTL_DEF_DRV(I915_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> + DRM_IOCTL_DEF_DRV(I915_FLUSH, drm_noop, DRM_AUTH),
> + DRM_IOCTL_DEF_DRV(I915_FLIP, drm_noop, DRM_AUTH),
> + DRM_IOCTL_DEF_DRV(I915_BATCHBUFFER, drm_noop, DRM_AUTH),
> + DRM_IOCTL_DEF_DRV(I915_IRQ_EMIT, drm_noop, DRM_AUTH),
> + DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, drm_noop, DRM_AUTH),
> + DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH|DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_SETPARAM, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> + DRM_IOCTL_DEF_DRV(I915_ALLOC, drm_noop, DRM_AUTH),
> + DRM_IOCTL_DEF_DRV(I915_FREE, drm_noop, DRM_AUTH),
> + DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> + DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, drm_noop, DRM_AUTH),
> + DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> + DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> + DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE, drm_noop, DRM_AUTH),
> + DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, drm_noop, DRM_AUTH),
> + DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> + DRM_IOCTL_DEF_DRV(I915_GEM_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> + DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
> + DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
> + DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
> + DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_SET_CACHING, i915_gem_set_caching_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_GET_CACHING, i915_gem_get_caching_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_ENTERVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> + DRM_IOCTL_DEF_DRV(I915_GEM_LEAVEVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
> + DRM_IOCTL_DEF_DRV(I915_GEM_CREATE, i915_gem_create_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
> + DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_gem_context_reset_stats_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_RENDER_ALLOW),
> +};
> +
> static struct drm_driver driver = {
> /* Don't use MTRRs here; the Xserver or userspace app should
> * deal with them for Intel hardware.
> @@ -1772,6 +3407,7 @@ static struct drm_driver driver = {
> .dumb_map_offset = i915_gem_mmap_gtt,
> .dumb_destroy = drm_gem_dumb_destroy,
> .ioctls = i915_ioctls,
> + .num_ioctls = ARRAY_SIZE(i915_ioctls),
> .fops = &i915_driver_fops,
> .name = DRIVER_NAME,
> .desc = DRIVER_DESC,
> @@ -1791,8 +3427,6 @@ static struct pci_driver i915_pci_driver = {
>
> static int __init i915_init(void)
> {
> - driver.num_ioctls = i915_max_ioctl;
> -
> /*
> * Enable KMS by default, unless explicitly overriden by
> * either the i915.modeset prarameter or by the
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index b95a10fa002a..1df141e4ab6b 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2857,16 +2857,13 @@ struct drm_i915_cmd_table {
>
> #include "i915_trace.h"
>
> -extern const struct drm_ioctl_desc i915_ioctls[];
> -extern int i915_max_ioctl;
> -
> extern int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state);
> extern int i915_resume_switcheroo(struct drm_device *dev);
>
> int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
> int enable_ppgtt);
>
> -/* i915_dma.c */
> +/* i915_drv.c */
> void __printf(3, 4)
> __i915_printk(struct drm_i915_private *dev_priv, const char *level,
> const char *fmt, ...);
> @@ -2874,16 +2871,6 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level,
> #define i915_report_error(dev_priv, fmt, ...) \
> __i915_printk(dev_priv, KERN_ERR, fmt, ##__VA_ARGS__)
>
> -extern int i915_driver_load(struct pci_dev *pdev,
> - const struct pci_device_id *ent,
> - struct drm_driver *driver);
> -extern int i915_driver_unload(struct drm_device *);
> -extern int i915_driver_open(struct drm_device *dev, struct drm_file *file);
> -extern void i915_driver_lastclose(struct drm_device * dev);
> -extern void i915_driver_preclose(struct drm_device *dev,
> - struct drm_file *file);
> -extern void i915_driver_postclose(struct drm_device *dev,
> - struct drm_file *file);
> #ifdef CONFIG_COMPAT
> extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
> unsigned long arg);
> @@ -3689,7 +3676,6 @@ extern void intel_init_pch_refclk(struct drm_device *dev);
> extern void intel_set_rps(struct drm_i915_private *dev_priv, u8 val);
> extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
> bool enable);
> -extern void intel_detect_pch(struct drm_device *dev);
>
> extern bool i915_semaphore_is_enabled(struct drm_i915_private *dev_priv);
> int i915_reg_read_ioctl(struct drm_device *dev, void *data,
--
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
More information about the Intel-gfx
mailing list