162306a36Sopenharmony_ci/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
262306a36Sopenharmony_ci */
362306a36Sopenharmony_ci/*
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
662306a36Sopenharmony_ci * All Rights Reserved.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
962306a36Sopenharmony_ci * copy of this software and associated documentation files (the
1062306a36Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
1162306a36Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
1262306a36Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
1362306a36Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
1462306a36Sopenharmony_ci * the following conditions:
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci * The above copyright notice and this permission notice (including the
1762306a36Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
1862306a36Sopenharmony_ci * of the Software.
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2162306a36Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2262306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2362306a36Sopenharmony_ci * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
2462306a36Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2562306a36Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2662306a36Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci */
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include <linux/acpi.h>
3162306a36Sopenharmony_ci#include <linux/device.h>
3262306a36Sopenharmony_ci#include <linux/module.h>
3362306a36Sopenharmony_ci#include <linux/oom.h>
3462306a36Sopenharmony_ci#include <linux/pci.h>
3562306a36Sopenharmony_ci#include <linux/pm.h>
3662306a36Sopenharmony_ci#include <linux/pm_runtime.h>
3762306a36Sopenharmony_ci#include <linux/slab.h>
3862306a36Sopenharmony_ci#include <linux/string_helpers.h>
3962306a36Sopenharmony_ci#include <linux/vga_switcheroo.h>
4062306a36Sopenharmony_ci#include <linux/vt.h>
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#include <drm/drm_aperture.h>
4362306a36Sopenharmony_ci#include <drm/drm_atomic_helper.h>
4462306a36Sopenharmony_ci#include <drm/drm_ioctl.h>
4562306a36Sopenharmony_ci#include <drm/drm_managed.h>
4662306a36Sopenharmony_ci#include <drm/drm_probe_helper.h>
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#include "display/intel_acpi.h"
4962306a36Sopenharmony_ci#include "display/intel_bw.h"
5062306a36Sopenharmony_ci#include "display/intel_cdclk.h"
5162306a36Sopenharmony_ci#include "display/intel_display_driver.h"
5262306a36Sopenharmony_ci#include "display/intel_display_types.h"
5362306a36Sopenharmony_ci#include "display/intel_dmc.h"
5462306a36Sopenharmony_ci#include "display/intel_dp.h"
5562306a36Sopenharmony_ci#include "display/intel_dpt.h"
5662306a36Sopenharmony_ci#include "display/intel_fbdev.h"
5762306a36Sopenharmony_ci#include "display/intel_hotplug.h"
5862306a36Sopenharmony_ci#include "display/intel_overlay.h"
5962306a36Sopenharmony_ci#include "display/intel_pch_refclk.h"
6062306a36Sopenharmony_ci#include "display/intel_pipe_crc.h"
6162306a36Sopenharmony_ci#include "display/intel_pps.h"
6262306a36Sopenharmony_ci#include "display/intel_sprite.h"
6362306a36Sopenharmony_ci#include "display/intel_vga.h"
6462306a36Sopenharmony_ci#include "display/skl_watermark.h"
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci#include "gem/i915_gem_context.h"
6762306a36Sopenharmony_ci#include "gem/i915_gem_create.h"
6862306a36Sopenharmony_ci#include "gem/i915_gem_dmabuf.h"
6962306a36Sopenharmony_ci#include "gem/i915_gem_ioctls.h"
7062306a36Sopenharmony_ci#include "gem/i915_gem_mman.h"
7162306a36Sopenharmony_ci#include "gem/i915_gem_pm.h"
7262306a36Sopenharmony_ci#include "gt/intel_gt.h"
7362306a36Sopenharmony_ci#include "gt/intel_gt_pm.h"
7462306a36Sopenharmony_ci#include "gt/intel_rc6.h"
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#include "pxp/intel_pxp.h"
7762306a36Sopenharmony_ci#include "pxp/intel_pxp_debugfs.h"
7862306a36Sopenharmony_ci#include "pxp/intel_pxp_pm.h"
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#include "soc/intel_dram.h"
8162306a36Sopenharmony_ci#include "soc/intel_gmch.h"
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci#include "i915_debugfs.h"
8462306a36Sopenharmony_ci#include "i915_driver.h"
8562306a36Sopenharmony_ci#include "i915_drm_client.h"
8662306a36Sopenharmony_ci#include "i915_drv.h"
8762306a36Sopenharmony_ci#include "i915_file_private.h"
8862306a36Sopenharmony_ci#include "i915_getparam.h"
8962306a36Sopenharmony_ci#include "i915_hwmon.h"
9062306a36Sopenharmony_ci#include "i915_ioc32.h"
9162306a36Sopenharmony_ci#include "i915_ioctl.h"
9262306a36Sopenharmony_ci#include "i915_irq.h"
9362306a36Sopenharmony_ci#include "i915_memcpy.h"
9462306a36Sopenharmony_ci#include "i915_perf.h"
9562306a36Sopenharmony_ci#include "i915_query.h"
9662306a36Sopenharmony_ci#include "i915_suspend.h"
9762306a36Sopenharmony_ci#include "i915_switcheroo.h"
9862306a36Sopenharmony_ci#include "i915_sysfs.h"
9962306a36Sopenharmony_ci#include "i915_utils.h"
10062306a36Sopenharmony_ci#include "i915_vgpu.h"
10162306a36Sopenharmony_ci#include "intel_clock_gating.h"
10262306a36Sopenharmony_ci#include "intel_gvt.h"
10362306a36Sopenharmony_ci#include "intel_memory_region.h"
10462306a36Sopenharmony_ci#include "intel_pci_config.h"
10562306a36Sopenharmony_ci#include "intel_pcode.h"
10662306a36Sopenharmony_ci#include "intel_region_ttm.h"
10762306a36Sopenharmony_ci#include "vlv_suspend.h"
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic const struct drm_driver i915_drm_driver;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic int i915_workqueues_init(struct drm_i915_private *dev_priv)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	/*
11462306a36Sopenharmony_ci	 * The i915 workqueue is primarily used for batched retirement of
11562306a36Sopenharmony_ci	 * requests (and thus managing bo) once the task has been completed
11662306a36Sopenharmony_ci	 * by the GPU. i915_retire_requests() is called directly when we
11762306a36Sopenharmony_ci	 * need high-priority retirement, such as waiting for an explicit
11862306a36Sopenharmony_ci	 * bo.
11962306a36Sopenharmony_ci	 *
12062306a36Sopenharmony_ci	 * It is also used for periodic low-priority events, such as
12162306a36Sopenharmony_ci	 * idle-timers and recording error state.
12262306a36Sopenharmony_ci	 *
12362306a36Sopenharmony_ci	 * All tasks on the workqueue are expected to acquire the dev mutex
12462306a36Sopenharmony_ci	 * so there is no point in running more than one instance of the
12562306a36Sopenharmony_ci	 * workqueue at any time.  Use an ordered one.
12662306a36Sopenharmony_ci	 */
12762306a36Sopenharmony_ci	dev_priv->wq = alloc_ordered_workqueue("i915", 0);
12862306a36Sopenharmony_ci	if (dev_priv->wq == NULL)
12962306a36Sopenharmony_ci		goto out_err;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	dev_priv->display.hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0);
13262306a36Sopenharmony_ci	if (dev_priv->display.hotplug.dp_wq == NULL)
13362306a36Sopenharmony_ci		goto out_free_wq;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	/*
13662306a36Sopenharmony_ci	 * The unordered i915 workqueue should be used for all work
13762306a36Sopenharmony_ci	 * scheduling that do not require running in order, which used
13862306a36Sopenharmony_ci	 * to be scheduled on the system_wq before moving to a driver
13962306a36Sopenharmony_ci	 * instance due deprecation of flush_scheduled_work().
14062306a36Sopenharmony_ci	 */
14162306a36Sopenharmony_ci	dev_priv->unordered_wq = alloc_workqueue("i915-unordered", 0, 0);
14262306a36Sopenharmony_ci	if (dev_priv->unordered_wq == NULL)
14362306a36Sopenharmony_ci		goto out_free_dp_wq;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	return 0;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ciout_free_dp_wq:
14862306a36Sopenharmony_ci	destroy_workqueue(dev_priv->display.hotplug.dp_wq);
14962306a36Sopenharmony_ciout_free_wq:
15062306a36Sopenharmony_ci	destroy_workqueue(dev_priv->wq);
15162306a36Sopenharmony_ciout_err:
15262306a36Sopenharmony_ci	drm_err(&dev_priv->drm, "Failed to allocate workqueues.\n");
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	return -ENOMEM;
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistatic void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
15862306a36Sopenharmony_ci{
15962306a36Sopenharmony_ci	destroy_workqueue(dev_priv->unordered_wq);
16062306a36Sopenharmony_ci	destroy_workqueue(dev_priv->display.hotplug.dp_wq);
16162306a36Sopenharmony_ci	destroy_workqueue(dev_priv->wq);
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci/*
16562306a36Sopenharmony_ci * We don't keep the workarounds for pre-production hardware, so we expect our
16662306a36Sopenharmony_ci * driver to fail on these machines in one way or another. A little warning on
16762306a36Sopenharmony_ci * dmesg may help both the user and the bug triagers.
16862306a36Sopenharmony_ci *
16962306a36Sopenharmony_ci * Our policy for removing pre-production workarounds is to keep the
17062306a36Sopenharmony_ci * current gen workarounds as a guide to the bring-up of the next gen
17162306a36Sopenharmony_ci * (workarounds have a habit of persisting!). Anything older than that
17262306a36Sopenharmony_ci * should be removed along with the complications they introduce.
17362306a36Sopenharmony_ci */
17462306a36Sopenharmony_cistatic void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	bool pre = false;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	pre |= IS_HASWELL_EARLY_SDV(dev_priv);
17962306a36Sopenharmony_ci	pre |= IS_SKYLAKE(dev_priv) && INTEL_REVID(dev_priv) < 0x6;
18062306a36Sopenharmony_ci	pre |= IS_BROXTON(dev_priv) && INTEL_REVID(dev_priv) < 0xA;
18162306a36Sopenharmony_ci	pre |= IS_KABYLAKE(dev_priv) && INTEL_REVID(dev_priv) < 0x1;
18262306a36Sopenharmony_ci	pre |= IS_GEMINILAKE(dev_priv) && INTEL_REVID(dev_priv) < 0x3;
18362306a36Sopenharmony_ci	pre |= IS_ICELAKE(dev_priv) && INTEL_REVID(dev_priv) < 0x7;
18462306a36Sopenharmony_ci	pre |= IS_TIGERLAKE(dev_priv) && INTEL_REVID(dev_priv) < 0x1;
18562306a36Sopenharmony_ci	pre |= IS_DG1(dev_priv) && INTEL_REVID(dev_priv) < 0x1;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	if (pre) {
18862306a36Sopenharmony_ci		drm_err(&dev_priv->drm, "This is a pre-production stepping. "
18962306a36Sopenharmony_ci			  "It may not be fully functional.\n");
19062306a36Sopenharmony_ci		add_taint(TAINT_MACHINE_CHECK, LOCKDEP_STILL_OK);
19162306a36Sopenharmony_ci	}
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cistatic void sanitize_gpu(struct drm_i915_private *i915)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	if (!INTEL_INFO(i915)->gpu_reset_clobbers_display) {
19762306a36Sopenharmony_ci		struct intel_gt *gt;
19862306a36Sopenharmony_ci		unsigned int i;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci		for_each_gt(gt, i915, i)
20162306a36Sopenharmony_ci			__intel_gt_reset(gt, ALL_ENGINES);
20262306a36Sopenharmony_ci	}
20362306a36Sopenharmony_ci}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci/**
20662306a36Sopenharmony_ci * i915_driver_early_probe - setup state not requiring device access
20762306a36Sopenharmony_ci * @dev_priv: device private
20862306a36Sopenharmony_ci *
20962306a36Sopenharmony_ci * Initialize everything that is a "SW-only" state, that is state not
21062306a36Sopenharmony_ci * requiring accessing the device or exposing the driver via kernel internal
21162306a36Sopenharmony_ci * or userspace interfaces. Example steps belonging here: lock initialization,
21262306a36Sopenharmony_ci * system memory allocation, setting up device specific attributes and
21362306a36Sopenharmony_ci * function hooks not requiring accessing the device.
21462306a36Sopenharmony_ci */
21562306a36Sopenharmony_cistatic int i915_driver_early_probe(struct drm_i915_private *dev_priv)
21662306a36Sopenharmony_ci{
21762306a36Sopenharmony_ci	int ret = 0;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	if (i915_inject_probe_failure(dev_priv))
22062306a36Sopenharmony_ci		return -ENODEV;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	intel_device_info_runtime_init_early(dev_priv);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	intel_step_init(dev_priv);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	intel_uncore_mmio_debug_init_early(dev_priv);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	spin_lock_init(&dev_priv->irq_lock);
22962306a36Sopenharmony_ci	spin_lock_init(&dev_priv->gpu_error.lock);
23062306a36Sopenharmony_ci	mutex_init(&dev_priv->display.backlight.lock);
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	mutex_init(&dev_priv->sb_lock);
23362306a36Sopenharmony_ci	cpu_latency_qos_add_request(&dev_priv->sb_qos, PM_QOS_DEFAULT_VALUE);
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	mutex_init(&dev_priv->display.audio.mutex);
23662306a36Sopenharmony_ci	mutex_init(&dev_priv->display.wm.wm_mutex);
23762306a36Sopenharmony_ci	mutex_init(&dev_priv->display.pps.mutex);
23862306a36Sopenharmony_ci	mutex_init(&dev_priv->display.hdcp.hdcp_mutex);
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	i915_memcpy_init_early(dev_priv);
24162306a36Sopenharmony_ci	intel_runtime_pm_init_early(&dev_priv->runtime_pm);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	ret = i915_workqueues_init(dev_priv);
24462306a36Sopenharmony_ci	if (ret < 0)
24562306a36Sopenharmony_ci		return ret;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	ret = vlv_suspend_init(dev_priv);
24862306a36Sopenharmony_ci	if (ret < 0)
24962306a36Sopenharmony_ci		goto err_workqueues;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	ret = intel_region_ttm_device_init(dev_priv);
25262306a36Sopenharmony_ci	if (ret)
25362306a36Sopenharmony_ci		goto err_ttm;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	ret = intel_root_gt_init_early(dev_priv);
25662306a36Sopenharmony_ci	if (ret < 0)
25762306a36Sopenharmony_ci		goto err_rootgt;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	i915_gem_init_early(dev_priv);
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	/* This must be called before any calls to HAS_PCH_* */
26262306a36Sopenharmony_ci	intel_detect_pch(dev_priv);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	intel_irq_init(dev_priv);
26562306a36Sopenharmony_ci	intel_display_driver_early_probe(dev_priv);
26662306a36Sopenharmony_ci	intel_clock_gating_hooks_init(dev_priv);
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	intel_detect_preproduction_hw(dev_priv);
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	return 0;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_cierr_rootgt:
27362306a36Sopenharmony_ci	intel_region_ttm_device_fini(dev_priv);
27462306a36Sopenharmony_cierr_ttm:
27562306a36Sopenharmony_ci	vlv_suspend_cleanup(dev_priv);
27662306a36Sopenharmony_cierr_workqueues:
27762306a36Sopenharmony_ci	i915_workqueues_cleanup(dev_priv);
27862306a36Sopenharmony_ci	return ret;
27962306a36Sopenharmony_ci}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci/**
28262306a36Sopenharmony_ci * i915_driver_late_release - cleanup the setup done in
28362306a36Sopenharmony_ci *			       i915_driver_early_probe()
28462306a36Sopenharmony_ci * @dev_priv: device private
28562306a36Sopenharmony_ci */
28662306a36Sopenharmony_cistatic void i915_driver_late_release(struct drm_i915_private *dev_priv)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	intel_irq_fini(dev_priv);
28962306a36Sopenharmony_ci	intel_power_domains_cleanup(dev_priv);
29062306a36Sopenharmony_ci	i915_gem_cleanup_early(dev_priv);
29162306a36Sopenharmony_ci	intel_gt_driver_late_release_all(dev_priv);
29262306a36Sopenharmony_ci	intel_region_ttm_device_fini(dev_priv);
29362306a36Sopenharmony_ci	vlv_suspend_cleanup(dev_priv);
29462306a36Sopenharmony_ci	i915_workqueues_cleanup(dev_priv);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	cpu_latency_qos_remove_request(&dev_priv->sb_qos);
29762306a36Sopenharmony_ci	mutex_destroy(&dev_priv->sb_lock);
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	i915_params_free(&dev_priv->params);
30062306a36Sopenharmony_ci}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci/**
30362306a36Sopenharmony_ci * i915_driver_mmio_probe - setup device MMIO
30462306a36Sopenharmony_ci * @dev_priv: device private
30562306a36Sopenharmony_ci *
30662306a36Sopenharmony_ci * Setup minimal device state necessary for MMIO accesses later in the
30762306a36Sopenharmony_ci * initialization sequence. The setup here should avoid any other device-wide
30862306a36Sopenharmony_ci * side effects or exposing the driver via kernel internal or user space
30962306a36Sopenharmony_ci * interfaces.
31062306a36Sopenharmony_ci */
31162306a36Sopenharmony_cistatic int i915_driver_mmio_probe(struct drm_i915_private *dev_priv)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci	struct intel_gt *gt;
31462306a36Sopenharmony_ci	int ret, i;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	if (i915_inject_probe_failure(dev_priv))
31762306a36Sopenharmony_ci		return -ENODEV;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	ret = intel_gmch_bridge_setup(dev_priv);
32062306a36Sopenharmony_ci	if (ret < 0)
32162306a36Sopenharmony_ci		return ret;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	for_each_gt(gt, dev_priv, i) {
32462306a36Sopenharmony_ci		ret = intel_uncore_init_mmio(gt->uncore);
32562306a36Sopenharmony_ci		if (ret)
32662306a36Sopenharmony_ci			return ret;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci		ret = drmm_add_action_or_reset(&dev_priv->drm,
32962306a36Sopenharmony_ci					       intel_uncore_fini_mmio,
33062306a36Sopenharmony_ci					       gt->uncore);
33162306a36Sopenharmony_ci		if (ret)
33262306a36Sopenharmony_ci			return ret;
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	/* Try to make sure MCHBAR is enabled before poking at it */
33662306a36Sopenharmony_ci	intel_gmch_bar_setup(dev_priv);
33762306a36Sopenharmony_ci	intel_device_info_runtime_init(dev_priv);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	for_each_gt(gt, dev_priv, i) {
34062306a36Sopenharmony_ci		ret = intel_gt_init_mmio(gt);
34162306a36Sopenharmony_ci		if (ret)
34262306a36Sopenharmony_ci			goto err_uncore;
34362306a36Sopenharmony_ci	}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	/* As early as possible, scrub existing GPU state before clobbering */
34662306a36Sopenharmony_ci	sanitize_gpu(dev_priv);
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	return 0;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_cierr_uncore:
35162306a36Sopenharmony_ci	intel_gmch_bar_teardown(dev_priv);
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	return ret;
35462306a36Sopenharmony_ci}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci/**
35762306a36Sopenharmony_ci * i915_driver_mmio_release - cleanup the setup done in i915_driver_mmio_probe()
35862306a36Sopenharmony_ci * @dev_priv: device private
35962306a36Sopenharmony_ci */
36062306a36Sopenharmony_cistatic void i915_driver_mmio_release(struct drm_i915_private *dev_priv)
36162306a36Sopenharmony_ci{
36262306a36Sopenharmony_ci	intel_gmch_bar_teardown(dev_priv);
36362306a36Sopenharmony_ci}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci/**
36662306a36Sopenharmony_ci * i915_set_dma_info - set all relevant PCI dma info as configured for the
36762306a36Sopenharmony_ci * platform
36862306a36Sopenharmony_ci * @i915: valid i915 instance
36962306a36Sopenharmony_ci *
37062306a36Sopenharmony_ci * Set the dma max segment size, device and coherent masks.  The dma mask set
37162306a36Sopenharmony_ci * needs to occur before i915_ggtt_probe_hw.
37262306a36Sopenharmony_ci *
37362306a36Sopenharmony_ci * A couple of platforms have special needs.  Address them as well.
37462306a36Sopenharmony_ci *
37562306a36Sopenharmony_ci */
37662306a36Sopenharmony_cistatic int i915_set_dma_info(struct drm_i915_private *i915)
37762306a36Sopenharmony_ci{
37862306a36Sopenharmony_ci	unsigned int mask_size = INTEL_INFO(i915)->dma_mask_size;
37962306a36Sopenharmony_ci	int ret;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	GEM_BUG_ON(!mask_size);
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	/*
38462306a36Sopenharmony_ci	 * We don't have a max segment size, so set it to the max so sg's
38562306a36Sopenharmony_ci	 * debugging layer doesn't complain
38662306a36Sopenharmony_ci	 */
38762306a36Sopenharmony_ci	dma_set_max_seg_size(i915->drm.dev, UINT_MAX);
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	ret = dma_set_mask(i915->drm.dev, DMA_BIT_MASK(mask_size));
39062306a36Sopenharmony_ci	if (ret)
39162306a36Sopenharmony_ci		goto mask_err;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	/* overlay on gen2 is broken and can't address above 1G */
39462306a36Sopenharmony_ci	if (GRAPHICS_VER(i915) == 2)
39562306a36Sopenharmony_ci		mask_size = 30;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	/*
39862306a36Sopenharmony_ci	 * 965GM sometimes incorrectly writes to hardware status page (HWS)
39962306a36Sopenharmony_ci	 * using 32bit addressing, overwriting memory if HWS is located
40062306a36Sopenharmony_ci	 * above 4GB.
40162306a36Sopenharmony_ci	 *
40262306a36Sopenharmony_ci	 * The documentation also mentions an issue with undefined
40362306a36Sopenharmony_ci	 * behaviour if any general state is accessed within a page above 4GB,
40462306a36Sopenharmony_ci	 * which also needs to be handled carefully.
40562306a36Sopenharmony_ci	 */
40662306a36Sopenharmony_ci	if (IS_I965G(i915) || IS_I965GM(i915))
40762306a36Sopenharmony_ci		mask_size = 32;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	ret = dma_set_coherent_mask(i915->drm.dev, DMA_BIT_MASK(mask_size));
41062306a36Sopenharmony_ci	if (ret)
41162306a36Sopenharmony_ci		goto mask_err;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	return 0;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_cimask_err:
41662306a36Sopenharmony_ci	drm_err(&i915->drm, "Can't set DMA mask/consistent mask (%d)\n", ret);
41762306a36Sopenharmony_ci	return ret;
41862306a36Sopenharmony_ci}
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_cistatic int i915_pcode_init(struct drm_i915_private *i915)
42162306a36Sopenharmony_ci{
42262306a36Sopenharmony_ci	struct intel_gt *gt;
42362306a36Sopenharmony_ci	int id, ret;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	for_each_gt(gt, i915, id) {
42662306a36Sopenharmony_ci		ret = intel_pcode_init(gt->uncore);
42762306a36Sopenharmony_ci		if (ret) {
42862306a36Sopenharmony_ci			drm_err(&gt->i915->drm, "gt%d: intel_pcode_init failed %d\n", id, ret);
42962306a36Sopenharmony_ci			return ret;
43062306a36Sopenharmony_ci		}
43162306a36Sopenharmony_ci	}
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	return 0;
43462306a36Sopenharmony_ci}
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci/**
43762306a36Sopenharmony_ci * i915_driver_hw_probe - setup state requiring device access
43862306a36Sopenharmony_ci * @dev_priv: device private
43962306a36Sopenharmony_ci *
44062306a36Sopenharmony_ci * Setup state that requires accessing the device, but doesn't require
44162306a36Sopenharmony_ci * exposing the driver via kernel internal or userspace interfaces.
44262306a36Sopenharmony_ci */
44362306a36Sopenharmony_cistatic int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
44462306a36Sopenharmony_ci{
44562306a36Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
44662306a36Sopenharmony_ci	int ret;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	if (i915_inject_probe_failure(dev_priv))
44962306a36Sopenharmony_ci		return -ENODEV;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	if (HAS_PPGTT(dev_priv)) {
45262306a36Sopenharmony_ci		if (intel_vgpu_active(dev_priv) &&
45362306a36Sopenharmony_ci		    !intel_vgpu_has_full_ppgtt(dev_priv)) {
45462306a36Sopenharmony_ci			i915_report_error(dev_priv,
45562306a36Sopenharmony_ci					  "incompatible vGPU found, support for isolated ppGTT required\n");
45662306a36Sopenharmony_ci			return -ENXIO;
45762306a36Sopenharmony_ci		}
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	if (HAS_EXECLISTS(dev_priv)) {
46162306a36Sopenharmony_ci		/*
46262306a36Sopenharmony_ci		 * Older GVT emulation depends upon intercepting CSB mmio,
46362306a36Sopenharmony_ci		 * which we no longer use, preferring to use the HWSP cache
46462306a36Sopenharmony_ci		 * instead.
46562306a36Sopenharmony_ci		 */
46662306a36Sopenharmony_ci		if (intel_vgpu_active(dev_priv) &&
46762306a36Sopenharmony_ci		    !intel_vgpu_has_hwsp_emulation(dev_priv)) {
46862306a36Sopenharmony_ci			i915_report_error(dev_priv,
46962306a36Sopenharmony_ci					  "old vGPU host found, support for HWSP emulation required\n");
47062306a36Sopenharmony_ci			return -ENXIO;
47162306a36Sopenharmony_ci		}
47262306a36Sopenharmony_ci	}
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	/* needs to be done before ggtt probe */
47562306a36Sopenharmony_ci	intel_dram_edram_detect(dev_priv);
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	ret = i915_set_dma_info(dev_priv);
47862306a36Sopenharmony_ci	if (ret)
47962306a36Sopenharmony_ci		return ret;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	ret = i915_perf_init(dev_priv);
48262306a36Sopenharmony_ci	if (ret)
48362306a36Sopenharmony_ci		return ret;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	ret = i915_ggtt_probe_hw(dev_priv);
48662306a36Sopenharmony_ci	if (ret)
48762306a36Sopenharmony_ci		goto err_perf;
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, dev_priv->drm.driver);
49062306a36Sopenharmony_ci	if (ret)
49162306a36Sopenharmony_ci		goto err_ggtt;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	ret = i915_ggtt_init_hw(dev_priv);
49462306a36Sopenharmony_ci	if (ret)
49562306a36Sopenharmony_ci		goto err_ggtt;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	/*
49862306a36Sopenharmony_ci	 * Make sure we probe lmem before we probe stolen-lmem. The BAR size
49962306a36Sopenharmony_ci	 * might be different due to bar resizing.
50062306a36Sopenharmony_ci	 */
50162306a36Sopenharmony_ci	ret = intel_gt_tiles_init(dev_priv);
50262306a36Sopenharmony_ci	if (ret)
50362306a36Sopenharmony_ci		goto err_ggtt;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	ret = intel_memory_regions_hw_probe(dev_priv);
50662306a36Sopenharmony_ci	if (ret)
50762306a36Sopenharmony_ci		goto err_ggtt;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	ret = i915_ggtt_enable_hw(dev_priv);
51062306a36Sopenharmony_ci	if (ret) {
51162306a36Sopenharmony_ci		drm_err(&dev_priv->drm, "failed to enable GGTT\n");
51262306a36Sopenharmony_ci		goto err_mem_regions;
51362306a36Sopenharmony_ci	}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	pci_set_master(pdev);
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	/* On the 945G/GM, the chipset reports the MSI capability on the
51862306a36Sopenharmony_ci	 * integrated graphics even though the support isn't actually there
51962306a36Sopenharmony_ci	 * according to the published specs.  It doesn't appear to function
52062306a36Sopenharmony_ci	 * correctly in testing on 945G.
52162306a36Sopenharmony_ci	 * This may be a side effect of MSI having been made available for PEG
52262306a36Sopenharmony_ci	 * and the registers being closely associated.
52362306a36Sopenharmony_ci	 *
52462306a36Sopenharmony_ci	 * According to chipset errata, on the 965GM, MSI interrupts may
52562306a36Sopenharmony_ci	 * be lost or delayed, and was defeatured. MSI interrupts seem to
52662306a36Sopenharmony_ci	 * get lost on g4x as well, and interrupt delivery seems to stay
52762306a36Sopenharmony_ci	 * properly dead afterwards. So we'll just disable them for all
52862306a36Sopenharmony_ci	 * pre-gen5 chipsets.
52962306a36Sopenharmony_ci	 *
53062306a36Sopenharmony_ci	 * dp aux and gmbus irq on gen4 seems to be able to generate legacy
53162306a36Sopenharmony_ci	 * interrupts even when in MSI mode. This results in spurious
53262306a36Sopenharmony_ci	 * interrupt warnings if the legacy irq no. is shared with another
53362306a36Sopenharmony_ci	 * device. The kernel then disables that interrupt source and so
53462306a36Sopenharmony_ci	 * prevents the other device from working properly.
53562306a36Sopenharmony_ci	 */
53662306a36Sopenharmony_ci	if (GRAPHICS_VER(dev_priv) >= 5) {
53762306a36Sopenharmony_ci		if (pci_enable_msi(pdev) < 0)
53862306a36Sopenharmony_ci			drm_dbg(&dev_priv->drm, "can't enable MSI");
53962306a36Sopenharmony_ci	}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	ret = intel_gvt_init(dev_priv);
54262306a36Sopenharmony_ci	if (ret)
54362306a36Sopenharmony_ci		goto err_msi;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	intel_opregion_setup(dev_priv);
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	ret = i915_pcode_init(dev_priv);
54862306a36Sopenharmony_ci	if (ret)
54962306a36Sopenharmony_ci		goto err_opregion;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	/*
55262306a36Sopenharmony_ci	 * Fill the dram structure to get the system dram info. This will be
55362306a36Sopenharmony_ci	 * used for memory latency calculation.
55462306a36Sopenharmony_ci	 */
55562306a36Sopenharmony_ci	intel_dram_detect(dev_priv);
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	intel_bw_init_hw(dev_priv);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	return 0;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_cierr_opregion:
56262306a36Sopenharmony_ci	intel_opregion_cleanup(dev_priv);
56362306a36Sopenharmony_cierr_msi:
56462306a36Sopenharmony_ci	if (pdev->msi_enabled)
56562306a36Sopenharmony_ci		pci_disable_msi(pdev);
56662306a36Sopenharmony_cierr_mem_regions:
56762306a36Sopenharmony_ci	intel_memory_regions_driver_release(dev_priv);
56862306a36Sopenharmony_cierr_ggtt:
56962306a36Sopenharmony_ci	i915_ggtt_driver_release(dev_priv);
57062306a36Sopenharmony_ci	i915_gem_drain_freed_objects(dev_priv);
57162306a36Sopenharmony_ci	i915_ggtt_driver_late_release(dev_priv);
57262306a36Sopenharmony_cierr_perf:
57362306a36Sopenharmony_ci	i915_perf_fini(dev_priv);
57462306a36Sopenharmony_ci	return ret;
57562306a36Sopenharmony_ci}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci/**
57862306a36Sopenharmony_ci * i915_driver_hw_remove - cleanup the setup done in i915_driver_hw_probe()
57962306a36Sopenharmony_ci * @dev_priv: device private
58062306a36Sopenharmony_ci */
58162306a36Sopenharmony_cistatic void i915_driver_hw_remove(struct drm_i915_private *dev_priv)
58262306a36Sopenharmony_ci{
58362306a36Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci	i915_perf_fini(dev_priv);
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	intel_opregion_cleanup(dev_priv);
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	if (pdev->msi_enabled)
59062306a36Sopenharmony_ci		pci_disable_msi(pdev);
59162306a36Sopenharmony_ci}
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci/**
59462306a36Sopenharmony_ci * i915_driver_register - register the driver with the rest of the system
59562306a36Sopenharmony_ci * @dev_priv: device private
59662306a36Sopenharmony_ci *
59762306a36Sopenharmony_ci * Perform any steps necessary to make the driver available via kernel
59862306a36Sopenharmony_ci * internal or userspace interfaces.
59962306a36Sopenharmony_ci */
60062306a36Sopenharmony_cistatic void i915_driver_register(struct drm_i915_private *dev_priv)
60162306a36Sopenharmony_ci{
60262306a36Sopenharmony_ci	struct intel_gt *gt;
60362306a36Sopenharmony_ci	unsigned int i;
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	i915_gem_driver_register(dev_priv);
60662306a36Sopenharmony_ci	i915_pmu_register(dev_priv);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	intel_vgpu_register(dev_priv);
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	/* Reveal our presence to userspace */
61162306a36Sopenharmony_ci	if (drm_dev_register(&dev_priv->drm, 0)) {
61262306a36Sopenharmony_ci		drm_err(&dev_priv->drm,
61362306a36Sopenharmony_ci			"Failed to register driver for userspace access!\n");
61462306a36Sopenharmony_ci		return;
61562306a36Sopenharmony_ci	}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	i915_debugfs_register(dev_priv);
61862306a36Sopenharmony_ci	i915_setup_sysfs(dev_priv);
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	/* Depends on sysfs having been initialized */
62162306a36Sopenharmony_ci	i915_perf_register(dev_priv);
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	for_each_gt(gt, dev_priv, i)
62462306a36Sopenharmony_ci		intel_gt_driver_register(gt);
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	intel_pxp_debugfs_register(dev_priv->pxp);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	i915_hwmon_register(dev_priv);
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci	intel_display_driver_register(dev_priv);
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	intel_power_domains_enable(dev_priv);
63362306a36Sopenharmony_ci	intel_runtime_pm_enable(&dev_priv->runtime_pm);
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	intel_register_dsm_handler();
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	if (i915_switcheroo_register(dev_priv))
63862306a36Sopenharmony_ci		drm_err(&dev_priv->drm, "Failed to register vga switcheroo!\n");
63962306a36Sopenharmony_ci}
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci/**
64262306a36Sopenharmony_ci * i915_driver_unregister - cleanup the registration done in i915_driver_regiser()
64362306a36Sopenharmony_ci * @dev_priv: device private
64462306a36Sopenharmony_ci */
64562306a36Sopenharmony_cistatic void i915_driver_unregister(struct drm_i915_private *dev_priv)
64662306a36Sopenharmony_ci{
64762306a36Sopenharmony_ci	struct intel_gt *gt;
64862306a36Sopenharmony_ci	unsigned int i;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	i915_switcheroo_unregister(dev_priv);
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	intel_unregister_dsm_handler();
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	intel_runtime_pm_disable(&dev_priv->runtime_pm);
65562306a36Sopenharmony_ci	intel_power_domains_disable(dev_priv);
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	intel_display_driver_unregister(dev_priv);
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	intel_pxp_fini(dev_priv);
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	for_each_gt(gt, dev_priv, i)
66262306a36Sopenharmony_ci		intel_gt_driver_unregister(gt);
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	i915_hwmon_unregister(dev_priv);
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	i915_perf_unregister(dev_priv);
66762306a36Sopenharmony_ci	i915_pmu_unregister(dev_priv);
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	i915_teardown_sysfs(dev_priv);
67062306a36Sopenharmony_ci	drm_dev_unplug(&dev_priv->drm);
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	i915_gem_driver_unregister(dev_priv);
67362306a36Sopenharmony_ci}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_civoid
67662306a36Sopenharmony_cii915_print_iommu_status(struct drm_i915_private *i915, struct drm_printer *p)
67762306a36Sopenharmony_ci{
67862306a36Sopenharmony_ci	drm_printf(p, "iommu: %s\n",
67962306a36Sopenharmony_ci		   str_enabled_disabled(i915_vtd_active(i915)));
68062306a36Sopenharmony_ci}
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_cistatic void i915_welcome_messages(struct drm_i915_private *dev_priv)
68362306a36Sopenharmony_ci{
68462306a36Sopenharmony_ci	if (drm_debug_enabled(DRM_UT_DRIVER)) {
68562306a36Sopenharmony_ci		struct drm_printer p = drm_debug_printer("i915 device info:");
68662306a36Sopenharmony_ci		struct intel_gt *gt;
68762306a36Sopenharmony_ci		unsigned int i;
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci		drm_printf(&p, "pciid=0x%04x rev=0x%02x platform=%s (subplatform=0x%x) gen=%i\n",
69062306a36Sopenharmony_ci			   INTEL_DEVID(dev_priv),
69162306a36Sopenharmony_ci			   INTEL_REVID(dev_priv),
69262306a36Sopenharmony_ci			   intel_platform_name(INTEL_INFO(dev_priv)->platform),
69362306a36Sopenharmony_ci			   intel_subplatform(RUNTIME_INFO(dev_priv),
69462306a36Sopenharmony_ci					     INTEL_INFO(dev_priv)->platform),
69562306a36Sopenharmony_ci			   GRAPHICS_VER(dev_priv));
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci		intel_device_info_print(INTEL_INFO(dev_priv),
69862306a36Sopenharmony_ci					RUNTIME_INFO(dev_priv), &p);
69962306a36Sopenharmony_ci		intel_display_device_info_print(DISPLAY_INFO(dev_priv),
70062306a36Sopenharmony_ci						DISPLAY_RUNTIME_INFO(dev_priv), &p);
70162306a36Sopenharmony_ci		i915_print_iommu_status(dev_priv, &p);
70262306a36Sopenharmony_ci		for_each_gt(gt, dev_priv, i)
70362306a36Sopenharmony_ci			intel_gt_info_print(&gt->info, &p);
70462306a36Sopenharmony_ci	}
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG))
70762306a36Sopenharmony_ci		drm_info(&dev_priv->drm, "DRM_I915_DEBUG enabled\n");
70862306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
70962306a36Sopenharmony_ci		drm_info(&dev_priv->drm, "DRM_I915_DEBUG_GEM enabled\n");
71062306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM))
71162306a36Sopenharmony_ci		drm_info(&dev_priv->drm,
71262306a36Sopenharmony_ci			 "DRM_I915_DEBUG_RUNTIME_PM enabled\n");
71362306a36Sopenharmony_ci}
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_cistatic struct drm_i915_private *
71662306a36Sopenharmony_cii915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent)
71762306a36Sopenharmony_ci{
71862306a36Sopenharmony_ci	const struct intel_device_info *match_info =
71962306a36Sopenharmony_ci		(struct intel_device_info *)ent->driver_data;
72062306a36Sopenharmony_ci	struct drm_i915_private *i915;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	i915 = devm_drm_dev_alloc(&pdev->dev, &i915_drm_driver,
72362306a36Sopenharmony_ci				  struct drm_i915_private, drm);
72462306a36Sopenharmony_ci	if (IS_ERR(i915))
72562306a36Sopenharmony_ci		return i915;
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	pci_set_drvdata(pdev, i915);
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	/* Device parameters start as a copy of module parameters. */
73062306a36Sopenharmony_ci	i915_params_copy(&i915->params, &i915_modparams);
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	/* Set up device info and initial runtime info. */
73362306a36Sopenharmony_ci	intel_device_info_driver_create(i915, pdev->device, match_info);
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	return i915;
73662306a36Sopenharmony_ci}
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci/**
73962306a36Sopenharmony_ci * i915_driver_probe - setup chip and create an initial config
74062306a36Sopenharmony_ci * @pdev: PCI device
74162306a36Sopenharmony_ci * @ent: matching PCI ID entry
74262306a36Sopenharmony_ci *
74362306a36Sopenharmony_ci * The driver probe routine has to do several things:
74462306a36Sopenharmony_ci *   - drive output discovery via intel_display_driver_probe()
74562306a36Sopenharmony_ci *   - initialize the memory manager
74662306a36Sopenharmony_ci *   - allocate initial config memory
74762306a36Sopenharmony_ci *   - setup the DRM framebuffer with the allocated memory
74862306a36Sopenharmony_ci */
74962306a36Sopenharmony_ciint i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
75062306a36Sopenharmony_ci{
75162306a36Sopenharmony_ci	struct drm_i915_private *i915;
75262306a36Sopenharmony_ci	int ret;
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci	ret = pci_enable_device(pdev);
75562306a36Sopenharmony_ci	if (ret) {
75662306a36Sopenharmony_ci		pr_err("Failed to enable graphics device: %pe\n", ERR_PTR(ret));
75762306a36Sopenharmony_ci		return ret;
75862306a36Sopenharmony_ci	}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	i915 = i915_driver_create(pdev, ent);
76162306a36Sopenharmony_ci	if (IS_ERR(i915)) {
76262306a36Sopenharmony_ci		pci_disable_device(pdev);
76362306a36Sopenharmony_ci		return PTR_ERR(i915);
76462306a36Sopenharmony_ci	}
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci	ret = i915_driver_early_probe(i915);
76762306a36Sopenharmony_ci	if (ret < 0)
76862306a36Sopenharmony_ci		goto out_pci_disable;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci	disable_rpm_wakeref_asserts(&i915->runtime_pm);
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	intel_vgpu_detect(i915);
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	ret = intel_gt_probe_all(i915);
77562306a36Sopenharmony_ci	if (ret < 0)
77662306a36Sopenharmony_ci		goto out_runtime_pm_put;
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci	ret = i915_driver_mmio_probe(i915);
77962306a36Sopenharmony_ci	if (ret < 0)
78062306a36Sopenharmony_ci		goto out_runtime_pm_put;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	ret = i915_driver_hw_probe(i915);
78362306a36Sopenharmony_ci	if (ret < 0)
78462306a36Sopenharmony_ci		goto out_cleanup_mmio;
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	ret = intel_display_driver_probe_noirq(i915);
78762306a36Sopenharmony_ci	if (ret < 0)
78862306a36Sopenharmony_ci		goto out_cleanup_hw;
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	ret = intel_irq_install(i915);
79162306a36Sopenharmony_ci	if (ret)
79262306a36Sopenharmony_ci		goto out_cleanup_modeset;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	ret = intel_display_driver_probe_nogem(i915);
79562306a36Sopenharmony_ci	if (ret)
79662306a36Sopenharmony_ci		goto out_cleanup_irq;
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	ret = i915_gem_init(i915);
79962306a36Sopenharmony_ci	if (ret)
80062306a36Sopenharmony_ci		goto out_cleanup_modeset2;
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	intel_pxp_init(i915);
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	ret = intel_display_driver_probe(i915);
80562306a36Sopenharmony_ci	if (ret)
80662306a36Sopenharmony_ci		goto out_cleanup_gem;
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	i915_driver_register(i915);
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci	enable_rpm_wakeref_asserts(&i915->runtime_pm);
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	i915_welcome_messages(i915);
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	i915->do_release = true;
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	return 0;
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ciout_cleanup_gem:
81962306a36Sopenharmony_ci	i915_gem_suspend(i915);
82062306a36Sopenharmony_ci	i915_gem_driver_remove(i915);
82162306a36Sopenharmony_ci	i915_gem_driver_release(i915);
82262306a36Sopenharmony_ciout_cleanup_modeset2:
82362306a36Sopenharmony_ci	/* FIXME clean up the error path */
82462306a36Sopenharmony_ci	intel_display_driver_remove(i915);
82562306a36Sopenharmony_ci	intel_irq_uninstall(i915);
82662306a36Sopenharmony_ci	intel_display_driver_remove_noirq(i915);
82762306a36Sopenharmony_ci	goto out_cleanup_modeset;
82862306a36Sopenharmony_ciout_cleanup_irq:
82962306a36Sopenharmony_ci	intel_irq_uninstall(i915);
83062306a36Sopenharmony_ciout_cleanup_modeset:
83162306a36Sopenharmony_ci	intel_display_driver_remove_nogem(i915);
83262306a36Sopenharmony_ciout_cleanup_hw:
83362306a36Sopenharmony_ci	i915_driver_hw_remove(i915);
83462306a36Sopenharmony_ci	intel_memory_regions_driver_release(i915);
83562306a36Sopenharmony_ci	i915_ggtt_driver_release(i915);
83662306a36Sopenharmony_ci	i915_gem_drain_freed_objects(i915);
83762306a36Sopenharmony_ci	i915_ggtt_driver_late_release(i915);
83862306a36Sopenharmony_ciout_cleanup_mmio:
83962306a36Sopenharmony_ci	i915_driver_mmio_release(i915);
84062306a36Sopenharmony_ciout_runtime_pm_put:
84162306a36Sopenharmony_ci	enable_rpm_wakeref_asserts(&i915->runtime_pm);
84262306a36Sopenharmony_ci	i915_driver_late_release(i915);
84362306a36Sopenharmony_ciout_pci_disable:
84462306a36Sopenharmony_ci	pci_disable_device(pdev);
84562306a36Sopenharmony_ci	i915_probe_error(i915, "Device initialization failed (%d)\n", ret);
84662306a36Sopenharmony_ci	return ret;
84762306a36Sopenharmony_ci}
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_civoid i915_driver_remove(struct drm_i915_private *i915)
85062306a36Sopenharmony_ci{
85162306a36Sopenharmony_ci	intel_wakeref_t wakeref;
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	i915_driver_unregister(i915);
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	/* Flush any external code that still may be under the RCU lock */
85862306a36Sopenharmony_ci	synchronize_rcu();
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	i915_gem_suspend(i915);
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	intel_gvt_driver_remove(i915);
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	intel_display_driver_remove(i915);
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	intel_irq_uninstall(i915);
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	intel_display_driver_remove_noirq(i915);
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci	i915_reset_error_state(i915);
87162306a36Sopenharmony_ci	i915_gem_driver_remove(i915);
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	intel_display_driver_remove_nogem(i915);
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	i915_driver_hw_remove(i915);
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
87862306a36Sopenharmony_ci}
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_cistatic void i915_driver_release(struct drm_device *dev)
88162306a36Sopenharmony_ci{
88262306a36Sopenharmony_ci	struct drm_i915_private *dev_priv = to_i915(dev);
88362306a36Sopenharmony_ci	struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
88462306a36Sopenharmony_ci	intel_wakeref_t wakeref;
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci	if (!dev_priv->do_release)
88762306a36Sopenharmony_ci		return;
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	wakeref = intel_runtime_pm_get(rpm);
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	i915_gem_driver_release(dev_priv);
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	intel_memory_regions_driver_release(dev_priv);
89462306a36Sopenharmony_ci	i915_ggtt_driver_release(dev_priv);
89562306a36Sopenharmony_ci	i915_gem_drain_freed_objects(dev_priv);
89662306a36Sopenharmony_ci	i915_ggtt_driver_late_release(dev_priv);
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	i915_driver_mmio_release(dev_priv);
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	intel_runtime_pm_put(rpm, wakeref);
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	intel_runtime_pm_driver_release(rpm);
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	i915_driver_late_release(dev_priv);
90562306a36Sopenharmony_ci}
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_cistatic int i915_driver_open(struct drm_device *dev, struct drm_file *file)
90862306a36Sopenharmony_ci{
90962306a36Sopenharmony_ci	struct drm_i915_private *i915 = to_i915(dev);
91062306a36Sopenharmony_ci	int ret;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	ret = i915_gem_open(i915, file);
91362306a36Sopenharmony_ci	if (ret)
91462306a36Sopenharmony_ci		return ret;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	return 0;
91762306a36Sopenharmony_ci}
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci/**
92062306a36Sopenharmony_ci * i915_driver_lastclose - clean up after all DRM clients have exited
92162306a36Sopenharmony_ci * @dev: DRM device
92262306a36Sopenharmony_ci *
92362306a36Sopenharmony_ci * Take care of cleaning up after all DRM clients have exited.  In the
92462306a36Sopenharmony_ci * mode setting case, we want to restore the kernel's initial mode (just
92562306a36Sopenharmony_ci * in case the last client left us in a bad state).
92662306a36Sopenharmony_ci *
92762306a36Sopenharmony_ci * Additionally, in the non-mode setting case, we'll tear down the GTT
92862306a36Sopenharmony_ci * and DMA structures, since the kernel won't be using them, and clea
92962306a36Sopenharmony_ci * up any GEM state.
93062306a36Sopenharmony_ci */
93162306a36Sopenharmony_cistatic void i915_driver_lastclose(struct drm_device *dev)
93262306a36Sopenharmony_ci{
93362306a36Sopenharmony_ci	struct drm_i915_private *i915 = to_i915(dev);
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci	intel_fbdev_restore_mode(i915);
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	vga_switcheroo_process_delayed_switch();
93862306a36Sopenharmony_ci}
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_cistatic void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
94162306a36Sopenharmony_ci{
94262306a36Sopenharmony_ci	struct drm_i915_file_private *file_priv = file->driver_priv;
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	i915_gem_context_close(file);
94562306a36Sopenharmony_ci	i915_drm_client_put(file_priv->client);
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	kfree_rcu(file_priv, rcu);
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci	/* Catch up with all the deferred frees from "this" client */
95062306a36Sopenharmony_ci	i915_gem_flush_free_objects(to_i915(dev));
95162306a36Sopenharmony_ci}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_cistatic void intel_suspend_encoders(struct drm_i915_private *dev_priv)
95462306a36Sopenharmony_ci{
95562306a36Sopenharmony_ci	struct intel_encoder *encoder;
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	if (!HAS_DISPLAY(dev_priv))
95862306a36Sopenharmony_ci		return;
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	/*
96162306a36Sopenharmony_ci	 * TODO: check and remove holding the modeset locks if none of
96262306a36Sopenharmony_ci	 * the encoders depends on this.
96362306a36Sopenharmony_ci	 */
96462306a36Sopenharmony_ci	drm_modeset_lock_all(&dev_priv->drm);
96562306a36Sopenharmony_ci	for_each_intel_encoder(&dev_priv->drm, encoder)
96662306a36Sopenharmony_ci		if (encoder->suspend)
96762306a36Sopenharmony_ci			encoder->suspend(encoder);
96862306a36Sopenharmony_ci	drm_modeset_unlock_all(&dev_priv->drm);
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	for_each_intel_encoder(&dev_priv->drm, encoder)
97162306a36Sopenharmony_ci		if (encoder->suspend_complete)
97262306a36Sopenharmony_ci			encoder->suspend_complete(encoder);
97362306a36Sopenharmony_ci}
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_cistatic void intel_shutdown_encoders(struct drm_i915_private *dev_priv)
97662306a36Sopenharmony_ci{
97762306a36Sopenharmony_ci	struct intel_encoder *encoder;
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	if (!HAS_DISPLAY(dev_priv))
98062306a36Sopenharmony_ci		return;
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	/*
98362306a36Sopenharmony_ci	 * TODO: check and remove holding the modeset locks if none of
98462306a36Sopenharmony_ci	 * the encoders depends on this.
98562306a36Sopenharmony_ci	 */
98662306a36Sopenharmony_ci	drm_modeset_lock_all(&dev_priv->drm);
98762306a36Sopenharmony_ci	for_each_intel_encoder(&dev_priv->drm, encoder)
98862306a36Sopenharmony_ci		if (encoder->shutdown)
98962306a36Sopenharmony_ci			encoder->shutdown(encoder);
99062306a36Sopenharmony_ci	drm_modeset_unlock_all(&dev_priv->drm);
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	for_each_intel_encoder(&dev_priv->drm, encoder)
99362306a36Sopenharmony_ci		if (encoder->shutdown_complete)
99462306a36Sopenharmony_ci			encoder->shutdown_complete(encoder);
99562306a36Sopenharmony_ci}
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_civoid i915_driver_shutdown(struct drm_i915_private *i915)
99862306a36Sopenharmony_ci{
99962306a36Sopenharmony_ci	disable_rpm_wakeref_asserts(&i915->runtime_pm);
100062306a36Sopenharmony_ci	intel_runtime_pm_disable(&i915->runtime_pm);
100162306a36Sopenharmony_ci	intel_power_domains_disable(i915);
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_ci	if (HAS_DISPLAY(i915)) {
100462306a36Sopenharmony_ci		drm_kms_helper_poll_disable(&i915->drm);
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci		drm_atomic_helper_shutdown(&i915->drm);
100762306a36Sopenharmony_ci	}
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	intel_dp_mst_suspend(i915);
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	intel_runtime_pm_disable_interrupts(i915);
101262306a36Sopenharmony_ci	intel_hpd_cancel_work(i915);
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	intel_suspend_encoders(i915);
101562306a36Sopenharmony_ci	intel_shutdown_encoders(i915);
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci	intel_dmc_suspend(i915);
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	i915_gem_suspend(i915);
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci	/*
102262306a36Sopenharmony_ci	 * The only requirement is to reboot with display DC states disabled,
102362306a36Sopenharmony_ci	 * for now leaving all display power wells in the INIT power domain
102462306a36Sopenharmony_ci	 * enabled.
102562306a36Sopenharmony_ci	 *
102662306a36Sopenharmony_ci	 * TODO:
102762306a36Sopenharmony_ci	 * - unify the pci_driver::shutdown sequence here with the
102862306a36Sopenharmony_ci	 *   pci_driver.driver.pm.poweroff,poweroff_late sequence.
102962306a36Sopenharmony_ci	 * - unify the driver remove and system/runtime suspend sequences with
103062306a36Sopenharmony_ci	 *   the above unified shutdown/poweroff sequence.
103162306a36Sopenharmony_ci	 */
103262306a36Sopenharmony_ci	intel_power_domains_driver_remove(i915);
103362306a36Sopenharmony_ci	enable_rpm_wakeref_asserts(&i915->runtime_pm);
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	intel_runtime_pm_driver_release(&i915->runtime_pm);
103662306a36Sopenharmony_ci}
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_cistatic bool suspend_to_idle(struct drm_i915_private *dev_priv)
103962306a36Sopenharmony_ci{
104062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_ACPI_SLEEP)
104162306a36Sopenharmony_ci	if (acpi_target_system_state() < ACPI_STATE_S3)
104262306a36Sopenharmony_ci		return true;
104362306a36Sopenharmony_ci#endif
104462306a36Sopenharmony_ci	return false;
104562306a36Sopenharmony_ci}
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_cistatic void i915_drm_complete(struct drm_device *dev)
104862306a36Sopenharmony_ci{
104962306a36Sopenharmony_ci	struct drm_i915_private *i915 = to_i915(dev);
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci	intel_pxp_resume_complete(i915->pxp);
105262306a36Sopenharmony_ci}
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_cistatic int i915_drm_prepare(struct drm_device *dev)
105562306a36Sopenharmony_ci{
105662306a36Sopenharmony_ci	struct drm_i915_private *i915 = to_i915(dev);
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci	intel_pxp_suspend_prepare(i915->pxp);
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	/*
106162306a36Sopenharmony_ci	 * NB intel_display_driver_suspend() may issue new requests after we've
106262306a36Sopenharmony_ci	 * ostensibly marked the GPU as ready-to-sleep here. We need to
106362306a36Sopenharmony_ci	 * split out that work and pull it forward so that after point,
106462306a36Sopenharmony_ci	 * the GPU is not woken again.
106562306a36Sopenharmony_ci	 */
106662306a36Sopenharmony_ci	return i915_gem_backup_suspend(i915);
106762306a36Sopenharmony_ci}
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_cistatic int i915_drm_suspend(struct drm_device *dev)
107062306a36Sopenharmony_ci{
107162306a36Sopenharmony_ci	struct drm_i915_private *dev_priv = to_i915(dev);
107262306a36Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
107362306a36Sopenharmony_ci	pci_power_t opregion_target_state;
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci	/* We do a lot of poking in a lot of registers, make sure they work
107862306a36Sopenharmony_ci	 * properly. */
107962306a36Sopenharmony_ci	intel_power_domains_disable(dev_priv);
108062306a36Sopenharmony_ci	if (HAS_DISPLAY(dev_priv))
108162306a36Sopenharmony_ci		drm_kms_helper_poll_disable(dev);
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	pci_save_state(pdev);
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	intel_display_driver_suspend(dev_priv);
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci	intel_dp_mst_suspend(dev_priv);
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	intel_runtime_pm_disable_interrupts(dev_priv);
109062306a36Sopenharmony_ci	intel_hpd_cancel_work(dev_priv);
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	intel_suspend_encoders(dev_priv);
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci	/* Must be called before GGTT is suspended. */
109562306a36Sopenharmony_ci	intel_dpt_suspend(dev_priv);
109662306a36Sopenharmony_ci	i915_ggtt_suspend(to_gt(dev_priv)->ggtt);
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci	i915_save_display(dev_priv);
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold;
110162306a36Sopenharmony_ci	intel_opregion_suspend(dev_priv, opregion_target_state);
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	dev_priv->suspend_count++;
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	intel_dmc_suspend(dev_priv);
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	i915_gem_drain_freed_objects(dev_priv);
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	return 0;
111462306a36Sopenharmony_ci}
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_cistatic int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
111762306a36Sopenharmony_ci{
111862306a36Sopenharmony_ci	struct drm_i915_private *dev_priv = to_i915(dev);
111962306a36Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
112062306a36Sopenharmony_ci	struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
112162306a36Sopenharmony_ci	struct intel_gt *gt;
112262306a36Sopenharmony_ci	int ret, i;
112362306a36Sopenharmony_ci	bool s2idle = !hibernation && suspend_to_idle(dev_priv);
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci	disable_rpm_wakeref_asserts(rpm);
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci	intel_pxp_suspend(dev_priv->pxp);
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci	i915_gem_suspend_late(dev_priv);
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_ci	for_each_gt(gt, dev_priv, i)
113262306a36Sopenharmony_ci		intel_uncore_suspend(gt->uncore);
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	intel_power_domains_suspend(dev_priv, s2idle);
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	intel_display_power_suspend_late(dev_priv);
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	ret = vlv_suspend_complete(dev_priv);
113962306a36Sopenharmony_ci	if (ret) {
114062306a36Sopenharmony_ci		drm_err(&dev_priv->drm, "Suspend complete failed: %d\n", ret);
114162306a36Sopenharmony_ci		intel_power_domains_resume(dev_priv);
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci		goto out;
114462306a36Sopenharmony_ci	}
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	pci_disable_device(pdev);
114762306a36Sopenharmony_ci	/*
114862306a36Sopenharmony_ci	 * During hibernation on some platforms the BIOS may try to access
114962306a36Sopenharmony_ci	 * the device even though it's already in D3 and hang the machine. So
115062306a36Sopenharmony_ci	 * leave the device in D0 on those platforms and hope the BIOS will
115162306a36Sopenharmony_ci	 * power down the device properly. The issue was seen on multiple old
115262306a36Sopenharmony_ci	 * GENs with different BIOS vendors, so having an explicit blacklist
115362306a36Sopenharmony_ci	 * is inpractical; apply the workaround on everything pre GEN6. The
115462306a36Sopenharmony_ci	 * platforms where the issue was seen:
115562306a36Sopenharmony_ci	 * Lenovo Thinkpad X301, X61s, X60, T60, X41
115662306a36Sopenharmony_ci	 * Fujitsu FSC S7110
115762306a36Sopenharmony_ci	 * Acer Aspire 1830T
115862306a36Sopenharmony_ci	 */
115962306a36Sopenharmony_ci	if (!(hibernation && GRAPHICS_VER(dev_priv) < 6))
116062306a36Sopenharmony_ci		pci_set_power_state(pdev, PCI_D3hot);
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ciout:
116362306a36Sopenharmony_ci	enable_rpm_wakeref_asserts(rpm);
116462306a36Sopenharmony_ci	if (!dev_priv->uncore.user_forcewake_count)
116562306a36Sopenharmony_ci		intel_runtime_pm_driver_release(rpm);
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	return ret;
116862306a36Sopenharmony_ci}
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ciint i915_driver_suspend_switcheroo(struct drm_i915_private *i915,
117162306a36Sopenharmony_ci				   pm_message_t state)
117262306a36Sopenharmony_ci{
117362306a36Sopenharmony_ci	int error;
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	if (drm_WARN_ON_ONCE(&i915->drm, state.event != PM_EVENT_SUSPEND &&
117662306a36Sopenharmony_ci			     state.event != PM_EVENT_FREEZE))
117762306a36Sopenharmony_ci		return -EINVAL;
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF)
118062306a36Sopenharmony_ci		return 0;
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	error = i915_drm_suspend(&i915->drm);
118362306a36Sopenharmony_ci	if (error)
118462306a36Sopenharmony_ci		return error;
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	return i915_drm_suspend_late(&i915->drm, false);
118762306a36Sopenharmony_ci}
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_cistatic int i915_drm_resume(struct drm_device *dev)
119062306a36Sopenharmony_ci{
119162306a36Sopenharmony_ci	struct drm_i915_private *dev_priv = to_i915(dev);
119262306a36Sopenharmony_ci	struct intel_gt *gt;
119362306a36Sopenharmony_ci	int ret, i;
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	ret = i915_pcode_init(dev_priv);
119862306a36Sopenharmony_ci	if (ret)
119962306a36Sopenharmony_ci		return ret;
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci	sanitize_gpu(dev_priv);
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	ret = i915_ggtt_enable_hw(dev_priv);
120462306a36Sopenharmony_ci	if (ret)
120562306a36Sopenharmony_ci		drm_err(&dev_priv->drm, "failed to re-enable GGTT\n");
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_ci	i915_ggtt_resume(to_gt(dev_priv)->ggtt);
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_ci	for_each_gt(gt, dev_priv, i)
121062306a36Sopenharmony_ci		if (GRAPHICS_VER(gt->i915) >= 8)
121162306a36Sopenharmony_ci			setup_private_pat(gt);
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci	/* Must be called after GGTT is resumed. */
121462306a36Sopenharmony_ci	intel_dpt_resume(dev_priv);
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	intel_dmc_resume(dev_priv);
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	i915_restore_display(dev_priv);
121962306a36Sopenharmony_ci	intel_pps_unlock_regs_wa(dev_priv);
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	intel_init_pch_refclk(dev_priv);
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci	/*
122462306a36Sopenharmony_ci	 * Interrupts have to be enabled before any batches are run. If not the
122562306a36Sopenharmony_ci	 * GPU will hang. i915_gem_init_hw() will initiate batches to
122662306a36Sopenharmony_ci	 * update/restore the context.
122762306a36Sopenharmony_ci	 *
122862306a36Sopenharmony_ci	 * drm_mode_config_reset() needs AUX interrupts.
122962306a36Sopenharmony_ci	 *
123062306a36Sopenharmony_ci	 * Modeset enabling in intel_display_driver_init_hw() also needs working
123162306a36Sopenharmony_ci	 * interrupts.
123262306a36Sopenharmony_ci	 */
123362306a36Sopenharmony_ci	intel_runtime_pm_enable_interrupts(dev_priv);
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci	if (HAS_DISPLAY(dev_priv))
123662306a36Sopenharmony_ci		drm_mode_config_reset(dev);
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci	i915_gem_resume(dev_priv);
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	intel_display_driver_init_hw(dev_priv);
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	intel_clock_gating_init(dev_priv);
124362306a36Sopenharmony_ci	intel_hpd_init(dev_priv);
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci	/* MST sideband requires HPD interrupts enabled */
124662306a36Sopenharmony_ci	intel_dp_mst_resume(dev_priv);
124762306a36Sopenharmony_ci	intel_display_driver_resume(dev_priv);
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	intel_hpd_poll_disable(dev_priv);
125062306a36Sopenharmony_ci	if (HAS_DISPLAY(dev_priv))
125162306a36Sopenharmony_ci		drm_kms_helper_poll_enable(dev);
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci	intel_opregion_resume(dev_priv);
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci	intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false);
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci	intel_power_domains_enable(dev_priv);
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	intel_gvt_resume(dev_priv);
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci	return 0;
126462306a36Sopenharmony_ci}
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_cistatic int i915_drm_resume_early(struct drm_device *dev)
126762306a36Sopenharmony_ci{
126862306a36Sopenharmony_ci	struct drm_i915_private *dev_priv = to_i915(dev);
126962306a36Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
127062306a36Sopenharmony_ci	struct intel_gt *gt;
127162306a36Sopenharmony_ci	int ret, i;
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_ci	/*
127462306a36Sopenharmony_ci	 * We have a resume ordering issue with the snd-hda driver also
127562306a36Sopenharmony_ci	 * requiring our device to be power up. Due to the lack of a
127662306a36Sopenharmony_ci	 * parent/child relationship we currently solve this with an early
127762306a36Sopenharmony_ci	 * resume hook.
127862306a36Sopenharmony_ci	 *
127962306a36Sopenharmony_ci	 * FIXME: This should be solved with a special hdmi sink device or
128062306a36Sopenharmony_ci	 * similar so that power domains can be employed.
128162306a36Sopenharmony_ci	 */
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	/*
128462306a36Sopenharmony_ci	 * Note that we need to set the power state explicitly, since we
128562306a36Sopenharmony_ci	 * powered off the device during freeze and the PCI core won't power
128662306a36Sopenharmony_ci	 * it back up for us during thaw. Powering off the device during
128762306a36Sopenharmony_ci	 * freeze is not a hard requirement though, and during the
128862306a36Sopenharmony_ci	 * suspend/resume phases the PCI core makes sure we get here with the
128962306a36Sopenharmony_ci	 * device powered on. So in case we change our freeze logic and keep
129062306a36Sopenharmony_ci	 * the device powered we can also remove the following set power state
129162306a36Sopenharmony_ci	 * call.
129262306a36Sopenharmony_ci	 */
129362306a36Sopenharmony_ci	ret = pci_set_power_state(pdev, PCI_D0);
129462306a36Sopenharmony_ci	if (ret) {
129562306a36Sopenharmony_ci		drm_err(&dev_priv->drm,
129662306a36Sopenharmony_ci			"failed to set PCI D0 power state (%d)\n", ret);
129762306a36Sopenharmony_ci		return ret;
129862306a36Sopenharmony_ci	}
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ci	/*
130162306a36Sopenharmony_ci	 * Note that pci_enable_device() first enables any parent bridge
130262306a36Sopenharmony_ci	 * device and only then sets the power state for this device. The
130362306a36Sopenharmony_ci	 * bridge enabling is a nop though, since bridge devices are resumed
130462306a36Sopenharmony_ci	 * first. The order of enabling power and enabling the device is
130562306a36Sopenharmony_ci	 * imposed by the PCI core as described above, so here we preserve the
130662306a36Sopenharmony_ci	 * same order for the freeze/thaw phases.
130762306a36Sopenharmony_ci	 *
130862306a36Sopenharmony_ci	 * TODO: eventually we should remove pci_disable_device() /
130962306a36Sopenharmony_ci	 * pci_enable_enable_device() from suspend/resume. Due to how they
131062306a36Sopenharmony_ci	 * depend on the device enable refcount we can't anyway depend on them
131162306a36Sopenharmony_ci	 * disabling/enabling the device.
131262306a36Sopenharmony_ci	 */
131362306a36Sopenharmony_ci	if (pci_enable_device(pdev))
131462306a36Sopenharmony_ci		return -EIO;
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_ci	pci_set_master(pdev);
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_ci	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci	ret = vlv_resume_prepare(dev_priv, false);
132162306a36Sopenharmony_ci	if (ret)
132262306a36Sopenharmony_ci		drm_err(&dev_priv->drm,
132362306a36Sopenharmony_ci			"Resume prepare failed: %d, continuing anyway\n", ret);
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	for_each_gt(gt, dev_priv, i) {
132662306a36Sopenharmony_ci		intel_uncore_resume_early(gt->uncore);
132762306a36Sopenharmony_ci		intel_gt_check_and_clear_faults(gt);
132862306a36Sopenharmony_ci	}
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_ci	intel_display_power_resume_early(dev_priv);
133162306a36Sopenharmony_ci
133262306a36Sopenharmony_ci	intel_power_domains_resume(dev_priv);
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	return ret;
133762306a36Sopenharmony_ci}
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_ciint i915_driver_resume_switcheroo(struct drm_i915_private *i915)
134062306a36Sopenharmony_ci{
134162306a36Sopenharmony_ci	int ret;
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci	if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF)
134462306a36Sopenharmony_ci		return 0;
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci	ret = i915_drm_resume_early(&i915->drm);
134762306a36Sopenharmony_ci	if (ret)
134862306a36Sopenharmony_ci		return ret;
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci	return i915_drm_resume(&i915->drm);
135162306a36Sopenharmony_ci}
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_cistatic int i915_pm_prepare(struct device *kdev)
135462306a36Sopenharmony_ci{
135562306a36Sopenharmony_ci	struct drm_i915_private *i915 = kdev_to_i915(kdev);
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci	if (!i915) {
135862306a36Sopenharmony_ci		dev_err(kdev, "DRM not initialized, aborting suspend.\n");
135962306a36Sopenharmony_ci		return -ENODEV;
136062306a36Sopenharmony_ci	}
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci	if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF)
136362306a36Sopenharmony_ci		return 0;
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci	return i915_drm_prepare(&i915->drm);
136662306a36Sopenharmony_ci}
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_cistatic int i915_pm_suspend(struct device *kdev)
136962306a36Sopenharmony_ci{
137062306a36Sopenharmony_ci	struct drm_i915_private *i915 = kdev_to_i915(kdev);
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	if (!i915) {
137362306a36Sopenharmony_ci		dev_err(kdev, "DRM not initialized, aborting suspend.\n");
137462306a36Sopenharmony_ci		return -ENODEV;
137562306a36Sopenharmony_ci	}
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF)
137862306a36Sopenharmony_ci		return 0;
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	return i915_drm_suspend(&i915->drm);
138162306a36Sopenharmony_ci}
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_cistatic int i915_pm_suspend_late(struct device *kdev)
138462306a36Sopenharmony_ci{
138562306a36Sopenharmony_ci	struct drm_i915_private *i915 = kdev_to_i915(kdev);
138662306a36Sopenharmony_ci
138762306a36Sopenharmony_ci	/*
138862306a36Sopenharmony_ci	 * We have a suspend ordering issue with the snd-hda driver also
138962306a36Sopenharmony_ci	 * requiring our device to be power up. Due to the lack of a
139062306a36Sopenharmony_ci	 * parent/child relationship we currently solve this with an late
139162306a36Sopenharmony_ci	 * suspend hook.
139262306a36Sopenharmony_ci	 *
139362306a36Sopenharmony_ci	 * FIXME: This should be solved with a special hdmi sink device or
139462306a36Sopenharmony_ci	 * similar so that power domains can be employed.
139562306a36Sopenharmony_ci	 */
139662306a36Sopenharmony_ci	if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF)
139762306a36Sopenharmony_ci		return 0;
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_ci	return i915_drm_suspend_late(&i915->drm, false);
140062306a36Sopenharmony_ci}
140162306a36Sopenharmony_ci
140262306a36Sopenharmony_cistatic int i915_pm_poweroff_late(struct device *kdev)
140362306a36Sopenharmony_ci{
140462306a36Sopenharmony_ci	struct drm_i915_private *i915 = kdev_to_i915(kdev);
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci	if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF)
140762306a36Sopenharmony_ci		return 0;
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ci	return i915_drm_suspend_late(&i915->drm, true);
141062306a36Sopenharmony_ci}
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_cistatic int i915_pm_resume_early(struct device *kdev)
141362306a36Sopenharmony_ci{
141462306a36Sopenharmony_ci	struct drm_i915_private *i915 = kdev_to_i915(kdev);
141562306a36Sopenharmony_ci
141662306a36Sopenharmony_ci	if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF)
141762306a36Sopenharmony_ci		return 0;
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	return i915_drm_resume_early(&i915->drm);
142062306a36Sopenharmony_ci}
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_cistatic int i915_pm_resume(struct device *kdev)
142362306a36Sopenharmony_ci{
142462306a36Sopenharmony_ci	struct drm_i915_private *i915 = kdev_to_i915(kdev);
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci	if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF)
142762306a36Sopenharmony_ci		return 0;
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci	return i915_drm_resume(&i915->drm);
143062306a36Sopenharmony_ci}
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_cistatic void i915_pm_complete(struct device *kdev)
143362306a36Sopenharmony_ci{
143462306a36Sopenharmony_ci	struct drm_i915_private *i915 = kdev_to_i915(kdev);
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_ci	if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF)
143762306a36Sopenharmony_ci		return;
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci	i915_drm_complete(&i915->drm);
144062306a36Sopenharmony_ci}
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci/* freeze: before creating the hibernation_image */
144362306a36Sopenharmony_cistatic int i915_pm_freeze(struct device *kdev)
144462306a36Sopenharmony_ci{
144562306a36Sopenharmony_ci	struct drm_i915_private *i915 = kdev_to_i915(kdev);
144662306a36Sopenharmony_ci	int ret;
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci	if (i915->drm.switch_power_state != DRM_SWITCH_POWER_OFF) {
144962306a36Sopenharmony_ci		ret = i915_drm_suspend(&i915->drm);
145062306a36Sopenharmony_ci		if (ret)
145162306a36Sopenharmony_ci			return ret;
145262306a36Sopenharmony_ci	}
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	ret = i915_gem_freeze(i915);
145562306a36Sopenharmony_ci	if (ret)
145662306a36Sopenharmony_ci		return ret;
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_ci	return 0;
145962306a36Sopenharmony_ci}
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_cistatic int i915_pm_freeze_late(struct device *kdev)
146262306a36Sopenharmony_ci{
146362306a36Sopenharmony_ci	struct drm_i915_private *i915 = kdev_to_i915(kdev);
146462306a36Sopenharmony_ci	int ret;
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	if (i915->drm.switch_power_state != DRM_SWITCH_POWER_OFF) {
146762306a36Sopenharmony_ci		ret = i915_drm_suspend_late(&i915->drm, true);
146862306a36Sopenharmony_ci		if (ret)
146962306a36Sopenharmony_ci			return ret;
147062306a36Sopenharmony_ci	}
147162306a36Sopenharmony_ci
147262306a36Sopenharmony_ci	ret = i915_gem_freeze_late(i915);
147362306a36Sopenharmony_ci	if (ret)
147462306a36Sopenharmony_ci		return ret;
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	return 0;
147762306a36Sopenharmony_ci}
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci/* thaw: called after creating the hibernation image, but before turning off. */
148062306a36Sopenharmony_cistatic int i915_pm_thaw_early(struct device *kdev)
148162306a36Sopenharmony_ci{
148262306a36Sopenharmony_ci	return i915_pm_resume_early(kdev);
148362306a36Sopenharmony_ci}
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_cistatic int i915_pm_thaw(struct device *kdev)
148662306a36Sopenharmony_ci{
148762306a36Sopenharmony_ci	return i915_pm_resume(kdev);
148862306a36Sopenharmony_ci}
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci/* restore: called after loading the hibernation image. */
149162306a36Sopenharmony_cistatic int i915_pm_restore_early(struct device *kdev)
149262306a36Sopenharmony_ci{
149362306a36Sopenharmony_ci	return i915_pm_resume_early(kdev);
149462306a36Sopenharmony_ci}
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_cistatic int i915_pm_restore(struct device *kdev)
149762306a36Sopenharmony_ci{
149862306a36Sopenharmony_ci	return i915_pm_resume(kdev);
149962306a36Sopenharmony_ci}
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_cistatic int intel_runtime_suspend(struct device *kdev)
150262306a36Sopenharmony_ci{
150362306a36Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
150462306a36Sopenharmony_ci	struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
150562306a36Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
150662306a36Sopenharmony_ci	struct pci_dev *root_pdev;
150762306a36Sopenharmony_ci	struct intel_gt *gt;
150862306a36Sopenharmony_ci	int ret, i;
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_ci	if (drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_RUNTIME_PM(dev_priv)))
151162306a36Sopenharmony_ci		return -ENODEV;
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	drm_dbg(&dev_priv->drm, "Suspending device\n");
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci	disable_rpm_wakeref_asserts(rpm);
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	/*
151862306a36Sopenharmony_ci	 * We are safe here against re-faults, since the fault handler takes
151962306a36Sopenharmony_ci	 * an RPM reference.
152062306a36Sopenharmony_ci	 */
152162306a36Sopenharmony_ci	i915_gem_runtime_suspend(dev_priv);
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci	intel_pxp_runtime_suspend(dev_priv->pxp);
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_ci	for_each_gt(gt, dev_priv, i)
152662306a36Sopenharmony_ci		intel_gt_runtime_suspend(gt);
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci	intel_runtime_pm_disable_interrupts(dev_priv);
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci	for_each_gt(gt, dev_priv, i)
153162306a36Sopenharmony_ci		intel_uncore_suspend(gt->uncore);
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci	intel_display_power_suspend(dev_priv);
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	ret = vlv_suspend_complete(dev_priv);
153662306a36Sopenharmony_ci	if (ret) {
153762306a36Sopenharmony_ci		drm_err(&dev_priv->drm,
153862306a36Sopenharmony_ci			"Runtime suspend failed, disabling it (%d)\n", ret);
153962306a36Sopenharmony_ci		intel_uncore_runtime_resume(&dev_priv->uncore);
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci		intel_runtime_pm_enable_interrupts(dev_priv);
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci		for_each_gt(gt, dev_priv, i)
154462306a36Sopenharmony_ci			intel_gt_runtime_resume(gt);
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci		enable_rpm_wakeref_asserts(rpm);
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci		return ret;
154962306a36Sopenharmony_ci	}
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	enable_rpm_wakeref_asserts(rpm);
155262306a36Sopenharmony_ci	intel_runtime_pm_driver_release(rpm);
155362306a36Sopenharmony_ci
155462306a36Sopenharmony_ci	if (intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore))
155562306a36Sopenharmony_ci		drm_err(&dev_priv->drm,
155662306a36Sopenharmony_ci			"Unclaimed access detected prior to suspending\n");
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci	/*
155962306a36Sopenharmony_ci	 * FIXME: Temporary hammer to avoid freezing the machine on our DGFX
156062306a36Sopenharmony_ci	 * This should be totally removed when we handle the pci states properly
156162306a36Sopenharmony_ci	 * on runtime PM.
156262306a36Sopenharmony_ci	 */
156362306a36Sopenharmony_ci	root_pdev = pcie_find_root_port(pdev);
156462306a36Sopenharmony_ci	if (root_pdev)
156562306a36Sopenharmony_ci		pci_d3cold_disable(root_pdev);
156662306a36Sopenharmony_ci
156762306a36Sopenharmony_ci	rpm->suspended = true;
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci	/*
157062306a36Sopenharmony_ci	 * FIXME: We really should find a document that references the arguments
157162306a36Sopenharmony_ci	 * used below!
157262306a36Sopenharmony_ci	 */
157362306a36Sopenharmony_ci	if (IS_BROADWELL(dev_priv)) {
157462306a36Sopenharmony_ci		/*
157562306a36Sopenharmony_ci		 * On Broadwell, if we use PCI_D1 the PCH DDI ports will stop
157662306a36Sopenharmony_ci		 * being detected, and the call we do at intel_runtime_resume()
157762306a36Sopenharmony_ci		 * won't be able to restore them. Since PCI_D3hot matches the
157862306a36Sopenharmony_ci		 * actual specification and appears to be working, use it.
157962306a36Sopenharmony_ci		 */
158062306a36Sopenharmony_ci		intel_opregion_notify_adapter(dev_priv, PCI_D3hot);
158162306a36Sopenharmony_ci	} else {
158262306a36Sopenharmony_ci		/*
158362306a36Sopenharmony_ci		 * current versions of firmware which depend on this opregion
158462306a36Sopenharmony_ci		 * notification have repurposed the D1 definition to mean
158562306a36Sopenharmony_ci		 * "runtime suspended" vs. what you would normally expect (D3)
158662306a36Sopenharmony_ci		 * to distinguish it from notifications that might be sent via
158762306a36Sopenharmony_ci		 * the suspend path.
158862306a36Sopenharmony_ci		 */
158962306a36Sopenharmony_ci		intel_opregion_notify_adapter(dev_priv, PCI_D1);
159062306a36Sopenharmony_ci	}
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_ci	assert_forcewakes_inactive(&dev_priv->uncore);
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
159562306a36Sopenharmony_ci		intel_hpd_poll_enable(dev_priv);
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	drm_dbg(&dev_priv->drm, "Device suspended\n");
159862306a36Sopenharmony_ci	return 0;
159962306a36Sopenharmony_ci}
160062306a36Sopenharmony_ci
160162306a36Sopenharmony_cistatic int intel_runtime_resume(struct device *kdev)
160262306a36Sopenharmony_ci{
160362306a36Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
160462306a36Sopenharmony_ci	struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
160562306a36Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
160662306a36Sopenharmony_ci	struct pci_dev *root_pdev;
160762306a36Sopenharmony_ci	struct intel_gt *gt;
160862306a36Sopenharmony_ci	int ret, i;
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	if (drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_RUNTIME_PM(dev_priv)))
161162306a36Sopenharmony_ci		return -ENODEV;
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_ci	drm_dbg(&dev_priv->drm, "Resuming device\n");
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	drm_WARN_ON_ONCE(&dev_priv->drm, atomic_read(&rpm->wakeref_count));
161662306a36Sopenharmony_ci	disable_rpm_wakeref_asserts(rpm);
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci	intel_opregion_notify_adapter(dev_priv, PCI_D0);
161962306a36Sopenharmony_ci	rpm->suspended = false;
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci	root_pdev = pcie_find_root_port(pdev);
162262306a36Sopenharmony_ci	if (root_pdev)
162362306a36Sopenharmony_ci		pci_d3cold_enable(root_pdev);
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci	if (intel_uncore_unclaimed_mmio(&dev_priv->uncore))
162662306a36Sopenharmony_ci		drm_dbg(&dev_priv->drm,
162762306a36Sopenharmony_ci			"Unclaimed access during suspend, bios?\n");
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci	intel_display_power_resume(dev_priv);
163062306a36Sopenharmony_ci
163162306a36Sopenharmony_ci	ret = vlv_resume_prepare(dev_priv, true);
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci	for_each_gt(gt, dev_priv, i)
163462306a36Sopenharmony_ci		intel_uncore_runtime_resume(gt->uncore);
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	intel_runtime_pm_enable_interrupts(dev_priv);
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_ci	/*
163962306a36Sopenharmony_ci	 * No point of rolling back things in case of an error, as the best
164062306a36Sopenharmony_ci	 * we can do is to hope that things will still work (and disable RPM).
164162306a36Sopenharmony_ci	 */
164262306a36Sopenharmony_ci	for_each_gt(gt, dev_priv, i)
164362306a36Sopenharmony_ci		intel_gt_runtime_resume(gt);
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	intel_pxp_runtime_resume(dev_priv->pxp);
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_ci	/*
164862306a36Sopenharmony_ci	 * On VLV/CHV display interrupts are part of the display
164962306a36Sopenharmony_ci	 * power well, so hpd is reinitialized from there. For
165062306a36Sopenharmony_ci	 * everyone else do it here.
165162306a36Sopenharmony_ci	 */
165262306a36Sopenharmony_ci	if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) {
165362306a36Sopenharmony_ci		intel_hpd_init(dev_priv);
165462306a36Sopenharmony_ci		intel_hpd_poll_disable(dev_priv);
165562306a36Sopenharmony_ci	}
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_ci	skl_watermark_ipc_update(dev_priv);
165862306a36Sopenharmony_ci
165962306a36Sopenharmony_ci	enable_rpm_wakeref_asserts(rpm);
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_ci	if (ret)
166262306a36Sopenharmony_ci		drm_err(&dev_priv->drm,
166362306a36Sopenharmony_ci			"Runtime resume failed, disabling it (%d)\n", ret);
166462306a36Sopenharmony_ci	else
166562306a36Sopenharmony_ci		drm_dbg(&dev_priv->drm, "Device resumed\n");
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci	return ret;
166862306a36Sopenharmony_ci}
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ciconst struct dev_pm_ops i915_pm_ops = {
167162306a36Sopenharmony_ci	/*
167262306a36Sopenharmony_ci	 * S0ix (via system suspend) and S3 event handlers [PMSG_SUSPEND,
167362306a36Sopenharmony_ci	 * PMSG_RESUME]
167462306a36Sopenharmony_ci	 */
167562306a36Sopenharmony_ci	.prepare = i915_pm_prepare,
167662306a36Sopenharmony_ci	.suspend = i915_pm_suspend,
167762306a36Sopenharmony_ci	.suspend_late = i915_pm_suspend_late,
167862306a36Sopenharmony_ci	.resume_early = i915_pm_resume_early,
167962306a36Sopenharmony_ci	.resume = i915_pm_resume,
168062306a36Sopenharmony_ci	.complete = i915_pm_complete,
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	/*
168362306a36Sopenharmony_ci	 * S4 event handlers
168462306a36Sopenharmony_ci	 * @freeze, @freeze_late    : called (1) before creating the
168562306a36Sopenharmony_ci	 *                            hibernation image [PMSG_FREEZE] and
168662306a36Sopenharmony_ci	 *                            (2) after rebooting, before restoring
168762306a36Sopenharmony_ci	 *                            the image [PMSG_QUIESCE]
168862306a36Sopenharmony_ci	 * @thaw, @thaw_early       : called (1) after creating the hibernation
168962306a36Sopenharmony_ci	 *                            image, before writing it [PMSG_THAW]
169062306a36Sopenharmony_ci	 *                            and (2) after failing to create or
169162306a36Sopenharmony_ci	 *                            restore the image [PMSG_RECOVER]
169262306a36Sopenharmony_ci	 * @poweroff, @poweroff_late: called after writing the hibernation
169362306a36Sopenharmony_ci	 *                            image, before rebooting [PMSG_HIBERNATE]
169462306a36Sopenharmony_ci	 * @restore, @restore_early : called after rebooting and restoring the
169562306a36Sopenharmony_ci	 *                            hibernation image [PMSG_RESTORE]
169662306a36Sopenharmony_ci	 */
169762306a36Sopenharmony_ci	.freeze = i915_pm_freeze,
169862306a36Sopenharmony_ci	.freeze_late = i915_pm_freeze_late,
169962306a36Sopenharmony_ci	.thaw_early = i915_pm_thaw_early,
170062306a36Sopenharmony_ci	.thaw = i915_pm_thaw,
170162306a36Sopenharmony_ci	.poweroff = i915_pm_suspend,
170262306a36Sopenharmony_ci	.poweroff_late = i915_pm_poweroff_late,
170362306a36Sopenharmony_ci	.restore_early = i915_pm_restore_early,
170462306a36Sopenharmony_ci	.restore = i915_pm_restore,
170562306a36Sopenharmony_ci
170662306a36Sopenharmony_ci	/* S0ix (via runtime suspend) event handlers */
170762306a36Sopenharmony_ci	.runtime_suspend = intel_runtime_suspend,
170862306a36Sopenharmony_ci	.runtime_resume = intel_runtime_resume,
170962306a36Sopenharmony_ci};
171062306a36Sopenharmony_ci
171162306a36Sopenharmony_cistatic const struct file_operations i915_driver_fops = {
171262306a36Sopenharmony_ci	.owner = THIS_MODULE,
171362306a36Sopenharmony_ci	.open = drm_open,
171462306a36Sopenharmony_ci	.release = drm_release_noglobal,
171562306a36Sopenharmony_ci	.unlocked_ioctl = drm_ioctl,
171662306a36Sopenharmony_ci	.mmap = i915_gem_mmap,
171762306a36Sopenharmony_ci	.poll = drm_poll,
171862306a36Sopenharmony_ci	.read = drm_read,
171962306a36Sopenharmony_ci	.compat_ioctl = i915_ioc32_compat_ioctl,
172062306a36Sopenharmony_ci	.llseek = noop_llseek,
172162306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
172262306a36Sopenharmony_ci	.show_fdinfo = drm_show_fdinfo,
172362306a36Sopenharmony_ci#endif
172462306a36Sopenharmony_ci};
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_cistatic int
172762306a36Sopenharmony_cii915_gem_reject_pin_ioctl(struct drm_device *dev, void *data,
172862306a36Sopenharmony_ci			  struct drm_file *file)
172962306a36Sopenharmony_ci{
173062306a36Sopenharmony_ci	return -ENODEV;
173162306a36Sopenharmony_ci}
173262306a36Sopenharmony_ci
173362306a36Sopenharmony_cistatic const struct drm_ioctl_desc i915_ioctls[] = {
173462306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
173562306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_FLUSH, drm_noop, DRM_AUTH),
173662306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_FLIP, drm_noop, DRM_AUTH),
173762306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_BATCHBUFFER, drm_noop, DRM_AUTH),
173862306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_IRQ_EMIT, drm_noop, DRM_AUTH),
173962306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, drm_noop, DRM_AUTH),
174062306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam_ioctl, DRM_RENDER_ALLOW),
174162306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_SETPARAM, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
174262306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_ALLOC, drm_noop, DRM_AUTH),
174362306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_FREE, drm_noop, DRM_AUTH),
174462306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
174562306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, drm_noop, DRM_AUTH),
174662306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP,  drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
174762306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE,  drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
174862306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE,  drm_noop, DRM_AUTH),
174962306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, drm_noop, DRM_AUTH),
175062306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
175162306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
175262306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, drm_invalid_op, DRM_AUTH),
175362306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2_WR, i915_gem_execbuffer2_ioctl, DRM_RENDER_ALLOW),
175462306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
175562306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
175662306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_RENDER_ALLOW),
175762306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_SET_CACHING, i915_gem_set_caching_ioctl, DRM_RENDER_ALLOW),
175862306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_GET_CACHING, i915_gem_get_caching_ioctl, DRM_RENDER_ALLOW),
175962306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_RENDER_ALLOW),
176062306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_ENTERVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
176162306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_LEAVEVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
176262306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_CREATE, i915_gem_create_ioctl, DRM_RENDER_ALLOW),
176362306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_CREATE_EXT, i915_gem_create_ext_ioctl, DRM_RENDER_ALLOW),
176462306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_RENDER_ALLOW),
176562306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_RENDER_ALLOW),
176662306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_RENDER_ALLOW),
176762306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_OFFSET, i915_gem_mmap_offset_ioctl, DRM_RENDER_ALLOW),
176862306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_RENDER_ALLOW),
176962306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_RENDER_ALLOW),
177062306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling_ioctl, DRM_RENDER_ALLOW),
177162306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling_ioctl, DRM_RENDER_ALLOW),
177262306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_RENDER_ALLOW),
177362306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id_ioctl, 0),
177462306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_RENDER_ALLOW),
177562306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image_ioctl, DRM_MASTER),
177662306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs_ioctl, DRM_MASTER),
177762306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey_ioctl, DRM_MASTER),
177862306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, drm_noop, DRM_MASTER),
177962306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_RENDER_ALLOW),
178062306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE_EXT, i915_gem_context_create_ioctl, DRM_RENDER_ALLOW),
178162306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_RENDER_ALLOW),
178262306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_RENDER_ALLOW),
178362306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_gem_context_reset_stats_ioctl, DRM_RENDER_ALLOW),
178462306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_RENDER_ALLOW),
178562306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW),
178662306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_RENDER_ALLOW),
178762306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_PERF_OPEN, i915_perf_open_ioctl, DRM_RENDER_ALLOW),
178862306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_PERF_ADD_CONFIG, i915_perf_add_config_ioctl, DRM_RENDER_ALLOW),
178962306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_PERF_REMOVE_CONFIG, i915_perf_remove_config_ioctl, DRM_RENDER_ALLOW),
179062306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_QUERY, i915_query_ioctl, DRM_RENDER_ALLOW),
179162306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_VM_CREATE, i915_gem_vm_create_ioctl, DRM_RENDER_ALLOW),
179262306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(I915_GEM_VM_DESTROY, i915_gem_vm_destroy_ioctl, DRM_RENDER_ALLOW),
179362306a36Sopenharmony_ci};
179462306a36Sopenharmony_ci
179562306a36Sopenharmony_ci/*
179662306a36Sopenharmony_ci * Interface history:
179762306a36Sopenharmony_ci *
179862306a36Sopenharmony_ci * 1.1: Original.
179962306a36Sopenharmony_ci * 1.2: Add Power Management
180062306a36Sopenharmony_ci * 1.3: Add vblank support
180162306a36Sopenharmony_ci * 1.4: Fix cmdbuffer path, add heap destroy
180262306a36Sopenharmony_ci * 1.5: Add vblank pipe configuration
180362306a36Sopenharmony_ci * 1.6: - New ioctl for scheduling buffer swaps on vertical blank
180462306a36Sopenharmony_ci *      - Support vertical blank on secondary display pipe
180562306a36Sopenharmony_ci */
180662306a36Sopenharmony_ci#define DRIVER_MAJOR		1
180762306a36Sopenharmony_ci#define DRIVER_MINOR		6
180862306a36Sopenharmony_ci#define DRIVER_PATCHLEVEL	0
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_cistatic const struct drm_driver i915_drm_driver = {
181162306a36Sopenharmony_ci	/* Don't use MTRRs here; the Xserver or userspace app should
181262306a36Sopenharmony_ci	 * deal with them for Intel hardware.
181362306a36Sopenharmony_ci	 */
181462306a36Sopenharmony_ci	.driver_features =
181562306a36Sopenharmony_ci	    DRIVER_GEM |
181662306a36Sopenharmony_ci	    DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_SYNCOBJ |
181762306a36Sopenharmony_ci	    DRIVER_SYNCOBJ_TIMELINE,
181862306a36Sopenharmony_ci	.release = i915_driver_release,
181962306a36Sopenharmony_ci	.open = i915_driver_open,
182062306a36Sopenharmony_ci	.lastclose = i915_driver_lastclose,
182162306a36Sopenharmony_ci	.postclose = i915_driver_postclose,
182262306a36Sopenharmony_ci	.show_fdinfo = PTR_IF(IS_ENABLED(CONFIG_PROC_FS), i915_drm_client_fdinfo),
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_ci	.gem_prime_import = i915_gem_prime_import,
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_ci	.dumb_create = i915_gem_dumb_create,
182762306a36Sopenharmony_ci	.dumb_map_offset = i915_gem_dumb_mmap_offset,
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_ci	.ioctls = i915_ioctls,
183062306a36Sopenharmony_ci	.num_ioctls = ARRAY_SIZE(i915_ioctls),
183162306a36Sopenharmony_ci	.fops = &i915_driver_fops,
183262306a36Sopenharmony_ci	.name = DRIVER_NAME,
183362306a36Sopenharmony_ci	.desc = DRIVER_DESC,
183462306a36Sopenharmony_ci	.date = DRIVER_DATE,
183562306a36Sopenharmony_ci	.major = DRIVER_MAJOR,
183662306a36Sopenharmony_ci	.minor = DRIVER_MINOR,
183762306a36Sopenharmony_ci	.patchlevel = DRIVER_PATCHLEVEL,
183862306a36Sopenharmony_ci};
1839