All of lore.kernel.org
 help / color / mirror / Atom feed
* Reordering debugfs registration vs driver loading
@ 2016-05-27 14:00 Chris Wilson
  2016-05-27 14:00 ` [PATCH 01/11] drm: Export drm_dev_init() for subclassing Chris Wilson
                   ` (11 more replies)
  0 siblings, 12 replies; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

What started out as a simple patch turned into a midlayer minefield,
thanks Daniel. The result though should be something much, much safer
for asynchronous loading - please review kindly!
-Chris

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 01/11] drm: Export drm_dev_init() for subclassing
  2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
@ 2016-05-27 14:00 ` Chris Wilson
  2016-05-27 15:29   ` Nils Wallménius
  2016-05-27 14:00 ` [PATCH 02/11] drm: Add a callback from connector registering Chris Wilson
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter, dri-devel

In order to allow drivers to pack their privates and drm_device into one
struct (e.g. for subclassing), export the initialisation routines for
struct drm_device.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: dri-devel@lists.freedesktop.org
---
 drivers/gpu/drm/drm_drv.c | 63 ++++++++++++++++++++++++++++++++++++-----------
 include/drm/drmP.h        |  3 +++
 2 files changed, 52 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index bff89226a344..ceb85e611a07 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -549,11 +549,12 @@ static void drm_fs_inode_free(struct inode *inode)
 }
 
 /**
- * drm_dev_alloc - Allocate new DRM device
- * @driver: DRM driver to allocate device for
+ * drm_dev_init - Initialise new DRM device
+ * @dev: DRM device
+ * @driver: DRM driver
  * @parent: Parent device object
  *
- * Allocate and initialize a new DRM device. No device registration is done.
+ * Initialize a new DRM device. No device registration is done.
  * Call drm_dev_register() to advertice the device to user space and register it
  * with other core subsystems. This should be done last in the device
  * initialization sequence to make sure userspace can't access an inconsistent
@@ -565,18 +566,14 @@ static void drm_fs_inode_free(struct inode *inode)
  * Note that for purely virtual devices @parent can be NULL.
  *
  * RETURNS:
- * Pointer to new DRM device, or NULL if out of memory.
+ * 0 on success, or error code on failure.
  */
-struct drm_device *drm_dev_alloc(struct drm_driver *driver,
-				 struct device *parent)
+int drm_dev_init(struct drm_device *dev,
+		 struct drm_driver *driver,
+		 struct device *parent)
 {
-	struct drm_device *dev;
 	int ret;
 
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return NULL;
-
 	kref_init(&dev->ref);
 	dev->dev = parent;
 	dev->driver = driver;
@@ -638,7 +635,7 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
 			goto err_setunique;
 	}
 
-	return dev;
+	return 0;
 
 err_setunique:
 	if (drm_core_check_feature(dev, DRIVER_GEM))
@@ -653,8 +650,46 @@ err_minors:
 	drm_fs_inode_free(dev->anon_inode);
 err_free:
 	mutex_destroy(&dev->master_mutex);
-	kfree(dev);
-	return NULL;
+	return 0;
+}
+EXPORT_SYMBOL(drm_dev_init);
+
+/**
+ * drm_dev_alloc - Allocate new DRM device
+ * @driver: DRM driver to allocate device for
+ * @parent: Parent device object
+ *
+ * Allocate and initialize a new DRM device. No device registration is done.
+ * Call drm_dev_register() to advertice the device to user space and register it
+ * with other core subsystems. This should be done last in the device
+ * initialization sequence to make sure userspace can't access an inconsistent
+ * state.
+ *
+ * The initial ref-count of the object is 1. Use drm_dev_ref() and
+ * drm_dev_unref() to take and drop further ref-counts.
+ *
+ * Note that for purely virtual devices @parent can be NULL.
+ *
+ * RETURNS:
+ * Pointer to new DRM device, or NULL if out of memory.
+ */
+struct drm_device *drm_dev_alloc(struct drm_driver *driver,
+				 struct device *parent)
+{
+	struct drm_device *dev;
+	int ret;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	ret = drm_dev_init(dev, driver, parent);
+	if (ret) {
+		kfree(dev);
+		return NULL;
+	}
+
+	return dev;
 }
 EXPORT_SYMBOL(drm_dev_alloc);
 
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index c5d29505f937..12dc5f9cad89 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1075,6 +1075,9 @@ extern void drm_sysfs_hotplug_event(struct drm_device *dev);
 
 struct drm_device *drm_dev_alloc(struct drm_driver *driver,
 				 struct device *parent);
+int drm_dev_init(struct drm_device *dev,
+		 struct drm_driver *driver,
+		 struct device *parent);
 void drm_dev_ref(struct drm_device *dev);
 void drm_dev_unref(struct drm_device *dev);
 int drm_dev_register(struct drm_device *dev, unsigned long flags);
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 02/11] drm: Add a callback from connector registering
  2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
  2016-05-27 14:00 ` [PATCH 01/11] drm: Export drm_dev_init() for subclassing Chris Wilson
@ 2016-05-27 14:00 ` Chris Wilson
  2016-05-30  8:49   ` Daniel Vetter
  2016-05-27 14:00 ` [PATCH 03/11] drm/i915: Perform async fbdev initialisation much later Chris Wilson
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter, dri-devel

If a driver wants to more precisely control its initialisation and in
particular, defer registering its interfaces with userspace until after
everything is setup, it also needs to defer registering the connectors.
As some devices need more work during registration, add a callback so
that drivers can do additional work if required for a connector.

Correspondingly, we also require an unregister callback.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: dri-devel@lists.freedesktop.org
---
 drivers/gpu/drm/drm_crtc.c | 18 ++++++++++++++++--
 include/drm/drm_crtc.h     | 21 +++++++++++++++++++++
 2 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index d2a6d958ca76..81641544ac3e 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1036,13 +1036,24 @@ int drm_connector_register(struct drm_connector *connector)
 
 	ret = drm_debugfs_connector_add(connector);
 	if (ret) {
-		drm_sysfs_connector_remove(connector);
-		return ret;
+		goto err_sysfs;
+	}
+
+	if (connector->funcs->late_register) {
+		ret = connector->funcs->late_register(connector);
+		if (ret)
+			goto err_debugfs;
 	}
 
 	drm_mode_object_register(connector->dev, &connector->base);
 
 	return 0;
+
+err_debugfs:
+	drm_debugfs_connector_remove(connector);
+err_sysfs:
+	drm_sysfs_connector_remove(connector);
+	return ret;
 }
 EXPORT_SYMBOL(drm_connector_register);
 
@@ -1054,6 +1065,9 @@ EXPORT_SYMBOL(drm_connector_register);
  */
 void drm_connector_unregister(struct drm_connector *connector)
 {
+	if (connector->funcs->early_unregister)
+		connector->funcs->early_unregister(connector);
+
 	drm_sysfs_connector_remove(connector);
 	drm_debugfs_connector_remove(connector);
 }
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index d1559cd04e3d..0f7425444a44 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -926,6 +926,27 @@ struct drm_connector_funcs {
 			     uint64_t val);
 
 	/**
+	 * @late_register:
+	 *
+	 * Register the connector with userspace, called from
+	 * drm_connector_register. This should be called after driver
+	 * load during its registration phase. All actions such as registering
+	 * with auxiliary devices (such as drm_dp_aux_register) should be done
+	 * during this callback.
+	 */
+	int (*late_register)(struct drm_connector *connector);
+
+	/**
+	 * @early_unregister:
+	 *
+	 * Unregister the connector with userspace, called from
+	 * drm_connector_unregister. This is called early in the driver
+	 * unload sequence to disable userspace access before data
+	 * structures are torndown.
+	 */
+	void (*early_unregister)(struct drm_connector *connector);
+
+	/**
 	 * @destroy:
 	 *
 	 * Clean up connector resources. This is called at driver unload time
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 03/11] drm/i915: Perform async fbdev initialisation much later
  2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
  2016-05-27 14:00 ` [PATCH 01/11] drm: Export drm_dev_init() for subclassing Chris Wilson
  2016-05-27 14:00 ` [PATCH 02/11] drm: Add a callback from connector registering Chris Wilson
@ 2016-05-27 14:00 ` Chris Wilson
  2016-05-27 14:00 ` [PATCH 04/11] drm/i915: Move connector registration to driver registration phase Chris Wilson
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

Setting up fbdev requires everything ready and registered (in particular
the connectors). In the next patch, we defer registration of the KMS
objects and unless we defer setting off fbdev, it may run before they are
registered and oops.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_dma.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 07edaed9d5a2..650b3f7e2a8e 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -525,18 +525,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
 	/* Only enable hotplug handling once the fbdev is fully set up. */
 	intel_hpd_init(dev_priv);
 
-	/*
-	 * Some ports require correctly set-up hpd registers for detection to
-	 * work properly (leading to ghost connected connector status), e.g. VGA
-	 * on gm45.  Hence we can only set up the initial fbdev config after hpd
-	 * irqs are fully enabled. Now we should scan for the initial config
-	 * only once hotplug handling is enabled, but due to screwed-up locking
-	 * around kms/fbdev init we can't protect the fdbev initial config
-	 * scanning against hotplug events. Hence do this first and ignore the
-	 * tiny window where we will loose hotplug notifactions.
-	 */
-	intel_fbdev_initial_config_async(dev);
-
 	drm_kms_helper_poll_init(dev);
 
 	return 0;
@@ -1384,6 +1372,18 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
 		intel_gpu_ips_init(dev_priv);
 
 	i915_audio_component_init(dev_priv);
+
+	/*
+	 * Some ports require correctly set-up hpd registers for detection to
+	 * work properly (leading to ghost connected connector status), e.g. VGA
+	 * on gm45.  Hence we can only set up the initial fbdev config after hpd
+	 * irqs are fully enabled. Now we should scan for the initial config
+	 * only once hotplug handling is enabled, but due to screwed-up locking
+	 * around kms/fbdev init we can't protect the fdbev initial config
+	 * scanning against hotplug events. Hence do this first and ignore the
+	 * tiny window where we will loose hotplug notifactions.
+	 */
+	intel_fbdev_initial_config_async(dev);
 }
 
 /**
-- 
2.8.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 04/11] drm/i915: Move connector registration to driver registration phase
  2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
                   ` (2 preceding siblings ...)
  2016-05-27 14:00 ` [PATCH 03/11] drm/i915: Perform async fbdev initialisation much later Chris Wilson
@ 2016-05-27 14:00 ` Chris Wilson
  2016-05-27 14:00 ` [PATCH 05/11] drm/i915: Register debugfs interface last Chris Wilson
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

Don't try and present the connectors to userspace (via sysfs and other
devices) before the driver is ready.

Correspondingly, be sure to make the userspace interfaces disappear
first.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c      |  2 ++
 drivers/gpu/drm/i915/i915_drv.h      |  4 ++-
 drivers/gpu/drm/i915/intel_crt.c     |  4 +--
 drivers/gpu/drm/i915/intel_display.c | 20 +++++++------
 drivers/gpu/drm/i915/intel_dp.c      | 58 +++++++++++++++++-------------------
 drivers/gpu/drm/i915/intel_dp_mst.c  |  6 ++--
 drivers/gpu/drm/i915/intel_drv.h     |  8 -----
 drivers/gpu/drm/i915/intel_dsi.c     |  4 +--
 drivers/gpu/drm/i915/intel_dvo.c     |  3 +-
 drivers/gpu/drm/i915/intel_hdmi.c    |  3 +-
 drivers/gpu/drm/i915/intel_lvds.c    |  3 +-
 drivers/gpu/drm/i915/intel_sdvo.c    | 55 ++++++++++++++--------------------
 drivers/gpu/drm/i915/intel_tv.c      |  3 +-
 13 files changed, 75 insertions(+), 98 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 650b3f7e2a8e..4a7a2c08becd 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1361,6 +1361,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
 		I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY);
 
 	i915_setup_sysfs(dev);
+	intel_modeset_register(dev_priv);
 
 	if (INTEL_INFO(dev_priv)->num_pipes) {
 		/* Must be done after probing outputs */
@@ -1396,6 +1397,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
 	intel_gpu_ips_teardown();
 	acpi_video_unregister();
 	intel_opregion_unregister(dev_priv);
+	intel_modeset_unregister(dev_priv);
 	i915_teardown_sysfs(dev_priv->dev);
 	i915_gem_shrinker_cleanup(dev_priv);
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e4c8e341655c..c530160c17d5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3671,7 +3671,9 @@ extern void intel_modeset_init_hw(struct drm_device *dev);
 extern void intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
-extern void intel_connector_unregister(struct intel_connector *);
+extern void intel_modeset_register(struct drm_i915_private *dev_priv);
+extern void intel_modeset_unregister(struct drm_i915_private *dev_priv);
+extern void intel_connector_unregister(struct drm_connector *);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
 extern void intel_display_resume(struct drm_device *dev);
 extern void i915_redisable_vga(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 3fbb6fc66451..3ea5da06b9f1 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -743,6 +743,7 @@ static const struct drm_connector_funcs intel_crt_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.detect = intel_crt_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
+	.early_unregister = intel_connector_unregister,
 	.destroy = intel_crt_destroy,
 	.set_property = intel_crt_set_property,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
@@ -876,12 +877,9 @@ void intel_crt_init(struct drm_device *dev)
 		crt->base.get_hw_state = intel_crt_get_hw_state;
 	}
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
-	intel_connector->unregister = intel_connector_unregister;
 
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
-	drm_connector_register(connector);
-
 	if (!I915_HAS_HOTPLUG(dev))
 		intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e775d08b121b..8c4094611b21 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15431,6 +15431,16 @@ void intel_modeset_init_hw(struct drm_device *dev)
 	intel_enable_gt_powersave(dev_priv);
 }
 
+void intel_modeset_register(struct drm_i915_private *dev_priv)
+{
+	drm_connector_register_all(dev_priv->dev);
+}
+
+void intel_modeset_unregister(struct drm_i915_private *dev_priv)
+{
+	drm_connector_unregister_all(dev_priv->dev);
+}
+
 /*
  * Calculate what we think the watermarks should be for the state we've read
  * out of the hardware and then immediately program those watermarks so that
@@ -16198,18 +16208,14 @@ void intel_modeset_gem_init(struct drm_device *dev)
 	intel_backlight_register(dev);
 }
 
-void intel_connector_unregister(struct intel_connector *intel_connector)
+void intel_connector_unregister(struct drm_connector *connector)
 {
-	struct drm_connector *connector = &intel_connector->base;
-
 	intel_panel_destroy_backlight(connector);
-	drm_connector_unregister(connector);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_connector *connector;
 
 	intel_disable_gt_powersave(dev_priv);
 
@@ -16235,10 +16241,6 @@ void intel_modeset_cleanup(struct drm_device *dev)
 	/* flush any delayed tasks or pending work */
 	flush_scheduled_work();
 
-	/* destroy the backlight and sysfs files before encoders/connectors */
-	for_each_intel_connector(dev, connector)
-		connector->unregister(connector);
-
 	drm_mode_config_cleanup(dev);
 
 	intel_cleanup_overlay(dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index aa9c59ee17f6..d077f30d6804 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1177,7 +1177,6 @@ static void intel_aux_reg_init(struct intel_dp *intel_dp)
 static void
 intel_dp_aux_fini(struct intel_dp *intel_dp)
 {
-	drm_dp_aux_unregister(&intel_dp->aux);
 	kfree(intel_dp->aux.name);
 }
 
@@ -1186,7 +1185,6 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	enum port port = intel_dig_port->port;
-	int ret;
 
 	intel_aux_reg_init(intel_dp);
 
@@ -1194,33 +1192,9 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
 	if (!intel_dp->aux.name)
 		return -ENOMEM;
 
-	intel_dp->aux.dev = connector->base.kdev;
-	intel_dp->aux.transfer = intel_dp_aux_transfer;
-
-	DRM_DEBUG_KMS("registering %s bus for %s\n",
-		      intel_dp->aux.name,
-		      connector->base.kdev->kobj.name);
-
-	ret = drm_dp_aux_register(&intel_dp->aux);
-	if (ret < 0) {
-		DRM_ERROR("drm_dp_aux_register() for %s failed (%d)\n",
-			  intel_dp->aux.name, ret);
-		kfree(intel_dp->aux.name);
-		return ret;
-	}
-
 	return 0;
 }
 
-static void
-intel_dp_connector_unregister(struct intel_connector *intel_connector)
-{
-	struct intel_dp *intel_dp = intel_attached_dp(&intel_connector->base);
-
-	intel_dp_aux_fini(intel_dp);
-	intel_connector_unregister(intel_connector);
-}
-
 static int
 intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
 {
@@ -4456,6 +4430,29 @@ done:
 	return 0;
 }
 
+static int
+intel_dp_connector_register(struct drm_connector *connector)
+{
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
+
+	i915_debugfs_connector_add(connector);
+
+	DRM_DEBUG_KMS("registering %s bus for %s\n",
+		      intel_dp->aux.name, connector->kdev->kobj.name);
+
+	intel_dp->aux.dev = connector->kdev;
+	intel_dp->aux.transfer = intel_dp_aux_transfer;
+
+	return drm_dp_aux_register(&intel_dp->aux);
+}
+
+static void
+intel_dp_connector_unregister(struct drm_connector *connector)
+{
+	drm_dp_aux_unregister(&intel_attached_dp(connector)->aux);
+	intel_connector_unregister(connector);
+}
+
 static void
 intel_dp_connector_destroy(struct drm_connector *connector)
 {
@@ -4466,6 +4463,8 @@ intel_dp_connector_destroy(struct drm_connector *connector)
 	if (!IS_ERR_OR_NULL(intel_connector->edid))
 		kfree(intel_connector->edid);
 
+	intel_dp_aux_fini(intel_attached_dp(connector));
+
 	/* Can't call is_edp() since the encoder may have been destroyed
 	 * already. */
 	if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
@@ -4572,6 +4571,8 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = {
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_dp_set_property,
 	.atomic_get_property = intel_connector_atomic_get_property,
+	.late_register = intel_dp_connector_register,
+	.early_unregister = intel_dp_connector_unregister,
 	.destroy = intel_dp_connector_destroy,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -5479,13 +5480,11 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 			  edp_panel_vdd_work);
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
-	drm_connector_register(connector);
 
 	if (HAS_DDI(dev))
 		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
 	else
 		intel_connector->get_hw_state = intel_connector_get_hw_state;
-	intel_connector->unregister = intel_dp_connector_unregister;
 
 	/* Set up the hotplug pin. */
 	switch (port) {
@@ -5547,8 +5546,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
 	}
 
-	i915_debugfs_connector_add(connector);
-
 	return true;
 
 fail:
@@ -5562,7 +5559,6 @@ fail:
 		edp_panel_vdd_off_sync(intel_dp);
 		pps_unlock(intel_dp);
 	}
-	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 
 	return false;
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 7a34090cef34..5d718d27eb64 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -336,6 +336,7 @@ static const struct drm_connector_funcs intel_dp_mst_connector_funcs = {
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_dp_mst_set_property,
 	.atomic_get_property = intel_connector_atomic_get_property,
+	.early_unregister = intel_connector_unregister,
 	.destroy = intel_dp_mst_connector_destroy,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -455,7 +456,6 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
 	drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort);
 	drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs);
 
-	intel_connector->unregister = intel_connector_unregister;
 	intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
 	intel_connector->mst_port = intel_dp;
 	intel_connector->port = port;
@@ -477,9 +477,11 @@ static void intel_dp_register_mst_connector(struct drm_connector *connector)
 {
 	struct intel_connector *intel_connector = to_intel_connector(connector);
 	struct drm_device *dev = connector->dev;
+
 	drm_modeset_lock_all(dev);
 	intel_connector_add_to_fbdev(intel_connector);
 	drm_modeset_unlock_all(dev);
+
 	drm_connector_register(&intel_connector->base);
 }
 
@@ -489,7 +491,7 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
 	struct intel_connector *intel_connector = to_intel_connector(connector);
 	struct drm_device *dev = connector->dev;
 
-	intel_connector->unregister(intel_connector);
+	drm_connector_unregister(connector);
 
 	/* need to nuke the connector */
 	drm_modeset_lock_all(dev);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9b5f6634c558..12099f9a1d3a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -242,14 +242,6 @@ struct intel_connector {
 	 * and active (i.e. dpms ON state). */
 	bool (*get_hw_state)(struct intel_connector *);
 
-	/*
-	 * Removes all interfaces through which the connector is accessible
-	 * - like sysfs, debugfs entries -, so that no new operations can be
-	 * started on the connector. Also makes sure all currently pending
-	 * operations finish before returing.
-	 */
-	void (*unregister)(struct intel_connector *);
-
 	/* Panel info for eDP and LVDS */
 	struct intel_panel panel;
 
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 4009618a5b34..0eb09bb34919 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -1385,6 +1385,7 @@ static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs
 static const struct drm_connector_funcs intel_dsi_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.detect = intel_dsi_detect,
+	.early_unregister = intel_connector_unregister,
 	.destroy = intel_dsi_connector_destroy,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_dsi_set_property,
@@ -1461,7 +1462,6 @@ void intel_dsi_init(struct drm_device *dev)
 	intel_encoder->get_config = intel_dsi_get_config;
 
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
-	intel_connector->unregister = intel_connector_unregister;
 
 	/*
 	 * On BYT/CHV, pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI
@@ -1582,8 +1582,6 @@ void intel_dsi_init(struct drm_device *dev)
 
 	intel_dsi_add_properties(intel_connector);
 
-	drm_connector_register(connector);
-
 	intel_panel_setup_backlight(connector, INVALID_PIPE);
 
 	return;
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 286baec979c8..199c3899496d 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -341,6 +341,7 @@ static void intel_dvo_destroy(struct drm_connector *connector)
 static const struct drm_connector_funcs intel_dvo_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.detect = intel_dvo_detect,
+	.early_unregister = intel_connector_unregister,
 	.destroy = intel_dvo_destroy,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.atomic_get_property = intel_connector_atomic_get_property,
@@ -438,7 +439,6 @@ void intel_dvo_init(struct drm_device *dev)
 	intel_encoder->compute_config = intel_dvo_compute_config;
 	intel_encoder->pre_enable = intel_dvo_pre_enable;
 	intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
-	intel_connector->unregister = intel_connector_unregister;
 
 	/* Now, try to find a controller */
 	for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
@@ -537,7 +537,6 @@ void intel_dvo_init(struct drm_device *dev)
 			intel_dvo->panel_wants_dither = true;
 		}
 
-		drm_connector_register(connector);
 		return;
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 6b52c6accf6a..cea6b4de4018 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1774,6 +1774,7 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_hdmi_set_property,
 	.atomic_get_property = intel_connector_atomic_get_property,
+	.early_unregister = intel_connector_unregister,
 	.destroy = intel_hdmi_destroy,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -1907,12 +1908,10 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
 	else
 		intel_connector->get_hw_state = intel_connector_get_hw_state;
-	intel_connector->unregister = intel_connector_unregister;
 
 	intel_hdmi_add_properties(intel_hdmi, connector);
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
-	drm_connector_register(connector);
 	intel_hdmi->attached_connector = intel_connector;
 
 	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index d65fd945607a..11a438dbd0c5 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -556,6 +556,7 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = {
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_lvds_set_property,
 	.atomic_get_property = intel_connector_atomic_get_property,
+	.early_unregister = intel_connector_unregister,
 	.destroy = intel_lvds_destroy,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -992,7 +993,6 @@ void intel_lvds_init(struct drm_device *dev)
 	intel_encoder->get_hw_state = intel_lvds_get_hw_state;
 	intel_encoder->get_config = intel_lvds_get_config;
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
-	intel_connector->unregister = intel_connector_unregister;
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_LVDS;
@@ -1129,7 +1129,6 @@ out:
 		DRM_DEBUG_KMS("lid notifier registration failed\n");
 		lvds_connector->lid_notifier.notifier_call = NULL;
 	}
-	drm_connector_register(connector);
 
 	intel_panel_setup_backlight(connector, INVALID_PIPE);
 
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 2128fae5687d..b83ad62c1273 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2177,12 +2177,34 @@ done:
 #undef CHECK_PROPERTY
 }
 
+static int
+intel_sdvo_register(struct drm_connector *connector)
+{
+	struct intel_sdvo *sdvo = intel_attached_sdvo(connector);
+
+	return sysfs_create_link(&connector->kdev->kobj,
+				 &sdvo->ddc.dev.kobj,
+				 sdvo->ddc.dev.kobj.name);
+}
+
+static void
+intel_sdvo_connector_unregister(struct drm_connector *connector)
+{
+	struct intel_sdvo *sdvo = intel_attached_sdvo(connector);
+
+	sysfs_remove_link(&connector->kdev->kobj,
+			  sdvo->ddc.dev.kobj.name);
+	intel_connector_unregister(connector);
+}
+
 static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.detect = intel_sdvo_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_sdvo_set_property,
 	.atomic_get_property = intel_connector_atomic_get_property,
+	.late_register = intel_sdvo_register,
+	.early_unregister = intel_sdvo_connector_unregister,
 	.destroy = intel_sdvo_destroy,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -2346,20 +2368,6 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, struct intel_sdvo *sdvo)
 		return 0x72;
 }
 
-static void
-intel_sdvo_connector_unregister(struct intel_connector *intel_connector)
-{
-	struct drm_connector *drm_connector;
-	struct intel_sdvo *sdvo_encoder;
-
-	drm_connector = &intel_connector->base;
-	sdvo_encoder = intel_attached_sdvo(&intel_connector->base);
-
-	sysfs_remove_link(&drm_connector->kdev->kobj,
-			  sdvo_encoder->ddc.dev.kobj.name);
-	intel_connector_unregister(intel_connector);
-}
-
 static int
 intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
 			  struct intel_sdvo *encoder)
@@ -2382,27 +2390,10 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
 	connector->base.base.doublescan_allowed = 0;
 	connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
 	connector->base.get_hw_state = intel_sdvo_connector_get_hw_state;
-	connector->base.unregister = intel_sdvo_connector_unregister;
 
 	intel_connector_attach_encoder(&connector->base, &encoder->base);
-	ret = drm_connector_register(drm_connector);
-	if (ret < 0)
-		goto err1;
-
-	ret = sysfs_create_link(&drm_connector->kdev->kobj,
-				&encoder->ddc.dev.kobj,
-				encoder->ddc.dev.kobj.name);
-	if (ret < 0)
-		goto err2;
 
 	return 0;
-
-err2:
-	drm_connector_unregister(drm_connector);
-err1:
-	drm_connector_cleanup(drm_connector);
-
-	return ret;
 }
 
 static void
@@ -2529,7 +2520,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
 	return true;
 
 err:
-	drm_connector_unregister(connector);
 	intel_sdvo_destroy(connector);
 	return false;
 }
@@ -2608,7 +2598,6 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
 	return true;
 
 err:
-	drm_connector_unregister(connector);
 	intel_sdvo_destroy(connector);
 	return false;
 }
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 223129d3c765..a054b4886a73 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1501,6 +1501,7 @@ out:
 static const struct drm_connector_funcs intel_tv_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.detect = intel_tv_detect,
+	.early_unregister = intel_connector_unregister,
 	.destroy = intel_tv_destroy,
 	.set_property = intel_tv_set_property,
 	.atomic_get_property = intel_connector_atomic_get_property,
@@ -1600,7 +1601,6 @@ intel_tv_init(struct drm_device *dev)
 	intel_encoder->disable = intel_disable_tv;
 	intel_encoder->get_hw_state = intel_tv_get_hw_state;
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
-	intel_connector->unregister = intel_connector_unregister;
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_TVOUT;
@@ -1642,5 +1642,4 @@ intel_tv_init(struct drm_device *dev)
 	drm_object_attach_property(&connector->base,
 				   dev->mode_config.tv_bottom_margin_property,
 				   intel_tv->margin[TV_MARGIN_BOTTOM]);
-	drm_connector_register(connector);
 }
-- 
2.8.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 05/11] drm/i915: Register debugfs interface last
  2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
                   ` (3 preceding siblings ...)
  2016-05-27 14:00 ` [PATCH 04/11] drm/i915: Move connector registration to driver registration phase Chris Wilson
@ 2016-05-27 14:00 ` Chris Wilson
  2016-05-27 14:00 ` [PATCH 06/11] drm/i915: Demidlayer driver loading Chris Wilson
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

Currently debugfs files are created before the driver is even loads.
This gives the opportunity for userspace to open that interface and poke
around before the backing data structures are initialised - with the
possibility of oopsing or worse.

Move the creation of the debugfs files to our registration phase, where
we announce our presence to the world when we are ready, i.e the
sequence changes from

	drm_dev_register()
	 -> drm_minor_register()
	  -> drm_debugfs_init()
	   -> i915_debugfs_init()
	 -> i915_driver_load()

to

	drm_dev_register()
	 -> drm_minor_register()
	  -> drm_debugfs_init()
	 -> i915_driver_load()
	  -> i915_debugfs_register()

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 6 ++++--
 drivers/gpu/drm/i915/i915_dma.c     | 2 ++
 drivers/gpu/drm/i915/i915_drv.c     | 4 ----
 drivers/gpu/drm/i915/i915_drv.h     | 6 ++++--
 4 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index ac7e5692496d..d018ec5093ba 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -5498,8 +5498,9 @@ void intel_display_crc_init(struct drm_device *dev)
 	}
 }
 
-int i915_debugfs_init(struct drm_minor *minor)
+int i915_debugfs_register(struct drm_i915_private *dev_priv)
 {
+	struct drm_minor *minor = dev_priv->dev->primary;
 	int ret, i;
 
 	ret = i915_forcewake_create(minor->debugfs_root, minor);
@@ -5525,8 +5526,9 @@ int i915_debugfs_init(struct drm_minor *minor)
 					minor->debugfs_root, minor);
 }
 
-void i915_debugfs_cleanup(struct drm_minor *minor)
+void i915_debugfs_unregister(struct drm_i915_private *dev_priv)
 {
+	struct drm_minor *minor = dev_priv->dev->primary;
 	int i;
 
 	drm_debugfs_remove_files(i915_debugfs_list,
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 4a7a2c08becd..6b36bca585c5 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1360,6 +1360,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
 	if (intel_vgpu_active(dev_priv))
 		I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY);
 
+	i915_debugfs_register(dev_priv);
 	i915_setup_sysfs(dev);
 	intel_modeset_register(dev_priv);
 
@@ -1399,6 +1400,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
 	intel_opregion_unregister(dev_priv);
 	intel_modeset_unregister(dev_priv);
 	i915_teardown_sysfs(dev_priv->dev);
+	i915_debugfs_unregister(dev_priv);
 	i915_gem_shrinker_cleanup(dev_priv);
 }
 
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 943d7b222fd4..fa9e16b2247c 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1761,10 +1761,6 @@ static struct drm_driver driver = {
 	.postclose = i915_driver_postclose,
 	.set_busid = drm_pci_set_busid,
 
-#if defined(CONFIG_DEBUG_FS)
-	.debugfs_init = i915_debugfs_init,
-	.debugfs_cleanup = i915_debugfs_cleanup,
-#endif
 	.gem_free_object = i915_gem_free_object,
 	.gem_vm_ops = &i915_gem_vm_ops,
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c530160c17d5..5e9f8d5cb7eb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3541,12 +3541,14 @@ int i915_verify_lists(struct drm_device *dev);
 #endif
 
 /* i915_debugfs.c */
-int i915_debugfs_init(struct drm_minor *minor);
-void i915_debugfs_cleanup(struct drm_minor *minor);
 #ifdef CONFIG_DEBUG_FS
+int i915_debugfs_register(struct drm_i915_private *dev_priv);
+void i915_debugfs_unregister(struct drm_i915_private *dev_priv);
 int i915_debugfs_connector_add(struct drm_connector *connector);
 void intel_display_crc_init(struct drm_device *dev);
 #else
+static inline int i915_debugfs_register(struct drm_i915_private *) {return 0;}
+static inline void i915_debugfs_unregister(struct drm_i915_private *) {}
 static inline int i915_debugfs_connector_add(struct drm_connector *connector)
 { return 0; }
 static inline void intel_display_crc_init(struct drm_device *dev) {}
-- 
2.8.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 06/11] drm/i915: Demidlayer driver loading
  2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
                   ` (4 preceding siblings ...)
  2016-05-27 14:00 ` [PATCH 05/11] drm/i915: Register debugfs interface last Chris Wilson
@ 2016-05-27 14:00 ` Chris Wilson
  2016-05-27 14:00 ` [PATCH 07/11] drm/i915: Demidlayer driver unloading Chris Wilson
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

Take control over allocating, loading and registering the driver from the
DRM midlayer by performing it manually from i915_pci_probe. This allows
us to carefully control the order of when we setup the hardware vs when
it becomes visible to third parties (including userspace). The current
ordering makes the driver visible to userspace first (in order to
coordinate with removed DRI1 userspace), but that ordering incurs risk.
The risk increases as we strive for more asynchronous loading.

One side effect of controlling the allocation is that we can allocate
both the drm_device + drm_i915_private in one block, the next step
towards subclassing.

Unload is still left as before, a mix of midlayer and driver.

Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c | 67 ++++++++++++++++++++++++++---------------
 drivers/gpu/drm/i915/i915_drv.c |  3 +-
 drivers/gpu/drm/i915/i915_drv.h |  6 +++-
 3 files changed, 49 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 6b36bca585c5..b5eeee6693f7 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1046,9 +1046,10 @@ static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
  * function hooks not requiring accessing the device.
  */
 static int i915_driver_init_early(struct drm_i915_private *dev_priv,
-				  struct drm_device *dev,
-				  struct intel_device_info *info)
+				  const struct pci_device_id *ent)
 {
+	const struct intel_device_info *match_info =
+		(struct intel_device_info *)ent->driver_data;
 	struct intel_device_info *device_info;
 	int ret = 0;
 
@@ -1057,8 +1058,8 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
 
 	/* Setup the write-once "constant" device info */
 	device_info = (struct intel_device_info *)&dev_priv->info;
-	memcpy(device_info, info, sizeof(dev_priv->info));
-	device_info->device_id = dev->pdev->device;
+	memcpy(device_info, match_info, sizeof(*device_info));
+	device_info->device_id = dev_priv->drm.pdev->device;
 
 	BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE);
 	device_info->gen_mask = BIT(device_info->gen - 1);
@@ -1080,18 +1081,18 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
 		return ret;
 
 	/* This must be called before any calls to HAS_PCH_* */
-	intel_detect_pch(dev);
+	intel_detect_pch(&dev_priv->drm);
 
-	intel_pm_setup(dev);
+	intel_pm_setup(&dev_priv->drm);
 	intel_init_dpio(dev_priv);
 	intel_power_domains_init(dev_priv);
 	intel_irq_init(dev_priv);
 	intel_init_display_hooks(dev_priv);
 	intel_init_clock_gating_hooks(dev_priv);
 	intel_init_audio_hooks(dev_priv);
-	i915_gem_load_init(dev);
+	i915_gem_load_init(&dev_priv->drm);
 
-	intel_display_crc_init(dev);
+	intel_display_crc_init(&dev_priv->drm);
 
 	i915_dump_device_info(dev_priv);
 
@@ -1099,7 +1100,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
 	 * very first ones. Almost everything should work, except for maybe
 	 * suspend/resume. And we don't implement workarounds that affect only
 	 * pre-production machines. */
-	if (IS_HSW_EARLY_SDV(dev))
+	if (IS_HSW_EARLY_SDV(dev_priv))
 		DRM_INFO("This is an early pre-production Haswell machine. "
 			 "It may not be fully functional.\n");
 
@@ -1353,6 +1354,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
 	struct drm_device *dev = dev_priv->dev;
 
 	i915_gem_shrinker_init(dev_priv);
+
 	/*
 	 * Notify a valid surface after modesetting,
 	 * when running inside a VM.
@@ -1360,9 +1362,13 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
 	if (intel_vgpu_active(dev_priv))
 		I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY);
 
-	i915_debugfs_register(dev_priv);
-	i915_setup_sysfs(dev);
-	intel_modeset_register(dev_priv);
+	/* Reveal our presence to userspace */
+	if (drm_dev_register(dev, 0) == 0) {
+		i915_debugfs_register(dev_priv);
+		i915_setup_sysfs(dev);
+		intel_modeset_register(dev_priv);
+	} else
+		DRM_ERROR("Failed to register driver for userspace access!\n");
 
 	if (INTEL_INFO(dev_priv)->num_pipes) {
 		/* Must be done after probing outputs */
@@ -1415,25 +1421,36 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
  *   - allocate initial config memory
  *   - setup the DRM framebuffer with the allocated memory
  */
-int i915_driver_load(struct drm_device *dev, unsigned long flags)
+int i915_driver_load(struct pci_dev *pdev,
+		     const struct pci_device_id *ent,
+		     struct drm_driver *driver)
 {
 	struct drm_i915_private *dev_priv;
-	int ret = 0;
+	int ret;
 
 	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
 	if (dev_priv == NULL)
 		return -ENOMEM;
 
-	dev->dev_private = dev_priv;
-	/* Must be set before calling __i915_printk */
-	dev_priv->dev = dev;
+	ret = drm_dev_init(&dev_priv->drm, driver, &pdev->dev);
+	if (ret)
+		goto out_free_priv;
 
-	ret = i915_driver_init_early(dev_priv, dev,
-				     (struct intel_device_info *)flags);
+	/* Must be set before calling __i915_printk */
+	dev_priv->drm.pdev = pdev;
+	dev_priv->drm.dev_private = dev_priv;
+	dev_priv->dev = &dev_priv->drm;
 
+	ret = i915_driver_init_early(dev_priv, ent);
 	if (ret < 0)
 		goto out_free_priv;
 
+	ret = pci_enable_device(pdev);
+	if (ret)
+		goto out_cleanup_early;
+
+	pci_set_drvdata(pdev, &dev_priv->drm);
+
 	intel_runtime_pm_get(dev_priv);
 
 	ret = i915_driver_init_mmio(dev_priv);
@@ -1449,13 +1466,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	 * of the i915_driver_init_/i915_driver_register functions according
 	 * to the role/effect of the given init step.
 	 */
-	if (INTEL_INFO(dev)->num_pipes) {
-		ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
+	if (INTEL_INFO(dev_priv)->num_pipes) {
+		ret = drm_vblank_init(dev_priv->dev,
+				      INTEL_INFO(dev_priv)->num_pipes);
 		if (ret)
 			goto out_cleanup_hw;
 	}
 
-	ret = i915_load_modeset_init(dev);
+	ret = i915_load_modeset_init(dev_priv->dev);
 	if (ret < 0)
 		goto out_cleanup_vblank;
 
@@ -1468,13 +1486,15 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	return 0;
 
 out_cleanup_vblank:
-	drm_vblank_cleanup(dev);
+	drm_vblank_cleanup(dev_priv->dev);
 out_cleanup_hw:
 	i915_driver_cleanup_hw(dev_priv);
 out_cleanup_mmio:
 	i915_driver_cleanup_mmio(dev_priv);
 out_runtime_pm_put:
 	intel_runtime_pm_put(dev_priv);
+	pci_disable_device(pdev);
+out_cleanup_early:
 	i915_driver_cleanup_early(dev_priv);
 out_free_priv:
 	i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret);
@@ -1543,7 +1563,6 @@ int i915_driver_unload(struct drm_device *dev)
 	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
 
 	i915_driver_cleanup_early(dev_priv);
-	kfree(dev_priv);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index fa9e16b2247c..d2792ce12c5f 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1039,7 +1039,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	    !vga_switcheroo_handler_flags())
 		return -EPROBE_DEFER;
 
-	return drm_get_pci_dev(pdev, ent, &driver);
+	return i915_driver_load(pdev, ent, &driver);
 }
 
 static void
@@ -1753,7 +1753,6 @@ static struct drm_driver driver = {
 	.driver_features =
 	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME |
 	    DRIVER_RENDER | DRIVER_MODESET,
-	.load = i915_driver_load,
 	.unload = i915_driver_unload,
 	.open = i915_driver_open,
 	.lastclose = i915_driver_lastclose,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5e9f8d5cb7eb..3f6a3648c50a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1722,6 +1722,8 @@ struct intel_wm_config {
 };
 
 struct drm_i915_private {
+	struct drm_device drm;
+
 	struct drm_device *dev;
 	struct kmem_cache *objects;
 	struct kmem_cache *vmas;
@@ -2872,7 +2874,9 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level,
 #define i915_report_error(dev_priv, fmt, ...)				   \
 	__i915_printk(dev_priv, KERN_ERR, fmt, ##__VA_ARGS__)
 
-extern int i915_driver_load(struct drm_device *, unsigned long flags);
+extern int i915_driver_load(struct pci_dev *pdev,
+			    const struct pci_device_id *ent,
+			    struct drm_driver *driver);
 extern int i915_driver_unload(struct drm_device *);
 extern int i915_driver_open(struct drm_device *dev, struct drm_file *file);
 extern void i915_driver_lastclose(struct drm_device * dev);
-- 
2.8.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 07/11] drm/i915: Demidlayer driver unloading
  2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
                   ` (5 preceding siblings ...)
  2016-05-27 14:00 ` [PATCH 06/11] drm/i915: Demidlayer driver loading Chris Wilson
@ 2016-05-27 14:00 ` Chris Wilson
  2016-05-27 14:00 ` [PATCH 08/11] drm/i915: Start exploiting drm_device subclassing Chris Wilson
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

To complete the transition to manual control of load/unload, we need to
take over unloading from i915_pci_remove(). This allows us to correctly
order our unregister vs shutdown phases, which currently are inverted
due to the midlayer.

However, the unload sequence is still invalid as we shutdown the driver
with the last reference. Ideally, all we want to do is remove the
userspace access on device removal, deferring the cleanup to the
drm_dev_release() - breaking the reference cycles is then left as an
exercise for the reader.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c | 4 ++++
 drivers/gpu/drm/i915/i915_drv.c | 4 ++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index b5eeee6693f7..0ec785d4505e 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1401,12 +1401,16 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
 static void i915_driver_unregister(struct drm_i915_private *dev_priv)
 {
 	i915_audio_component_cleanup(dev_priv);
+
 	intel_gpu_ips_teardown();
 	acpi_video_unregister();
 	intel_opregion_unregister(dev_priv);
+
 	intel_modeset_unregister(dev_priv);
 	i915_teardown_sysfs(dev_priv->dev);
 	i915_debugfs_unregister(dev_priv);
+	drm_dev_unregister(dev_priv->dev);
+
 	i915_gem_shrinker_cleanup(dev_priv);
 }
 
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index d2792ce12c5f..b13d6751ebe4 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1047,7 +1047,8 @@ i915_pci_remove(struct pci_dev *pdev)
 {
 	struct drm_device *dev = pci_get_drvdata(pdev);
 
-	drm_put_dev(dev);
+	i915_driver_unload(dev);
+	drm_dev_unref(dev);
 }
 
 static int i915_pm_suspend(struct device *dev)
@@ -1753,7 +1754,6 @@ static struct drm_driver driver = {
 	.driver_features =
 	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME |
 	    DRIVER_RENDER | DRIVER_MODESET,
-	.unload = i915_driver_unload,
 	.open = i915_driver_open,
 	.lastclose = i915_driver_lastclose,
 	.preclose = i915_driver_preclose,
-- 
2.8.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 08/11] drm/i915: Start exploiting drm_device subclassing
  2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
                   ` (6 preceding siblings ...)
  2016-05-27 14:00 ` [PATCH 07/11] drm/i915: Demidlayer driver unloading Chris Wilson
@ 2016-05-27 14:00 ` Chris Wilson
  2016-05-27 14:15   ` Tvrtko Ursulin
  2016-05-27 14:00 ` [PATCH 09/11] drm/i915: Merge i915_dma.c into i915_drv.c Chris Wilson
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

Baby step, update to_i915() conversion from drm_device to
drm_i915_private:

   text	   data	    bss	    dec	    hex	filename
1108812	  23207	    416	1132435	 114793	i915.ko (before)
1104999	  23207	    416	1128622	 1138ae	i915.ko (after)

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.h | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3f6a3648c50a..b95a10fa002a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2033,7 +2033,7 @@ struct drm_i915_private {
 
 static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
 {
-	return dev->dev_private;
+	return container_of(dev, struct drm_i915_private, drm);
 }
 
 static inline struct drm_i915_private *dev_to_i915(struct device *dev)
@@ -2602,7 +2602,7 @@ struct drm_i915_cmd_table {
 #define INTEL_DEVID(p)	(INTEL_INFO(p)->device_id)
 
 #define REVID_FOREVER		0xff
-#define INTEL_REVID(p)	(__I915__(p)->dev->pdev->revision)
+#define INTEL_REVID(p)	(__I915__(p)->drm.pdev->revision)
 
 #define GEN_FOREVER (0)
 /*
@@ -3439,7 +3439,7 @@ i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
 {
 	struct i915_gem_context *ctx;
 
-	lockdep_assert_held(&file_priv->dev_priv->dev->struct_mutex);
+	lockdep_assert_held(&file_priv->dev_priv->drm.struct_mutex);
 
 	ctx = idr_find(&file_priv->context_idr, id);
 	if (!ctx)
@@ -3455,7 +3455,7 @@ static inline void i915_gem_context_reference(struct i915_gem_context *ctx)
 
 static inline void i915_gem_context_unreference(struct i915_gem_context *ctx)
 {
-	lockdep_assert_held(&ctx->i915->dev->struct_mutex);
+	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
 	kref_put(&ctx->ref, i915_gem_context_free);
 }
 
@@ -3531,7 +3531,7 @@ void i915_gem_shrinker_cleanup(struct drm_i915_private *dev_priv);
 /* i915_gem_tiling.c */
 static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
 {
-	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
 
 	return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
 		obj->tiling_mode != I915_TILING_NONE;
-- 
2.8.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 09/11] drm/i915: Merge i915_dma.c into i915_drv.c
  2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
                   ` (7 preceding siblings ...)
  2016-05-27 14:00 ` [PATCH 08/11] drm/i915: Start exploiting drm_device subclassing Chris Wilson
@ 2016-05-27 14:00 ` Chris Wilson
  2016-05-30  6:30   ` Joonas Lahtinen
  2016-05-27 14:00 ` [PATCH 10/11] drm/i915: Split out the PCI driver interface to i915_pci.c Chris Wilson
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

i915_dma.c used to contain the DRI1/UMS horror show, but now all that
remains are the out-of-place driver level interfaces (such as
allocating, initialising and registering the driver). These should be in
i915_drv.c alongside similar routines for suspend/resume.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/Makefile   |    3 -
 drivers/gpu/drm/i915/i915_dma.c | 1680 --------------------------------
 drivers/gpu/drm/i915/i915_drv.c | 2014 +++++++++++++++++++++++++++++++++++----
 drivers/gpu/drm/i915/i915_drv.h |   16 +-
 4 files changed, 1825 insertions(+), 1888 deletions(-)
 delete mode 100644 drivers/gpu/drm/i915/i915_dma.c

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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 10/11] drm/i915: Split out the PCI driver interface to i915_pci.c
  2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
                   ` (8 preceding siblings ...)
  2016-05-27 14:00 ` [PATCH 09/11] drm/i915: Merge i915_dma.c into i915_drv.c Chris Wilson
@ 2016-05-27 14:00 ` Chris Wilson
  2016-05-30  6:36   ` Joonas Lahtinen
  2016-05-27 14:00 ` [PATCH 11/11] drm/i915: Move module init/exit " Chris Wilson
  2016-05-27 14:58 ` ✗ Ro.CI.BAT: failure for series starting with [01/11] drm: Export drm_dev_init() for subclassing (rev2) Patchwork
  11 siblings, 1 reply; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

To reclaim a bit of space from i915_drv.c, we can move the routines that
just hook us into the PCI device tree into i915_pci.c

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/Makefile   |   1 +
 drivers/gpu/drm/i915/i915_drv.c | 450 +-------------------------------------
 drivers/gpu/drm/i915/i915_pci.c | 463 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 473 insertions(+), 441 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/i915_pci.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 2ea7c245923e..7aecd309604c 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -10,6 +10,7 @@ subdir-ccflags-$(CONFIG_DRM_I915_WERROR) := -Werror
 i915-y := i915_drv.o \
 	  i915_irq.o \
 	  i915_params.o \
+	  i915_pci.o \
           i915_suspend.o \
 	  i915_sysfs.o \
 	  intel_csr.o \
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index e20f63ac73d3..79b6834bc6b2 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -28,7 +28,6 @@
  */
 
 #include <linux/acpi.h>
-#include <linux/apple-gmux.h>
 #include <linux/console.h>
 #include <linux/device.h>
 #include <linux/oom.h>
@@ -54,386 +53,6 @@
 
 static struct drm_driver driver;
 
-#define GEN_DEFAULT_PIPEOFFSETS \
-	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
-			  PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \
-	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
-			   TRANSCODER_C_OFFSET, TRANSCODER_EDP_OFFSET }, \
-	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET }
-
-#define GEN_CHV_PIPEOFFSETS \
-	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
-			  CHV_PIPE_C_OFFSET }, \
-	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
-			   CHV_TRANSCODER_C_OFFSET, }, \
-	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET, \
-			     CHV_PALETTE_C_OFFSET }
-
-#define CURSOR_OFFSETS \
-	.cursor_offsets = { CURSOR_A_OFFSET, CURSOR_B_OFFSET, CHV_CURSOR_C_OFFSET }
-
-#define IVB_CURSOR_OFFSETS \
-	.cursor_offsets = { CURSOR_A_OFFSET, IVB_CURSOR_B_OFFSET, IVB_CURSOR_C_OFFSET }
-
-#define BDW_COLORS \
-	.color = { .degamma_lut_size = 512, .gamma_lut_size = 512 }
-#define CHV_COLORS \
-	.color = { .degamma_lut_size = 65, .gamma_lut_size = 257 }
-
-static const struct intel_device_info intel_i830_info = {
-	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
-	.has_overlay = 1, .overlay_needs_physical = 1,
-	.ring_mask = RENDER_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_845g_info = {
-	.gen = 2, .num_pipes = 1,
-	.has_overlay = 1, .overlay_needs_physical = 1,
-	.ring_mask = RENDER_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_i85x_info = {
-	.gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,
-	.cursor_needs_physical = 1,
-	.has_overlay = 1, .overlay_needs_physical = 1,
-	.has_fbc = 1,
-	.ring_mask = RENDER_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_i865g_info = {
-	.gen = 2, .num_pipes = 1,
-	.has_overlay = 1, .overlay_needs_physical = 1,
-	.ring_mask = RENDER_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_i915g_info = {
-	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2,
-	.has_overlay = 1, .overlay_needs_physical = 1,
-	.ring_mask = RENDER_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-static const struct intel_device_info intel_i915gm_info = {
-	.gen = 3, .is_mobile = 1, .num_pipes = 2,
-	.cursor_needs_physical = 1,
-	.has_overlay = 1, .overlay_needs_physical = 1,
-	.supports_tv = 1,
-	.has_fbc = 1,
-	.ring_mask = RENDER_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-static const struct intel_device_info intel_i945g_info = {
-	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2,
-	.has_overlay = 1, .overlay_needs_physical = 1,
-	.ring_mask = RENDER_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-static const struct intel_device_info intel_i945gm_info = {
-	.gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2,
-	.has_hotplug = 1, .cursor_needs_physical = 1,
-	.has_overlay = 1, .overlay_needs_physical = 1,
-	.supports_tv = 1,
-	.has_fbc = 1,
-	.ring_mask = RENDER_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_i965g_info = {
-	.gen = 4, .is_broadwater = 1, .num_pipes = 2,
-	.has_hotplug = 1,
-	.has_overlay = 1,
-	.ring_mask = RENDER_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_i965gm_info = {
-	.gen = 4, .is_crestline = 1, .num_pipes = 2,
-	.is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,
-	.has_overlay = 1,
-	.supports_tv = 1,
-	.ring_mask = RENDER_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_g33_info = {
-	.gen = 3, .is_g33 = 1, .num_pipes = 2,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.has_overlay = 1,
-	.ring_mask = RENDER_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_g45_info = {
-	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2,
-	.has_pipe_cxsr = 1, .has_hotplug = 1,
-	.ring_mask = RENDER_RING | BSD_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_gm45_info = {
-	.gen = 4, .is_g4x = 1, .num_pipes = 2,
-	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,
-	.has_pipe_cxsr = 1, .has_hotplug = 1,
-	.supports_tv = 1,
-	.ring_mask = RENDER_RING | BSD_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_pineview_info = {
-	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .num_pipes = 2,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.has_overlay = 1,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_ironlake_d_info = {
-	.gen = 5, .num_pipes = 2,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.ring_mask = RENDER_RING | BSD_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_ironlake_m_info = {
-	.gen = 5, .is_mobile = 1, .num_pipes = 2,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.has_fbc = 1,
-	.ring_mask = RENDER_RING | BSD_RING,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_sandybridge_d_info = {
-	.gen = 6, .num_pipes = 2,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.has_fbc = 1,
-	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
-	.has_llc = 1,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-static const struct intel_device_info intel_sandybridge_m_info = {
-	.gen = 6, .is_mobile = 1, .num_pipes = 2,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.has_fbc = 1,
-	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
-	.has_llc = 1,
-	GEN_DEFAULT_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-};
-
-#define GEN7_FEATURES  \
-	.gen = 7, .num_pipes = 3, \
-	.need_gfx_hws = 1, .has_hotplug = 1, \
-	.has_fbc = 1, \
-	.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
-	.has_llc = 1, \
-	GEN_DEFAULT_PIPEOFFSETS, \
-	IVB_CURSOR_OFFSETS
-
-static const struct intel_device_info intel_ivybridge_d_info = {
-	GEN7_FEATURES,
-	.is_ivybridge = 1,
-};
-
-static const struct intel_device_info intel_ivybridge_m_info = {
-	GEN7_FEATURES,
-	.is_ivybridge = 1,
-	.is_mobile = 1,
-};
-
-static const struct intel_device_info intel_ivybridge_q_info = {
-	GEN7_FEATURES,
-	.is_ivybridge = 1,
-	.num_pipes = 0, /* legal, last one wins */
-};
-
-#define VLV_FEATURES  \
-	.gen = 7, .num_pipes = 2, \
-	.need_gfx_hws = 1, .has_hotplug = 1, \
-	.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
-	.display_mmio_offset = VLV_DISPLAY_BASE, \
-	GEN_DEFAULT_PIPEOFFSETS, \
-	CURSOR_OFFSETS
-
-static const struct intel_device_info intel_valleyview_m_info = {
-	VLV_FEATURES,
-	.is_valleyview = 1,
-	.is_mobile = 1,
-};
-
-static const struct intel_device_info intel_valleyview_d_info = {
-	VLV_FEATURES,
-	.is_valleyview = 1,
-};
-
-#define HSW_FEATURES  \
-	GEN7_FEATURES, \
-	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \
-	.has_ddi = 1, \
-	.has_fpga_dbg = 1
-
-static const struct intel_device_info intel_haswell_d_info = {
-	HSW_FEATURES,
-	.is_haswell = 1,
-};
-
-static const struct intel_device_info intel_haswell_m_info = {
-	HSW_FEATURES,
-	.is_haswell = 1,
-	.is_mobile = 1,
-};
-
-#define BDW_FEATURES \
-	HSW_FEATURES, \
-	BDW_COLORS
-
-static const struct intel_device_info intel_broadwell_d_info = {
-	BDW_FEATURES,
-	.gen = 8,
-	.is_broadwell = 1,
-};
-
-static const struct intel_device_info intel_broadwell_m_info = {
-	BDW_FEATURES,
-	.gen = 8, .is_mobile = 1,
-	.is_broadwell = 1,
-};
-
-static const struct intel_device_info intel_broadwell_gt3d_info = {
-	BDW_FEATURES,
-	.gen = 8,
-	.is_broadwell = 1,
-	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
-};
-
-static const struct intel_device_info intel_broadwell_gt3m_info = {
-	BDW_FEATURES,
-	.gen = 8, .is_mobile = 1,
-	.is_broadwell = 1,
-	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
-};
-
-static const struct intel_device_info intel_cherryview_info = {
-	.gen = 8, .num_pipes = 3,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
-	.is_cherryview = 1,
-	.display_mmio_offset = VLV_DISPLAY_BASE,
-	GEN_CHV_PIPEOFFSETS,
-	CURSOR_OFFSETS,
-	CHV_COLORS,
-};
-
-static const struct intel_device_info intel_skylake_info = {
-	BDW_FEATURES,
-	.is_skylake = 1,
-	.gen = 9,
-};
-
-static const struct intel_device_info intel_skylake_gt3_info = {
-	BDW_FEATURES,
-	.is_skylake = 1,
-	.gen = 9,
-	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
-};
-
-static const struct intel_device_info intel_broxton_info = {
-	.is_preliminary = 1,
-	.is_broxton = 1,
-	.gen = 9,
-	.need_gfx_hws = 1, .has_hotplug = 1,
-	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
-	.num_pipes = 3,
-	.has_ddi = 1,
-	.has_fpga_dbg = 1,
-	.has_fbc = 1,
-	GEN_DEFAULT_PIPEOFFSETS,
-	IVB_CURSOR_OFFSETS,
-	BDW_COLORS,
-};
-
-static const struct intel_device_info intel_kabylake_info = {
-	BDW_FEATURES,
-	.is_kabylake = 1,
-	.gen = 9,
-};
-
-static const struct intel_device_info intel_kabylake_gt3_info = {
-	BDW_FEATURES,
-	.is_kabylake = 1,
-	.gen = 9,
-	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
-};
-
-/*
- * Make sure any device matches here are from most specific to most
- * general.  For example, since the Quanta match is based on the subsystem
- * and subvendor IDs, we need it to come before the more general IVB
- * PCI ID matches, otherwise we'll use the wrong info struct above.
- */
-static const struct pci_device_id pciidlist[] = {
-	INTEL_I830_IDS(&intel_i830_info),
-	INTEL_I845G_IDS(&intel_845g_info),
-	INTEL_I85X_IDS(&intel_i85x_info),
-	INTEL_I865G_IDS(&intel_i865g_info),
-	INTEL_I915G_IDS(&intel_i915g_info),
-	INTEL_I915GM_IDS(&intel_i915gm_info),
-	INTEL_I945G_IDS(&intel_i945g_info),
-	INTEL_I945GM_IDS(&intel_i945gm_info),
-	INTEL_I965G_IDS(&intel_i965g_info),
-	INTEL_G33_IDS(&intel_g33_info),
-	INTEL_I965GM_IDS(&intel_i965gm_info),
-	INTEL_GM45_IDS(&intel_gm45_info),
-	INTEL_G45_IDS(&intel_g45_info),
-	INTEL_PINEVIEW_IDS(&intel_pineview_info),
-	INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info),
-	INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info),
-	INTEL_SNB_D_IDS(&intel_sandybridge_d_info),
-	INTEL_SNB_M_IDS(&intel_sandybridge_m_info),
-	INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */
-	INTEL_IVB_M_IDS(&intel_ivybridge_m_info),
-	INTEL_IVB_D_IDS(&intel_ivybridge_d_info),
-	INTEL_HSW_D_IDS(&intel_haswell_d_info),
-	INTEL_HSW_M_IDS(&intel_haswell_m_info),
-	INTEL_VLV_M_IDS(&intel_valleyview_m_info),
-	INTEL_VLV_D_IDS(&intel_valleyview_d_info),
-	INTEL_BDW_GT12M_IDS(&intel_broadwell_m_info),
-	INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info),
-	INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info),
-	INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info),
-	INTEL_CHV_IDS(&intel_cherryview_info),
-	INTEL_SKL_GT1_IDS(&intel_skylake_info),
-	INTEL_SKL_GT2_IDS(&intel_skylake_info),
-	INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info),
-	INTEL_SKL_GT4_IDS(&intel_skylake_gt3_info),
-	INTEL_BXT_IDS(&intel_broxton_info),
-	INTEL_KBL_GT1_IDS(&intel_kabylake_info),
-	INTEL_KBL_GT2_IDS(&intel_kabylake_info),
-	INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info),
-	INTEL_KBL_GT4_IDS(&intel_kabylake_gt3_info),
-	{0, 0, 0}
-};
-MODULE_DEVICE_TABLE(pci, pciidlist);
-
 static unsigned int i915_load_fail_count;
 
 bool __i915_inject_load_failure(const char *func, int line)
@@ -1939,8 +1558,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
  *   - allocate initial config memory
  *   - setup the DRM framebuffer with the allocated memory
  */
-static int i915_driver_load(struct pci_dev *pdev,
-			    const struct pci_device_id *ent)
+int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct drm_i915_private *dev_priv;
 	int ret;
@@ -2021,18 +1639,14 @@ out_free_priv:
 	return ret;
 }
 
-static int i915_driver_unload(struct drm_device *dev)
+void i915_driver_unload(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int ret;
 
 	intel_fbdev_fini(dev);
 
-	ret = i915_gem_suspend(dev);
-	if (ret) {
-		DRM_ERROR("failed to idle hardware: %d\n", ret);
-		return ret;
-	}
+	if (i915_gem_suspend(dev))
+		DRM_ERROR("failed to idle hardware; continuing to unload!\n");
 
 	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
@@ -2080,8 +1694,6 @@ static int i915_driver_unload(struct drm_device *dev)
 	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
 
 	i915_driver_cleanup_early(dev_priv);
-
-	return 0;
 }
 
 static int i915_driver_open(struct drm_device *dev, struct drm_file *file)
@@ -2584,46 +2196,6 @@ error:
 	return ret;
 }
 
-static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	struct intel_device_info *intel_info =
-		(struct intel_device_info *) ent->driver_data;
-
-	if (IS_PRELIMINARY_HW(intel_info) && !i915.preliminary_hw_support) {
-		DRM_INFO("This hardware requires preliminary hardware support.\n"
-			 "See CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT, and/or modparam preliminary_hw_support\n");
-		return -ENODEV;
-	}
-
-	/* Only bind to function 0 of the device. Early generations
-	 * used function 1 as a placeholder for multi-head. This causes
-	 * us confusion instead, especially on the systems where both
-	 * functions have the same PCI-ID!
-	 */
-	if (PCI_FUNC(pdev->devfn))
-		return -ENODEV;
-
-	/*
-	 * apple-gmux is needed on dual GPU MacBook Pro
-	 * to probe the panel if we're the inactive GPU.
-	 */
-	if (IS_ENABLED(CONFIG_VGA_ARB) && IS_ENABLED(CONFIG_VGA_SWITCHEROO) &&
-	    apple_gmux_present() && pdev != vga_default_device() &&
-	    !vga_switcheroo_handler_flags())
-		return -EPROBE_DEFER;
-
-	return i915_driver_load(pdev, ent);
-}
-
-static void
-i915_pci_remove(struct pci_dev *pdev)
-{
-	struct drm_device *dev = pci_get_drvdata(pdev);
-
-	i915_driver_unload(dev);
-	drm_dev_unref(dev);
-}
-
 static int i915_pm_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -3261,7 +2833,7 @@ static int intel_runtime_resume(struct device *device)
 	return ret;
 }
 
-static const struct dev_pm_ops i915_pm_ops = {
+const struct dev_pm_ops i915_pm_ops = {
 	/*
 	 * S0ix (via system suspend) and S3 event handlers [PMSG_SUSPEND,
 	 * PMSG_RESUME]
@@ -3417,16 +2989,10 @@ static struct drm_driver driver = {
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
-static struct pci_driver i915_pci_driver = {
-	.name = DRIVER_NAME,
-	.id_table = pciidlist,
-	.probe = i915_pci_probe,
-	.remove = i915_pci_remove,
-	.driver.pm = &i915_pm_ops,
-};
-
 static int __init i915_init(void)
 {
+	extern struct pci_driver i915_pci_driver;
+
 	/*
 	 * Enable KMS by default, unless explicitly overriden by
 	 * either the i915.modeset prarameter or by the
@@ -3453,6 +3019,8 @@ static int __init i915_init(void)
 
 static void __exit i915_exit(void)
 {
+	extern struct pci_driver i915_pci_driver;
+
 	if (!(driver.driver_features & DRIVER_MODESET))
 		return; /* Never loaded a driver. */
 
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
new file mode 100644
index 000000000000..514d8b784319
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -0,0 +1,463 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/apple-gmux.h>
+#include <linux/vgaarb.h>
+#include <linux/vga_switcheroo.h>
+
+#include "i915_drv.h"
+
+#define GEN_DEFAULT_PIPEOFFSETS \
+	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
+			  PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \
+	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
+			   TRANSCODER_C_OFFSET, TRANSCODER_EDP_OFFSET }, \
+	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET }
+
+#define GEN_CHV_PIPEOFFSETS \
+	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
+			  CHV_PIPE_C_OFFSET }, \
+	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
+			   CHV_TRANSCODER_C_OFFSET, }, \
+	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET, \
+			     CHV_PALETTE_C_OFFSET }
+
+#define CURSOR_OFFSETS \
+	.cursor_offsets = { CURSOR_A_OFFSET, CURSOR_B_OFFSET, CHV_CURSOR_C_OFFSET }
+
+#define IVB_CURSOR_OFFSETS \
+	.cursor_offsets = { CURSOR_A_OFFSET, IVB_CURSOR_B_OFFSET, IVB_CURSOR_C_OFFSET }
+
+#define BDW_COLORS \
+	.color = { .degamma_lut_size = 512, .gamma_lut_size = 512 }
+#define CHV_COLORS \
+	.color = { .degamma_lut_size = 65, .gamma_lut_size = 257 }
+
+static const struct intel_device_info intel_i830_info = {
+	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
+	.has_overlay = 1, .overlay_needs_physical = 1,
+	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_845g_info = {
+	.gen = 2, .num_pipes = 1,
+	.has_overlay = 1, .overlay_needs_physical = 1,
+	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_i85x_info = {
+	.gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,
+	.cursor_needs_physical = 1,
+	.has_overlay = 1, .overlay_needs_physical = 1,
+	.has_fbc = 1,
+	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_i865g_info = {
+	.gen = 2, .num_pipes = 1,
+	.has_overlay = 1, .overlay_needs_physical = 1,
+	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_i915g_info = {
+	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2,
+	.has_overlay = 1, .overlay_needs_physical = 1,
+	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+static const struct intel_device_info intel_i915gm_info = {
+	.gen = 3, .is_mobile = 1, .num_pipes = 2,
+	.cursor_needs_physical = 1,
+	.has_overlay = 1, .overlay_needs_physical = 1,
+	.supports_tv = 1,
+	.has_fbc = 1,
+	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+static const struct intel_device_info intel_i945g_info = {
+	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2,
+	.has_overlay = 1, .overlay_needs_physical = 1,
+	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+static const struct intel_device_info intel_i945gm_info = {
+	.gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2,
+	.has_hotplug = 1, .cursor_needs_physical = 1,
+	.has_overlay = 1, .overlay_needs_physical = 1,
+	.supports_tv = 1,
+	.has_fbc = 1,
+	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_i965g_info = {
+	.gen = 4, .is_broadwater = 1, .num_pipes = 2,
+	.has_hotplug = 1,
+	.has_overlay = 1,
+	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_i965gm_info = {
+	.gen = 4, .is_crestline = 1, .num_pipes = 2,
+	.is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,
+	.has_overlay = 1,
+	.supports_tv = 1,
+	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_g33_info = {
+	.gen = 3, .is_g33 = 1, .num_pipes = 2,
+	.need_gfx_hws = 1, .has_hotplug = 1,
+	.has_overlay = 1,
+	.ring_mask = RENDER_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_g45_info = {
+	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2,
+	.has_pipe_cxsr = 1, .has_hotplug = 1,
+	.ring_mask = RENDER_RING | BSD_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_gm45_info = {
+	.gen = 4, .is_g4x = 1, .num_pipes = 2,
+	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,
+	.has_pipe_cxsr = 1, .has_hotplug = 1,
+	.supports_tv = 1,
+	.ring_mask = RENDER_RING | BSD_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_pineview_info = {
+	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .num_pipes = 2,
+	.need_gfx_hws = 1, .has_hotplug = 1,
+	.has_overlay = 1,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_ironlake_d_info = {
+	.gen = 5, .num_pipes = 2,
+	.need_gfx_hws = 1, .has_hotplug = 1,
+	.ring_mask = RENDER_RING | BSD_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_ironlake_m_info = {
+	.gen = 5, .is_mobile = 1, .num_pipes = 2,
+	.need_gfx_hws = 1, .has_hotplug = 1,
+	.has_fbc = 1,
+	.ring_mask = RENDER_RING | BSD_RING,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_sandybridge_d_info = {
+	.gen = 6, .num_pipes = 2,
+	.need_gfx_hws = 1, .has_hotplug = 1,
+	.has_fbc = 1,
+	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
+	.has_llc = 1,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_sandybridge_m_info = {
+	.gen = 6, .is_mobile = 1, .num_pipes = 2,
+	.need_gfx_hws = 1, .has_hotplug = 1,
+	.has_fbc = 1,
+	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
+	.has_llc = 1,
+	GEN_DEFAULT_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+};
+
+#define GEN7_FEATURES  \
+	.gen = 7, .num_pipes = 3, \
+	.need_gfx_hws = 1, .has_hotplug = 1, \
+	.has_fbc = 1, \
+	.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
+	.has_llc = 1, \
+	GEN_DEFAULT_PIPEOFFSETS, \
+	IVB_CURSOR_OFFSETS
+
+static const struct intel_device_info intel_ivybridge_d_info = {
+	GEN7_FEATURES,
+	.is_ivybridge = 1,
+};
+
+static const struct intel_device_info intel_ivybridge_m_info = {
+	GEN7_FEATURES,
+	.is_ivybridge = 1,
+	.is_mobile = 1,
+};
+
+static const struct intel_device_info intel_ivybridge_q_info = {
+	GEN7_FEATURES,
+	.is_ivybridge = 1,
+	.num_pipes = 0, /* legal, last one wins */
+};
+
+#define VLV_FEATURES  \
+	.gen = 7, .num_pipes = 2, \
+	.need_gfx_hws = 1, .has_hotplug = 1, \
+	.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
+	.display_mmio_offset = VLV_DISPLAY_BASE, \
+	GEN_DEFAULT_PIPEOFFSETS, \
+	CURSOR_OFFSETS
+
+static const struct intel_device_info intel_valleyview_m_info = {
+	VLV_FEATURES,
+	.is_valleyview = 1,
+	.is_mobile = 1,
+};
+
+static const struct intel_device_info intel_valleyview_d_info = {
+	VLV_FEATURES,
+	.is_valleyview = 1,
+};
+
+#define HSW_FEATURES  \
+	GEN7_FEATURES, \
+	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \
+	.has_ddi = 1, \
+	.has_fpga_dbg = 1
+
+static const struct intel_device_info intel_haswell_d_info = {
+	HSW_FEATURES,
+	.is_haswell = 1,
+};
+
+static const struct intel_device_info intel_haswell_m_info = {
+	HSW_FEATURES,
+	.is_haswell = 1,
+	.is_mobile = 1,
+};
+
+#define BDW_FEATURES \
+	HSW_FEATURES, \
+	BDW_COLORS
+
+static const struct intel_device_info intel_broadwell_d_info = {
+	BDW_FEATURES,
+	.gen = 8,
+	.is_broadwell = 1,
+};
+
+static const struct intel_device_info intel_broadwell_m_info = {
+	BDW_FEATURES,
+	.gen = 8, .is_mobile = 1,
+	.is_broadwell = 1,
+};
+
+static const struct intel_device_info intel_broadwell_gt3d_info = {
+	BDW_FEATURES,
+	.gen = 8,
+	.is_broadwell = 1,
+	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
+};
+
+static const struct intel_device_info intel_broadwell_gt3m_info = {
+	BDW_FEATURES,
+	.gen = 8, .is_mobile = 1,
+	.is_broadwell = 1,
+	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
+};
+
+static const struct intel_device_info intel_cherryview_info = {
+	.gen = 8, .num_pipes = 3,
+	.need_gfx_hws = 1, .has_hotplug = 1,
+	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
+	.is_cherryview = 1,
+	.display_mmio_offset = VLV_DISPLAY_BASE,
+	GEN_CHV_PIPEOFFSETS,
+	CURSOR_OFFSETS,
+	CHV_COLORS,
+};
+
+static const struct intel_device_info intel_skylake_info = {
+	BDW_FEATURES,
+	.is_skylake = 1,
+	.gen = 9,
+};
+
+static const struct intel_device_info intel_skylake_gt3_info = {
+	BDW_FEATURES,
+	.is_skylake = 1,
+	.gen = 9,
+	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
+};
+
+static const struct intel_device_info intel_broxton_info = {
+	.is_preliminary = 1,
+	.is_broxton = 1,
+	.gen = 9,
+	.need_gfx_hws = 1, .has_hotplug = 1,
+	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
+	.num_pipes = 3,
+	.has_ddi = 1,
+	.has_fpga_dbg = 1,
+	.has_fbc = 1,
+	GEN_DEFAULT_PIPEOFFSETS,
+	IVB_CURSOR_OFFSETS,
+	BDW_COLORS,
+};
+
+static const struct intel_device_info intel_kabylake_info = {
+	BDW_FEATURES,
+	.is_kabylake = 1,
+	.gen = 9,
+};
+
+static const struct intel_device_info intel_kabylake_gt3_info = {
+	BDW_FEATURES,
+	.is_kabylake = 1,
+	.gen = 9,
+	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
+};
+
+/*
+ * Make sure any device matches here are from most specific to most
+ * general.  For example, since the Quanta match is based on the subsystem
+ * and subvendor IDs, we need it to come before the more general IVB
+ * PCI ID matches, otherwise we'll use the wrong info struct above.
+ */
+static const struct pci_device_id pciidlist[] = {
+	INTEL_I830_IDS(&intel_i830_info),
+	INTEL_I845G_IDS(&intel_845g_info),
+	INTEL_I85X_IDS(&intel_i85x_info),
+	INTEL_I865G_IDS(&intel_i865g_info),
+	INTEL_I915G_IDS(&intel_i915g_info),
+	INTEL_I915GM_IDS(&intel_i915gm_info),
+	INTEL_I945G_IDS(&intel_i945g_info),
+	INTEL_I945GM_IDS(&intel_i945gm_info),
+	INTEL_I965G_IDS(&intel_i965g_info),
+	INTEL_G33_IDS(&intel_g33_info),
+	INTEL_I965GM_IDS(&intel_i965gm_info),
+	INTEL_GM45_IDS(&intel_gm45_info),
+	INTEL_G45_IDS(&intel_g45_info),
+	INTEL_PINEVIEW_IDS(&intel_pineview_info),
+	INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info),
+	INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info),
+	INTEL_SNB_D_IDS(&intel_sandybridge_d_info),
+	INTEL_SNB_M_IDS(&intel_sandybridge_m_info),
+	INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */
+	INTEL_IVB_M_IDS(&intel_ivybridge_m_info),
+	INTEL_IVB_D_IDS(&intel_ivybridge_d_info),
+	INTEL_HSW_D_IDS(&intel_haswell_d_info),
+	INTEL_HSW_M_IDS(&intel_haswell_m_info),
+	INTEL_VLV_M_IDS(&intel_valleyview_m_info),
+	INTEL_VLV_D_IDS(&intel_valleyview_d_info),
+	INTEL_BDW_GT12M_IDS(&intel_broadwell_m_info),
+	INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info),
+	INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info),
+	INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info),
+	INTEL_CHV_IDS(&intel_cherryview_info),
+	INTEL_SKL_GT1_IDS(&intel_skylake_info),
+	INTEL_SKL_GT2_IDS(&intel_skylake_info),
+	INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info),
+	INTEL_SKL_GT4_IDS(&intel_skylake_gt3_info),
+	INTEL_BXT_IDS(&intel_broxton_info),
+	INTEL_KBL_GT1_IDS(&intel_kabylake_info),
+	INTEL_KBL_GT2_IDS(&intel_kabylake_info),
+	INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info),
+	INTEL_KBL_GT4_IDS(&intel_kabylake_gt3_info),
+	{0, 0, 0}
+};
+MODULE_DEVICE_TABLE(pci, pciidlist);
+
+extern int i915_driver_load(struct pci_dev *pdev,
+			    const struct pci_device_id *ent);
+
+static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct intel_device_info *intel_info =
+		(struct intel_device_info *) ent->driver_data;
+
+	if (IS_PRELIMINARY_HW(intel_info) && !i915.preliminary_hw_support) {
+		DRM_INFO("This hardware requires preliminary hardware support.\n"
+			 "See CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT, and/or modparam preliminary_hw_support\n");
+		return -ENODEV;
+	}
+
+	/* Only bind to function 0 of the device. Early generations
+	 * used function 1 as a placeholder for multi-head. This causes
+	 * us confusion instead, especially on the systems where both
+	 * functions have the same PCI-ID!
+	 */
+	if (PCI_FUNC(pdev->devfn))
+		return -ENODEV;
+
+	/*
+	 * apple-gmux is needed on dual GPU MacBook Pro
+	 * to probe the panel if we're the inactive GPU.
+	 */
+	if (IS_ENABLED(CONFIG_VGA_ARB) && IS_ENABLED(CONFIG_VGA_SWITCHEROO) &&
+	    apple_gmux_present() && pdev != vga_default_device() &&
+	    !vga_switcheroo_handler_flags())
+		return -EPROBE_DEFER;
+
+	return i915_driver_load(pdev, ent);
+}
+
+extern void i915_driver_unload(struct drm_device *dev);
+
+static void i915_pci_remove(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+
+	i915_driver_unload(dev);
+	drm_dev_unref(dev);
+}
+
+extern const struct dev_pm_ops i915_pm_ops;
+
+struct pci_driver i915_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+	.probe = i915_pci_probe,
+	.remove = i915_pci_remove,
+	.driver.pm = &i915_pm_ops,
+};
-- 
2.8.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 11/11] drm/i915: Move module init/exit to i915_pci.c
  2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
                   ` (9 preceding siblings ...)
  2016-05-27 14:00 ` [PATCH 10/11] drm/i915: Split out the PCI driver interface to i915_pci.c Chris Wilson
@ 2016-05-27 14:00 ` Chris Wilson
  2016-05-30  6:44   ` Joonas Lahtinen
  2016-05-27 14:58 ` ✗ Ro.CI.BAT: failure for series starting with [01/11] drm: Export drm_dev_init() for subclassing (rev2) Patchwork
  11 siblings, 1 reply; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

The module init/exit routines are a wrapper around the PCI device
init/exit, so move them across.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.c | 51 +++--------------------------------------
 drivers/gpu/drm/i915/i915_pci.c | 45 +++++++++++++++++++++++++++++++++++-
 2 files changed, 47 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 79b6834bc6b2..bf607ca8ddb4 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -28,7 +28,6 @@
  */
 
 #include <linux/acpi.h>
-#include <linux/console.h>
 #include <linux/device.h>
 #include <linux/oom.h>
 #include <linux/module.h>
@@ -1563,6 +1562,9 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct drm_i915_private *dev_priv;
 	int ret;
 
+	if (i915.nuclear_pageflip)
+		driver.driver_features |= DRIVER_ATOMIC;
+
 	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
 	if (dev_priv == NULL)
 		return -ENOMEM;
@@ -2988,50 +2990,3 @@ static struct drm_driver driver = {
 	.minor = DRIVER_MINOR,
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
-
-static int __init i915_init(void)
-{
-	extern struct pci_driver i915_pci_driver;
-
-	/*
-	 * Enable KMS by default, unless explicitly overriden by
-	 * either the i915.modeset prarameter or by the
-	 * vga_text_mode_force boot option.
-	 */
-
-	if (i915.modeset == 0)
-		driver.driver_features &= ~DRIVER_MODESET;
-
-	if (vgacon_text_force() && i915.modeset == -1)
-		driver.driver_features &= ~DRIVER_MODESET;
-
-	if (!(driver.driver_features & DRIVER_MODESET)) {
-		/* Silently fail loading to not upset userspace. */
-		DRM_DEBUG_DRIVER("KMS and UMS disabled.\n");
-		return 0;
-	}
-
-	if (i915.nuclear_pageflip)
-		driver.driver_features |= DRIVER_ATOMIC;
-
-	return drm_pci_init(&driver, &i915_pci_driver);
-}
-
-static void __exit i915_exit(void)
-{
-	extern struct pci_driver i915_pci_driver;
-
-	if (!(driver.driver_features & DRIVER_MODESET))
-		return; /* Never loaded a driver. */
-
-	drm_pci_exit(&driver, &i915_pci_driver);
-}
-
-module_init(i915_init);
-module_exit(i915_exit);
-
-MODULE_AUTHOR("Tungsten Graphics, Inc.");
-MODULE_AUTHOR("Intel Corporation");
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 514d8b784319..3cb3a900b969 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/console.h>
 #include <linux/apple-gmux.h>
 #include <linux/vgaarb.h>
 #include <linux/vga_switcheroo.h>
@@ -454,10 +455,52 @@ static void i915_pci_remove(struct pci_dev *pdev)
 
 extern const struct dev_pm_ops i915_pm_ops;
 
-struct pci_driver i915_pci_driver = {
+static struct pci_driver i915_pci_driver = {
 	.name = DRIVER_NAME,
 	.id_table = pciidlist,
 	.probe = i915_pci_probe,
 	.remove = i915_pci_remove,
 	.driver.pm = &i915_pm_ops,
 };
+
+static int __init i915_init(void)
+{
+	bool use_kms = true;
+
+	/*
+	 * Enable KMS by default, unless explicitly overriden by
+	 * either the i915.modeset prarameter or by the
+	 * vga_text_mode_force boot option.
+	 */
+
+	if (i915.modeset == 0)
+		use_kms = false;
+
+	if (vgacon_text_force() && i915.modeset == -1)
+		use_kms = false;
+
+	if (!use_kms) {
+		/* Silently fail loading to not upset userspace. */
+		DRM_DEBUG_DRIVER("KMS and UMS disabled.\n");
+		return 0;
+	}
+
+	return pci_register_driver(&i915_pci_driver);
+}
+
+static void __exit i915_exit(void)
+{
+	if (!i915_pci_driver.driver.owner)
+		return;
+
+	pci_unregister_driver(&i915_pci_driver);
+}
+
+module_init(i915_init);
+module_exit(i915_exit);
+
+MODULE_AUTHOR("Tungsten Graphics, Inc.");
+MODULE_AUTHOR("Intel Corporation");
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
-- 
2.8.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH 08/11] drm/i915: Start exploiting drm_device subclassing
  2016-05-27 14:00 ` [PATCH 08/11] drm/i915: Start exploiting drm_device subclassing Chris Wilson
@ 2016-05-27 14:15   ` Tvrtko Ursulin
  2016-05-27 14:46     ` [PATCH] drm/i915: Remove drm_i915_private->dev backpointer Chris Wilson
  0 siblings, 1 reply; 28+ messages in thread
From: Tvrtko Ursulin @ 2016-05-27 14:15 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Daniel Vetter


On 27/05/16 15:00, Chris Wilson wrote:
> Baby step, update to_i915() conversion from drm_device to
> drm_i915_private:
>
>     text	   data	    bss	    dec	    hex	filename
> 1108812	  23207	    416	1132435	 114793	i915.ko (before)
> 1104999	  23207	    416	1128622	 1138ae	i915.ko (after)

This patch on its own? Impressive!

>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>   drivers/gpu/drm/i915/i915_drv.h | 10 +++++-----
>   1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 3f6a3648c50a..b95a10fa002a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2033,7 +2033,7 @@ struct drm_i915_private {
>
>   static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
>   {
> -	return dev->dev_private;
> +	return container_of(dev, struct drm_i915_private, drm);
>   }
>
>   static inline struct drm_i915_private *dev_to_i915(struct device *dev)
> @@ -2602,7 +2602,7 @@ struct drm_i915_cmd_table {
>   #define INTEL_DEVID(p)	(INTEL_INFO(p)->device_id)
>
>   #define REVID_FOREVER		0xff
> -#define INTEL_REVID(p)	(__I915__(p)->dev->pdev->revision)
> +#define INTEL_REVID(p)	(__I915__(p)->drm.pdev->revision)
>
>   #define GEN_FOREVER (0)
>   /*
> @@ -3439,7 +3439,7 @@ i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
>   {
>   	struct i915_gem_context *ctx;
>
> -	lockdep_assert_held(&file_priv->dev_priv->dev->struct_mutex);
> +	lockdep_assert_held(&file_priv->dev_priv->drm.struct_mutex);
>
>   	ctx = idr_find(&file_priv->context_idr, id);
>   	if (!ctx)
> @@ -3455,7 +3455,7 @@ static inline void i915_gem_context_reference(struct i915_gem_context *ctx)
>
>   static inline void i915_gem_context_unreference(struct i915_gem_context *ctx)
>   {
> -	lockdep_assert_held(&ctx->i915->dev->struct_mutex);
> +	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
>   	kref_put(&ctx->ref, i915_gem_context_free);
>   }
>
> @@ -3531,7 +3531,7 @@ void i915_gem_shrinker_cleanup(struct drm_i915_private *dev_priv);
>   /* i915_gem_tiling.c */
>   static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
>   {
> -	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
> +	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
>
>   	return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
>   		obj->tiling_mode != I915_TILING_NONE;
>

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH] drm/i915: Remove drm_i915_private->dev backpointer
  2016-05-27 14:15   ` Tvrtko Ursulin
@ 2016-05-27 14:46     ` Chris Wilson
  2016-05-30  6:58       ` Joonas Lahtinen
  0 siblings, 1 reply; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 14:46 UTC (permalink / raw)
  To: intel-gfx

Now that drm_i915_private contains drm_device, we can directly go to the
drm_device as required:

   text	   data	    bss	    dec	    hex	filename
1105153	  23207	    416	1128776	 113948	i915.ko (before)
1102849	  23207	    416	1126472	 113048	i915.ko (after)

s/dev_priv->dev->/dev_priv->drm./
s/dev_priv->dev/\&dev_priv->drm./

There is still a fair amount that we can tidy by hand.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---

This will cause a fair amount of conflict though. Nowhere as near as
pleasant as it could be yet.
-Chris

---
 drivers/gpu/drm/i915/i915_debugfs.c          | 16 ++++----
 drivers/gpu/drm/i915/i915_drv.c              | 45 +++++++++++----------
 drivers/gpu/drm/i915/i915_drv.h              | 13 +++----
 drivers/gpu/drm/i915/i915_gem.c              | 10 ++---
 drivers/gpu/drm/i915/i915_gem_context.c      |  6 +--
 drivers/gpu/drm/i915/i915_gem_execbuffer.c   |  4 +-
 drivers/gpu/drm/i915/i915_gem_gtt.c          | 10 ++---
 drivers/gpu/drm/i915/i915_gem_render_state.c |  2 +-
 drivers/gpu/drm/i915/i915_gem_shrinker.c     | 10 ++---
 drivers/gpu/drm/i915/i915_gpu_error.c        |  4 +-
 drivers/gpu/drm/i915/i915_guc_submission.c   |  8 ++--
 drivers/gpu/drm/i915/i915_irq.c              | 36 ++++++++---------
 drivers/gpu/drm/i915/i915_trace.h            | 20 +++++-----
 drivers/gpu/drm/i915/intel_audio.c           | 12 +++---
 drivers/gpu/drm/i915/intel_bios.c            |  2 +-
 drivers/gpu/drm/i915/intel_csr.c             |  4 +-
 drivers/gpu/drm/i915/intel_display.c         | 58 ++++++++++++++--------------
 drivers/gpu/drm/i915/intel_dp.c              | 14 +++----
 drivers/gpu/drm/i915/intel_dpll_mgr.c        |  2 +-
 drivers/gpu/drm/i915/intel_fbc.c             |  4 +-
 drivers/gpu/drm/i915/intel_fbdev.c           |  8 ++--
 drivers/gpu/drm/i915/intel_fifo_underrun.c   | 10 ++---
 drivers/gpu/drm/i915/intel_guc_loader.c      |  2 +-
 drivers/gpu/drm/i915/intel_hdmi.c            |  2 +-
 drivers/gpu/drm/i915/intel_hotplug.c         |  8 ++--
 drivers/gpu/drm/i915/intel_i2c.c             |  6 +--
 drivers/gpu/drm/i915/intel_lrc.c             | 10 ++---
 drivers/gpu/drm/i915/intel_opregion.c        | 10 ++---
 drivers/gpu/drm/i915/intel_overlay.c         | 22 +++++------
 drivers/gpu/drm/i915/intel_panel.c           |  6 +--
 drivers/gpu/drm/i915/intel_pm.c              | 30 +++++++-------
 drivers/gpu/drm/i915/intel_ringbuffer.c      | 10 ++---
 drivers/gpu/drm/i915/intel_runtime_pm.c      | 26 ++++++-------
 drivers/gpu/drm/i915/intel_sdvo.c            |  2 +-
 drivers/gpu/drm/i915/intel_uncore.c          |  6 +--
 35 files changed, 218 insertions(+), 220 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index d018ec5093ba..abe12ac134cf 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -440,15 +440,15 @@ static void print_context_stats(struct seq_file *m,
 
 	memset(&stats, 0, sizeof(stats));
 
-	mutex_lock(&dev_priv->dev->struct_mutex);
+	mutex_lock(&dev_priv->drm.struct_mutex);
 	if (dev_priv->kernel_context)
 		per_file_ctx_stats(0, dev_priv->kernel_context, &stats);
 
-	list_for_each_entry(file, &dev_priv->dev->filelist, lhead) {
+	list_for_each_entry(file, &dev_priv->drm.filelist, lhead) {
 		struct drm_i915_file_private *fpriv = file->driver_priv;
 		idr_for_each(&fpriv->context_idr, per_file_ctx_stats, &stats);
 	}
-	mutex_unlock(&dev_priv->dev->struct_mutex);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
 
 	print_file_stats(m, "[k]contexts", stats);
 }
@@ -2777,8 +2777,8 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
 	seq_printf(m, "Device Power Management (CONFIG_PM) disabled\n");
 #endif
 	seq_printf(m, "PCI device power state: %s [%d]\n",
-		   pci_power_name(dev_priv->dev->pdev->current_state),
-		   dev_priv->dev->pdev->current_state);
+		   pci_power_name(dev_priv->drm.pdev->current_state),
+		   dev_priv->drm.pdev->current_state);
 
 	return 0;
 }
@@ -5118,7 +5118,7 @@ i915_cache_sharing_get(void *data, u64 *val)
 	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
 
 	intel_runtime_pm_put(dev_priv);
-	mutex_unlock(&dev_priv->dev->struct_mutex);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
 
 	*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
 
@@ -5500,7 +5500,7 @@ void intel_display_crc_init(struct drm_device *dev)
 
 int i915_debugfs_register(struct drm_i915_private *dev_priv)
 {
-	struct drm_minor *minor = dev_priv->dev->primary;
+	struct drm_minor *minor = dev_priv->drm.primary;
 	int ret, i;
 
 	ret = i915_forcewake_create(minor->debugfs_root, minor);
@@ -5528,7 +5528,7 @@ int i915_debugfs_register(struct drm_i915_private *dev_priv)
 
 void i915_debugfs_unregister(struct drm_i915_private *dev_priv)
 {
-	struct drm_minor *minor = dev_priv->dev->primary;
+	struct drm_minor *minor = dev_priv->drm.primary;
 	int i;
 
 	drm_debugfs_remove_files(i915_debugfs_list,
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index bf607ca8ddb4..7c70469219e2 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -77,7 +77,7 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level,
 	      const char *fmt, ...)
 {
 	static bool shown_bug_once;
-	struct device *dev = dev_priv->dev->dev;
+	struct device *dev = dev_priv->drm.dev;
 	bool is_error = level[1] <= KERN_ERR[1];
 	bool is_debug = level[1] == KERN_DEBUG[1];
 	struct va_format vaf;
@@ -681,7 +681,7 @@ out:
 static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 {
 	struct apertures_struct *ap;
-	struct pci_dev *pdev = dev_priv->dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	bool primary;
 	int ret;
@@ -753,8 +753,8 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 	DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags="
 			 DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
 			 info->gen,
-			 dev_priv->dev->pdev->device,
-			 dev_priv->dev->pdev->revision,
+			 dev_priv->drm.pdev->device,
+			 dev_priv->drm.pdev->revision,
 			 DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
 #undef PRINT_S
 #undef SEP_EMPTY
@@ -1245,7 +1245,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
  */
 static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
 {
-	i915_gem_load_cleanup(dev_priv->dev);
+	i915_gem_load_cleanup(&dev_priv->drm);
 	i915_workqueues_cleanup(dev_priv);
 }
 
@@ -1300,7 +1300,7 @@ static void i915_mmio_cleanup(struct drm_device *dev)
  */
 static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	int ret;
 
 	if (i915_inject_load_failure())
@@ -1329,7 +1329,7 @@ put_bridge:
  */
 static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 
 	intel_uncore_fini(dev_priv);
 	i915_mmio_cleanup(dev);
@@ -1345,7 +1345,7 @@ static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv)
  */
 static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	uint32_t aperture_size;
 	int ret;
@@ -1462,7 +1462,7 @@ out_ggtt:
  */
 static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 
 	if (dev->pdev->msi_enabled)
@@ -1483,7 +1483,7 @@ static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv)
  */
 static void i915_driver_register(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 
 	i915_gem_shrinker_init(dev_priv);
 
@@ -1539,9 +1539,9 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
 	intel_opregion_unregister(dev_priv);
 
 	intel_modeset_unregister(dev_priv);
-	i915_teardown_sysfs(dev_priv->dev);
+	i915_teardown_sysfs(&dev_priv->drm);
 	i915_debugfs_unregister(dev_priv);
-	drm_dev_unregister(dev_priv->dev);
+	drm_dev_unregister(&dev_priv->drm);
 
 	i915_gem_shrinker_cleanup(dev_priv);
 }
@@ -1576,7 +1576,6 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
 	/* Must be set before calling __i915_printk */
 	dev_priv->drm.pdev = pdev;
 	dev_priv->drm.dev_private = dev_priv;
-	dev_priv->dev = &dev_priv->drm;
 
 	ret = i915_driver_init_early(dev_priv, ent);
 	if (ret < 0)
@@ -1604,13 +1603,13 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 * to the role/effect of the given init step.
 	 */
 	if (INTEL_INFO(dev_priv)->num_pipes) {
-		ret = drm_vblank_init(dev_priv->dev,
+		ret = drm_vblank_init(&dev_priv->drm,
 				      INTEL_INFO(dev_priv)->num_pipes);
 		if (ret)
 			goto out_cleanup_hw;
 	}
 
-	ret = i915_load_modeset_init(dev_priv->dev);
+	ret = i915_load_modeset_init(&dev_priv->drm);
 	if (ret < 0)
 		goto out_cleanup_vblank;
 
@@ -1623,7 +1622,7 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
 	return 0;
 
 out_cleanup_vblank:
-	drm_vblank_cleanup(dev_priv->dev);
+	drm_vblank_cleanup(&dev_priv->drm);
 out_cleanup_hw:
 	i915_driver_cleanup_hw(dev_priv);
 out_cleanup_mmio:
@@ -1744,7 +1743,7 @@ static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
 
 static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct intel_encoder *encoder;
 
 	drm_modeset_lock_all(dev);
@@ -2112,7 +2111,7 @@ int i915_resume_switcheroo(struct drm_device *dev)
  */
 int i915_reset(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct i915_gpu_error *error = &dev_priv->gpu_error;
 	unsigned reset_counter;
 	int ret;
@@ -2216,7 +2215,7 @@ static int i915_pm_suspend(struct device *dev)
 
 static int i915_pm_suspend_late(struct device *dev)
 {
-	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
+	struct drm_device *drm_dev = &dev_to_i915(dev)->drm;
 
 	/*
 	 * We have a suspend ordering issue with the snd-hda driver also
@@ -2235,7 +2234,7 @@ static int i915_pm_suspend_late(struct device *dev)
 
 static int i915_pm_poweroff_late(struct device *dev)
 {
-	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
+	struct drm_device *drm_dev = &dev_to_i915(dev)->drm;
 
 	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
@@ -2245,7 +2244,7 @@ static int i915_pm_poweroff_late(struct device *dev)
 
 static int i915_pm_resume_early(struct device *dev)
 {
-	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
+	struct drm_device *drm_dev = &dev_to_i915(dev)->drm;
 
 	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
@@ -2255,7 +2254,7 @@ static int i915_pm_resume_early(struct device *dev)
 
 static int i915_pm_resume(struct device *dev)
 {
-	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
+	struct drm_device *drm_dev = &dev_to_i915(dev)->drm;
 
 	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
@@ -2630,7 +2629,7 @@ err1:
 static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
 				bool rpm_resume)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	int err;
 	int ret;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1df141e4ab6b..3ba289df3843 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -317,15 +317,15 @@ struct i915_hotplug {
 		for_each_if ((__ports_mask) & (1 << (__port)))
 
 #define for_each_crtc(dev, crtc) \
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+	list_for_each_entry(crtc, &(dev)->mode_config.crtc_list, head)
 
 #define for_each_intel_plane(dev, intel_plane) \
 	list_for_each_entry(intel_plane,			\
-			    &dev->mode_config.plane_list,	\
+			    &(dev)->mode_config.plane_list,	\
 			    base.head)
 
 #define for_each_intel_plane_mask(dev, intel_plane, plane_mask)		\
-	list_for_each_entry(intel_plane, &dev->mode_config.plane_list,	\
+	list_for_each_entry(intel_plane, &(dev)->mode_config.plane_list,	\
 			    base.head)					\
 		for_each_if ((plane_mask) &				\
 			     (1 << drm_plane_index(&intel_plane->base)))
@@ -337,10 +337,10 @@ struct i915_hotplug {
 		for_each_if ((intel_plane)->pipe == (intel_crtc)->pipe)
 
 #define for_each_intel_crtc(dev, intel_crtc) \
-	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
+	list_for_each_entry(intel_crtc, &(dev)->mode_config.crtc_list, base.head)
 
 #define for_each_intel_crtc_mask(dev, intel_crtc, crtc_mask) \
-	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) \
+	list_for_each_entry(intel_crtc, &(dev)->mode_config.crtc_list, base.head) \
 		for_each_if ((crtc_mask) & (1 << drm_crtc_index(&intel_crtc->base)))
 
 #define for_each_intel_encoder(dev, intel_encoder)		\
@@ -350,7 +350,7 @@ struct i915_hotplug {
 
 #define for_each_intel_connector(dev, intel_connector)		\
 	list_for_each_entry(intel_connector,			\
-			    &dev->mode_config.connector_list,	\
+			    &(dev)->mode_config.connector_list,	\
 			    base.head)
 
 #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \
@@ -1724,7 +1724,6 @@ struct intel_wm_config {
 struct drm_i915_private {
 	struct drm_device drm;
 
-	struct drm_device *dev;
 	struct kmem_cache *objects;
 	struct kmem_cache *vmas;
 	struct kmem_cache *requests;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 89967f97c097..49e0590726d5 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1428,7 +1428,7 @@ __i915_gem_request_retire__upto(struct drm_i915_gem_request *req)
 	struct intel_engine_cs *engine = req->engine;
 	struct drm_i915_gem_request *tmp;
 
-	lockdep_assert_held(&engine->i915->dev->struct_mutex);
+	lockdep_assert_held(&engine->i915->drm.struct_mutex);
 
 	if (list_empty(&req->list))
 		return;
@@ -1456,7 +1456,7 @@ i915_wait_request(struct drm_i915_gem_request *req)
 
 	interruptible = dev_priv->mm.interruptible;
 
-	BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+	BUG_ON(!mutex_is_locked(&dev_priv->drm.struct_mutex));
 
 	ret = __i915_wait_request(req, interruptible, NULL, NULL);
 	if (ret)
@@ -3027,7 +3027,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
 {
 	struct drm_i915_private *dev_priv =
 		container_of(work, typeof(*dev_priv), mm.retire_work.work);
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	bool idle;
 
 	/* Come back later if the device is busy... */
@@ -3046,7 +3046,7 @@ i915_gem_idle_work_handler(struct work_struct *work)
 {
 	struct drm_i915_private *dev_priv =
 		container_of(work, typeof(*dev_priv), mm.idle_work.work);
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct intel_engine_cs *engine;
 
 	for_each_engine(engine, dev_priv)
@@ -4976,7 +4976,7 @@ init_engine_lists(struct intel_engine_cs *engine)
 void
 i915_gem_load_init_fences(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 
 	if (INTEL_INFO(dev_priv)->gen >= 7 && !IS_VALLEYVIEW(dev_priv) &&
 	    !IS_CHERRYVIEW(dev_priv))
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index a3b11aac23a4..4f3949e6d480 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -154,7 +154,7 @@ void i915_gem_context_free(struct kref *ctx_ref)
 	struct i915_gem_context *ctx = container_of(ctx_ref, typeof(*ctx), ref);
 	int i;
 
-	lockdep_assert_held(&ctx->i915->dev->struct_mutex);
+	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
 	trace_i915_context_free(ctx);
 
 	/*
@@ -445,7 +445,7 @@ void i915_gem_context_lost(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
 
-	lockdep_assert_held(&dev_priv->dev->struct_mutex);
+	lockdep_assert_held(&dev_priv->drm.struct_mutex);
 
 	for_each_engine(engine, dev_priv) {
 		if (engine->last_context) {
@@ -863,7 +863,7 @@ int i915_switch_context(struct drm_i915_gem_request *req)
 	struct intel_engine_cs *engine = req->engine;
 
 	WARN_ON(i915.enable_execlists);
-	lockdep_assert_held(&req->i915->dev->struct_mutex);
+	lockdep_assert_held(&req->i915->drm.struct_mutex);
 
 	if (!req->ctx->engine[engine->id].state) {
 		struct i915_gem_context *to = req->ctx;
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 84d990331abd..e2b6272ba3da 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1330,10 +1330,10 @@ gen8_dispatch_bsd_ring(struct drm_i915_private *dev_priv, struct drm_file *file)
 	/* Check whether the file_priv has already selected one ring. */
 	if ((int)file_priv->bsd_ring < 0) {
 		/* If not, use the ping-pong mechanism to select one. */
-		mutex_lock(&dev_priv->dev->struct_mutex);
+		mutex_lock(&dev_priv->drm.struct_mutex);
 		file_priv->bsd_ring = dev_priv->mm.bsd_ring_dispatch_index;
 		dev_priv->mm.bsd_ring_dispatch_index ^= 1;
-		mutex_unlock(&dev_priv->dev->struct_mutex);
+		mutex_unlock(&dev_priv->drm.struct_mutex);
 	}
 
 	return file_priv->bsd_ring;
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 46684779d4d6..98065eb43fb5 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -153,7 +153,7 @@ int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
 #endif
 
 	/* Early VLV doesn't have this */
-	if (IS_VALLEYVIEW(dev_priv) && dev_priv->dev->pdev->revision < 0xb) {
+	if (IS_VALLEYVIEW(dev_priv) && dev_priv->drm.pdev->revision < 0xb) {
 		DRM_DEBUG_DRIVER("disabling PPGTT on pre-B3 step VLV\n");
 		return 0;
 	}
@@ -2133,7 +2133,7 @@ static void i915_address_space_init(struct i915_address_space *vm,
 				    struct drm_i915_private *dev_priv)
 {
 	drm_mm_init(&vm->mm, vm->start, vm->total);
-	vm->dev = dev_priv->dev;
+	vm->dev = &dev_priv->drm;
 	INIT_LIST_HEAD(&vm->active_list);
 	INIT_LIST_HEAD(&vm->inactive_list);
 	list_add_tail(&vm->global_link, &dev_priv->vm_list);
@@ -2261,7 +2261,7 @@ static bool do_idling(struct drm_i915_private *dev_priv)
 
 	if (unlikely(ggtt->do_idle_maps)) {
 		dev_priv->mm.interruptible = false;
-		if (i915_gpu_idle(dev_priv->dev)) {
+		if (i915_gpu_idle(&dev_priv->drm)) {
 			DRM_ERROR("Couldn't idle GPU\n");
 			/* Wait a bit, in hopes it avoids the hang */
 			udelay(10);
@@ -3137,7 +3137,7 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	int ret;
 
-	ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->dev->pdev, NULL);
+	ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->drm.pdev, NULL);
 	if (!ret) {
 		DRM_ERROR("failed to set up gmch\n");
 		return -EIO;
@@ -3146,7 +3146,7 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt)
 	intel_gtt_get(&ggtt->base.total, &ggtt->stolen_size,
 		      &ggtt->mappable_base, &ggtt->mappable_end);
 
-	ggtt->do_idle_maps = needs_idle_maps(dev_priv->dev);
+	ggtt->do_idle_maps = needs_idle_maps(&dev_priv->drm);
 	ggtt->base.insert_entries = i915_ggtt_insert_entries;
 	ggtt->base.clear_range = i915_ggtt_clear_range;
 	ggtt->base.bind_vma = ggtt_bind_vma;
diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c
index 7c93327b70fe..8a129843956f 100644
--- a/drivers/gpu/drm/i915/i915_gem_render_state.c
+++ b/drivers/gpu/drm/i915/i915_gem_render_state.c
@@ -58,7 +58,7 @@ static int render_state_init(struct render_state *so,
 	if (so->rodata->batch_items * 4 > 4096)
 		return -EINVAL;
 
-	so->obj = i915_gem_object_create(dev_priv->dev, 4096);
+	so->obj = i915_gem_object_create(&dev_priv->drm, 4096);
 	if (IS_ERR(so->obj))
 		return PTR_ERR(so->obj);
 
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index 538c30499848..e63852795395 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -257,7 +257,7 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
 {
 	struct drm_i915_private *dev_priv =
 		container_of(shrinker, struct drm_i915_private, mm.shrinker);
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct drm_i915_gem_object *obj;
 	unsigned long count;
 	bool unlock;
@@ -286,7 +286,7 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
 {
 	struct drm_i915_private *dev_priv =
 		container_of(shrinker, struct drm_i915_private, mm.shrinker);
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	unsigned long freed;
 	bool unlock;
 
@@ -321,7 +321,7 @@ i915_gem_shrinker_lock_uninterruptible(struct drm_i915_private *dev_priv,
 {
 	unsigned long timeout = msecs_to_jiffies(timeout_ms) + 1;
 
-	while (!i915_gem_shrinker_lock(dev_priv->dev, &slu->unlock)) {
+	while (!i915_gem_shrinker_lock(&dev_priv->drm, &slu->unlock)) {
 		schedule_timeout_killable(1);
 		if (fatal_signal_pending(current))
 			return false;
@@ -342,7 +342,7 @@ i915_gem_shrinker_unlock_uninterruptible(struct drm_i915_private *dev_priv,
 {
 	dev_priv->mm.interruptible = slu->was_interruptible;
 	if (slu->unlock)
-		mutex_unlock(&dev_priv->dev->struct_mutex);
+		mutex_unlock(&dev_priv->drm.struct_mutex);
 }
 
 static int
@@ -408,7 +408,7 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr
 		return NOTIFY_DONE;
 
 	/* Force everything onto the inactive lists */
-	ret = i915_gpu_idle(dev_priv->dev);
+	ret = i915_gpu_idle(&dev_priv->drm);
 	if (ret)
 		goto out;
 
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 34ff2459ceea..0c69e4bee7a4 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1230,7 +1230,7 @@ static void i915_gem_capture_buffers(struct drm_i915_private *dev_priv,
 static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
 				   struct drm_i915_error_state *error)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	int i;
 
 	/* General organization
@@ -1395,7 +1395,7 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv,
 		DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n");
 		DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n");
 		DRM_INFO("The gpu crash dump is required to analyze gpu hangs, so please always attach it.\n");
-		DRM_INFO("GPU crash dump saved to /sys/class/drm/card%d/error\n", dev_priv->dev->primary->index);
+		DRM_INFO("GPU crash dump saved to /sys/class/drm/card%d/error\n", dev_priv->drm.primary->index);
 		warned = true;
 	}
 }
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index ac72451c571c..214139055013 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -153,7 +153,7 @@ static int host2guc_sample_forcewake(struct intel_guc *guc,
 				     struct i915_guc_client *client)
 {
 	struct drm_i915_private *dev_priv = guc_to_i915(guc);
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	u32 data[2];
 
 	data[0] = HOST2GUC_ACTION_SAMPLE_FORCEWAKE;
@@ -790,7 +790,7 @@ static void guc_create_log(struct intel_guc *guc)
 
 	obj = guc->log_obj;
 	if (!obj) {
-		obj = gem_allocate_guc_obj(dev_priv->dev, size);
+		obj = gem_allocate_guc_obj(&dev_priv->drm, size);
 		if (!obj) {
 			/* logging will be off */
 			i915.guc_log_level = -1;
@@ -850,7 +850,7 @@ static void guc_create_ads(struct intel_guc *guc)
 
 	obj = guc->ads_obj;
 	if (!obj) {
-		obj = gem_allocate_guc_obj(dev_priv->dev, PAGE_ALIGN(size));
+		obj = gem_allocate_guc_obj(&dev_priv->drm, PAGE_ALIGN(size));
 		if (!obj)
 			return;
 
@@ -918,7 +918,7 @@ int i915_guc_submission_init(struct drm_device *dev)
 	if (guc->ctx_pool_obj)
 		return 0; /* already allocated */
 
-	guc->ctx_pool_obj = gem_allocate_guc_obj(dev_priv->dev, gemsize);
+	guc->ctx_pool_obj = gem_allocate_guc_obj(&dev_priv->drm, gemsize);
 	if (!guc->ctx_pool_obj)
 		return -ENOMEM;
 
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index caaf1e2a7bc1..95b87549f41c 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -397,7 +397,7 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv)
 
 	spin_unlock_irq(&dev_priv->irq_lock);
 
-	synchronize_irq(dev_priv->dev->irq);
+	synchronize_irq(dev_priv->drm.irq);
 }
 
 /**
@@ -577,7 +577,7 @@ i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
 	u32 enable_mask;
 
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
+		enable_mask = vlv_get_pipestat_enable_mask(&dev_priv->drm,
 							   status_mask);
 	else
 		enable_mask = status_mask << 16;
@@ -591,7 +591,7 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
 	u32 enable_mask;
 
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
+		enable_mask = vlv_get_pipestat_enable_mask(&dev_priv->drm,
 							   status_mask);
 	else
 		enable_mask = status_mask << 16;
@@ -1197,7 +1197,7 @@ static void ivybridge_parity_work(struct work_struct *work)
 	 * In order to prevent a get/put style interface, acquire struct mutex
 	 * any time we access those registers.
 	 */
-	mutex_lock(&dev_priv->dev->struct_mutex);
+	mutex_lock(&dev_priv->drm.struct_mutex);
 
 	/* If we've screwed up tracking, just let the interrupt fire again */
 	if (WARN_ON(!dev_priv->l3_parity.which_slice))
@@ -1233,7 +1233,7 @@ static void ivybridge_parity_work(struct work_struct *work)
 		parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice);
 		parity_event[5] = NULL;
 
-		kobject_uevent_env(&dev_priv->dev->primary->kdev->kobj,
+		kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj,
 				   KOBJ_CHANGE, parity_event);
 
 		DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n",
@@ -1253,7 +1253,7 @@ out:
 	gen5_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv));
 	spin_unlock_irq(&dev_priv->irq_lock);
 
-	mutex_unlock(&dev_priv->dev->struct_mutex);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
 }
 
 static void ivybridge_parity_error_irq_handler(struct drm_i915_private *dev_priv,
@@ -1538,7 +1538,7 @@ static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
 
 	entry = &pipe_crc->entries[head];
 
-	entry->frame = dev_priv->dev->driver->get_vblank_counter(dev_priv->dev,
+	entry->frame = dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm,
 								 pipe);
 	entry->crc[0] = crc0;
 	entry->crc[1] = crc1;
@@ -1636,7 +1636,7 @@ static bool intel_pipe_handle_vblank(struct drm_i915_private *dev_priv,
 {
 	bool ret;
 
-	ret = drm_handle_vblank(dev_priv->dev, pipe);
+	ret = drm_handle_vblank(&dev_priv->drm, pipe);
 	if (ret)
 		intel_finish_page_flip_mmio(dev_priv, pipe);
 
@@ -2536,7 +2536,7 @@ static void i915_error_wake_up(struct drm_i915_private *dev_priv,
  */
 static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv)
 {
-	struct kobject *kobj = &dev_priv->dev->primary->kdev->kobj;
+	struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj;
 	char *error_event[] = { I915_ERROR_UEVENT "=1", NULL };
 	char *reset_event[] = { I915_RESET_UEVENT "=1", NULL };
 	char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL };
@@ -3455,7 +3455,7 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
 	spin_unlock_irq(&dev_priv->irq_lock);
 
 	/* make sure we're done processing display irqs */
-	synchronize_irq(dev_priv->dev->irq);
+	synchronize_irq(dev_priv->drm.irq);
 }
 
 static void cherryview_irq_preinstall(struct drm_device *dev)
@@ -3481,7 +3481,7 @@ static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv,
 	struct intel_encoder *encoder;
 	u32 enabled_irqs = 0;
 
-	for_each_intel_encoder(dev_priv->dev, encoder)
+	for_each_intel_encoder(&dev_priv->drm, encoder)
 		if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED)
 			enabled_irqs |= hpd[encoder->hpd_pin];
 
@@ -4564,7 +4564,7 @@ static void i965_irq_uninstall(struct drm_device * dev)
  */
 void intel_irq_init(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 
 	intel_hpd_init_work(dev_priv);
 
@@ -4684,7 +4684,7 @@ int intel_irq_install(struct drm_i915_private *dev_priv)
 	 */
 	dev_priv->pm.irqs_enabled = true;
 
-	return drm_irq_install(dev_priv->dev, dev_priv->dev->pdev->irq);
+	return drm_irq_install(&dev_priv->drm, dev_priv->drm.pdev->irq);
 }
 
 /**
@@ -4696,7 +4696,7 @@ int intel_irq_install(struct drm_i915_private *dev_priv)
  */
 void intel_irq_uninstall(struct drm_i915_private *dev_priv)
 {
-	drm_irq_uninstall(dev_priv->dev);
+	drm_irq_uninstall(&dev_priv->drm);
 	intel_hpd_cancel_work(dev_priv);
 	dev_priv->pm.irqs_enabled = false;
 }
@@ -4710,9 +4710,9 @@ void intel_irq_uninstall(struct drm_i915_private *dev_priv)
  */
 void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv)
 {
-	dev_priv->dev->driver->irq_uninstall(dev_priv->dev);
+	dev_priv->drm.driver->irq_uninstall(&dev_priv->drm);
 	dev_priv->pm.irqs_enabled = false;
-	synchronize_irq(dev_priv->dev->irq);
+	synchronize_irq(dev_priv->drm.irq);
 }
 
 /**
@@ -4725,6 +4725,6 @@ void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv)
 void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv)
 {
 	dev_priv->pm.irqs_enabled = true;
-	dev_priv->dev->driver->irq_preinstall(dev_priv->dev);
-	dev_priv->dev->driver->irq_postinstall(dev_priv->dev);
+	dev_priv->drm.driver->irq_preinstall(&dev_priv->drm);
+	dev_priv->drm.driver->irq_postinstall(&dev_priv->drm);
 }
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 6768db032f84..4d530dd3eed0 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -118,7 +118,7 @@ TRACE_EVENT(i915_gem_shrink,
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = i915->dev->primary->index;
+			   __entry->dev = i915->drm.primary->index;
 			   __entry->target = target;
 			   __entry->flags = flags;
 			   ),
@@ -462,7 +462,7 @@ TRACE_EVENT(i915_gem_ring_sync_to,
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = from->i915->dev->primary->index;
+			   __entry->dev = from->i915->drm.primary->index;
 			   __entry->sync_from = from->id;
 			   __entry->sync_to = to_req->engine->id;
 			   __entry->seqno = i915_gem_request_get_seqno(req);
@@ -486,7 +486,7 @@ TRACE_EVENT(i915_gem_ring_dispatch,
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = req->i915->dev->primary->index;
+			   __entry->dev = req->i915->drm.primary->index;
 			   __entry->ring = req->engine->id;
 			   __entry->seqno = req->seqno;
 			   __entry->flags = flags;
@@ -509,7 +509,7 @@ TRACE_EVENT(i915_gem_ring_flush,
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = req->i915->dev->primary->index;
+			   __entry->dev = req->i915->drm.primary->index;
 			   __entry->ring = req->engine->id;
 			   __entry->invalidate = invalidate;
 			   __entry->flush = flush;
@@ -531,7 +531,7 @@ DECLARE_EVENT_CLASS(i915_gem_request,
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = req->i915->dev->primary->index;
+			   __entry->dev = req->i915->drm.primary->index;
 			   __entry->ring = req->engine->id;
 			   __entry->seqno = req->seqno;
 			   ),
@@ -556,7 +556,7 @@ TRACE_EVENT(i915_gem_request_notify,
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = engine->i915->dev->primary->index;
+			   __entry->dev = engine->i915->drm.primary->index;
 			   __entry->ring = engine->id;
 			   __entry->seqno = engine->get_seqno(engine);
 			   ),
@@ -593,11 +593,11 @@ TRACE_EVENT(i915_gem_request_wait_begin,
 	     * less desirable.
 	     */
 	    TP_fast_assign(
-			   __entry->dev = req->i915->dev->primary->index;
+			   __entry->dev = req->i915->drm.primary->index;
 			   __entry->ring = req->engine->id;
 			   __entry->seqno = req->seqno;
 			   __entry->blocking =
-				     mutex_is_locked(&req->i915->dev->struct_mutex);
+				     mutex_is_locked(&req->i915->drm.struct_mutex);
 			   ),
 
 	    TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s",
@@ -746,7 +746,7 @@ DECLARE_EVENT_CLASS(i915_context,
 	TP_fast_assign(
 			__entry->ctx = ctx;
 			__entry->vm = ctx->ppgtt ? &ctx->ppgtt->base : NULL;
-			__entry->dev = ctx->i915->dev->primary->index;
+			__entry->dev = ctx->i915->drm.primary->index;
 	),
 
 	TP_printk("dev=%u, ctx=%p, ctx_vm=%p",
@@ -786,7 +786,7 @@ TRACE_EVENT(switch_mm,
 			__entry->ring = engine->id;
 			__entry->to = to;
 			__entry->vm = to->ppgtt? &to->ppgtt->base : NULL;
-			__entry->dev = engine->i915->dev->primary->index;
+			__entry->dev = engine->i915->drm.primary->index;
 	),
 
 	TP_printk("dev=%u, ring=%u, ctx=%p, ctx_vm=%p",
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index b9329c2a670a..28d7d4437e32 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -749,14 +749,14 @@ static int i915_audio_component_bind(struct device *i915_dev,
 	if (WARN_ON(acomp->ops || acomp->dev))
 		return -EEXIST;
 
-	drm_modeset_lock_all(dev_priv->dev);
+	drm_modeset_lock_all(&dev_priv->drm);
 	acomp->ops = &i915_audio_component_ops;
 	acomp->dev = i915_dev;
 	BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS);
 	for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++)
 		acomp->aud_sample_rate[i] = 0;
 	dev_priv->audio_component = acomp;
-	drm_modeset_unlock_all(dev_priv->dev);
+	drm_modeset_unlock_all(&dev_priv->drm);
 
 	return 0;
 }
@@ -767,11 +767,11 @@ static void i915_audio_component_unbind(struct device *i915_dev,
 	struct i915_audio_component *acomp = data;
 	struct drm_i915_private *dev_priv = dev_to_i915(i915_dev);
 
-	drm_modeset_lock_all(dev_priv->dev);
+	drm_modeset_lock_all(&dev_priv->drm);
 	acomp->ops = NULL;
 	acomp->dev = NULL;
 	dev_priv->audio_component = NULL;
-	drm_modeset_unlock_all(dev_priv->dev);
+	drm_modeset_unlock_all(&dev_priv->drm);
 }
 
 static const struct component_ops i915_audio_component_bind_ops = {
@@ -799,7 +799,7 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv)
 {
 	int ret;
 
-	ret = component_add(dev_priv->dev->dev, &i915_audio_component_bind_ops);
+	ret = component_add(dev_priv->drm.dev, &i915_audio_component_bind_ops);
 	if (ret < 0) {
 		DRM_ERROR("failed to add audio component (%d)\n", ret);
 		/* continue with reduced functionality */
@@ -821,6 +821,6 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv)
 	if (!dev_priv->audio_component_registered)
 		return;
 
-	component_del(dev_priv->dev->dev, &i915_audio_component_bind_ops);
+	component_del(dev_priv->drm.dev, &i915_audio_component_bind_ops);
 	dev_priv->audio_component_registered = false;
 }
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 624e755e451f..b356a149eb4a 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -1421,7 +1421,7 @@ static const struct vbt_header *find_vbt(void __iomem *bios, size_t size)
 int
 intel_bios_init(struct drm_i915_private *dev_priv)
 {
-	struct pci_dev *pdev = dev_priv->dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 	const struct vbt_header *vbt = dev_priv->opregion.vbt;
 	const struct bdb_header *bdb;
 	u8 __iomem *bios = NULL;
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
index 2b3b428d9cd2..1a6486932fc7 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -413,7 +413,7 @@ static void csr_load_work_fn(struct work_struct *work)
 	csr = &dev_priv->csr;
 
 	ret = request_firmware(&fw, dev_priv->csr.fw_path,
-			       &dev_priv->dev->pdev->dev);
+			       &dev_priv->drm.pdev->dev);
 	if (fw)
 		dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw);
 
@@ -427,7 +427,7 @@ static void csr_load_work_fn(struct work_struct *work)
 			 CSR_VERSION_MAJOR(csr->version),
 			 CSR_VERSION_MINOR(csr->version));
 	} else {
-		dev_notice(dev_priv->dev->dev,
+		dev_notice(dev_priv->drm.dev,
 			   "Failed to load DMC firmware"
 			   " [" FIRMWARE_URL "],"
 			   " disabling runtime power management.\n");
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 8c4094611b21..a346832cb5e1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1234,7 +1234,7 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
 void assert_panel_unlocked(struct drm_i915_private *dev_priv,
 			   enum pipe pipe)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	i915_reg_t pp_reg;
 	u32 val;
 	enum pipe panel_pipe = PIPE_A;
@@ -1276,7 +1276,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
 static void assert_cursor(struct drm_i915_private *dev_priv,
 			  enum pipe pipe, bool state)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	bool cur_state;
 
 	if (IS_845G(dev) || IS_I865G(dev))
@@ -1338,7 +1338,7 @@ static void assert_plane(struct drm_i915_private *dev_priv,
 static void assert_planes_disabled(struct drm_i915_private *dev_priv,
 				   enum pipe pipe)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	int i;
 
 	/* Primary planes are fixed to pipes on gen4+ */
@@ -1364,7 +1364,7 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv,
 static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
 				    enum pipe pipe)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	int sprite;
 
 	if (INTEL_INFO(dev)->gen >= 9) {
@@ -1821,7 +1821,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
 static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
 					   enum pipe pipe)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	i915_reg_t reg;
@@ -1906,7 +1906,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
 static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
 					    enum pipe pipe)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	i915_reg_t reg;
 	uint32_t val;
 
@@ -3118,7 +3118,7 @@ static void intel_complete_page_flips(struct drm_i915_private *dev_priv)
 {
 	struct intel_crtc *crtc;
 
-	for_each_intel_crtc(dev_priv->dev, crtc)
+	for_each_intel_crtc(&dev_priv->drm, crtc)
 		intel_finish_page_flip_cs(dev_priv, crtc->pipe);
 }
 
@@ -3152,12 +3152,12 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
 	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
 		return;
 
-	drm_modeset_lock_all(dev_priv->dev);
+	drm_modeset_lock_all(&dev_priv->drm);
 	/*
 	 * Disabling the crtcs gracefully seems nicer. Also the
 	 * g33 docs say we should at least disable all the planes.
 	 */
-	intel_display_suspend(dev_priv->dev);
+	intel_display_suspend(&dev_priv->drm);
 }
 
 void intel_finish_reset(struct drm_i915_private *dev_priv)
@@ -3184,7 +3184,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
 		 * FIXME: Atomic will make this obsolete since we won't schedule
 		 * CS-based flips (which might get lost in gpu resets) any more.
 		 */
-		intel_update_primary_planes(dev_priv->dev);
+		intel_update_primary_planes(&dev_priv->drm);
 		return;
 	}
 
@@ -3195,18 +3195,18 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
 	intel_runtime_pm_disable_interrupts(dev_priv);
 	intel_runtime_pm_enable_interrupts(dev_priv);
 
-	intel_modeset_init_hw(dev_priv->dev);
+	intel_modeset_init_hw(&dev_priv->drm);
 
 	spin_lock_irq(&dev_priv->irq_lock);
 	if (dev_priv->display.hpd_irq_setup)
 		dev_priv->display.hpd_irq_setup(dev_priv);
 	spin_unlock_irq(&dev_priv->irq_lock);
 
-	intel_display_resume(dev_priv->dev);
+	intel_display_resume(&dev_priv->drm);
 
 	intel_hpd_init(dev_priv);
 
-	drm_modeset_unlock_all(dev_priv->dev);
+	drm_modeset_unlock_all(&dev_priv->drm);
 }
 
 static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
@@ -5488,14 +5488,14 @@ static void broxton_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
 		return;
 	}
 
-	intel_update_cdclk(dev_priv->dev);
+	intel_update_cdclk(&dev_priv->drm);
 }
 
 static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
 {
 	u32 cdctl, expected;
 
-	intel_update_cdclk(dev_priv->dev);
+	intel_update_cdclk(&dev_priv->drm);
 
 	if (dev_priv->cdclk_pll.vco == 0 ||
 	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
@@ -5628,7 +5628,7 @@ void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco)
 	dev_priv->skl_preferred_vco_freq = vco;
 
 	if (changed)
-		intel_update_max_cdclk(dev_priv->dev);
+		intel_update_max_cdclk(&dev_priv->drm);
 }
 
 static void
@@ -5718,7 +5718,7 @@ static bool skl_cdclk_wait_for_pcu_ready(struct drm_i915_private *dev_priv)
 
 static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int vco)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	u32 freq_select, pcu_ack;
 
 	WARN_ON((cdclk == 24000) != (vco == 0));
@@ -5816,7 +5816,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
 	if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
 		goto sanitize;
 
-	intel_update_cdclk(dev_priv->dev);
+	intel_update_cdclk(&dev_priv->drm);
 	/* Is PLL enabled and locked ? */
 	if (dev_priv->cdclk_pll.vco == 0 ||
 	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
@@ -9451,7 +9451,7 @@ out:
 
 static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct intel_crtc *crtc;
 
 	for_each_intel_crtc(dev, crtc)
@@ -9485,7 +9485,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 
 static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 
 	if (IS_HASWELL(dev))
 		return I915_READ(D_COMP_HSW);
@@ -9495,7 +9495,7 @@ static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
 
 static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 
 	if (IS_HASWELL(dev)) {
 		mutex_lock(&dev_priv->rps.hw_lock);
@@ -9610,7 +9610,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 	}
 
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
-	intel_update_cdclk(dev_priv->dev);
+	intel_update_cdclk(&dev_priv->drm);
 }
 
 /*
@@ -9638,7 +9638,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
  */
 void hsw_enable_pc8(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	uint32_t val;
 
 	DRM_DEBUG_KMS("Enabling package C8+\n");
@@ -9655,7 +9655,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv)
 
 void hsw_disable_pc8(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	uint32_t val;
 
 	DRM_DEBUG_KMS("Disabling package C8+\n");
@@ -11128,7 +11128,7 @@ static bool pageflip_finished(struct intel_crtc *crtc,
 
 void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_flip_work *work;
@@ -11155,7 +11155,7 @@ void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe)
 
 void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_flip_work *work;
@@ -11611,7 +11611,7 @@ static bool __pageflip_stall_check_cs(struct drm_i915_private *dev_priv,
 
 void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_flip_work *work;
@@ -15433,12 +15433,12 @@ void intel_modeset_init_hw(struct drm_device *dev)
 
 void intel_modeset_register(struct drm_i915_private *dev_priv)
 {
-	drm_connector_register_all(dev_priv->dev);
+	drm_connector_register_all(&dev_priv->drm);
 }
 
 void intel_modeset_unregister(struct drm_i915_private *dev_priv)
 {
-	drm_connector_unregister_all(dev_priv->dev);
+	drm_connector_unregister_all(&dev_priv->drm);
 }
 
 /*
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index d077f30d6804..97f39e4f1361 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -509,7 +509,7 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
 
 void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct intel_encoder *encoder;
 
 	if (WARN_ON(!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)))
@@ -2213,7 +2213,7 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
 	 * 2. Program DP PLL enable
 	 */
 	if (IS_GEN5(dev_priv))
-		intel_wait_for_vblank_if_active(dev_priv->dev, !crtc->pipe);
+		intel_wait_for_vblank_if_active(&dev_priv->drm, !crtc->pipe);
 
 	intel_dp->DP |= DP_PLL_ENABLE;
 
@@ -3312,7 +3312,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 		I915_WRITE(intel_dp->output_reg, DP);
 		POSTING_READ(intel_dp->output_reg);
 
-		intel_wait_for_vblank_if_active(dev_priv->dev, PIPE_A);
+		intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A);
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 	}
@@ -5078,7 +5078,7 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp)
 	}
 
 	if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
-		intel_dp_set_drrs_state(dev_priv->dev,
+		intel_dp_set_drrs_state(&dev_priv->drm,
 			intel_dp->attached_connector->panel.
 			fixed_mode->vrefresh);
 
@@ -5110,7 +5110,7 @@ static void intel_edp_drrs_downclock_work(struct work_struct *work)
 		goto unlock;
 
 	if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR)
-		intel_dp_set_drrs_state(dev_priv->dev,
+		intel_dp_set_drrs_state(&dev_priv->drm,
 			intel_dp->attached_connector->panel.
 			downclock_mode->vrefresh);
 
@@ -5154,7 +5154,7 @@ void intel_edp_drrs_invalidate(struct drm_device *dev,
 
 	/* invalidate means busy screen hence upclock */
 	if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
-		intel_dp_set_drrs_state(dev_priv->dev,
+		intel_dp_set_drrs_state(&dev_priv->drm,
 				dev_priv->drrs.dp->attached_connector->panel.
 				fixed_mode->vrefresh);
 
@@ -5199,7 +5199,7 @@ void intel_edp_drrs_flush(struct drm_device *dev,
 
 	/* flush means busy screen hence upclock */
 	if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
-		intel_dp_set_drrs_state(dev_priv->dev,
+		intel_dp_set_drrs_state(&dev_priv->drm,
 				dev_priv->drrs.dp->attached_connector->panel.
 				fixed_mode->vrefresh);
 
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index 02a7962a67f1..f7c18f3d61c9 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
@@ -331,7 +331,7 @@ static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
 static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
 				 struct intel_shared_dpll *pll)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct intel_crtc *crtc;
 
 	/* Make sure no transcoder isn't still depending on us. */
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 0dea5fbcd8aa..4aa649c7fa31 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -389,7 +389,7 @@ static void intel_fbc_work_fn(struct work_struct *__work)
 	struct intel_fbc *fbc = &dev_priv->fbc;
 	struct intel_fbc_work *work = &fbc->work;
 	struct intel_crtc *crtc = fbc->crtc;
-	struct drm_vblank_crtc *vblank = &dev_priv->dev->vblank[crtc->pipe];
+	struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[crtc->pipe];
 
 	if (drm_crtc_vblank_get(&crtc->base)) {
 		DRM_ERROR("vblank not available for FBC on pipe %c\n",
@@ -1216,7 +1216,7 @@ void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv)
 	if (!no_fbc_on_multiple_pipes(dev_priv))
 		return;
 
-	for_each_intel_crtc(dev_priv->dev, crtc)
+	for_each_intel_crtc(&dev_priv->drm, crtc)
 		if (intel_crtc_active(&crtc->base) &&
 		    to_intel_plane_state(crtc->base.primary->state)->visible)
 			dev_priv->fbc.visible_pipes_mask |= (1 << crtc->pipe);
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 99e27530e264..a91ac90f0ecb 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -692,9 +692,9 @@ out:
 
 static void intel_fbdev_suspend_worker(struct work_struct *work)
 {
-	intel_fbdev_set_suspend(container_of(work,
-					     struct drm_i915_private,
-					     fbdev_suspend_work)->dev,
+	intel_fbdev_set_suspend(&container_of(work,
+					      struct drm_i915_private,
+					      fbdev_suspend_work)->drm,
 				FBINFO_STATE_RUNNING,
 				true);
 }
@@ -742,7 +742,7 @@ static void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
 	/* Due to peculiar init order wrt to hpd handling this is separate. */
 	if (drm_fb_helper_initial_config(&ifbdev->helper,
 					 ifbdev->preferred_bpp))
-		intel_fbdev_fini(dev_priv->dev);
+		intel_fbdev_fini(&dev_priv->drm);
 }
 
 void intel_fbdev_initial_config_async(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c
index 9be839a242f9..d6ef8e5833ad 100644
--- a/drivers/gpu/drm/i915/intel_fifo_underrun.c
+++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c
@@ -289,7 +289,7 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
 	bool ret;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	ret = __intel_set_cpu_fifo_underrun_reporting(dev_priv->dev, pipe,
+	ret = __intel_set_cpu_fifo_underrun_reporting(&dev_priv->drm, pipe,
 						      enable);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
@@ -334,10 +334,10 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
 	intel_crtc->pch_fifo_underrun_disabled = !enable;
 
 	if (HAS_PCH_IBX(dev_priv))
-		ibx_set_fifo_underrun_reporting(dev_priv->dev, pch_transcoder,
+		ibx_set_fifo_underrun_reporting(&dev_priv->drm, pch_transcoder,
 						enable);
 	else
-		cpt_set_fifo_underrun_reporting(dev_priv->dev, pch_transcoder,
+		cpt_set_fifo_underrun_reporting(&dev_priv->drm, pch_transcoder,
 						enable, old);
 
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
@@ -405,7 +405,7 @@ void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv)
 
 	spin_lock_irq(&dev_priv->irq_lock);
 
-	for_each_intel_crtc(dev_priv->dev, crtc) {
+	for_each_intel_crtc(&dev_priv->drm, crtc) {
 		if (crtc->cpu_fifo_underrun_disabled)
 			continue;
 
@@ -432,7 +432,7 @@ void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv)
 
 	spin_lock_irq(&dev_priv->irq_lock);
 
-	for_each_intel_crtc(dev_priv->dev, crtc) {
+	for_each_intel_crtc(&dev_priv->drm, crtc) {
 		if (crtc->pch_fifo_underrun_disabled)
 			continue;
 
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index 29273e5fee22..63ccaf00a14e 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -301,7 +301,7 @@ static u32 guc_wopcm_size(struct drm_i915_private *dev_priv)
 static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
 {
 	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	int ret;
 
 	ret = i915_gem_object_set_to_gtt_domain(guc_fw->guc_fw_obj, false);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index cea6b4de4018..b02c52d3e799 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1154,7 +1154,7 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
 		I915_WRITE(intel_hdmi->hdmi_reg, temp);
 		POSTING_READ(intel_hdmi->hdmi_reg);
 
-		intel_wait_for_vblank_if_active(dev_priv->dev, PIPE_A);
+		intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A);
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 	}
diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
index 38eeca7a6e72..51434ec871f2 100644
--- a/drivers/gpu/drm/i915/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/intel_hotplug.c
@@ -144,7 +144,7 @@ static bool intel_hpd_irq_storm_detect(struct drm_i915_private *dev_priv,
 
 static void intel_hpd_irq_storm_disable(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct drm_mode_config *mode_config = &dev->mode_config;
 	struct intel_connector *intel_connector;
 	struct intel_encoder *intel_encoder;
@@ -191,7 +191,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
 	struct drm_i915_private *dev_priv =
 		container_of(work, typeof(*dev_priv),
 			     hotplug.reenable_work.work);
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct drm_mode_config *mode_config = &dev->mode_config;
 	int i;
 
@@ -302,7 +302,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
 {
 	struct drm_i915_private *dev_priv =
 		container_of(work, struct drm_i915_private, hotplug.hotplug_work);
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct drm_mode_config *mode_config = &dev->mode_config;
 	struct intel_connector *intel_connector;
 	struct intel_encoder *intel_encoder;
@@ -455,7 +455,7 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
  */
 void intel_hpd_init(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct drm_mode_config *mode_config = &dev->mode_config;
 	struct drm_connector *connector;
 	int i;
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 81de23098be7..bef4310a305d 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -138,7 +138,7 @@ static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
 static u32 get_reserved(struct intel_gmbus *bus)
 {
 	struct drm_i915_private *dev_priv = bus->dev_priv;
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	u32 reserved = 0;
 
 	/* On most chips, these bits must be preserved in software. */
@@ -212,7 +212,7 @@ intel_gpio_pre_xfer(struct i2c_adapter *adapter)
 					       adapter);
 	struct drm_i915_private *dev_priv = bus->dev_priv;
 
-	intel_i2c_reset(dev_priv->dev);
+	intel_i2c_reset(&dev_priv->drm);
 	intel_i2c_quirk_set(dev_priv, true);
 	set_data(bus, 1);
 	set_clock(bus, 1);
@@ -688,7 +688,7 @@ int intel_setup_gmbus(struct drm_device *dev)
 			goto err;
 	}
 
-	intel_i2c_reset(dev_priv->dev);
+	intel_i2c_reset(&dev_priv->drm);
 
 	return 0;
 
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 5c191a1afaaf..6ecadef8f43d 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -883,7 +883,7 @@ void intel_execlists_cancel_requests(struct intel_engine_cs *engine)
 	struct drm_i915_gem_request *req, *tmp;
 	LIST_HEAD(cancel_list);
 
-	WARN_ON(!mutex_is_locked(&engine->i915->dev->struct_mutex));
+	WARN_ON(!mutex_is_locked(&engine->i915->drm.struct_mutex));
 
 	spin_lock_bh(&engine->execlist_lock);
 	list_replace_init(&engine->execlist_queue, &cancel_list);
@@ -942,7 +942,7 @@ static int intel_lr_context_pin(struct i915_gem_context *ctx,
 	u32 *lrc_reg_state;
 	int ret;
 
-	lockdep_assert_held(&ctx->i915->dev->struct_mutex);
+	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
 
 	if (ce->pin_count++)
 		return 0;
@@ -992,7 +992,7 @@ void intel_lr_context_unpin(struct i915_gem_context *ctx,
 {
 	struct intel_context *ce = &ctx->engine[engine->id];
 
-	lockdep_assert_held(&ctx->i915->dev->struct_mutex);
+	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
 	GEM_BUG_ON(ce->pin_count == 0);
 
 	if (--ce->pin_count)
@@ -1317,7 +1317,7 @@ static int lrc_setup_wa_ctx_obj(struct intel_engine_cs *engine, u32 size)
 {
 	int ret;
 
-	engine->wa_ctx.obj = i915_gem_object_create(engine->i915->dev,
+	engine->wa_ctx.obj = i915_gem_object_create(&engine->i915->drm,
 						   PAGE_ALIGN(size));
 	if (IS_ERR(engine->wa_ctx.obj)) {
 		DRM_DEBUG_DRIVER("alloc LRC WA ctx backing obj failed.\n");
@@ -2478,7 +2478,7 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
 	/* One extra page as the sharing data between driver and GuC */
 	context_size += PAGE_SIZE * LRC_PPHWSP_PN;
 
-	ctx_obj = i915_gem_object_create(ctx->i915->dev, context_size);
+	ctx_obj = i915_gem_object_create(&ctx->i915->drm, context_size);
 	if (IS_ERR(ctx_obj)) {
 		DRM_DEBUG_DRIVER("Alloc LRC backing obj failed.\n");
 		return PTR_ERR(ctx_obj);
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index f6d8a21d2c49..08476c1e4ea4 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -244,7 +244,7 @@ static int swsci(struct drm_i915_private *dev_priv,
 		 u32 function, u32 parm, u32 *parm_out)
 {
 	struct opregion_swsci *swsci = dev_priv->opregion.swsci;
-	struct pci_dev *pdev = dev_priv->dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 	u32 main_function, sub_function, scic;
 	u16 swsci_val;
 	u32 dslp;
@@ -418,7 +418,7 @@ static u32 asle_set_backlight(struct drm_i915_private *dev_priv, u32 bclp)
 {
 	struct intel_connector *connector;
 	struct opregion_asle *asle = dev_priv->opregion.asle;
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 
 	DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
 
@@ -660,7 +660,7 @@ static void set_did(struct intel_opregion *opregion, int i, u32 val)
 static void intel_didl_outputs(struct drm_i915_private *dev_priv)
 {
 	struct intel_opregion *opregion = &dev_priv->opregion;
-	struct pci_dev *pdev = dev_priv->dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 	struct drm_connector *connector;
 	acpi_handle handle;
 	struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
@@ -724,7 +724,7 @@ end:
 
 blind_set:
 	i = 0;
-	list_for_each_entry(connector, &dev_priv->dev->mode_config.connector_list, head) {
+	list_for_each_entry(connector, &dev_priv->drm.mode_config.connector_list, head) {
 		int output_type = ACPI_OTHER_OUTPUT;
 		if (i >= max_outputs) {
 			DRM_DEBUG_KMS("More than %u outputs in connector list\n",
@@ -916,7 +916,7 @@ static const struct dmi_system_id intel_no_opregion_vbt[] = {
 int intel_opregion_setup(struct drm_i915_private *dev_priv)
 {
 	struct intel_opregion *opregion = &dev_priv->opregion;
-	struct pci_dev *pdev = dev_priv->dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 	u32 asls, mboxes;
 	char buf[sizeof(OPREGION_SIGNATURE)];
 	int err = 0;
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index eb93f90bb74d..5c83d7196a51 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -409,7 +409,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
 	struct intel_engine_cs *engine = &dev_priv->engine[RCS];
 	int ret;
 
-	lockdep_assert_held(&dev_priv->dev->struct_mutex);
+	lockdep_assert_held(&dev_priv->drm.struct_mutex);
 
 	/* Only wait if there is actually an old frame to release to
 	 * guarantee forward progress.
@@ -741,8 +741,8 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
 	u32 swidth, swidthsw, sheight, ostride;
 	enum pipe pipe = overlay->crtc->pipe;
 
-	lockdep_assert_held(&dev_priv->dev->struct_mutex);
-	WARN_ON(!drm_modeset_is_locked(&dev_priv->dev->mode_config.connection_mutex));
+	lockdep_assert_held(&dev_priv->drm.struct_mutex);
+	WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
 
 	ret = intel_overlay_release_old_vid(overlay);
 	if (ret != 0)
@@ -836,7 +836,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
 	overlay->old_vid_bo = overlay->vid_bo;
 	overlay->vid_bo = new_bo;
 
-	intel_frontbuffer_flip(dev_priv->dev, INTEL_FRONTBUFFER_OVERLAY(pipe));
+	intel_frontbuffer_flip(&dev_priv->drm, INTEL_FRONTBUFFER_OVERLAY(pipe));
 
 	return 0;
 
@@ -851,8 +851,8 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
 	struct overlay_registers __iomem *regs;
 	int ret;
 
-	lockdep_assert_held(&dev_priv->dev->struct_mutex);
-	WARN_ON(!drm_modeset_is_locked(&dev_priv->dev->mode_config.connection_mutex));
+	lockdep_assert_held(&dev_priv->drm.struct_mutex);
+	WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
 
 	ret = intel_overlay_recover_from_interrupt(overlay);
 	if (ret != 0)
@@ -1379,7 +1379,7 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv)
 	if (!overlay)
 		return;
 
-	mutex_lock(&dev_priv->dev->struct_mutex);
+	mutex_lock(&dev_priv->drm.struct_mutex);
 	if (WARN_ON(dev_priv->overlay))
 		goto out_free;
 
@@ -1387,9 +1387,9 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv)
 
 	reg_bo = NULL;
 	if (!OVERLAY_NEEDS_PHYSICAL(dev_priv))
-		reg_bo = i915_gem_object_create_stolen(dev_priv->dev, PAGE_SIZE);
+		reg_bo = i915_gem_object_create_stolen(&dev_priv->drm, PAGE_SIZE);
 	if (reg_bo == NULL)
-		reg_bo = i915_gem_object_create(dev_priv->dev, PAGE_SIZE);
+		reg_bo = i915_gem_object_create(&dev_priv->drm, PAGE_SIZE);
 	if (IS_ERR(reg_bo))
 		goto out_free;
 	overlay->reg_bo = reg_bo;
@@ -1434,7 +1434,7 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv)
 	intel_overlay_unmap_regs(overlay, regs);
 
 	dev_priv->overlay = overlay;
-	mutex_unlock(&dev_priv->dev->struct_mutex);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
 	DRM_INFO("initialized overlay support\n");
 	return;
 
@@ -1444,7 +1444,7 @@ out_unpin_bo:
 out_free_bo:
 	drm_gem_object_unreference(&reg_bo->base);
 out_free:
-	mutex_unlock(&dev_priv->dev->struct_mutex);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
 	kfree(overlay);
 	return;
 }
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index efaee7a7f933..620e4d58df8e 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -504,7 +504,7 @@ static u32 i9xx_get_backlight(struct intel_connector *connector)
 	if (panel->backlight.combination_mode) {
 		u8 lbpc;
 
-		pci_read_config_byte(dev_priv->dev->pdev, LBPC, &lbpc);
+		pci_read_config_byte(dev_priv->drm.pdev, LBPC, &lbpc);
 		val *= lbpc;
 	}
 
@@ -592,7 +592,7 @@ static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
 
 		lbpc = level * 0xfe / panel->backlight.max + 1;
 		level /= lbpc;
-		pci_write_config_byte(dev_priv->dev->pdev, LBPC, lbpc);
+		pci_write_config_byte(dev_priv->drm.pdev, LBPC, lbpc);
 	}
 
 	if (IS_GEN4(dev_priv)) {
@@ -822,7 +822,7 @@ void intel_panel_disable_backlight(struct intel_connector *connector)
 	 * backlight. This will leave the backlight on unnecessarily when
 	 * another client is not activated.
 	 */
-	if (dev_priv->dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
+	if (dev_priv->drm.switch_power_state == DRM_SWITCH_POWER_CHANGING) {
 		DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
 		return;
 	}
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index b6dfd0264950..e96ab1c81bf9 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -294,7 +294,7 @@ static void chv_set_memory_pm5(struct drm_i915_private *dev_priv, bool enable)
 
 void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	u32 val;
 
 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
@@ -2211,7 +2211,7 @@ static void intel_print_wm_latency(struct drm_device *dev,
 static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv,
 				    uint16_t wm[5], uint16_t min)
 {
-	int level, max_level = ilk_wm_max_level(dev_priv->dev);
+	int level, max_level = ilk_wm_max_level(&dev_priv->drm);
 
 	if (wm[0] >= min)
 		return false;
@@ -2740,7 +2740,7 @@ static bool _ilk_disable_lp_wm(struct drm_i915_private *dev_priv,
 static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
 				struct ilk_wm_values *results)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct ilk_wm_values *previous = &dev_priv->wm.hw;
 	unsigned int dirty;
 	uint32_t val;
@@ -3336,13 +3336,13 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
 }
 
 static int
-skl_compute_wm_level(const struct drm_i915_private *dev_priv,
+skl_compute_wm_level(struct drm_i915_private *dev_priv,
 		     struct skl_ddb_allocation *ddb,
 		     struct intel_crtc_state *cstate,
 		     int level,
 		     struct skl_wm_level *result)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct drm_atomic_state *state = cstate->base.state;
 	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
 	struct drm_plane *plane;
@@ -3439,7 +3439,7 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate,
 			     struct skl_pipe_wm *pipe_wm)
 {
 	struct drm_device *dev = cstate->base.crtc->dev;
-	const struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	int level, max_level = ilk_wm_max_level(dev);
 	int ret;
 
@@ -3526,7 +3526,7 @@ static void skl_ddb_entry_write(struct drm_i915_private *dev_priv,
 static void skl_write_wm_values(struct drm_i915_private *dev_priv,
 				const struct skl_wm_values *new)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct intel_crtc *crtc;
 
 	for_each_intel_crtc(dev, crtc) {
@@ -3623,7 +3623,7 @@ skl_ddb_allocation_included(const struct skl_ddb_allocation *old,
 static void skl_flush_wm_values(struct drm_i915_private *dev_priv,
 				struct skl_wm_values *new_values)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct skl_ddb_allocation *cur_ddb, *new_ddb;
 	bool reallocated[I915_MAX_PIPES] = {};
 	struct intel_crtc *crtc;
@@ -3887,7 +3887,7 @@ static void ilk_compute_wm_config(struct drm_device *dev,
 
 static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
 	struct ilk_wm_maximums max;
 	struct intel_wm_config config = {};
@@ -5505,7 +5505,7 @@ static void valleyview_setup_pctx(struct drm_i915_private *dev_priv)
 	u32 pcbr;
 	int pctx_size = 24*1024;
 
-	mutex_lock(&dev_priv->dev->struct_mutex);
+	mutex_lock(&dev_priv->drm.struct_mutex);
 
 	pcbr = I915_READ(VLV_PCBR);
 	if (pcbr) {
@@ -5513,7 +5513,7 @@ static void valleyview_setup_pctx(struct drm_i915_private *dev_priv)
 		int pcbr_offset;
 
 		pcbr_offset = (pcbr & (~4095)) - dev_priv->mm.stolen_base;
-		pctx = i915_gem_object_create_stolen_for_preallocated(dev_priv->dev,
+		pctx = i915_gem_object_create_stolen_for_preallocated(&dev_priv->drm,
 								      pcbr_offset,
 								      I915_GTT_OFFSET_NONE,
 								      pctx_size);
@@ -5530,7 +5530,7 @@ static void valleyview_setup_pctx(struct drm_i915_private *dev_priv)
 	 * overlap with other ranges, such as the frame buffer, protected
 	 * memory, or any other relevant ranges.
 	 */
-	pctx = i915_gem_object_create_stolen(dev_priv->dev, pctx_size);
+	pctx = i915_gem_object_create_stolen(&dev_priv->drm, pctx_size);
 	if (!pctx) {
 		DRM_DEBUG("not enough stolen space for PCTX, disabling\n");
 		goto out;
@@ -5542,7 +5542,7 @@ static void valleyview_setup_pctx(struct drm_i915_private *dev_priv)
 out:
 	DRM_DEBUG_DRIVER("PCBR: 0x%08x\n", I915_READ(VLV_PCBR));
 	dev_priv->vlv_pctx = pctx;
-	mutex_unlock(&dev_priv->dev->struct_mutex);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
 }
 
 static void valleyview_cleanup_pctx(struct drm_i915_private *dev_priv)
@@ -6486,9 +6486,9 @@ void intel_enable_gt_powersave(struct drm_i915_private *dev_priv)
 
 	if (IS_IRONLAKE_M(dev_priv)) {
 		ironlake_enable_drps(dev_priv);
-		mutex_lock(&dev_priv->dev->struct_mutex);
+		mutex_lock(&dev_priv->drm.struct_mutex);
 		intel_init_emon(dev_priv);
-		mutex_unlock(&dev_priv->dev->struct_mutex);
+		mutex_unlock(&dev_priv->drm.struct_mutex);
 	} else if (INTEL_INFO(dev_priv)->gen >= 6) {
 		/*
 		 * PCU communication is slow and this doesn't need to be
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 8d35a3978f9b..17c55e3bf346 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -665,7 +665,7 @@ intel_init_pipe_control(struct intel_engine_cs *engine)
 
 	WARN_ON(engine->scratch.obj);
 
-	engine->scratch.obj = i915_gem_object_create(engine->i915->dev, 4096);
+	engine->scratch.obj = i915_gem_object_create(&engine->i915->drm, 4096);
 	if (IS_ERR(engine->scratch.obj)) {
 		DRM_ERROR("Failed to allocate seqno page\n");
 		ret = PTR_ERR(engine->scratch.obj);
@@ -2012,7 +2012,7 @@ static void cleanup_phys_status_page(struct intel_engine_cs *engine)
 	if (!dev_priv->status_page_dmah)
 		return;
 
-	drm_pci_free(dev_priv->dev, dev_priv->status_page_dmah);
+	drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah);
 	engine->status_page.page_addr = NULL;
 }
 
@@ -2038,7 +2038,7 @@ static int init_status_page(struct intel_engine_cs *engine)
 		unsigned flags;
 		int ret;
 
-		obj = i915_gem_object_create(engine->i915->dev, 4096);
+		obj = i915_gem_object_create(&engine->i915->drm, 4096);
 		if (IS_ERR(obj)) {
 			DRM_ERROR("Failed to allocate status page\n");
 			return PTR_ERR(obj);
@@ -2087,7 +2087,7 @@ static int init_phys_status_page(struct intel_engine_cs *engine)
 
 	if (!dev_priv->status_page_dmah) {
 		dev_priv->status_page_dmah =
-			drm_pci_alloc(dev_priv->dev, PAGE_SIZE, PAGE_SIZE);
+			drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE);
 		if (!dev_priv->status_page_dmah)
 			return -ENOMEM;
 	}
@@ -2220,7 +2220,7 @@ intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size)
 	ring->last_retired_head = -1;
 	intel_ring_update_space(ring);
 
-	ret = intel_alloc_ringbuffer_obj(engine->i915->dev, ring);
+	ret = intel_alloc_ringbuffer_obj(&engine->i915->drm, ring);
 	if (ret) {
 		DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n",
 				 engine->name, ret);
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index fe8faf30bda7..742467b84ccd 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -267,7 +267,7 @@ void intel_display_set_init_power(struct drm_i915_private *dev_priv,
  */
 static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 
 	/*
 	 * After we re-enable the power well, if we touch VGA register 0x3d5
@@ -298,7 +298,7 @@ static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv)
 static void skl_power_well_post_enable(struct drm_i915_private *dev_priv,
 				       struct i915_power_well *power_well)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 
 	/*
 	 * After we re-enable the power well, if we touch VGA register 0x3d5
@@ -821,7 +821,7 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
 
 	WARN_ON(dev_priv->cdclk_freq !=
-		dev_priv->display.get_display_clock_speed(dev_priv->dev));
+		dev_priv->display.get_display_clock_speed(&dev_priv->drm));
 
 	gen9_assert_dbuf_enabled(dev_priv);
 
@@ -979,7 +979,7 @@ static void vlv_display_power_well_init(struct drm_i915_private *dev_priv)
 	 *
 	 * CHV DPLL B/C have some issues if VGA mode is enabled.
 	 */
-	for_each_pipe(dev_priv->dev, pipe) {
+	for_each_pipe(&dev_priv->drm, pipe) {
 		u32 val = I915_READ(DPLL(pipe));
 
 		val |= DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
@@ -1004,7 +1004,7 @@ static void vlv_display_power_well_init(struct drm_i915_private *dev_priv)
 
 	intel_hpd_init(dev_priv);
 
-	i915_redisable_vga_power_on(dev_priv->dev);
+	i915_redisable_vga_power_on(&dev_priv->drm);
 }
 
 static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv)
@@ -1014,7 +1014,7 @@ static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv)
 	spin_unlock_irq(&dev_priv->irq_lock);
 
 	/* make sure we're done processing display irqs */
-	synchronize_irq(dev_priv->dev->irq);
+	synchronize_irq(dev_priv->drm.irq);
 
 	vlv_power_sequencer_reset(dev_priv);
 }
@@ -2148,7 +2148,7 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
  */
 void intel_power_domains_fini(struct drm_i915_private *dev_priv)
 {
-	struct device *device = &dev_priv->dev->pdev->dev;
+	struct device *device = &dev_priv->drm.pdev->dev;
 
 	/*
 	 * The i915.ko module is still not prepared to be loaded when
@@ -2454,7 +2454,7 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
  */
 void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
 
 	power_domains->initializing = true;
@@ -2516,7 +2516,7 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv)
  */
 void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct device *device = &dev->pdev->dev;
 
 	pm_runtime_get_sync(device);
@@ -2537,7 +2537,7 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
  */
 bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct device *device = &dev->pdev->dev;
 
 	if (IS_ENABLED(CONFIG_PM)) {
@@ -2579,7 +2579,7 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
  */
 void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct device *device = &dev->pdev->dev;
 
 	assert_rpm_wakelock_held(dev_priv);
@@ -2598,7 +2598,7 @@ void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
  */
 void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct device *device = &dev->pdev->dev;
 
 	assert_rpm_wakelock_held(dev_priv);
@@ -2621,7 +2621,7 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
  */
 void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = &dev_priv->drm;
 	struct device *device = &dev->pdev->dev;
 
 	pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index b83ad62c1273..3aee03e0b178 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1471,7 +1471,7 @@ static void intel_disable_sdvo(struct intel_encoder *encoder)
 		temp &= ~SDVO_ENABLE;
 		intel_sdvo_write_sdvox(intel_sdvo, temp);
 
-		intel_wait_for_vblank_if_active(dev_priv->dev, PIPE_A);
+		intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A);
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 	}
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index c1ca458d688e..58ac3f975180 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -1469,7 +1469,7 @@ static int i915_reset_complete(struct pci_dev *pdev)
 
 static int i915_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask)
 {
-	struct pci_dev *pdev = dev_priv->dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 
 	/* assert reset for at least 20 usec */
 	pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE);
@@ -1488,14 +1488,14 @@ static int g4x_reset_complete(struct pci_dev *pdev)
 
 static int g33_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask)
 {
-	struct pci_dev *pdev = dev_priv->dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 	pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE);
 	return wait_for(g4x_reset_complete(pdev), 500);
 }
 
 static int g4x_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask)
 {
-	struct pci_dev *pdev = dev_priv->dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 	int ret;
 
 	pci_write_config_byte(pdev, I915_GDRST,
-- 
2.8.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* ✗ Ro.CI.BAT: failure for series starting with [01/11] drm: Export drm_dev_init() for subclassing (rev2)
  2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
                   ` (10 preceding siblings ...)
  2016-05-27 14:00 ` [PATCH 11/11] drm/i915: Move module init/exit " Chris Wilson
@ 2016-05-27 14:58 ` Patchwork
  11 siblings, 0 replies; 28+ messages in thread
From: Patchwork @ 2016-05-27 14:58 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

== Series Details ==

Series: series starting with [01/11] drm: Export drm_dev_init() for subclassing (rev2)
URL   : https://patchwork.freedesktop.org/series/7890/
State : failure

== Summary ==

Applying: drm: Export drm_dev_init() for subclassing
Applying: drm: Add a callback from connector registering
Applying: drm/i915: Perform async fbdev initialisation much later
Applying: drm/i915: Move connector registration to driver registration phase
Applying: drm/i915: Register debugfs interface last
Applying: drm/i915: Demidlayer driver loading
Applying: drm/i915: Demidlayer driver unloading
Applying: drm/i915: Remove drm_i915_private->dev backpointer
Patch failed at 0008 drm/i915: Remove drm_i915_private->dev backpointer
The copy of the patch that failed is found in: .git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/11] drm: Export drm_dev_init() for subclassing
  2016-05-27 14:00 ` [PATCH 01/11] drm: Export drm_dev_init() for subclassing Chris Wilson
@ 2016-05-27 15:29   ` Nils Wallménius
  2016-05-27 15:36     ` Chris Wilson
  0 siblings, 1 reply; 28+ messages in thread
From: Nils Wallménius @ 2016-05-27 15:29 UTC (permalink / raw)
  To: Chris Wilson; +Cc: Daniel Vetter, intel-gfx, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 4918 bytes --]

Hi, Chris

See comment below

BR
Nils
On 27 May 2016 7:01 a.m., "Chris Wilson" <chris@chris-wilson.co.uk> wrote:
>
> In order to allow drivers to pack their privates and drm_device into one
> struct (e.g. for subclassing), export the initialisation routines for
> struct drm_device.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: dri-devel@lists.freedesktop.org
> ---
>  drivers/gpu/drm/drm_drv.c | 63
++++++++++++++++++++++++++++++++++++-----------
>  include/drm/drmP.h        |  3 +++
>  2 files changed, 52 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index bff89226a344..ceb85e611a07 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -549,11 +549,12 @@ static void drm_fs_inode_free(struct inode *inode)
>  }
>
>  /**
> - * drm_dev_alloc - Allocate new DRM device
> - * @driver: DRM driver to allocate device for
> + * drm_dev_init - Initialise new DRM device
> + * @dev: DRM device
> + * @driver: DRM driver
>   * @parent: Parent device object
>   *
> - * Allocate and initialize a new DRM device. No device registration is
done.
> + * Initialize a new DRM device. No device registration is done.
>   * Call drm_dev_register() to advertice the device to user space and
register it
>   * with other core subsystems. This should be done last in the device
>   * initialization sequence to make sure userspace can't access an
inconsistent
> @@ -565,18 +566,14 @@ static void drm_fs_inode_free(struct inode *inode)
>   * Note that for purely virtual devices @parent can be NULL.
>   *
>   * RETURNS:
> - * Pointer to new DRM device, or NULL if out of memory.
> + * 0 on success, or error code on failure.
>   */
> -struct drm_device *drm_dev_alloc(struct drm_driver *driver,
> -                                struct device *parent)
> +int drm_dev_init(struct drm_device *dev,
> +                struct drm_driver *driver,
> +                struct device *parent)
>  {
> -       struct drm_device *dev;
>         int ret;
>
> -       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
> -       if (!dev)
> -               return NULL;
> -
>         kref_init(&dev->ref);
>         dev->dev = parent;
>         dev->driver = driver;
> @@ -638,7 +635,7 @@ struct drm_device *drm_dev_alloc(struct drm_driver
*driver,
>                         goto err_setunique;
>         }
>
> -       return dev;
> +       return 0;
>
>  err_setunique:
>         if (drm_core_check_feature(dev, DRIVER_GEM))
> @@ -653,8 +650,46 @@ err_minors:
>         drm_fs_inode_free(dev->anon_inode);
>  err_free:
>         mutex_destroy(&dev->master_mutex);
> -       kfree(dev);
> -       return NULL;
> +       return 0;

Shouldn't this return != 0?

> +}
> +EXPORT_SYMBOL(drm_dev_init);
> +
> +/**
> + * drm_dev_alloc - Allocate new DRM device
> + * @driver: DRM driver to allocate device for
> + * @parent: Parent device object
> + *
> + * Allocate and initialize a new DRM device. No device registration is
done.
> + * Call drm_dev_register() to advertice the device to user space and
register it
> + * with other core subsystems. This should be done last in the device
> + * initialization sequence to make sure userspace can't access an
inconsistent
> + * state.
> + *
> + * The initial ref-count of the object is 1. Use drm_dev_ref() and
> + * drm_dev_unref() to take and drop further ref-counts.
> + *
> + * Note that for purely virtual devices @parent can be NULL.
> + *
> + * RETURNS:
> + * Pointer to new DRM device, or NULL if out of memory.
> + */
> +struct drm_device *drm_dev_alloc(struct drm_driver *driver,
> +                                struct device *parent)
> +{
> +       struct drm_device *dev;
> +       int ret;
> +
> +       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
> +       if (!dev)
> +               return NULL;
> +
> +       ret = drm_dev_init(dev, driver, parent);
> +       if (ret) {
> +               kfree(dev);
> +               return NULL;
> +       }
> +
> +       return dev;
>  }
>  EXPORT_SYMBOL(drm_dev_alloc);
>
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index c5d29505f937..12dc5f9cad89 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -1075,6 +1075,9 @@ extern void drm_sysfs_hotplug_event(struct
drm_device *dev);
>
>  struct drm_device *drm_dev_alloc(struct drm_driver *driver,
>                                  struct device *parent);
> +int drm_dev_init(struct drm_device *dev,
> +                struct drm_driver *driver,
> +                struct device *parent);
>  void drm_dev_ref(struct drm_device *dev);
>  void drm_dev_unref(struct drm_device *dev);
>  int drm_dev_register(struct drm_device *dev, unsigned long flags);
> --
> 2.8.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

[-- Attachment #1.2: Type: text/html, Size: 6720 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/11] drm: Export drm_dev_init() for subclassing
  2016-05-27 15:29   ` Nils Wallménius
@ 2016-05-27 15:36     ` Chris Wilson
  2016-05-27 15:54       ` Emil Velikov
  0 siblings, 1 reply; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 15:36 UTC (permalink / raw)
  To: Nils Wallménius; +Cc: Daniel Vetter, intel-gfx, dri-devel

On Fri, May 27, 2016 at 05:29:43PM +0200, Nils Wallménius wrote:
>    Hi, Chris
> 
>    See comment below
> 
>    >  err_setunique:
>    >         if (drm_core_check_feature(dev, DRIVER_GEM))
>    > @@ -653,8 +650,46 @@ err_minors:
>    >         drm_fs_inode_free(dev->anon_inode);
>    >  err_free:
>    >         mutex_destroy(&dev->master_mutex);
>    > -       kfree(dev);
>    > -       return NULL;
>    > +       return 0;
> 
>    Shouldn't this return != 0?

You saw nothing, it always said return ret!
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/11] drm: Export drm_dev_init() for subclassing
  2016-05-27 15:36     ` Chris Wilson
@ 2016-05-27 15:54       ` Emil Velikov
  2016-05-27 16:08         ` [Intel-gfx] " Chris Wilson
  0 siblings, 1 reply; 28+ messages in thread
From: Emil Velikov @ 2016-05-27 15:54 UTC (permalink / raw)
  To: Chris Wilson, Nils Wallménius, Daniel Vetter, intel-gfx,
	ML dri-devel

On 27 May 2016 at 16:36, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> On Fri, May 27, 2016 at 05:29:43PM +0200, Nils Wallménius wrote:
>>    Hi, Chris
>>
>>    See comment below
>>
>>    >  err_setunique:
>>    >         if (drm_core_check_feature(dev, DRIVER_GEM))
>>    > @@ -653,8 +650,46 @@ err_minors:
>>    >         drm_fs_inode_free(dev->anon_inode);
>>    >  err_free:
>>    >         mutex_destroy(&dev->master_mutex);
>>    > -       kfree(dev);
>>    > -       return NULL;
>>    > +       return 0;
>>
>>    Shouldn't this return != 0?
>
> You saw nothing, it always said return ret!
Chris can you please elaborate ? I believe Nils has a point here.

Afact the error path of _init should return != 0, plus you already
handle that case in _alloc, yet the function always returns 0.

Regards,
Emil
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Intel-gfx] [PATCH 01/11] drm: Export drm_dev_init() for subclassing
  2016-05-27 15:54       ` Emil Velikov
@ 2016-05-27 16:08         ` Chris Wilson
  2016-05-27 16:11           ` Emil Velikov
  0 siblings, 1 reply; 28+ messages in thread
From: Chris Wilson @ 2016-05-27 16:08 UTC (permalink / raw)
  To: Emil Velikov; +Cc: Daniel Vetter, intel-gfx, Nils Wallménius, ML dri-devel

On Fri, May 27, 2016 at 04:54:46PM +0100, Emil Velikov wrote:
> On 27 May 2016 at 16:36, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> > On Fri, May 27, 2016 at 05:29:43PM +0200, Nils Wallménius wrote:
> >>    Hi, Chris
> >>
> >>    See comment below
> >>
> >>    >  err_setunique:
> >>    >         if (drm_core_check_feature(dev, DRIVER_GEM))
> >>    > @@ -653,8 +650,46 @@ err_minors:
> >>    >         drm_fs_inode_free(dev->anon_inode);
> >>    >  err_free:
> >>    >         mutex_destroy(&dev->master_mutex);
> >>    > -       kfree(dev);
> >>    > -       return NULL;
> >>    > +       return 0;
> >>
> >>    Shouldn't this return != 0?
> >
> > You saw nothing, it always said return ret!
> Chris can you please elaborate ? I believe Nils has a point here.

I mean, "thanks for bringing that to my attention, oops it was meant to
say return ret ofc, fixed".
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Intel-gfx] [PATCH 01/11] drm: Export drm_dev_init() for subclassing
  2016-05-27 16:08         ` [Intel-gfx] " Chris Wilson
@ 2016-05-27 16:11           ` Emil Velikov
  0 siblings, 0 replies; 28+ messages in thread
From: Emil Velikov @ 2016-05-27 16:11 UTC (permalink / raw)
  To: Chris Wilson, Emil Velikov, Nils Wallménius, Daniel Vetter,
	intel-gfx, ML dri-devel

On 27 May 2016 at 17:08, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> On Fri, May 27, 2016 at 04:54:46PM +0100, Emil Velikov wrote:
>> On 27 May 2016 at 16:36, Chris Wilson <chris@chris-wilson.co.uk> wrote:
>> > On Fri, May 27, 2016 at 05:29:43PM +0200, Nils Wallménius wrote:
>> >>    Hi, Chris
>> >>
>> >>    See comment below
>> >>
>> >>    >  err_setunique:
>> >>    >         if (drm_core_check_feature(dev, DRIVER_GEM))
>> >>    > @@ -653,8 +650,46 @@ err_minors:
>> >>    >         drm_fs_inode_free(dev->anon_inode);
>> >>    >  err_free:
>> >>    >         mutex_destroy(&dev->master_mutex);
>> >>    > -       kfree(dev);
>> >>    > -       return NULL;
>> >>    > +       return 0;
>> >>
>> >>    Shouldn't this return != 0?
>> >
>> > You saw nothing, it always said return ret!
>> Chris can you please elaborate ? I believe Nils has a point here.
>
> I mean, "thanks for bringing that to my attention, oops it was meant to
> say return ret ofc, fixed".
Seems like I had a dull moment. Thanks for explaining !

-Emil
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 09/11] drm/i915: Merge i915_dma.c into i915_drv.c
  2016-05-27 14:00 ` [PATCH 09/11] drm/i915: Merge i915_dma.c into i915_drv.c Chris Wilson
@ 2016-05-30  6:30   ` Joonas Lahtinen
  0 siblings, 0 replies; 28+ messages in thread
From: Joonas Lahtinen @ 2016-05-30  6:30 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Daniel Vetter

On pe, 2016-05-27 at 15:00 +0100, Chris Wilson wrote:
> i915_dma.c used to contain the DRI1/UMS horror show, but now all that
> remains are the out-of-place driver level interfaces (such as
> allocating, initialising and registering the driver). These should be in
> i915_drv.c alongside similar routines for suspend/resume.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

Assuming this was NOP change,

Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>

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

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 10/11] drm/i915: Split out the PCI driver interface to i915_pci.c
  2016-05-27 14:00 ` [PATCH 10/11] drm/i915: Split out the PCI driver interface to i915_pci.c Chris Wilson
@ 2016-05-30  6:36   ` Joonas Lahtinen
  0 siblings, 0 replies; 28+ messages in thread
From: Joonas Lahtinen @ 2016-05-30  6:36 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Daniel Vetter

On pe, 2016-05-27 at 15:00 +0100, Chris Wilson wrote:
> To reclaim a bit of space from i915_drv.c, we can move the routines that
> just hook us into the PCI device tree into i915_pci.c
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

Assuming bulk move + addition of a few extern keywords;

Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>

> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/Makefile   |   1 +
>  drivers/gpu/drm/i915/i915_drv.c | 450 +-------------------------------------
>  drivers/gpu/drm/i915/i915_pci.c | 463 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 473 insertions(+), 441 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/i915_pci.c
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 2ea7c245923e..7aecd309604c 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -10,6 +10,7 @@ subdir-ccflags-$(CONFIG_DRM_I915_WERROR) := -Werror
>  i915-y := i915_drv.o \
>  	  i915_irq.o \
>  	  i915_params.o \
> +	  i915_pci.o \
>            i915_suspend.o \
>  	  i915_sysfs.o \
>  	  intel_csr.o \
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index e20f63ac73d3..79b6834bc6b2 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -28,7 +28,6 @@
>   */
>  
>  #include 
> -#include 
>  #include 
>  #include 
>  #include 
> @@ -54,386 +53,6 @@
>  
>  static struct drm_driver driver;
>  
> -#define GEN_DEFAULT_PIPEOFFSETS \
> -	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
> -			  PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \
> -	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
> -			   TRANSCODER_C_OFFSET, TRANSCODER_EDP_OFFSET }, \
> -	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET }
> -
> -#define GEN_CHV_PIPEOFFSETS \
> -	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
> -			  CHV_PIPE_C_OFFSET }, \
> -	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
> -			   CHV_TRANSCODER_C_OFFSET, }, \
> -	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET, \
> -			     CHV_PALETTE_C_OFFSET }
> -
> -#define CURSOR_OFFSETS \
> -	.cursor_offsets = { CURSOR_A_OFFSET, CURSOR_B_OFFSET, CHV_CURSOR_C_OFFSET }
> -
> -#define IVB_CURSOR_OFFSETS \
> -	.cursor_offsets = { CURSOR_A_OFFSET, IVB_CURSOR_B_OFFSET, IVB_CURSOR_C_OFFSET }
> -
> -#define BDW_COLORS \
> -	.color = { .degamma_lut_size = 512, .gamma_lut_size = 512 }
> -#define CHV_COLORS \
> -	.color = { .degamma_lut_size = 65, .gamma_lut_size = 257 }
> -
> -static const struct intel_device_info intel_i830_info = {
> -	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
> -	.has_overlay = 1, .overlay_needs_physical = 1,
> -	.ring_mask = RENDER_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_845g_info = {
> -	.gen = 2, .num_pipes = 1,
> -	.has_overlay = 1, .overlay_needs_physical = 1,
> -	.ring_mask = RENDER_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_i85x_info = {
> -	.gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,
> -	.cursor_needs_physical = 1,
> -	.has_overlay = 1, .overlay_needs_physical = 1,
> -	.has_fbc = 1,
> -	.ring_mask = RENDER_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_i865g_info = {
> -	.gen = 2, .num_pipes = 1,
> -	.has_overlay = 1, .overlay_needs_physical = 1,
> -	.ring_mask = RENDER_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_i915g_info = {
> -	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2,
> -	.has_overlay = 1, .overlay_needs_physical = 1,
> -	.ring_mask = RENDER_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -static const struct intel_device_info intel_i915gm_info = {
> -	.gen = 3, .is_mobile = 1, .num_pipes = 2,
> -	.cursor_needs_physical = 1,
> -	.has_overlay = 1, .overlay_needs_physical = 1,
> -	.supports_tv = 1,
> -	.has_fbc = 1,
> -	.ring_mask = RENDER_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -static const struct intel_device_info intel_i945g_info = {
> -	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2,
> -	.has_overlay = 1, .overlay_needs_physical = 1,
> -	.ring_mask = RENDER_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -static const struct intel_device_info intel_i945gm_info = {
> -	.gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2,
> -	.has_hotplug = 1, .cursor_needs_physical = 1,
> -	.has_overlay = 1, .overlay_needs_physical = 1,
> -	.supports_tv = 1,
> -	.has_fbc = 1,
> -	.ring_mask = RENDER_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_i965g_info = {
> -	.gen = 4, .is_broadwater = 1, .num_pipes = 2,
> -	.has_hotplug = 1,
> -	.has_overlay = 1,
> -	.ring_mask = RENDER_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_i965gm_info = {
> -	.gen = 4, .is_crestline = 1, .num_pipes = 2,
> -	.is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,
> -	.has_overlay = 1,
> -	.supports_tv = 1,
> -	.ring_mask = RENDER_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_g33_info = {
> -	.gen = 3, .is_g33 = 1, .num_pipes = 2,
> -	.need_gfx_hws = 1, .has_hotplug = 1,
> -	.has_overlay = 1,
> -	.ring_mask = RENDER_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_g45_info = {
> -	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2,
> -	.has_pipe_cxsr = 1, .has_hotplug = 1,
> -	.ring_mask = RENDER_RING | BSD_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_gm45_info = {
> -	.gen = 4, .is_g4x = 1, .num_pipes = 2,
> -	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,
> -	.has_pipe_cxsr = 1, .has_hotplug = 1,
> -	.supports_tv = 1,
> -	.ring_mask = RENDER_RING | BSD_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_pineview_info = {
> -	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .num_pipes = 2,
> -	.need_gfx_hws = 1, .has_hotplug = 1,
> -	.has_overlay = 1,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_ironlake_d_info = {
> -	.gen = 5, .num_pipes = 2,
> -	.need_gfx_hws = 1, .has_hotplug = 1,
> -	.ring_mask = RENDER_RING | BSD_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_ironlake_m_info = {
> -	.gen = 5, .is_mobile = 1, .num_pipes = 2,
> -	.need_gfx_hws = 1, .has_hotplug = 1,
> -	.has_fbc = 1,
> -	.ring_mask = RENDER_RING | BSD_RING,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_sandybridge_d_info = {
> -	.gen = 6, .num_pipes = 2,
> -	.need_gfx_hws = 1, .has_hotplug = 1,
> -	.has_fbc = 1,
> -	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
> -	.has_llc = 1,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -static const struct intel_device_info intel_sandybridge_m_info = {
> -	.gen = 6, .is_mobile = 1, .num_pipes = 2,
> -	.need_gfx_hws = 1, .has_hotplug = 1,
> -	.has_fbc = 1,
> -	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
> -	.has_llc = 1,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -};
> -
> -#define GEN7_FEATURES  \
> -	.gen = 7, .num_pipes = 3, \
> -	.need_gfx_hws = 1, .has_hotplug = 1, \
> -	.has_fbc = 1, \
> -	.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
> -	.has_llc = 1, \
> -	GEN_DEFAULT_PIPEOFFSETS, \
> -	IVB_CURSOR_OFFSETS
> -
> -static const struct intel_device_info intel_ivybridge_d_info = {
> -	GEN7_FEATURES,
> -	.is_ivybridge = 1,
> -};
> -
> -static const struct intel_device_info intel_ivybridge_m_info = {
> -	GEN7_FEATURES,
> -	.is_ivybridge = 1,
> -	.is_mobile = 1,
> -};
> -
> -static const struct intel_device_info intel_ivybridge_q_info = {
> -	GEN7_FEATURES,
> -	.is_ivybridge = 1,
> -	.num_pipes = 0, /* legal, last one wins */
> -};
> -
> -#define VLV_FEATURES  \
> -	.gen = 7, .num_pipes = 2, \
> -	.need_gfx_hws = 1, .has_hotplug = 1, \
> -	.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
> -	.display_mmio_offset = VLV_DISPLAY_BASE, \
> -	GEN_DEFAULT_PIPEOFFSETS, \
> -	CURSOR_OFFSETS
> -
> -static const struct intel_device_info intel_valleyview_m_info = {
> -	VLV_FEATURES,
> -	.is_valleyview = 1,
> -	.is_mobile = 1,
> -};
> -
> -static const struct intel_device_info intel_valleyview_d_info = {
> -	VLV_FEATURES,
> -	.is_valleyview = 1,
> -};
> -
> -#define HSW_FEATURES  \
> -	GEN7_FEATURES, \
> -	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \
> -	.has_ddi = 1, \
> -	.has_fpga_dbg = 1
> -
> -static const struct intel_device_info intel_haswell_d_info = {
> -	HSW_FEATURES,
> -	.is_haswell = 1,
> -};
> -
> -static const struct intel_device_info intel_haswell_m_info = {
> -	HSW_FEATURES,
> -	.is_haswell = 1,
> -	.is_mobile = 1,
> -};
> -
> -#define BDW_FEATURES \
> -	HSW_FEATURES, \
> -	BDW_COLORS
> -
> -static const struct intel_device_info intel_broadwell_d_info = {
> -	BDW_FEATURES,
> -	.gen = 8,
> -	.is_broadwell = 1,
> -};
> -
> -static const struct intel_device_info intel_broadwell_m_info = {
> -	BDW_FEATURES,
> -	.gen = 8, .is_mobile = 1,
> -	.is_broadwell = 1,
> -};
> -
> -static const struct intel_device_info intel_broadwell_gt3d_info = {
> -	BDW_FEATURES,
> -	.gen = 8,
> -	.is_broadwell = 1,
> -	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
> -};
> -
> -static const struct intel_device_info intel_broadwell_gt3m_info = {
> -	BDW_FEATURES,
> -	.gen = 8, .is_mobile = 1,
> -	.is_broadwell = 1,
> -	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
> -};
> -
> -static const struct intel_device_info intel_cherryview_info = {
> -	.gen = 8, .num_pipes = 3,
> -	.need_gfx_hws = 1, .has_hotplug = 1,
> -	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
> -	.is_cherryview = 1,
> -	.display_mmio_offset = VLV_DISPLAY_BASE,
> -	GEN_CHV_PIPEOFFSETS,
> -	CURSOR_OFFSETS,
> -	CHV_COLORS,
> -};
> -
> -static const struct intel_device_info intel_skylake_info = {
> -	BDW_FEATURES,
> -	.is_skylake = 1,
> -	.gen = 9,
> -};
> -
> -static const struct intel_device_info intel_skylake_gt3_info = {
> -	BDW_FEATURES,
> -	.is_skylake = 1,
> -	.gen = 9,
> -	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
> -};
> -
> -static const struct intel_device_info intel_broxton_info = {
> -	.is_preliminary = 1,
> -	.is_broxton = 1,
> -	.gen = 9,
> -	.need_gfx_hws = 1, .has_hotplug = 1,
> -	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
> -	.num_pipes = 3,
> -	.has_ddi = 1,
> -	.has_fpga_dbg = 1,
> -	.has_fbc = 1,
> -	GEN_DEFAULT_PIPEOFFSETS,
> -	IVB_CURSOR_OFFSETS,
> -	BDW_COLORS,
> -};
> -
> -static const struct intel_device_info intel_kabylake_info = {
> -	BDW_FEATURES,
> -	.is_kabylake = 1,
> -	.gen = 9,
> -};
> -
> -static const struct intel_device_info intel_kabylake_gt3_info = {
> -	BDW_FEATURES,
> -	.is_kabylake = 1,
> -	.gen = 9,
> -	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
> -};
> -
> -/*
> - * Make sure any device matches here are from most specific to most
> - * general.  For example, since the Quanta match is based on the subsystem
> - * and subvendor IDs, we need it to come before the more general IVB
> - * PCI ID matches, otherwise we'll use the wrong info struct above.
> - */
> -static const struct pci_device_id pciidlist[] = {
> -	INTEL_I830_IDS(&intel_i830_info),
> -	INTEL_I845G_IDS(&intel_845g_info),
> -	INTEL_I85X_IDS(&intel_i85x_info),
> -	INTEL_I865G_IDS(&intel_i865g_info),
> -	INTEL_I915G_IDS(&intel_i915g_info),
> -	INTEL_I915GM_IDS(&intel_i915gm_info),
> -	INTEL_I945G_IDS(&intel_i945g_info),
> -	INTEL_I945GM_IDS(&intel_i945gm_info),
> -	INTEL_I965G_IDS(&intel_i965g_info),
> -	INTEL_G33_IDS(&intel_g33_info),
> -	INTEL_I965GM_IDS(&intel_i965gm_info),
> -	INTEL_GM45_IDS(&intel_gm45_info),
> -	INTEL_G45_IDS(&intel_g45_info),
> -	INTEL_PINEVIEW_IDS(&intel_pineview_info),
> -	INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info),
> -	INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info),
> -	INTEL_SNB_D_IDS(&intel_sandybridge_d_info),
> -	INTEL_SNB_M_IDS(&intel_sandybridge_m_info),
> -	INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */
> -	INTEL_IVB_M_IDS(&intel_ivybridge_m_info),
> -	INTEL_IVB_D_IDS(&intel_ivybridge_d_info),
> -	INTEL_HSW_D_IDS(&intel_haswell_d_info),
> -	INTEL_HSW_M_IDS(&intel_haswell_m_info),
> -	INTEL_VLV_M_IDS(&intel_valleyview_m_info),
> -	INTEL_VLV_D_IDS(&intel_valleyview_d_info),
> -	INTEL_BDW_GT12M_IDS(&intel_broadwell_m_info),
> -	INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info),
> -	INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info),
> -	INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info),
> -	INTEL_CHV_IDS(&intel_cherryview_info),
> -	INTEL_SKL_GT1_IDS(&intel_skylake_info),
> -	INTEL_SKL_GT2_IDS(&intel_skylake_info),
> -	INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info),
> -	INTEL_SKL_GT4_IDS(&intel_skylake_gt3_info),
> -	INTEL_BXT_IDS(&intel_broxton_info),
> -	INTEL_KBL_GT1_IDS(&intel_kabylake_info),
> -	INTEL_KBL_GT2_IDS(&intel_kabylake_info),
> -	INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info),
> -	INTEL_KBL_GT4_IDS(&intel_kabylake_gt3_info),
> -	{0, 0, 0}
> -};
> -MODULE_DEVICE_TABLE(pci, pciidlist);
> -
>  static unsigned int i915_load_fail_count;
>  
>  bool __i915_inject_load_failure(const char *func, int line)
> @@ -1939,8 +1558,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
>   *   - allocate initial config memory
>   *   - setup the DRM framebuffer with the allocated memory
>   */
> -static int i915_driver_load(struct pci_dev *pdev,
> -			    const struct pci_device_id *ent)
> +int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
>  {
>  	struct drm_i915_private *dev_priv;
>  	int ret;
> @@ -2021,18 +1639,14 @@ out_free_priv:
>  	return ret;
>  }
>  
> -static int i915_driver_unload(struct drm_device *dev)
> +void i915_driver_unload(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	int ret;
>  
>  	intel_fbdev_fini(dev);
>  
> -	ret = i915_gem_suspend(dev);
> -	if (ret) {
> -		DRM_ERROR("failed to idle hardware: %d\n", ret);
> -		return ret;
> -	}
> +	if (i915_gem_suspend(dev))
> +		DRM_ERROR("failed to idle hardware; continuing to unload!\n");
>  
>  	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
>  
> @@ -2080,8 +1694,6 @@ static int i915_driver_unload(struct drm_device *dev)
>  	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
>  
>  	i915_driver_cleanup_early(dev_priv);
> -
> -	return 0;
>  }
>  
>  static int i915_driver_open(struct drm_device *dev, struct drm_file *file)
> @@ -2584,46 +2196,6 @@ error:
>  	return ret;
>  }
>  
> -static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> -{
> -	struct intel_device_info *intel_info =
> -		(struct intel_device_info *) ent->driver_data;
> -
> -	if (IS_PRELIMINARY_HW(intel_info) && !i915.preliminary_hw_support) {
> -		DRM_INFO("This hardware requires preliminary hardware support.\n"
> -			 "See CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT, and/or modparam preliminary_hw_support\n");
> -		return -ENODEV;
> -	}
> -
> -	/* Only bind to function 0 of the device. Early generations
> -	 * used function 1 as a placeholder for multi-head. This causes
> -	 * us confusion instead, especially on the systems where both
> -	 * functions have the same PCI-ID!
> -	 */
> -	if (PCI_FUNC(pdev->devfn))
> -		return -ENODEV;
> -
> -	/*
> -	 * apple-gmux is needed on dual GPU MacBook Pro
> -	 * to probe the panel if we're the inactive GPU.
> -	 */
> -	if (IS_ENABLED(CONFIG_VGA_ARB) && IS_ENABLED(CONFIG_VGA_SWITCHEROO) &&
> -	    apple_gmux_present() && pdev != vga_default_device() &&
> -	    !vga_switcheroo_handler_flags())
> -		return -EPROBE_DEFER;
> -
> -	return i915_driver_load(pdev, ent);
> -}
> -
> -static void
> -i915_pci_remove(struct pci_dev *pdev)
> -{
> -	struct drm_device *dev = pci_get_drvdata(pdev);
> -
> -	i915_driver_unload(dev);
> -	drm_dev_unref(dev);
> -}
> -
>  static int i915_pm_suspend(struct device *dev)
>  {
>  	struct pci_dev *pdev = to_pci_dev(dev);
> @@ -3261,7 +2833,7 @@ static int intel_runtime_resume(struct device *device)
>  	return ret;
>  }
>  
> -static const struct dev_pm_ops i915_pm_ops = {
> +const struct dev_pm_ops i915_pm_ops = {
>  	/*
>  	 * S0ix (via system suspend) and S3 event handlers [PMSG_SUSPEND,
>  	 * PMSG_RESUME]
> @@ -3417,16 +2989,10 @@ static struct drm_driver driver = {
>  	.patchlevel = DRIVER_PATCHLEVEL,
>  };
>  
> -static struct pci_driver i915_pci_driver = {
> -	.name = DRIVER_NAME,
> -	.id_table = pciidlist,
> -	.probe = i915_pci_probe,
> -	.remove = i915_pci_remove,
> -	.driver.pm = &i915_pm_ops,
> -};
> -
>  static int __init i915_init(void)
>  {
> +	extern struct pci_driver i915_pci_driver;
> +
>  	/*
>  	 * Enable KMS by default, unless explicitly overriden by
>  	 * either the i915.modeset prarameter or by the
> @@ -3453,6 +3019,8 @@ static int __init i915_init(void)
>  
>  static void __exit i915_exit(void)
>  {
> +	extern struct pci_driver i915_pci_driver;
> +
>  	if (!(driver.driver_features & DRIVER_MODESET))
>  		return; /* Never loaded a driver. */
>  
> diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
> new file mode 100644
> index 000000000000..514d8b784319
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/i915_pci.c
> @@ -0,0 +1,463 @@
> +/*
> + * Copyright © 2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include 
> +#include 
> +#include 
> +
> +#include "i915_drv.h"
> +
> +#define GEN_DEFAULT_PIPEOFFSETS \
> +	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
> +			  PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \
> +	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
> +			   TRANSCODER_C_OFFSET, TRANSCODER_EDP_OFFSET }, \
> +	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET }
> +
> +#define GEN_CHV_PIPEOFFSETS \
> +	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
> +			  CHV_PIPE_C_OFFSET }, \
> +	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
> +			   CHV_TRANSCODER_C_OFFSET, }, \
> +	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET, \
> +			     CHV_PALETTE_C_OFFSET }
> +
> +#define CURSOR_OFFSETS \
> +	.cursor_offsets = { CURSOR_A_OFFSET, CURSOR_B_OFFSET, CHV_CURSOR_C_OFFSET }
> +
> +#define IVB_CURSOR_OFFSETS \
> +	.cursor_offsets = { CURSOR_A_OFFSET, IVB_CURSOR_B_OFFSET, IVB_CURSOR_C_OFFSET }
> +
> +#define BDW_COLORS \
> +	.color = { .degamma_lut_size = 512, .gamma_lut_size = 512 }
> +#define CHV_COLORS \
> +	.color = { .degamma_lut_size = 65, .gamma_lut_size = 257 }
> +
> +static const struct intel_device_info intel_i830_info = {
> +	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
> +	.has_overlay = 1, .overlay_needs_physical = 1,
> +	.ring_mask = RENDER_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_845g_info = {
> +	.gen = 2, .num_pipes = 1,
> +	.has_overlay = 1, .overlay_needs_physical = 1,
> +	.ring_mask = RENDER_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_i85x_info = {
> +	.gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,
> +	.cursor_needs_physical = 1,
> +	.has_overlay = 1, .overlay_needs_physical = 1,
> +	.has_fbc = 1,
> +	.ring_mask = RENDER_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_i865g_info = {
> +	.gen = 2, .num_pipes = 1,
> +	.has_overlay = 1, .overlay_needs_physical = 1,
> +	.ring_mask = RENDER_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_i915g_info = {
> +	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2,
> +	.has_overlay = 1, .overlay_needs_physical = 1,
> +	.ring_mask = RENDER_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +static const struct intel_device_info intel_i915gm_info = {
> +	.gen = 3, .is_mobile = 1, .num_pipes = 2,
> +	.cursor_needs_physical = 1,
> +	.has_overlay = 1, .overlay_needs_physical = 1,
> +	.supports_tv = 1,
> +	.has_fbc = 1,
> +	.ring_mask = RENDER_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +static const struct intel_device_info intel_i945g_info = {
> +	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2,
> +	.has_overlay = 1, .overlay_needs_physical = 1,
> +	.ring_mask = RENDER_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +static const struct intel_device_info intel_i945gm_info = {
> +	.gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2,
> +	.has_hotplug = 1, .cursor_needs_physical = 1,
> +	.has_overlay = 1, .overlay_needs_physical = 1,
> +	.supports_tv = 1,
> +	.has_fbc = 1,
> +	.ring_mask = RENDER_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_i965g_info = {
> +	.gen = 4, .is_broadwater = 1, .num_pipes = 2,
> +	.has_hotplug = 1,
> +	.has_overlay = 1,
> +	.ring_mask = RENDER_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_i965gm_info = {
> +	.gen = 4, .is_crestline = 1, .num_pipes = 2,
> +	.is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,
> +	.has_overlay = 1,
> +	.supports_tv = 1,
> +	.ring_mask = RENDER_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_g33_info = {
> +	.gen = 3, .is_g33 = 1, .num_pipes = 2,
> +	.need_gfx_hws = 1, .has_hotplug = 1,
> +	.has_overlay = 1,
> +	.ring_mask = RENDER_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_g45_info = {
> +	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2,
> +	.has_pipe_cxsr = 1, .has_hotplug = 1,
> +	.ring_mask = RENDER_RING | BSD_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_gm45_info = {
> +	.gen = 4, .is_g4x = 1, .num_pipes = 2,
> +	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,
> +	.has_pipe_cxsr = 1, .has_hotplug = 1,
> +	.supports_tv = 1,
> +	.ring_mask = RENDER_RING | BSD_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_pineview_info = {
> +	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .num_pipes = 2,
> +	.need_gfx_hws = 1, .has_hotplug = 1,
> +	.has_overlay = 1,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_ironlake_d_info = {
> +	.gen = 5, .num_pipes = 2,
> +	.need_gfx_hws = 1, .has_hotplug = 1,
> +	.ring_mask = RENDER_RING | BSD_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_ironlake_m_info = {
> +	.gen = 5, .is_mobile = 1, .num_pipes = 2,
> +	.need_gfx_hws = 1, .has_hotplug = 1,
> +	.has_fbc = 1,
> +	.ring_mask = RENDER_RING | BSD_RING,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_sandybridge_d_info = {
> +	.gen = 6, .num_pipes = 2,
> +	.need_gfx_hws = 1, .has_hotplug = 1,
> +	.has_fbc = 1,
> +	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
> +	.has_llc = 1,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +static const struct intel_device_info intel_sandybridge_m_info = {
> +	.gen = 6, .is_mobile = 1, .num_pipes = 2,
> +	.need_gfx_hws = 1, .has_hotplug = 1,
> +	.has_fbc = 1,
> +	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
> +	.has_llc = 1,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +};
> +
> +#define GEN7_FEATURES  \
> +	.gen = 7, .num_pipes = 3, \
> +	.need_gfx_hws = 1, .has_hotplug = 1, \
> +	.has_fbc = 1, \
> +	.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
> +	.has_llc = 1, \
> +	GEN_DEFAULT_PIPEOFFSETS, \
> +	IVB_CURSOR_OFFSETS
> +
> +static const struct intel_device_info intel_ivybridge_d_info = {
> +	GEN7_FEATURES,
> +	.is_ivybridge = 1,
> +};
> +
> +static const struct intel_device_info intel_ivybridge_m_info = {
> +	GEN7_FEATURES,
> +	.is_ivybridge = 1,
> +	.is_mobile = 1,
> +};
> +
> +static const struct intel_device_info intel_ivybridge_q_info = {
> +	GEN7_FEATURES,
> +	.is_ivybridge = 1,
> +	.num_pipes = 0, /* legal, last one wins */
> +};
> +
> +#define VLV_FEATURES  \
> +	.gen = 7, .num_pipes = 2, \
> +	.need_gfx_hws = 1, .has_hotplug = 1, \
> +	.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
> +	.display_mmio_offset = VLV_DISPLAY_BASE, \
> +	GEN_DEFAULT_PIPEOFFSETS, \
> +	CURSOR_OFFSETS
> +
> +static const struct intel_device_info intel_valleyview_m_info = {
> +	VLV_FEATURES,
> +	.is_valleyview = 1,
> +	.is_mobile = 1,
> +};
> +
> +static const struct intel_device_info intel_valleyview_d_info = {
> +	VLV_FEATURES,
> +	.is_valleyview = 1,
> +};
> +
> +#define HSW_FEATURES  \
> +	GEN7_FEATURES, \
> +	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \
> +	.has_ddi = 1, \
> +	.has_fpga_dbg = 1
> +
> +static const struct intel_device_info intel_haswell_d_info = {
> +	HSW_FEATURES,
> +	.is_haswell = 1,
> +};
> +
> +static const struct intel_device_info intel_haswell_m_info = {
> +	HSW_FEATURES,
> +	.is_haswell = 1,
> +	.is_mobile = 1,
> +};
> +
> +#define BDW_FEATURES \
> +	HSW_FEATURES, \
> +	BDW_COLORS
> +
> +static const struct intel_device_info intel_broadwell_d_info = {
> +	BDW_FEATURES,
> +	.gen = 8,
> +	.is_broadwell = 1,
> +};
> +
> +static const struct intel_device_info intel_broadwell_m_info = {
> +	BDW_FEATURES,
> +	.gen = 8, .is_mobile = 1,
> +	.is_broadwell = 1,
> +};
> +
> +static const struct intel_device_info intel_broadwell_gt3d_info = {
> +	BDW_FEATURES,
> +	.gen = 8,
> +	.is_broadwell = 1,
> +	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
> +};
> +
> +static const struct intel_device_info intel_broadwell_gt3m_info = {
> +	BDW_FEATURES,
> +	.gen = 8, .is_mobile = 1,
> +	.is_broadwell = 1,
> +	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
> +};
> +
> +static const struct intel_device_info intel_cherryview_info = {
> +	.gen = 8, .num_pipes = 3,
> +	.need_gfx_hws = 1, .has_hotplug = 1,
> +	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
> +	.is_cherryview = 1,
> +	.display_mmio_offset = VLV_DISPLAY_BASE,
> +	GEN_CHV_PIPEOFFSETS,
> +	CURSOR_OFFSETS,
> +	CHV_COLORS,
> +};
> +
> +static const struct intel_device_info intel_skylake_info = {
> +	BDW_FEATURES,
> +	.is_skylake = 1,
> +	.gen = 9,
> +};
> +
> +static const struct intel_device_info intel_skylake_gt3_info = {
> +	BDW_FEATURES,
> +	.is_skylake = 1,
> +	.gen = 9,
> +	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
> +};
> +
> +static const struct intel_device_info intel_broxton_info = {
> +	.is_preliminary = 1,
> +	.is_broxton = 1,
> +	.gen = 9,
> +	.need_gfx_hws = 1, .has_hotplug = 1,
> +	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
> +	.num_pipes = 3,
> +	.has_ddi = 1,
> +	.has_fpga_dbg = 1,
> +	.has_fbc = 1,
> +	GEN_DEFAULT_PIPEOFFSETS,
> +	IVB_CURSOR_OFFSETS,
> +	BDW_COLORS,
> +};
> +
> +static const struct intel_device_info intel_kabylake_info = {
> +	BDW_FEATURES,
> +	.is_kabylake = 1,
> +	.gen = 9,
> +};
> +
> +static const struct intel_device_info intel_kabylake_gt3_info = {
> +	BDW_FEATURES,
> +	.is_kabylake = 1,
> +	.gen = 9,
> +	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
> +};
> +
> +/*
> + * Make sure any device matches here are from most specific to most
> + * general.  For example, since the Quanta match is based on the subsystem
> + * and subvendor IDs, we need it to come before the more general IVB
> + * PCI ID matches, otherwise we'll use the wrong info struct above.
> + */
> +static const struct pci_device_id pciidlist[] = {
> +	INTEL_I830_IDS(&intel_i830_info),
> +	INTEL_I845G_IDS(&intel_845g_info),
> +	INTEL_I85X_IDS(&intel_i85x_info),
> +	INTEL_I865G_IDS(&intel_i865g_info),
> +	INTEL_I915G_IDS(&intel_i915g_info),
> +	INTEL_I915GM_IDS(&intel_i915gm_info),
> +	INTEL_I945G_IDS(&intel_i945g_info),
> +	INTEL_I945GM_IDS(&intel_i945gm_info),
> +	INTEL_I965G_IDS(&intel_i965g_info),
> +	INTEL_G33_IDS(&intel_g33_info),
> +	INTEL_I965GM_IDS(&intel_i965gm_info),
> +	INTEL_GM45_IDS(&intel_gm45_info),
> +	INTEL_G45_IDS(&intel_g45_info),
> +	INTEL_PINEVIEW_IDS(&intel_pineview_info),
> +	INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info),
> +	INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info),
> +	INTEL_SNB_D_IDS(&intel_sandybridge_d_info),
> +	INTEL_SNB_M_IDS(&intel_sandybridge_m_info),
> +	INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */
> +	INTEL_IVB_M_IDS(&intel_ivybridge_m_info),
> +	INTEL_IVB_D_IDS(&intel_ivybridge_d_info),
> +	INTEL_HSW_D_IDS(&intel_haswell_d_info),
> +	INTEL_HSW_M_IDS(&intel_haswell_m_info),
> +	INTEL_VLV_M_IDS(&intel_valleyview_m_info),
> +	INTEL_VLV_D_IDS(&intel_valleyview_d_info),
> +	INTEL_BDW_GT12M_IDS(&intel_broadwell_m_info),
> +	INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info),
> +	INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info),
> +	INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info),
> +	INTEL_CHV_IDS(&intel_cherryview_info),
> +	INTEL_SKL_GT1_IDS(&intel_skylake_info),
> +	INTEL_SKL_GT2_IDS(&intel_skylake_info),
> +	INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info),
> +	INTEL_SKL_GT4_IDS(&intel_skylake_gt3_info),
> +	INTEL_BXT_IDS(&intel_broxton_info),
> +	INTEL_KBL_GT1_IDS(&intel_kabylake_info),
> +	INTEL_KBL_GT2_IDS(&intel_kabylake_info),
> +	INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info),
> +	INTEL_KBL_GT4_IDS(&intel_kabylake_gt3_info),
> +	{0, 0, 0}
> +};
> +MODULE_DEVICE_TABLE(pci, pciidlist);
> +
> +extern int i915_driver_load(struct pci_dev *pdev,
> +			    const struct pci_device_id *ent);
> +
> +static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> +{
> +	struct intel_device_info *intel_info =
> +		(struct intel_device_info *) ent->driver_data;
> +
> +	if (IS_PRELIMINARY_HW(intel_info) && !i915.preliminary_hw_support) {
> +		DRM_INFO("This hardware requires preliminary hardware support.\n"
> +			 "See CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT, and/or modparam preliminary_hw_support\n");
> +		return -ENODEV;
> +	}
> +
> +	/* Only bind to function 0 of the device. Early generations
> +	 * used function 1 as a placeholder for multi-head. This causes
> +	 * us confusion instead, especially on the systems where both
> +	 * functions have the same PCI-ID!
> +	 */
> +	if (PCI_FUNC(pdev->devfn))
> +		return -ENODEV;
> +
> +	/*
> +	 * apple-gmux is needed on dual GPU MacBook Pro
> +	 * to probe the panel if we're the inactive GPU.
> +	 */
> +	if (IS_ENABLED(CONFIG_VGA_ARB) && IS_ENABLED(CONFIG_VGA_SWITCHEROO) &&
> +	    apple_gmux_present() && pdev != vga_default_device() &&
> +	    !vga_switcheroo_handler_flags())
> +		return -EPROBE_DEFER;
> +
> +	return i915_driver_load(pdev, ent);
> +}
> +
> +extern void i915_driver_unload(struct drm_device *dev);
> +
> +static void i915_pci_remove(struct pci_dev *pdev)
> +{
> +	struct drm_device *dev = pci_get_drvdata(pdev);
> +
> +	i915_driver_unload(dev);
> +	drm_dev_unref(dev);
> +}
> +
> +extern const struct dev_pm_ops i915_pm_ops;
> +
> +struct pci_driver i915_pci_driver = {
> +	.name = DRIVER_NAME,
> +	.id_table = pciidlist,
> +	.probe = i915_pci_probe,
> +	.remove = i915_pci_remove,
> +	.driver.pm = &i915_pm_ops,
> +};
-- 
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 11/11] drm/i915: Move module init/exit to i915_pci.c
  2016-05-27 14:00 ` [PATCH 11/11] drm/i915: Move module init/exit " Chris Wilson
@ 2016-05-30  6:44   ` Joonas Lahtinen
  2016-05-30  7:55     ` Chris Wilson
  0 siblings, 1 reply; 28+ messages in thread
From: Joonas Lahtinen @ 2016-05-30  6:44 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Daniel Vetter

On pe, 2016-05-27 at 15:00 +0100, Chris Wilson wrote:
> The module init/exit routines are a wrapper around the PCI device
> init/exit, so move them across.
> 

This is not a simple move operation (i915_init), this should be noted
in the commit message or preferably split into two commits, first move,
then restructure.

Regards, Joonas

> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 51 +++--------------------------------------
>  drivers/gpu/drm/i915/i915_pci.c | 45 +++++++++++++++++++++++++++++++++++-
>  2 files changed, 47 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 79b6834bc6b2..bf607ca8ddb4 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -28,7 +28,6 @@
>   */
>  
>  #include 
> -#include 
>  #include 
>  #include 
>  #include 
> @@ -1563,6 +1562,9 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
>  	struct drm_i915_private *dev_priv;
>  	int ret;
>  
> +	if (i915.nuclear_pageflip)
> +		driver.driver_features |= DRIVER_ATOMIC;
> +
>  	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
>  	if (dev_priv == NULL)
>  		return -ENOMEM;
> @@ -2988,50 +2990,3 @@ static struct drm_driver driver = {
>  	.minor = DRIVER_MINOR,
>  	.patchlevel = DRIVER_PATCHLEVEL,
>  };
> -
> -static int __init i915_init(void)
> -{
> -	extern struct pci_driver i915_pci_driver;
> -
> -	/*
> -	 * Enable KMS by default, unless explicitly overriden by
> -	 * either the i915.modeset prarameter or by the
> -	 * vga_text_mode_force boot option.
> -	 */
> -
> -	if (i915.modeset == 0)
> -		driver.driver_features &= ~DRIVER_MODESET;
> -
> -	if (vgacon_text_force() && i915.modeset == -1)
> -		driver.driver_features &= ~DRIVER_MODESET;
> -
> -	if (!(driver.driver_features & DRIVER_MODESET)) {
> -		/* Silently fail loading to not upset userspace. */
> -		DRM_DEBUG_DRIVER("KMS and UMS disabled.\n");
> -		return 0;
> -	}
> -
> -	if (i915.nuclear_pageflip)
> -		driver.driver_features |= DRIVER_ATOMIC;
> -
> -	return drm_pci_init(&driver, &i915_pci_driver);
> -}
> -
> -static void __exit i915_exit(void)
> -{
> -	extern struct pci_driver i915_pci_driver;
> -
> -	if (!(driver.driver_features & DRIVER_MODESET))
> -		return; /* Never loaded a driver. */
> -
> -	drm_pci_exit(&driver, &i915_pci_driver);
> -}
> -
> -module_init(i915_init);
> -module_exit(i915_exit);
> -
> -MODULE_AUTHOR("Tungsten Graphics, Inc.");
> -MODULE_AUTHOR("Intel Corporation");
> -
> -MODULE_DESCRIPTION(DRIVER_DESC);
> -MODULE_LICENSE("GPL and additional rights");
> diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
> index 514d8b784319..3cb3a900b969 100644
> --- a/drivers/gpu/drm/i915/i915_pci.c
> +++ b/drivers/gpu/drm/i915/i915_pci.c
> @@ -22,6 +22,7 @@
>   *
>   */
>  
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -454,10 +455,52 @@ static void i915_pci_remove(struct pci_dev *pdev)
>  
>  extern const struct dev_pm_ops i915_pm_ops;
>  
> -struct pci_driver i915_pci_driver = {
> +static struct pci_driver i915_pci_driver = {
>  	.name = DRIVER_NAME,
>  	.id_table = pciidlist,
>  	.probe = i915_pci_probe,
>  	.remove = i915_pci_remove,
>  	.driver.pm = &i915_pm_ops,
>  };
> +
> +static int __init i915_init(void)
> +{
> +	bool use_kms = true;
> +
> +	/*
> +	 * Enable KMS by default, unless explicitly overriden by
> +	 * either the i915.modeset prarameter or by the
> +	 * vga_text_mode_force boot option.
> +	 */
> +
> +	if (i915.modeset == 0)
> +		use_kms = false;
> +
> +	if (vgacon_text_force() && i915.modeset == -1)
> +		use_kms = false;
> +
> +	if (!use_kms) {
> +		/* Silently fail loading to not upset userspace. */
> +		DRM_DEBUG_DRIVER("KMS and UMS disabled.\n");
> +		return 0;
> +	}
> +
> +	return pci_register_driver(&i915_pci_driver);
> +}
> +
> +static void __exit i915_exit(void)
> +{
> +	if (!i915_pci_driver.driver.owner)
> +		return;
> +
> +	pci_unregister_driver(&i915_pci_driver);
> +}
> +
> +module_init(i915_init);
> +module_exit(i915_exit);
> +
> +MODULE_AUTHOR("Tungsten Graphics, Inc.");
> +MODULE_AUTHOR("Intel Corporation");
> +
> +MODULE_DESCRIPTION(DRIVER_DESC);
> +MODULE_LICENSE("GPL and additional rights");
-- 
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] drm/i915: Remove drm_i915_private->dev backpointer
  2016-05-27 14:46     ` [PATCH] drm/i915: Remove drm_i915_private->dev backpointer Chris Wilson
@ 2016-05-30  6:58       ` Joonas Lahtinen
  2016-05-30  8:21         ` Chris Wilson
  0 siblings, 1 reply; 28+ messages in thread
From: Joonas Lahtinen @ 2016-05-30  6:58 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx

On pe, 2016-05-27 at 15:46 +0100, Chris Wilson wrote:
> Now that drm_i915_private contains drm_device, we can directly go to the
> drm_device as required:
> 
>    text	   data	    bss	    dec	    hex	filename
> 1105153	  23207	    416	1128776	 113948	i915.ko (before)
> 1102849	  23207	    416	1126472	 113048	i915.ko (after)
> 
> s/dev_priv->dev->/dev_priv->drm./
> s/dev_priv->dev/\&dev_priv->drm./

Lose the dot from last replaement pattern, and I'm also pretty sure \
is not needed in front of &

> 
> There is still a fair amount that we can tidy by hand.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

With actual working command lines for people to deal with the conflict
pain;

Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>

> ---
> 
> This will cause a fair amount of conflict though. Nowhere as near as
> pleasant as it could be yet.
> -Chris
> 
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c          | 16 ++++----
>  drivers/gpu/drm/i915/i915_drv.c              | 45 +++++++++++----------
>  drivers/gpu/drm/i915/i915_drv.h              | 13 +++----
>  drivers/gpu/drm/i915/i915_gem.c              | 10 ++---
>  drivers/gpu/drm/i915/i915_gem_context.c      |  6 +--
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c   |  4 +-
>  drivers/gpu/drm/i915/i915_gem_gtt.c          | 10 ++---
>  drivers/gpu/drm/i915/i915_gem_render_state.c |  2 +-
>  drivers/gpu/drm/i915/i915_gem_shrinker.c     | 10 ++---
>  drivers/gpu/drm/i915/i915_gpu_error.c        |  4 +-
>  drivers/gpu/drm/i915/i915_guc_submission.c   |  8 ++--
>  drivers/gpu/drm/i915/i915_irq.c              | 36 ++++++++---------
>  drivers/gpu/drm/i915/i915_trace.h            | 20 +++++-----
>  drivers/gpu/drm/i915/intel_audio.c           | 12 +++---
>  drivers/gpu/drm/i915/intel_bios.c            |  2 +-
>  drivers/gpu/drm/i915/intel_csr.c             |  4 +-
>  drivers/gpu/drm/i915/intel_display.c         | 58 ++++++++++++++--------------
>  drivers/gpu/drm/i915/intel_dp.c              | 14 +++----
>  drivers/gpu/drm/i915/intel_dpll_mgr.c        |  2 +-
>  drivers/gpu/drm/i915/intel_fbc.c             |  4 +-
>  drivers/gpu/drm/i915/intel_fbdev.c           |  8 ++--
>  drivers/gpu/drm/i915/intel_fifo_underrun.c   | 10 ++---
>  drivers/gpu/drm/i915/intel_guc_loader.c      |  2 +-
>  drivers/gpu/drm/i915/intel_hdmi.c            |  2 +-
>  drivers/gpu/drm/i915/intel_hotplug.c         |  8 ++--
>  drivers/gpu/drm/i915/intel_i2c.c             |  6 +--
>  drivers/gpu/drm/i915/intel_lrc.c             | 10 ++---
>  drivers/gpu/drm/i915/intel_opregion.c        | 10 ++---
>  drivers/gpu/drm/i915/intel_overlay.c         | 22 +++++------
>  drivers/gpu/drm/i915/intel_panel.c           |  6 +--
>  drivers/gpu/drm/i915/intel_pm.c              | 30 +++++++-------
>  drivers/gpu/drm/i915/intel_ringbuffer.c      | 10 ++---
>  drivers/gpu/drm/i915/intel_runtime_pm.c      | 26 ++++++-------
>  drivers/gpu/drm/i915/intel_sdvo.c            |  2 +-
>  drivers/gpu/drm/i915/intel_uncore.c          |  6 +--
>  35 files changed, 218 insertions(+), 220 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index d018ec5093ba..abe12ac134cf 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -440,15 +440,15 @@ static void print_context_stats(struct seq_file *m,
>  
>  	memset(&stats, 0, sizeof(stats));
>  
> -	mutex_lock(&dev_priv->dev->struct_mutex);
> +	mutex_lock(&dev_priv->drm.struct_mutex);
>  	if (dev_priv->kernel_context)
>  		per_file_ctx_stats(0, dev_priv->kernel_context, &stats);
>  
> -	list_for_each_entry(file, &dev_priv->dev->filelist, lhead) {
> +	list_for_each_entry(file, &dev_priv->drm.filelist, lhead) {
>  		struct drm_i915_file_private *fpriv = file->driver_priv;
>  		idr_for_each(&fpriv->context_idr, per_file_ctx_stats, &stats);
>  	}
> -	mutex_unlock(&dev_priv->dev->struct_mutex);
> +	mutex_unlock(&dev_priv->drm.struct_mutex);
>  
>  	print_file_stats(m, "[k]contexts", stats);
>  }
> @@ -2777,8 +2777,8 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
>  	seq_printf(m, "Device Power Management (CONFIG_PM) disabled\n");
>  #endif
>  	seq_printf(m, "PCI device power state: %s [%d]\n",
> -		   pci_power_name(dev_priv->dev->pdev->current_state),
> -		   dev_priv->dev->pdev->current_state);
> +		   pci_power_name(dev_priv->drm.pdev->current_state),
> +		   dev_priv->drm.pdev->current_state);
>  
>  	return 0;
>  }
> @@ -5118,7 +5118,7 @@ i915_cache_sharing_get(void *data, u64 *val)
>  	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
>  
>  	intel_runtime_pm_put(dev_priv);
> -	mutex_unlock(&dev_priv->dev->struct_mutex);
> +	mutex_unlock(&dev_priv->drm.struct_mutex);
>  
>  	*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
>  
> @@ -5500,7 +5500,7 @@ void intel_display_crc_init(struct drm_device *dev)
>  
>  int i915_debugfs_register(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_minor *minor = dev_priv->dev->primary;
> +	struct drm_minor *minor = dev_priv->drm.primary;
>  	int ret, i;
>  
>  	ret = i915_forcewake_create(minor->debugfs_root, minor);
> @@ -5528,7 +5528,7 @@ int i915_debugfs_register(struct drm_i915_private *dev_priv)
>  
>  void i915_debugfs_unregister(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_minor *minor = dev_priv->dev->primary;
> +	struct drm_minor *minor = dev_priv->drm.primary;
>  	int i;
>  
>  	drm_debugfs_remove_files(i915_debugfs_list,
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index bf607ca8ddb4..7c70469219e2 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -77,7 +77,7 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level,
>  	      const char *fmt, ...)
>  {
>  	static bool shown_bug_once;
> -	struct device *dev = dev_priv->dev->dev;
> +	struct device *dev = dev_priv->drm.dev;
>  	bool is_error = level[1] <= KERN_ERR[1];
>  	bool is_debug = level[1] == KERN_DEBUG[1];
>  	struct va_format vaf;
> @@ -681,7 +681,7 @@ out:
>  static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
>  {
>  	struct apertures_struct *ap;
> -	struct pci_dev *pdev = dev_priv->dev->pdev;
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	struct i915_ggtt *ggtt = &dev_priv->ggtt;
>  	bool primary;
>  	int ret;
> @@ -753,8 +753,8 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
>  	DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags="
>  			 DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
>  			 info->gen,
> -			 dev_priv->dev->pdev->device,
> -			 dev_priv->dev->pdev->revision,
> +			 dev_priv->drm.pdev->device,
> +			 dev_priv->drm.pdev->revision,
>  			 DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
>  #undef PRINT_S
>  #undef SEP_EMPTY
> @@ -1245,7 +1245,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
>   */
>  static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
>  {
> -	i915_gem_load_cleanup(dev_priv->dev);
> +	i915_gem_load_cleanup(&dev_priv->drm);
>  	i915_workqueues_cleanup(dev_priv);
>  }
>  
> @@ -1300,7 +1300,7 @@ static void i915_mmio_cleanup(struct drm_device *dev)
>   */
>  static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	int ret;
>  
>  	if (i915_inject_load_failure())
> @@ -1329,7 +1329,7 @@ put_bridge:
>   */
>  static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  
>  	intel_uncore_fini(dev_priv);
>  	i915_mmio_cleanup(dev);
> @@ -1345,7 +1345,7 @@ static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv)
>   */
>  static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct i915_ggtt *ggtt = &dev_priv->ggtt;
>  	uint32_t aperture_size;
>  	int ret;
> @@ -1462,7 +1462,7 @@ out_ggtt:
>   */
>  static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct i915_ggtt *ggtt = &dev_priv->ggtt;
>  
>  	if (dev->pdev->msi_enabled)
> @@ -1483,7 +1483,7 @@ static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv)
>   */
>  static void i915_driver_register(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  
>  	i915_gem_shrinker_init(dev_priv);
>  
> @@ -1539,9 +1539,9 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
>  	intel_opregion_unregister(dev_priv);
>  
>  	intel_modeset_unregister(dev_priv);
> -	i915_teardown_sysfs(dev_priv->dev);
> +	i915_teardown_sysfs(&dev_priv->drm);
>  	i915_debugfs_unregister(dev_priv);
> -	drm_dev_unregister(dev_priv->dev);
> +	drm_dev_unregister(&dev_priv->drm);
>  
>  	i915_gem_shrinker_cleanup(dev_priv);
>  }
> @@ -1576,7 +1576,6 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
>  	/* Must be set before calling __i915_printk */
>  	dev_priv->drm.pdev = pdev;
>  	dev_priv->drm.dev_private = dev_priv;
> -	dev_priv->dev = &dev_priv->drm;
>  
>  	ret = i915_driver_init_early(dev_priv, ent);
>  	if (ret < 0)
> @@ -1604,13 +1603,13 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
>  	 * to the role/effect of the given init step.
>  	 */
>  	if (INTEL_INFO(dev_priv)->num_pipes) {
> -		ret = drm_vblank_init(dev_priv->dev,
> +		ret = drm_vblank_init(&dev_priv->drm,
>  				      INTEL_INFO(dev_priv)->num_pipes);
>  		if (ret)
>  			goto out_cleanup_hw;
>  	}
>  
> -	ret = i915_load_modeset_init(dev_priv->dev);
> +	ret = i915_load_modeset_init(&dev_priv->drm);
>  	if (ret < 0)
>  		goto out_cleanup_vblank;
>  
> @@ -1623,7 +1622,7 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
>  	return 0;
>  
>  out_cleanup_vblank:
> -	drm_vblank_cleanup(dev_priv->dev);
> +	drm_vblank_cleanup(&dev_priv->drm);
>  out_cleanup_hw:
>  	i915_driver_cleanup_hw(dev_priv);
>  out_cleanup_mmio:
> @@ -1744,7 +1743,7 @@ static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
>  
>  static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct intel_encoder *encoder;
>  
>  	drm_modeset_lock_all(dev);
> @@ -2112,7 +2111,7 @@ int i915_resume_switcheroo(struct drm_device *dev)
>   */
>  int i915_reset(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct i915_gpu_error *error = &dev_priv->gpu_error;
>  	unsigned reset_counter;
>  	int ret;
> @@ -2216,7 +2215,7 @@ static int i915_pm_suspend(struct device *dev)
>  
>  static int i915_pm_suspend_late(struct device *dev)
>  {
> -	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
> +	struct drm_device *drm_dev = &dev_to_i915(dev)->drm;
>  
>  	/*
>  	 * We have a suspend ordering issue with the snd-hda driver also
> @@ -2235,7 +2234,7 @@ static int i915_pm_suspend_late(struct device *dev)
>  
>  static int i915_pm_poweroff_late(struct device *dev)
>  {
> -	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
> +	struct drm_device *drm_dev = &dev_to_i915(dev)->drm;
>  
>  	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
>  		return 0;
> @@ -2245,7 +2244,7 @@ static int i915_pm_poweroff_late(struct device *dev)
>  
>  static int i915_pm_resume_early(struct device *dev)
>  {
> -	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
> +	struct drm_device *drm_dev = &dev_to_i915(dev)->drm;
>  
>  	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
>  		return 0;
> @@ -2255,7 +2254,7 @@ static int i915_pm_resume_early(struct device *dev)
>  
>  static int i915_pm_resume(struct device *dev)
>  {
> -	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
> +	struct drm_device *drm_dev = &dev_to_i915(dev)->drm;
>  
>  	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
>  		return 0;
> @@ -2630,7 +2629,7 @@ err1:
>  static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
>  				bool rpm_resume)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	int err;
>  	int ret;
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 1df141e4ab6b..3ba289df3843 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -317,15 +317,15 @@ struct i915_hotplug {
>  		for_each_if ((__ports_mask) & (1 << (__port)))
>  
>  #define for_each_crtc(dev, crtc) \
> -	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> +	list_for_each_entry(crtc, &(dev)->mode_config.crtc_list, head)
>  
>  #define for_each_intel_plane(dev, intel_plane) \
>  	list_for_each_entry(intel_plane,			\
> -			    &dev->mode_config.plane_list,	\
> +			    &(dev)->mode_config.plane_list,	\
>  			    base.head)
>  
>  #define for_each_intel_plane_mask(dev, intel_plane, plane_mask)		\
> -	list_for_each_entry(intel_plane, &dev->mode_config.plane_list,	\
> +	list_for_each_entry(intel_plane, &(dev)->mode_config.plane_list,	\
>  			    base.head)					\
>  		for_each_if ((plane_mask) &				\
>  			     (1 << drm_plane_index(&intel_plane->base)))
> @@ -337,10 +337,10 @@ struct i915_hotplug {
>  		for_each_if ((intel_plane)->pipe == (intel_crtc)->pipe)
>  
>  #define for_each_intel_crtc(dev, intel_crtc) \
> -	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
> +	list_for_each_entry(intel_crtc, &(dev)->mode_config.crtc_list, base.head)
>  
>  #define for_each_intel_crtc_mask(dev, intel_crtc, crtc_mask) \
> -	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) \
> +	list_for_each_entry(intel_crtc, &(dev)->mode_config.crtc_list, base.head) \
>  		for_each_if ((crtc_mask) & (1 << drm_crtc_index(&intel_crtc->base)))
>  
>  #define for_each_intel_encoder(dev, intel_encoder)		\
> @@ -350,7 +350,7 @@ struct i915_hotplug {
>  
>  #define for_each_intel_connector(dev, intel_connector)		\
>  	list_for_each_entry(intel_connector,			\
> -			    &dev->mode_config.connector_list,	\
> +			    &(dev)->mode_config.connector_list,	\
>  			    base.head)
>  
>  #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \
> @@ -1724,7 +1724,6 @@ struct intel_wm_config {
>  struct drm_i915_private {
>  	struct drm_device drm;
>  
> -	struct drm_device *dev;
>  	struct kmem_cache *objects;
>  	struct kmem_cache *vmas;
>  	struct kmem_cache *requests;
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 89967f97c097..49e0590726d5 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -1428,7 +1428,7 @@ __i915_gem_request_retire__upto(struct drm_i915_gem_request *req)
>  	struct intel_engine_cs *engine = req->engine;
>  	struct drm_i915_gem_request *tmp;
>  
> -	lockdep_assert_held(&engine->i915->dev->struct_mutex);
> +	lockdep_assert_held(&engine->i915->drm.struct_mutex);
>  
>  	if (list_empty(&req->list))
>  		return;
> @@ -1456,7 +1456,7 @@ i915_wait_request(struct drm_i915_gem_request *req)
>  
>  	interruptible = dev_priv->mm.interruptible;
>  
> -	BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
> +	BUG_ON(!mutex_is_locked(&dev_priv->drm.struct_mutex));
>  
>  	ret = __i915_wait_request(req, interruptible, NULL, NULL);
>  	if (ret)
> @@ -3027,7 +3027,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
>  {
>  	struct drm_i915_private *dev_priv =
>  		container_of(work, typeof(*dev_priv), mm.retire_work.work);
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	bool idle;
>  
>  	/* Come back later if the device is busy... */
> @@ -3046,7 +3046,7 @@ i915_gem_idle_work_handler(struct work_struct *work)
>  {
>  	struct drm_i915_private *dev_priv =
>  		container_of(work, typeof(*dev_priv), mm.idle_work.work);
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct intel_engine_cs *engine;
>  
>  	for_each_engine(engine, dev_priv)
> @@ -4976,7 +4976,7 @@ init_engine_lists(struct intel_engine_cs *engine)
>  void
>  i915_gem_load_init_fences(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  
>  	if (INTEL_INFO(dev_priv)->gen >= 7 && !IS_VALLEYVIEW(dev_priv) &&
>  	    !IS_CHERRYVIEW(dev_priv))
> diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
> index a3b11aac23a4..4f3949e6d480 100644
> --- a/drivers/gpu/drm/i915/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/i915_gem_context.c
> @@ -154,7 +154,7 @@ void i915_gem_context_free(struct kref *ctx_ref)
>  	struct i915_gem_context *ctx = container_of(ctx_ref, typeof(*ctx), ref);
>  	int i;
>  
> -	lockdep_assert_held(&ctx->i915->dev->struct_mutex);
> +	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
>  	trace_i915_context_free(ctx);
>  
>  	/*
> @@ -445,7 +445,7 @@ void i915_gem_context_lost(struct drm_i915_private *dev_priv)
>  {
>  	struct intel_engine_cs *engine;
>  
> -	lockdep_assert_held(&dev_priv->dev->struct_mutex);
> +	lockdep_assert_held(&dev_priv->drm.struct_mutex);
>  
>  	for_each_engine(engine, dev_priv) {
>  		if (engine->last_context) {
> @@ -863,7 +863,7 @@ int i915_switch_context(struct drm_i915_gem_request *req)
>  	struct intel_engine_cs *engine = req->engine;
>  
>  	WARN_ON(i915.enable_execlists);
> -	lockdep_assert_held(&req->i915->dev->struct_mutex);
> +	lockdep_assert_held(&req->i915->drm.struct_mutex);
>  
>  	if (!req->ctx->engine[engine->id].state) {
>  		struct i915_gem_context *to = req->ctx;
> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> index 84d990331abd..e2b6272ba3da 100644
> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> @@ -1330,10 +1330,10 @@ gen8_dispatch_bsd_ring(struct drm_i915_private *dev_priv, struct drm_file *file)
>  	/* Check whether the file_priv has already selected one ring. */
>  	if ((int)file_priv->bsd_ring < 0) {
>  		/* If not, use the ping-pong mechanism to select one. */
> -		mutex_lock(&dev_priv->dev->struct_mutex);
> +		mutex_lock(&dev_priv->drm.struct_mutex);
>  		file_priv->bsd_ring = dev_priv->mm.bsd_ring_dispatch_index;
>  		dev_priv->mm.bsd_ring_dispatch_index ^= 1;
> -		mutex_unlock(&dev_priv->dev->struct_mutex);
> +		mutex_unlock(&dev_priv->drm.struct_mutex);
>  	}
>  
>  	return file_priv->bsd_ring;
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index 46684779d4d6..98065eb43fb5 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -153,7 +153,7 @@ int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
>  #endif
>  
>  	/* Early VLV doesn't have this */
> -	if (IS_VALLEYVIEW(dev_priv) && dev_priv->dev->pdev->revision < 0xb) {
> +	if (IS_VALLEYVIEW(dev_priv) && dev_priv->drm.pdev->revision < 0xb) {
>  		DRM_DEBUG_DRIVER("disabling PPGTT on pre-B3 step VLV\n");
>  		return 0;
>  	}
> @@ -2133,7 +2133,7 @@ static void i915_address_space_init(struct i915_address_space *vm,
>  				    struct drm_i915_private *dev_priv)
>  {
>  	drm_mm_init(&vm->mm, vm->start, vm->total);
> -	vm->dev = dev_priv->dev;
> +	vm->dev = &dev_priv->drm;
>  	INIT_LIST_HEAD(&vm->active_list);
>  	INIT_LIST_HEAD(&vm->inactive_list);
>  	list_add_tail(&vm->global_link, &dev_priv->vm_list);
> @@ -2261,7 +2261,7 @@ static bool do_idling(struct drm_i915_private *dev_priv)
>  
>  	if (unlikely(ggtt->do_idle_maps)) {
>  		dev_priv->mm.interruptible = false;
> -		if (i915_gpu_idle(dev_priv->dev)) {
> +		if (i915_gpu_idle(&dev_priv->drm)) {
>  			DRM_ERROR("Couldn't idle GPU\n");
>  			/* Wait a bit, in hopes it avoids the hang */
>  			udelay(10);
> @@ -3137,7 +3137,7 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt)
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	int ret;
>  
> -	ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->dev->pdev, NULL);
> +	ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->drm.pdev, NULL);
>  	if (!ret) {
>  		DRM_ERROR("failed to set up gmch\n");
>  		return -EIO;
> @@ -3146,7 +3146,7 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt)
>  	intel_gtt_get(&ggtt->base.total, &ggtt->stolen_size,
>  		      &ggtt->mappable_base, &ggtt->mappable_end);
>  
> -	ggtt->do_idle_maps = needs_idle_maps(dev_priv->dev);
> +	ggtt->do_idle_maps = needs_idle_maps(&dev_priv->drm);
>  	ggtt->base.insert_entries = i915_ggtt_insert_entries;
>  	ggtt->base.clear_range = i915_ggtt_clear_range;
>  	ggtt->base.bind_vma = ggtt_bind_vma;
> diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c
> index 7c93327b70fe..8a129843956f 100644
> --- a/drivers/gpu/drm/i915/i915_gem_render_state.c
> +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c
> @@ -58,7 +58,7 @@ static int render_state_init(struct render_state *so,
>  	if (so->rodata->batch_items * 4 > 4096)
>  		return -EINVAL;
>  
> -	so->obj = i915_gem_object_create(dev_priv->dev, 4096);
> +	so->obj = i915_gem_object_create(&dev_priv->drm, 4096);
>  	if (IS_ERR(so->obj))
>  		return PTR_ERR(so->obj);
>  
> diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
> index 538c30499848..e63852795395 100644
> --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
> +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
> @@ -257,7 +257,7 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
>  {
>  	struct drm_i915_private *dev_priv =
>  		container_of(shrinker, struct drm_i915_private, mm.shrinker);
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct drm_i915_gem_object *obj;
>  	unsigned long count;
>  	bool unlock;
> @@ -286,7 +286,7 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
>  {
>  	struct drm_i915_private *dev_priv =
>  		container_of(shrinker, struct drm_i915_private, mm.shrinker);
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	unsigned long freed;
>  	bool unlock;
>  
> @@ -321,7 +321,7 @@ i915_gem_shrinker_lock_uninterruptible(struct drm_i915_private *dev_priv,
>  {
>  	unsigned long timeout = msecs_to_jiffies(timeout_ms) + 1;
>  
> -	while (!i915_gem_shrinker_lock(dev_priv->dev, &slu->unlock)) {
> +	while (!i915_gem_shrinker_lock(&dev_priv->drm, &slu->unlock)) {
>  		schedule_timeout_killable(1);
>  		if (fatal_signal_pending(current))
>  			return false;
> @@ -342,7 +342,7 @@ i915_gem_shrinker_unlock_uninterruptible(struct drm_i915_private *dev_priv,
>  {
>  	dev_priv->mm.interruptible = slu->was_interruptible;
>  	if (slu->unlock)
> -		mutex_unlock(&dev_priv->dev->struct_mutex);
> +		mutex_unlock(&dev_priv->drm.struct_mutex);
>  }
>  
>  static int
> @@ -408,7 +408,7 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr
>  		return NOTIFY_DONE;
>  
>  	/* Force everything onto the inactive lists */
> -	ret = i915_gpu_idle(dev_priv->dev);
> +	ret = i915_gpu_idle(&dev_priv->drm);
>  	if (ret)
>  		goto out;
>  
> diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
> index 34ff2459ceea..0c69e4bee7a4 100644
> --- a/drivers/gpu/drm/i915/i915_gpu_error.c
> +++ b/drivers/gpu/drm/i915/i915_gpu_error.c
> @@ -1230,7 +1230,7 @@ static void i915_gem_capture_buffers(struct drm_i915_private *dev_priv,
>  static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
>  				   struct drm_i915_error_state *error)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	int i;
>  
>  	/* General organization
> @@ -1395,7 +1395,7 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv,
>  		DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n");
>  		DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n");
>  		DRM_INFO("The gpu crash dump is required to analyze gpu hangs, so please always attach it.\n");
> -		DRM_INFO("GPU crash dump saved to /sys/class/drm/card%d/error\n", dev_priv->dev->primary->index);
> +		DRM_INFO("GPU crash dump saved to /sys/class/drm/card%d/error\n", dev_priv->drm.primary->index);
>  		warned = true;
>  	}
>  }
> diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
> index ac72451c571c..214139055013 100644
> --- a/drivers/gpu/drm/i915/i915_guc_submission.c
> +++ b/drivers/gpu/drm/i915/i915_guc_submission.c
> @@ -153,7 +153,7 @@ static int host2guc_sample_forcewake(struct intel_guc *guc,
>  				     struct i915_guc_client *client)
>  {
>  	struct drm_i915_private *dev_priv = guc_to_i915(guc);
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	u32 data[2];
>  
>  	data[0] = HOST2GUC_ACTION_SAMPLE_FORCEWAKE;
> @@ -790,7 +790,7 @@ static void guc_create_log(struct intel_guc *guc)
>  
>  	obj = guc->log_obj;
>  	if (!obj) {
> -		obj = gem_allocate_guc_obj(dev_priv->dev, size);
> +		obj = gem_allocate_guc_obj(&dev_priv->drm, size);
>  		if (!obj) {
>  			/* logging will be off */
>  			i915.guc_log_level = -1;
> @@ -850,7 +850,7 @@ static void guc_create_ads(struct intel_guc *guc)
>  
>  	obj = guc->ads_obj;
>  	if (!obj) {
> -		obj = gem_allocate_guc_obj(dev_priv->dev, PAGE_ALIGN(size));
> +		obj = gem_allocate_guc_obj(&dev_priv->drm, PAGE_ALIGN(size));
>  		if (!obj)
>  			return;
>  
> @@ -918,7 +918,7 @@ int i915_guc_submission_init(struct drm_device *dev)
>  	if (guc->ctx_pool_obj)
>  		return 0; /* already allocated */
>  
> -	guc->ctx_pool_obj = gem_allocate_guc_obj(dev_priv->dev, gemsize);
> +	guc->ctx_pool_obj = gem_allocate_guc_obj(&dev_priv->drm, gemsize);
>  	if (!guc->ctx_pool_obj)
>  		return -ENOMEM;
>  
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index caaf1e2a7bc1..95b87549f41c 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -397,7 +397,7 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv)
>  
>  	spin_unlock_irq(&dev_priv->irq_lock);
>  
> -	synchronize_irq(dev_priv->dev->irq);
> +	synchronize_irq(dev_priv->drm.irq);
>  }
>  
>  /**
> @@ -577,7 +577,7 @@ i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
>  	u32 enable_mask;
>  
>  	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
> +		enable_mask = vlv_get_pipestat_enable_mask(&dev_priv->drm,
>  							   status_mask);
>  	else
>  		enable_mask = status_mask << 16;
> @@ -591,7 +591,7 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
>  	u32 enable_mask;
>  
>  	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
> +		enable_mask = vlv_get_pipestat_enable_mask(&dev_priv->drm,
>  							   status_mask);
>  	else
>  		enable_mask = status_mask << 16;
> @@ -1197,7 +1197,7 @@ static void ivybridge_parity_work(struct work_struct *work)
>  	 * In order to prevent a get/put style interface, acquire struct mutex
>  	 * any time we access those registers.
>  	 */
> -	mutex_lock(&dev_priv->dev->struct_mutex);
> +	mutex_lock(&dev_priv->drm.struct_mutex);
>  
>  	/* If we've screwed up tracking, just let the interrupt fire again */
>  	if (WARN_ON(!dev_priv->l3_parity.which_slice))
> @@ -1233,7 +1233,7 @@ static void ivybridge_parity_work(struct work_struct *work)
>  		parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice);
>  		parity_event[5] = NULL;
>  
> -		kobject_uevent_env(&dev_priv->dev->primary->kdev->kobj,
> +		kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj,
>  				   KOBJ_CHANGE, parity_event);
>  
>  		DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n",
> @@ -1253,7 +1253,7 @@ out:
>  	gen5_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv));
>  	spin_unlock_irq(&dev_priv->irq_lock);
>  
> -	mutex_unlock(&dev_priv->dev->struct_mutex);
> +	mutex_unlock(&dev_priv->drm.struct_mutex);
>  }
>  
>  static void ivybridge_parity_error_irq_handler(struct drm_i915_private *dev_priv,
> @@ -1538,7 +1538,7 @@ static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
>  
>  	entry = &pipe_crc->entries[head];
>  
> -	entry->frame = dev_priv->dev->driver->get_vblank_counter(dev_priv->dev,
> +	entry->frame = dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm,
>  								 pipe);
>  	entry->crc[0] = crc0;
>  	entry->crc[1] = crc1;
> @@ -1636,7 +1636,7 @@ static bool intel_pipe_handle_vblank(struct drm_i915_private *dev_priv,
>  {
>  	bool ret;
>  
> -	ret = drm_handle_vblank(dev_priv->dev, pipe);
> +	ret = drm_handle_vblank(&dev_priv->drm, pipe);
>  	if (ret)
>  		intel_finish_page_flip_mmio(dev_priv, pipe);
>  
> @@ -2536,7 +2536,7 @@ static void i915_error_wake_up(struct drm_i915_private *dev_priv,
>   */
>  static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv)
>  {
> -	struct kobject *kobj = &dev_priv->dev->primary->kdev->kobj;
> +	struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj;
>  	char *error_event[] = { I915_ERROR_UEVENT "=1", NULL };
>  	char *reset_event[] = { I915_RESET_UEVENT "=1", NULL };
>  	char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL };
> @@ -3455,7 +3455,7 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
>  	spin_unlock_irq(&dev_priv->irq_lock);
>  
>  	/* make sure we're done processing display irqs */
> -	synchronize_irq(dev_priv->dev->irq);
> +	synchronize_irq(dev_priv->drm.irq);
>  }
>  
>  static void cherryview_irq_preinstall(struct drm_device *dev)
> @@ -3481,7 +3481,7 @@ static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv,
>  	struct intel_encoder *encoder;
>  	u32 enabled_irqs = 0;
>  
> -	for_each_intel_encoder(dev_priv->dev, encoder)
> +	for_each_intel_encoder(&dev_priv->drm, encoder)
>  		if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED)
>  			enabled_irqs |= hpd[encoder->hpd_pin];
>  
> @@ -4564,7 +4564,7 @@ static void i965_irq_uninstall(struct drm_device * dev)
>   */
>  void intel_irq_init(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  
>  	intel_hpd_init_work(dev_priv);
>  
> @@ -4684,7 +4684,7 @@ int intel_irq_install(struct drm_i915_private *dev_priv)
>  	 */
>  	dev_priv->pm.irqs_enabled = true;
>  
> -	return drm_irq_install(dev_priv->dev, dev_priv->dev->pdev->irq);
> +	return drm_irq_install(&dev_priv->drm, dev_priv->drm.pdev->irq);
>  }
>  
>  /**
> @@ -4696,7 +4696,7 @@ int intel_irq_install(struct drm_i915_private *dev_priv)
>   */
>  void intel_irq_uninstall(struct drm_i915_private *dev_priv)
>  {
> -	drm_irq_uninstall(dev_priv->dev);
> +	drm_irq_uninstall(&dev_priv->drm);
>  	intel_hpd_cancel_work(dev_priv);
>  	dev_priv->pm.irqs_enabled = false;
>  }
> @@ -4710,9 +4710,9 @@ void intel_irq_uninstall(struct drm_i915_private *dev_priv)
>   */
>  void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv)
>  {
> -	dev_priv->dev->driver->irq_uninstall(dev_priv->dev);
> +	dev_priv->drm.driver->irq_uninstall(&dev_priv->drm);
>  	dev_priv->pm.irqs_enabled = false;
> -	synchronize_irq(dev_priv->dev->irq);
> +	synchronize_irq(dev_priv->drm.irq);
>  }
>  
>  /**
> @@ -4725,6 +4725,6 @@ void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv)
>  void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv)
>  {
>  	dev_priv->pm.irqs_enabled = true;
> -	dev_priv->dev->driver->irq_preinstall(dev_priv->dev);
> -	dev_priv->dev->driver->irq_postinstall(dev_priv->dev);
> +	dev_priv->drm.driver->irq_preinstall(&dev_priv->drm);
> +	dev_priv->drm.driver->irq_postinstall(&dev_priv->drm);
>  }
> diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
> index 6768db032f84..4d530dd3eed0 100644
> --- a/drivers/gpu/drm/i915/i915_trace.h
> +++ b/drivers/gpu/drm/i915/i915_trace.h
> @@ -118,7 +118,7 @@ TRACE_EVENT(i915_gem_shrink,
>  			     ),
>  
>  	    TP_fast_assign(
> -			   __entry->dev = i915->dev->primary->index;
> +			   __entry->dev = i915->drm.primary->index;
>  			   __entry->target = target;
>  			   __entry->flags = flags;
>  			   ),
> @@ -462,7 +462,7 @@ TRACE_EVENT(i915_gem_ring_sync_to,
>  			     ),
>  
>  	    TP_fast_assign(
> -			   __entry->dev = from->i915->dev->primary->index;
> +			   __entry->dev = from->i915->drm.primary->index;
>  			   __entry->sync_from = from->id;
>  			   __entry->sync_to = to_req->engine->id;
>  			   __entry->seqno = i915_gem_request_get_seqno(req);
> @@ -486,7 +486,7 @@ TRACE_EVENT(i915_gem_ring_dispatch,
>  			     ),
>  
>  	    TP_fast_assign(
> -			   __entry->dev = req->i915->dev->primary->index;
> +			   __entry->dev = req->i915->drm.primary->index;
>  			   __entry->ring = req->engine->id;
>  			   __entry->seqno = req->seqno;
>  			   __entry->flags = flags;
> @@ -509,7 +509,7 @@ TRACE_EVENT(i915_gem_ring_flush,
>  			     ),
>  
>  	    TP_fast_assign(
> -			   __entry->dev = req->i915->dev->primary->index;
> +			   __entry->dev = req->i915->drm.primary->index;
>  			   __entry->ring = req->engine->id;
>  			   __entry->invalidate = invalidate;
>  			   __entry->flush = flush;
> @@ -531,7 +531,7 @@ DECLARE_EVENT_CLASS(i915_gem_request,
>  			     ),
>  
>  	    TP_fast_assign(
> -			   __entry->dev = req->i915->dev->primary->index;
> +			   __entry->dev = req->i915->drm.primary->index;
>  			   __entry->ring = req->engine->id;
>  			   __entry->seqno = req->seqno;
>  			   ),
> @@ -556,7 +556,7 @@ TRACE_EVENT(i915_gem_request_notify,
>  			     ),
>  
>  	    TP_fast_assign(
> -			   __entry->dev = engine->i915->dev->primary->index;
> +			   __entry->dev = engine->i915->drm.primary->index;
>  			   __entry->ring = engine->id;
>  			   __entry->seqno = engine->get_seqno(engine);
>  			   ),
> @@ -593,11 +593,11 @@ TRACE_EVENT(i915_gem_request_wait_begin,
>  	     * less desirable.
>  	     */
>  	    TP_fast_assign(
> -			   __entry->dev = req->i915->dev->primary->index;
> +			   __entry->dev = req->i915->drm.primary->index;
>  			   __entry->ring = req->engine->id;
>  			   __entry->seqno = req->seqno;
>  			   __entry->blocking =
> -				     mutex_is_locked(&req->i915->dev->struct_mutex);
> +				     mutex_is_locked(&req->i915->drm.struct_mutex);
>  			   ),
>  
>  	    TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s",
> @@ -746,7 +746,7 @@ DECLARE_EVENT_CLASS(i915_context,
>  	TP_fast_assign(
>  			__entry->ctx = ctx;
>  			__entry->vm = ctx->ppgtt ? &ctx->ppgtt->base : NULL;
> -			__entry->dev = ctx->i915->dev->primary->index;
> +			__entry->dev = ctx->i915->drm.primary->index;
>  	),
>  
>  	TP_printk("dev=%u, ctx=%p, ctx_vm=%p",
> @@ -786,7 +786,7 @@ TRACE_EVENT(switch_mm,
>  			__entry->ring = engine->id;
>  			__entry->to = to;
>  			__entry->vm = to->ppgtt? &to->ppgtt->base : NULL;
> -			__entry->dev = engine->i915->dev->primary->index;
> +			__entry->dev = engine->i915->drm.primary->index;
>  	),
>  
>  	TP_printk("dev=%u, ring=%u, ctx=%p, ctx_vm=%p",
> diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
> index b9329c2a670a..28d7d4437e32 100644
> --- a/drivers/gpu/drm/i915/intel_audio.c
> +++ b/drivers/gpu/drm/i915/intel_audio.c
> @@ -749,14 +749,14 @@ static int i915_audio_component_bind(struct device *i915_dev,
>  	if (WARN_ON(acomp->ops || acomp->dev))
>  		return -EEXIST;
>  
> -	drm_modeset_lock_all(dev_priv->dev);
> +	drm_modeset_lock_all(&dev_priv->drm);
>  	acomp->ops = &i915_audio_component_ops;
>  	acomp->dev = i915_dev;
>  	BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS);
>  	for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++)
>  		acomp->aud_sample_rate[i] = 0;
>  	dev_priv->audio_component = acomp;
> -	drm_modeset_unlock_all(dev_priv->dev);
> +	drm_modeset_unlock_all(&dev_priv->drm);
>  
>  	return 0;
>  }
> @@ -767,11 +767,11 @@ static void i915_audio_component_unbind(struct device *i915_dev,
>  	struct i915_audio_component *acomp = data;
>  	struct drm_i915_private *dev_priv = dev_to_i915(i915_dev);
>  
> -	drm_modeset_lock_all(dev_priv->dev);
> +	drm_modeset_lock_all(&dev_priv->drm);
>  	acomp->ops = NULL;
>  	acomp->dev = NULL;
>  	dev_priv->audio_component = NULL;
> -	drm_modeset_unlock_all(dev_priv->dev);
> +	drm_modeset_unlock_all(&dev_priv->drm);
>  }
>  
>  static const struct component_ops i915_audio_component_bind_ops = {
> @@ -799,7 +799,7 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv)
>  {
>  	int ret;
>  
> -	ret = component_add(dev_priv->dev->dev, &i915_audio_component_bind_ops);
> +	ret = component_add(dev_priv->drm.dev, &i915_audio_component_bind_ops);
>  	if (ret < 0) {
>  		DRM_ERROR("failed to add audio component (%d)\n", ret);
>  		/* continue with reduced functionality */
> @@ -821,6 +821,6 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv)
>  	if (!dev_priv->audio_component_registered)
>  		return;
>  
> -	component_del(dev_priv->dev->dev, &i915_audio_component_bind_ops);
> +	component_del(dev_priv->drm.dev, &i915_audio_component_bind_ops);
>  	dev_priv->audio_component_registered = false;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
> index 624e755e451f..b356a149eb4a 100644
> --- a/drivers/gpu/drm/i915/intel_bios.c
> +++ b/drivers/gpu/drm/i915/intel_bios.c
> @@ -1421,7 +1421,7 @@ static const struct vbt_header *find_vbt(void __iomem *bios, size_t size)
>  int
>  intel_bios_init(struct drm_i915_private *dev_priv)
>  {
> -	struct pci_dev *pdev = dev_priv->dev->pdev;
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	const struct vbt_header *vbt = dev_priv->opregion.vbt;
>  	const struct bdb_header *bdb;
>  	u8 __iomem *bios = NULL;
> diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
> index 2b3b428d9cd2..1a6486932fc7 100644
> --- a/drivers/gpu/drm/i915/intel_csr.c
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -413,7 +413,7 @@ static void csr_load_work_fn(struct work_struct *work)
>  	csr = &dev_priv->csr;
>  
>  	ret = request_firmware(&fw, dev_priv->csr.fw_path,
> -			       &dev_priv->dev->pdev->dev);
> +			       &dev_priv->drm.pdev->dev);
>  	if (fw)
>  		dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw);
>  
> @@ -427,7 +427,7 @@ static void csr_load_work_fn(struct work_struct *work)
>  			 CSR_VERSION_MAJOR(csr->version),
>  			 CSR_VERSION_MINOR(csr->version));
>  	} else {
> -		dev_notice(dev_priv->dev->dev,
> +		dev_notice(dev_priv->drm.dev,
>  			   "Failed to load DMC firmware"
>  			   " [" FIRMWARE_URL "],"
>  			   " disabling runtime power management.\n");
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 8c4094611b21..a346832cb5e1 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1234,7 +1234,7 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
>  void assert_panel_unlocked(struct drm_i915_private *dev_priv,
>  			   enum pipe pipe)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	i915_reg_t pp_reg;
>  	u32 val;
>  	enum pipe panel_pipe = PIPE_A;
> @@ -1276,7 +1276,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
>  static void assert_cursor(struct drm_i915_private *dev_priv,
>  			  enum pipe pipe, bool state)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	bool cur_state;
>  
>  	if (IS_845G(dev) || IS_I865G(dev))
> @@ -1338,7 +1338,7 @@ static void assert_plane(struct drm_i915_private *dev_priv,
>  static void assert_planes_disabled(struct drm_i915_private *dev_priv,
>  				   enum pipe pipe)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	int i;
>  
>  	/* Primary planes are fixed to pipes on gen4+ */
> @@ -1364,7 +1364,7 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv,
>  static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
>  				    enum pipe pipe)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	int sprite;
>  
>  	if (INTEL_INFO(dev)->gen >= 9) {
> @@ -1821,7 +1821,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
>  static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
>  					   enum pipe pipe)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	i915_reg_t reg;
> @@ -1906,7 +1906,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
>  static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
>  					    enum pipe pipe)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	i915_reg_t reg;
>  	uint32_t val;
>  
> @@ -3118,7 +3118,7 @@ static void intel_complete_page_flips(struct drm_i915_private *dev_priv)
>  {
>  	struct intel_crtc *crtc;
>  
> -	for_each_intel_crtc(dev_priv->dev, crtc)
> +	for_each_intel_crtc(&dev_priv->drm, crtc)
>  		intel_finish_page_flip_cs(dev_priv, crtc->pipe);
>  }
>  
> @@ -3152,12 +3152,12 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
>  	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
>  		return;
>  
> -	drm_modeset_lock_all(dev_priv->dev);
> +	drm_modeset_lock_all(&dev_priv->drm);
>  	/*
>  	 * Disabling the crtcs gracefully seems nicer. Also the
>  	 * g33 docs say we should at least disable all the planes.
>  	 */
> -	intel_display_suspend(dev_priv->dev);
> +	intel_display_suspend(&dev_priv->drm);
>  }
>  
>  void intel_finish_reset(struct drm_i915_private *dev_priv)
> @@ -3184,7 +3184,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
>  		 * FIXME: Atomic will make this obsolete since we won't schedule
>  		 * CS-based flips (which might get lost in gpu resets) any more.
>  		 */
> -		intel_update_primary_planes(dev_priv->dev);
> +		intel_update_primary_planes(&dev_priv->drm);
>  		return;
>  	}
>  
> @@ -3195,18 +3195,18 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
>  	intel_runtime_pm_disable_interrupts(dev_priv);
>  	intel_runtime_pm_enable_interrupts(dev_priv);
>  
> -	intel_modeset_init_hw(dev_priv->dev);
> +	intel_modeset_init_hw(&dev_priv->drm);
>  
>  	spin_lock_irq(&dev_priv->irq_lock);
>  	if (dev_priv->display.hpd_irq_setup)
>  		dev_priv->display.hpd_irq_setup(dev_priv);
>  	spin_unlock_irq(&dev_priv->irq_lock);
>  
> -	intel_display_resume(dev_priv->dev);
> +	intel_display_resume(&dev_priv->drm);
>  
>  	intel_hpd_init(dev_priv);
>  
> -	drm_modeset_unlock_all(dev_priv->dev);
> +	drm_modeset_unlock_all(&dev_priv->drm);
>  }
>  
>  static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
> @@ -5488,14 +5488,14 @@ static void broxton_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
>  		return;
>  	}
>  
> -	intel_update_cdclk(dev_priv->dev);
> +	intel_update_cdclk(&dev_priv->drm);
>  }
>  
>  static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
>  {
>  	u32 cdctl, expected;
>  
> -	intel_update_cdclk(dev_priv->dev);
> +	intel_update_cdclk(&dev_priv->drm);
>  
>  	if (dev_priv->cdclk_pll.vco == 0 ||
>  	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> @@ -5628,7 +5628,7 @@ void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco)
>  	dev_priv->skl_preferred_vco_freq = vco;
>  
>  	if (changed)
> -		intel_update_max_cdclk(dev_priv->dev);
> +		intel_update_max_cdclk(&dev_priv->drm);
>  }
>  
>  static void
> @@ -5718,7 +5718,7 @@ static bool skl_cdclk_wait_for_pcu_ready(struct drm_i915_private *dev_priv)
>  
>  static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int vco)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	u32 freq_select, pcu_ack;
>  
>  	WARN_ON((cdclk == 24000) != (vco == 0));
> @@ -5816,7 +5816,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
>  	if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
>  		goto sanitize;
>  
> -	intel_update_cdclk(dev_priv->dev);
> +	intel_update_cdclk(&dev_priv->drm);
>  	/* Is PLL enabled and locked ? */
>  	if (dev_priv->cdclk_pll.vco == 0 ||
>  	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
> @@ -9451,7 +9451,7 @@ out:
>  
>  static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct intel_crtc *crtc;
>  
>  	for_each_intel_crtc(dev, crtc)
> @@ -9485,7 +9485,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
>  
>  static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  
>  	if (IS_HASWELL(dev))
>  		return I915_READ(D_COMP_HSW);
> @@ -9495,7 +9495,7 @@ static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
>  
>  static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  
>  	if (IS_HASWELL(dev)) {
>  		mutex_lock(&dev_priv->rps.hw_lock);
> @@ -9610,7 +9610,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
>  	}
>  
>  	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
> -	intel_update_cdclk(dev_priv->dev);
> +	intel_update_cdclk(&dev_priv->drm);
>  }
>  
>  /*
> @@ -9638,7 +9638,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
>   */
>  void hsw_enable_pc8(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	uint32_t val;
>  
>  	DRM_DEBUG_KMS("Enabling package C8+\n");
> @@ -9655,7 +9655,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv)
>  
>  void hsw_disable_pc8(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	uint32_t val;
>  
>  	DRM_DEBUG_KMS("Disabling package C8+\n");
> @@ -11128,7 +11128,7 @@ static bool pageflip_finished(struct intel_crtc *crtc,
>  
>  void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	struct intel_flip_work *work;
> @@ -11155,7 +11155,7 @@ void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe)
>  
>  void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	struct intel_flip_work *work;
> @@ -11611,7 +11611,7 @@ static bool __pageflip_stall_check_cs(struct drm_i915_private *dev_priv,
>  
>  void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	struct intel_flip_work *work;
> @@ -15433,12 +15433,12 @@ void intel_modeset_init_hw(struct drm_device *dev)
>  
>  void intel_modeset_register(struct drm_i915_private *dev_priv)
>  {
> -	drm_connector_register_all(dev_priv->dev);
> +	drm_connector_register_all(&dev_priv->drm);
>  }
>  
>  void intel_modeset_unregister(struct drm_i915_private *dev_priv)
>  {
> -	drm_connector_unregister_all(dev_priv->dev);
> +	drm_connector_unregister_all(&dev_priv->drm);
>  }
>  
>  /*
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index d077f30d6804..97f39e4f1361 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -509,7 +509,7 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
>  
>  void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct intel_encoder *encoder;
>  
>  	if (WARN_ON(!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)))
> @@ -2213,7 +2213,7 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
>  	 * 2. Program DP PLL enable
>  	 */
>  	if (IS_GEN5(dev_priv))
> -		intel_wait_for_vblank_if_active(dev_priv->dev, !crtc->pipe);
> +		intel_wait_for_vblank_if_active(&dev_priv->drm, !crtc->pipe);
>  
>  	intel_dp->DP |= DP_PLL_ENABLE;
>  
> @@ -3312,7 +3312,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
>  		I915_WRITE(intel_dp->output_reg, DP);
>  		POSTING_READ(intel_dp->output_reg);
>  
> -		intel_wait_for_vblank_if_active(dev_priv->dev, PIPE_A);
> +		intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A);
>  		intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
>  		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
>  	}
> @@ -5078,7 +5078,7 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp)
>  	}
>  
>  	if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
> -		intel_dp_set_drrs_state(dev_priv->dev,
> +		intel_dp_set_drrs_state(&dev_priv->drm,
>  			intel_dp->attached_connector->panel.
>  			fixed_mode->vrefresh);
>  
> @@ -5110,7 +5110,7 @@ static void intel_edp_drrs_downclock_work(struct work_struct *work)
>  		goto unlock;
>  
>  	if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR)
> -		intel_dp_set_drrs_state(dev_priv->dev,
> +		intel_dp_set_drrs_state(&dev_priv->drm,
>  			intel_dp->attached_connector->panel.
>  			downclock_mode->vrefresh);
>  
> @@ -5154,7 +5154,7 @@ void intel_edp_drrs_invalidate(struct drm_device *dev,
>  
>  	/* invalidate means busy screen hence upclock */
>  	if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
> -		intel_dp_set_drrs_state(dev_priv->dev,
> +		intel_dp_set_drrs_state(&dev_priv->drm,
>  				dev_priv->drrs.dp->attached_connector->panel.
>  				fixed_mode->vrefresh);
>  
> @@ -5199,7 +5199,7 @@ void intel_edp_drrs_flush(struct drm_device *dev,
>  
>  	/* flush means busy screen hence upclock */
>  	if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
> -		intel_dp_set_drrs_state(dev_priv->dev,
> +		intel_dp_set_drrs_state(&dev_priv->drm,
>  				dev_priv->drrs.dp->attached_connector->panel.
>  				fixed_mode->vrefresh);
>  
> diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> index 02a7962a67f1..f7c18f3d61c9 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> @@ -331,7 +331,7 @@ static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
>  static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
>  				 struct intel_shared_dpll *pll)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct intel_crtc *crtc;
>  
>  	/* Make sure no transcoder isn't still depending on us. */
> diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
> index 0dea5fbcd8aa..4aa649c7fa31 100644
> --- a/drivers/gpu/drm/i915/intel_fbc.c
> +++ b/drivers/gpu/drm/i915/intel_fbc.c
> @@ -389,7 +389,7 @@ static void intel_fbc_work_fn(struct work_struct *__work)
>  	struct intel_fbc *fbc = &dev_priv->fbc;
>  	struct intel_fbc_work *work = &fbc->work;
>  	struct intel_crtc *crtc = fbc->crtc;
> -	struct drm_vblank_crtc *vblank = &dev_priv->dev->vblank[crtc->pipe];
> +	struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[crtc->pipe];
>  
>  	if (drm_crtc_vblank_get(&crtc->base)) {
>  		DRM_ERROR("vblank not available for FBC on pipe %c\n",
> @@ -1216,7 +1216,7 @@ void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv)
>  	if (!no_fbc_on_multiple_pipes(dev_priv))
>  		return;
>  
> -	for_each_intel_crtc(dev_priv->dev, crtc)
> +	for_each_intel_crtc(&dev_priv->drm, crtc)
>  		if (intel_crtc_active(&crtc->base) &&
>  		    to_intel_plane_state(crtc->base.primary->state)->visible)
>  			dev_priv->fbc.visible_pipes_mask |= (1 << crtc->pipe);
> diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
> index 99e27530e264..a91ac90f0ecb 100644
> --- a/drivers/gpu/drm/i915/intel_fbdev.c
> +++ b/drivers/gpu/drm/i915/intel_fbdev.c
> @@ -692,9 +692,9 @@ out:
>  
>  static void intel_fbdev_suspend_worker(struct work_struct *work)
>  {
> -	intel_fbdev_set_suspend(container_of(work,
> -					     struct drm_i915_private,
> -					     fbdev_suspend_work)->dev,
> +	intel_fbdev_set_suspend(&container_of(work,
> +					      struct drm_i915_private,
> +					      fbdev_suspend_work)->drm,
>  				FBINFO_STATE_RUNNING,
>  				true);
>  }
> @@ -742,7 +742,7 @@ static void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
>  	/* Due to peculiar init order wrt to hpd handling this is separate. */
>  	if (drm_fb_helper_initial_config(&ifbdev->helper,
>  					 ifbdev->preferred_bpp))
> -		intel_fbdev_fini(dev_priv->dev);
> +		intel_fbdev_fini(&dev_priv->drm);
>  }
>  
>  void intel_fbdev_initial_config_async(struct drm_device *dev)
> diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c
> index 9be839a242f9..d6ef8e5833ad 100644
> --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c
> +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c
> @@ -289,7 +289,7 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
>  	bool ret;
>  
>  	spin_lock_irqsave(&dev_priv->irq_lock, flags);
> -	ret = __intel_set_cpu_fifo_underrun_reporting(dev_priv->dev, pipe,
> +	ret = __intel_set_cpu_fifo_underrun_reporting(&dev_priv->drm, pipe,
>  						      enable);
>  	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
>  
> @@ -334,10 +334,10 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
>  	intel_crtc->pch_fifo_underrun_disabled = !enable;
>  
>  	if (HAS_PCH_IBX(dev_priv))
> -		ibx_set_fifo_underrun_reporting(dev_priv->dev, pch_transcoder,
> +		ibx_set_fifo_underrun_reporting(&dev_priv->drm, pch_transcoder,
>  						enable);
>  	else
> -		cpt_set_fifo_underrun_reporting(dev_priv->dev, pch_transcoder,
> +		cpt_set_fifo_underrun_reporting(&dev_priv->drm, pch_transcoder,
>  						enable, old);
>  
>  	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
> @@ -405,7 +405,7 @@ void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv)
>  
>  	spin_lock_irq(&dev_priv->irq_lock);
>  
> -	for_each_intel_crtc(dev_priv->dev, crtc) {
> +	for_each_intel_crtc(&dev_priv->drm, crtc) {
>  		if (crtc->cpu_fifo_underrun_disabled)
>  			continue;
>  
> @@ -432,7 +432,7 @@ void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv)
>  
>  	spin_lock_irq(&dev_priv->irq_lock);
>  
> -	for_each_intel_crtc(dev_priv->dev, crtc) {
> +	for_each_intel_crtc(&dev_priv->drm, crtc) {
>  		if (crtc->pch_fifo_underrun_disabled)
>  			continue;
>  
> diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
> index 29273e5fee22..63ccaf00a14e 100644
> --- a/drivers/gpu/drm/i915/intel_guc_loader.c
> +++ b/drivers/gpu/drm/i915/intel_guc_loader.c
> @@ -301,7 +301,7 @@ static u32 guc_wopcm_size(struct drm_i915_private *dev_priv)
>  static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
>  {
>  	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	int ret;
>  
>  	ret = i915_gem_object_set_to_gtt_domain(guc_fw->guc_fw_obj, false);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index cea6b4de4018..b02c52d3e799 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1154,7 +1154,7 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
>  		I915_WRITE(intel_hdmi->hdmi_reg, temp);
>  		POSTING_READ(intel_hdmi->hdmi_reg);
>  
> -		intel_wait_for_vblank_if_active(dev_priv->dev, PIPE_A);
> +		intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A);
>  		intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
>  		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
> index 38eeca7a6e72..51434ec871f2 100644
> --- a/drivers/gpu/drm/i915/intel_hotplug.c
> +++ b/drivers/gpu/drm/i915/intel_hotplug.c
> @@ -144,7 +144,7 @@ static bool intel_hpd_irq_storm_detect(struct drm_i915_private *dev_priv,
>  
>  static void intel_hpd_irq_storm_disable(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct drm_mode_config *mode_config = &dev->mode_config;
>  	struct intel_connector *intel_connector;
>  	struct intel_encoder *intel_encoder;
> @@ -191,7 +191,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
>  	struct drm_i915_private *dev_priv =
>  		container_of(work, typeof(*dev_priv),
>  			     hotplug.reenable_work.work);
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct drm_mode_config *mode_config = &dev->mode_config;
>  	int i;
>  
> @@ -302,7 +302,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
>  {
>  	struct drm_i915_private *dev_priv =
>  		container_of(work, struct drm_i915_private, hotplug.hotplug_work);
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct drm_mode_config *mode_config = &dev->mode_config;
>  	struct intel_connector *intel_connector;
>  	struct intel_encoder *intel_encoder;
> @@ -455,7 +455,7 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
>   */
>  void intel_hpd_init(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct drm_mode_config *mode_config = &dev->mode_config;
>  	struct drm_connector *connector;
>  	int i;
> diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
> index 81de23098be7..bef4310a305d 100644
> --- a/drivers/gpu/drm/i915/intel_i2c.c
> +++ b/drivers/gpu/drm/i915/intel_i2c.c
> @@ -138,7 +138,7 @@ static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
>  static u32 get_reserved(struct intel_gmbus *bus)
>  {
>  	struct drm_i915_private *dev_priv = bus->dev_priv;
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	u32 reserved = 0;
>  
>  	/* On most chips, these bits must be preserved in software. */
> @@ -212,7 +212,7 @@ intel_gpio_pre_xfer(struct i2c_adapter *adapter)
>  					       adapter);
>  	struct drm_i915_private *dev_priv = bus->dev_priv;
>  
> -	intel_i2c_reset(dev_priv->dev);
> +	intel_i2c_reset(&dev_priv->drm);
>  	intel_i2c_quirk_set(dev_priv, true);
>  	set_data(bus, 1);
>  	set_clock(bus, 1);
> @@ -688,7 +688,7 @@ int intel_setup_gmbus(struct drm_device *dev)
>  			goto err;
>  	}
>  
> -	intel_i2c_reset(dev_priv->dev);
> +	intel_i2c_reset(&dev_priv->drm);
>  
>  	return 0;
>  
> diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
> index 5c191a1afaaf..6ecadef8f43d 100644
> --- a/drivers/gpu/drm/i915/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/intel_lrc.c
> @@ -883,7 +883,7 @@ void intel_execlists_cancel_requests(struct intel_engine_cs *engine)
>  	struct drm_i915_gem_request *req, *tmp;
>  	LIST_HEAD(cancel_list);
>  
> -	WARN_ON(!mutex_is_locked(&engine->i915->dev->struct_mutex));
> +	WARN_ON(!mutex_is_locked(&engine->i915->drm.struct_mutex));
>  
>  	spin_lock_bh(&engine->execlist_lock);
>  	list_replace_init(&engine->execlist_queue, &cancel_list);
> @@ -942,7 +942,7 @@ static int intel_lr_context_pin(struct i915_gem_context *ctx,
>  	u32 *lrc_reg_state;
>  	int ret;
>  
> -	lockdep_assert_held(&ctx->i915->dev->struct_mutex);
> +	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
>  
>  	if (ce->pin_count++)
>  		return 0;
> @@ -992,7 +992,7 @@ void intel_lr_context_unpin(struct i915_gem_context *ctx,
>  {
>  	struct intel_context *ce = &ctx->engine[engine->id];
>  
> -	lockdep_assert_held(&ctx->i915->dev->struct_mutex);
> +	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
>  	GEM_BUG_ON(ce->pin_count == 0);
>  
>  	if (--ce->pin_count)
> @@ -1317,7 +1317,7 @@ static int lrc_setup_wa_ctx_obj(struct intel_engine_cs *engine, u32 size)
>  {
>  	int ret;
>  
> -	engine->wa_ctx.obj = i915_gem_object_create(engine->i915->dev,
> +	engine->wa_ctx.obj = i915_gem_object_create(&engine->i915->drm,
>  						   PAGE_ALIGN(size));
>  	if (IS_ERR(engine->wa_ctx.obj)) {
>  		DRM_DEBUG_DRIVER("alloc LRC WA ctx backing obj failed.\n");
> @@ -2478,7 +2478,7 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
>  	/* One extra page as the sharing data between driver and GuC */
>  	context_size += PAGE_SIZE * LRC_PPHWSP_PN;
>  
> -	ctx_obj = i915_gem_object_create(ctx->i915->dev, context_size);
> +	ctx_obj = i915_gem_object_create(&ctx->i915->drm, context_size);
>  	if (IS_ERR(ctx_obj)) {
>  		DRM_DEBUG_DRIVER("Alloc LRC backing obj failed.\n");
>  		return PTR_ERR(ctx_obj);
> diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
> index f6d8a21d2c49..08476c1e4ea4 100644
> --- a/drivers/gpu/drm/i915/intel_opregion.c
> +++ b/drivers/gpu/drm/i915/intel_opregion.c
> @@ -244,7 +244,7 @@ static int swsci(struct drm_i915_private *dev_priv,
>  		 u32 function, u32 parm, u32 *parm_out)
>  {
>  	struct opregion_swsci *swsci = dev_priv->opregion.swsci;
> -	struct pci_dev *pdev = dev_priv->dev->pdev;
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	u32 main_function, sub_function, scic;
>  	u16 swsci_val;
>  	u32 dslp;
> @@ -418,7 +418,7 @@ static u32 asle_set_backlight(struct drm_i915_private *dev_priv, u32 bclp)
>  {
>  	struct intel_connector *connector;
>  	struct opregion_asle *asle = dev_priv->opregion.asle;
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  
>  	DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
>  
> @@ -660,7 +660,7 @@ static void set_did(struct intel_opregion *opregion, int i, u32 val)
>  static void intel_didl_outputs(struct drm_i915_private *dev_priv)
>  {
>  	struct intel_opregion *opregion = &dev_priv->opregion;
> -	struct pci_dev *pdev = dev_priv->dev->pdev;
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	struct drm_connector *connector;
>  	acpi_handle handle;
>  	struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
> @@ -724,7 +724,7 @@ end:
>  
>  blind_set:
>  	i = 0;
> -	list_for_each_entry(connector, &dev_priv->dev->mode_config.connector_list, head) {
> +	list_for_each_entry(connector, &dev_priv->drm.mode_config.connector_list, head) {
>  		int output_type = ACPI_OTHER_OUTPUT;
>  		if (i >= max_outputs) {
>  			DRM_DEBUG_KMS("More than %u outputs in connector list\n",
> @@ -916,7 +916,7 @@ static const struct dmi_system_id intel_no_opregion_vbt[] = {
>  int intel_opregion_setup(struct drm_i915_private *dev_priv)
>  {
>  	struct intel_opregion *opregion = &dev_priv->opregion;
> -	struct pci_dev *pdev = dev_priv->dev->pdev;
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	u32 asls, mboxes;
>  	char buf[sizeof(OPREGION_SIGNATURE)];
>  	int err = 0;
> diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
> index eb93f90bb74d..5c83d7196a51 100644
> --- a/drivers/gpu/drm/i915/intel_overlay.c
> +++ b/drivers/gpu/drm/i915/intel_overlay.c
> @@ -409,7 +409,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
>  	struct intel_engine_cs *engine = &dev_priv->engine[RCS];
>  	int ret;
>  
> -	lockdep_assert_held(&dev_priv->dev->struct_mutex);
> +	lockdep_assert_held(&dev_priv->drm.struct_mutex);
>  
>  	/* Only wait if there is actually an old frame to release to
>  	 * guarantee forward progress.
> @@ -741,8 +741,8 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
>  	u32 swidth, swidthsw, sheight, ostride;
>  	enum pipe pipe = overlay->crtc->pipe;
>  
> -	lockdep_assert_held(&dev_priv->dev->struct_mutex);
> -	WARN_ON(!drm_modeset_is_locked(&dev_priv->dev->mode_config.connection_mutex));
> +	lockdep_assert_held(&dev_priv->drm.struct_mutex);
> +	WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
>  
>  	ret = intel_overlay_release_old_vid(overlay);
>  	if (ret != 0)
> @@ -836,7 +836,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
>  	overlay->old_vid_bo = overlay->vid_bo;
>  	overlay->vid_bo = new_bo;
>  
> -	intel_frontbuffer_flip(dev_priv->dev, INTEL_FRONTBUFFER_OVERLAY(pipe));
> +	intel_frontbuffer_flip(&dev_priv->drm, INTEL_FRONTBUFFER_OVERLAY(pipe));
>  
>  	return 0;
>  
> @@ -851,8 +851,8 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
>  	struct overlay_registers __iomem *regs;
>  	int ret;
>  
> -	lockdep_assert_held(&dev_priv->dev->struct_mutex);
> -	WARN_ON(!drm_modeset_is_locked(&dev_priv->dev->mode_config.connection_mutex));
> +	lockdep_assert_held(&dev_priv->drm.struct_mutex);
> +	WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
>  
>  	ret = intel_overlay_recover_from_interrupt(overlay);
>  	if (ret != 0)
> @@ -1379,7 +1379,7 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv)
>  	if (!overlay)
>  		return;
>  
> -	mutex_lock(&dev_priv->dev->struct_mutex);
> +	mutex_lock(&dev_priv->drm.struct_mutex);
>  	if (WARN_ON(dev_priv->overlay))
>  		goto out_free;
>  
> @@ -1387,9 +1387,9 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv)
>  
>  	reg_bo = NULL;
>  	if (!OVERLAY_NEEDS_PHYSICAL(dev_priv))
> -		reg_bo = i915_gem_object_create_stolen(dev_priv->dev, PAGE_SIZE);
> +		reg_bo = i915_gem_object_create_stolen(&dev_priv->drm, PAGE_SIZE);
>  	if (reg_bo == NULL)
> -		reg_bo = i915_gem_object_create(dev_priv->dev, PAGE_SIZE);
> +		reg_bo = i915_gem_object_create(&dev_priv->drm, PAGE_SIZE);
>  	if (IS_ERR(reg_bo))
>  		goto out_free;
>  	overlay->reg_bo = reg_bo;
> @@ -1434,7 +1434,7 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv)
>  	intel_overlay_unmap_regs(overlay, regs);
>  
>  	dev_priv->overlay = overlay;
> -	mutex_unlock(&dev_priv->dev->struct_mutex);
> +	mutex_unlock(&dev_priv->drm.struct_mutex);
>  	DRM_INFO("initialized overlay support\n");
>  	return;
>  
> @@ -1444,7 +1444,7 @@ out_unpin_bo:
>  out_free_bo:
>  	drm_gem_object_unreference(®_bo->base);
>  out_free:
> -	mutex_unlock(&dev_priv->dev->struct_mutex);
> +	mutex_unlock(&dev_priv->drm.struct_mutex);
>  	kfree(overlay);
>  	return;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index efaee7a7f933..620e4d58df8e 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -504,7 +504,7 @@ static u32 i9xx_get_backlight(struct intel_connector *connector)
>  	if (panel->backlight.combination_mode) {
>  		u8 lbpc;
>  
> -		pci_read_config_byte(dev_priv->dev->pdev, LBPC, &lbpc);
> +		pci_read_config_byte(dev_priv->drm.pdev, LBPC, &lbpc);
>  		val *= lbpc;
>  	}
>  
> @@ -592,7 +592,7 @@ static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
>  
>  		lbpc = level * 0xfe / panel->backlight.max + 1;
>  		level /= lbpc;
> -		pci_write_config_byte(dev_priv->dev->pdev, LBPC, lbpc);
> +		pci_write_config_byte(dev_priv->drm.pdev, LBPC, lbpc);
>  	}
>  
>  	if (IS_GEN4(dev_priv)) {
> @@ -822,7 +822,7 @@ void intel_panel_disable_backlight(struct intel_connector *connector)
>  	 * backlight. This will leave the backlight on unnecessarily when
>  	 * another client is not activated.
>  	 */
> -	if (dev_priv->dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
> +	if (dev_priv->drm.switch_power_state == DRM_SWITCH_POWER_CHANGING) {
>  		DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
>  		return;
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index b6dfd0264950..e96ab1c81bf9 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -294,7 +294,7 @@ static void chv_set_memory_pm5(struct drm_i915_private *dev_priv, bool enable)
>  
>  void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	u32 val;
>  
>  	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
> @@ -2211,7 +2211,7 @@ static void intel_print_wm_latency(struct drm_device *dev,
>  static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv,
>  				    uint16_t wm[5], uint16_t min)
>  {
> -	int level, max_level = ilk_wm_max_level(dev_priv->dev);
> +	int level, max_level = ilk_wm_max_level(&dev_priv->drm);
>  
>  	if (wm[0] >= min)
>  		return false;
> @@ -2740,7 +2740,7 @@ static bool _ilk_disable_lp_wm(struct drm_i915_private *dev_priv,
>  static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
>  				struct ilk_wm_values *results)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct ilk_wm_values *previous = &dev_priv->wm.hw;
>  	unsigned int dirty;
>  	uint32_t val;
> @@ -3336,13 +3336,13 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
>  }
>  
>  static int
> -skl_compute_wm_level(const struct drm_i915_private *dev_priv,
> +skl_compute_wm_level(struct drm_i915_private *dev_priv,
>  		     struct skl_ddb_allocation *ddb,
>  		     struct intel_crtc_state *cstate,
>  		     int level,
>  		     struct skl_wm_level *result)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct drm_atomic_state *state = cstate->base.state;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
>  	struct drm_plane *plane;
> @@ -3439,7 +3439,7 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate,
>  			     struct skl_pipe_wm *pipe_wm)
>  {
>  	struct drm_device *dev = cstate->base.crtc->dev;
> -	const struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int level, max_level = ilk_wm_max_level(dev);
>  	int ret;
>  
> @@ -3526,7 +3526,7 @@ static void skl_ddb_entry_write(struct drm_i915_private *dev_priv,
>  static void skl_write_wm_values(struct drm_i915_private *dev_priv,
>  				const struct skl_wm_values *new)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct intel_crtc *crtc;
>  
>  	for_each_intel_crtc(dev, crtc) {
> @@ -3623,7 +3623,7 @@ skl_ddb_allocation_included(const struct skl_ddb_allocation *old,
>  static void skl_flush_wm_values(struct drm_i915_private *dev_priv,
>  				struct skl_wm_values *new_values)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct skl_ddb_allocation *cur_ddb, *new_ddb;
>  	bool reallocated[I915_MAX_PIPES] = {};
>  	struct intel_crtc *crtc;
> @@ -3887,7 +3887,7 @@ static void ilk_compute_wm_config(struct drm_device *dev,
>  
>  static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
>  	struct ilk_wm_maximums max;
>  	struct intel_wm_config config = {};
> @@ -5505,7 +5505,7 @@ static void valleyview_setup_pctx(struct drm_i915_private *dev_priv)
>  	u32 pcbr;
>  	int pctx_size = 24*1024;
>  
> -	mutex_lock(&dev_priv->dev->struct_mutex);
> +	mutex_lock(&dev_priv->drm.struct_mutex);
>  
>  	pcbr = I915_READ(VLV_PCBR);
>  	if (pcbr) {
> @@ -5513,7 +5513,7 @@ static void valleyview_setup_pctx(struct drm_i915_private *dev_priv)
>  		int pcbr_offset;
>  
>  		pcbr_offset = (pcbr & (~4095)) - dev_priv->mm.stolen_base;
> -		pctx = i915_gem_object_create_stolen_for_preallocated(dev_priv->dev,
> +		pctx = i915_gem_object_create_stolen_for_preallocated(&dev_priv->drm,
>  								      pcbr_offset,
>  								      I915_GTT_OFFSET_NONE,
>  								      pctx_size);
> @@ -5530,7 +5530,7 @@ static void valleyview_setup_pctx(struct drm_i915_private *dev_priv)
>  	 * overlap with other ranges, such as the frame buffer, protected
>  	 * memory, or any other relevant ranges.
>  	 */
> -	pctx = i915_gem_object_create_stolen(dev_priv->dev, pctx_size);
> +	pctx = i915_gem_object_create_stolen(&dev_priv->drm, pctx_size);
>  	if (!pctx) {
>  		DRM_DEBUG("not enough stolen space for PCTX, disabling\n");
>  		goto out;
> @@ -5542,7 +5542,7 @@ static void valleyview_setup_pctx(struct drm_i915_private *dev_priv)
>  out:
>  	DRM_DEBUG_DRIVER("PCBR: 0x%08x\n", I915_READ(VLV_PCBR));
>  	dev_priv->vlv_pctx = pctx;
> -	mutex_unlock(&dev_priv->dev->struct_mutex);
> +	mutex_unlock(&dev_priv->drm.struct_mutex);
>  }
>  
>  static void valleyview_cleanup_pctx(struct drm_i915_private *dev_priv)
> @@ -6486,9 +6486,9 @@ void intel_enable_gt_powersave(struct drm_i915_private *dev_priv)
>  
>  	if (IS_IRONLAKE_M(dev_priv)) {
>  		ironlake_enable_drps(dev_priv);
> -		mutex_lock(&dev_priv->dev->struct_mutex);
> +		mutex_lock(&dev_priv->drm.struct_mutex);
>  		intel_init_emon(dev_priv);
> -		mutex_unlock(&dev_priv->dev->struct_mutex);
> +		mutex_unlock(&dev_priv->drm.struct_mutex);
>  	} else if (INTEL_INFO(dev_priv)->gen >= 6) {
>  		/*
>  		 * PCU communication is slow and this doesn't need to be
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
> index 8d35a3978f9b..17c55e3bf346 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.c
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
> @@ -665,7 +665,7 @@ intel_init_pipe_control(struct intel_engine_cs *engine)
>  
>  	WARN_ON(engine->scratch.obj);
>  
> -	engine->scratch.obj = i915_gem_object_create(engine->i915->dev, 4096);
> +	engine->scratch.obj = i915_gem_object_create(&engine->i915->drm, 4096);
>  	if (IS_ERR(engine->scratch.obj)) {
>  		DRM_ERROR("Failed to allocate seqno page\n");
>  		ret = PTR_ERR(engine->scratch.obj);
> @@ -2012,7 +2012,7 @@ static void cleanup_phys_status_page(struct intel_engine_cs *engine)
>  	if (!dev_priv->status_page_dmah)
>  		return;
>  
> -	drm_pci_free(dev_priv->dev, dev_priv->status_page_dmah);
> +	drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah);
>  	engine->status_page.page_addr = NULL;
>  }
>  
> @@ -2038,7 +2038,7 @@ static int init_status_page(struct intel_engine_cs *engine)
>  		unsigned flags;
>  		int ret;
>  
> -		obj = i915_gem_object_create(engine->i915->dev, 4096);
> +		obj = i915_gem_object_create(&engine->i915->drm, 4096);
>  		if (IS_ERR(obj)) {
>  			DRM_ERROR("Failed to allocate status page\n");
>  			return PTR_ERR(obj);
> @@ -2087,7 +2087,7 @@ static int init_phys_status_page(struct intel_engine_cs *engine)
>  
>  	if (!dev_priv->status_page_dmah) {
>  		dev_priv->status_page_dmah =
> -			drm_pci_alloc(dev_priv->dev, PAGE_SIZE, PAGE_SIZE);
> +			drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE);
>  		if (!dev_priv->status_page_dmah)
>  			return -ENOMEM;
>  	}
> @@ -2220,7 +2220,7 @@ intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size)
>  	ring->last_retired_head = -1;
>  	intel_ring_update_space(ring);
>  
> -	ret = intel_alloc_ringbuffer_obj(engine->i915->dev, ring);
> +	ret = intel_alloc_ringbuffer_obj(&engine->i915->drm, ring);
>  	if (ret) {
>  		DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n",
>  				 engine->name, ret);
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index fe8faf30bda7..742467b84ccd 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -267,7 +267,7 @@ void intel_display_set_init_power(struct drm_i915_private *dev_priv,
>   */
>  static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  
>  	/*
>  	 * After we re-enable the power well, if we touch VGA register 0x3d5
> @@ -298,7 +298,7 @@ static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv)
>  static void skl_power_well_post_enable(struct drm_i915_private *dev_priv,
>  				       struct i915_power_well *power_well)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  
>  	/*
>  	 * After we re-enable the power well, if we touch VGA register 0x3d5
> @@ -821,7 +821,7 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
>  	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
>  
>  	WARN_ON(dev_priv->cdclk_freq !=
> -		dev_priv->display.get_display_clock_speed(dev_priv->dev));
> +		dev_priv->display.get_display_clock_speed(&dev_priv->drm));
>  
>  	gen9_assert_dbuf_enabled(dev_priv);
>  
> @@ -979,7 +979,7 @@ static void vlv_display_power_well_init(struct drm_i915_private *dev_priv)
>  	 *
>  	 * CHV DPLL B/C have some issues if VGA mode is enabled.
>  	 */
> -	for_each_pipe(dev_priv->dev, pipe) {
> +	for_each_pipe(&dev_priv->drm, pipe) {
>  		u32 val = I915_READ(DPLL(pipe));
>  
>  		val |= DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
> @@ -1004,7 +1004,7 @@ static void vlv_display_power_well_init(struct drm_i915_private *dev_priv)
>  
>  	intel_hpd_init(dev_priv);
>  
> -	i915_redisable_vga_power_on(dev_priv->dev);
> +	i915_redisable_vga_power_on(&dev_priv->drm);
>  }
>  
>  static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv)
> @@ -1014,7 +1014,7 @@ static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv)
>  	spin_unlock_irq(&dev_priv->irq_lock);
>  
>  	/* make sure we're done processing display irqs */
> -	synchronize_irq(dev_priv->dev->irq);
> +	synchronize_irq(dev_priv->drm.irq);
>  
>  	vlv_power_sequencer_reset(dev_priv);
>  }
> @@ -2148,7 +2148,7 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
>   */
>  void intel_power_domains_fini(struct drm_i915_private *dev_priv)
>  {
> -	struct device *device = &dev_priv->dev->pdev->dev;
> +	struct device *device = &dev_priv->drm.pdev->dev;
>  
>  	/*
>  	 * The i915.ko module is still not prepared to be loaded when
> @@ -2454,7 +2454,7 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
>   */
>  void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct i915_power_domains *power_domains = &dev_priv->power_domains;
>  
>  	power_domains->initializing = true;
> @@ -2516,7 +2516,7 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv)
>   */
>  void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct device *device = &dev->pdev->dev;
>  
>  	pm_runtime_get_sync(device);
> @@ -2537,7 +2537,7 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
>   */
>  bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct device *device = &dev->pdev->dev;
>  
>  	if (IS_ENABLED(CONFIG_PM)) {
> @@ -2579,7 +2579,7 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
>   */
>  void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct device *device = &dev->pdev->dev;
>  
>  	assert_rpm_wakelock_held(dev_priv);
> @@ -2598,7 +2598,7 @@ void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
>   */
>  void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct device *device = &dev->pdev->dev;
>  
>  	assert_rpm_wakelock_held(dev_priv);
> @@ -2621,7 +2621,7 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
>   */
>  void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
> +	struct drm_device *dev = &dev_priv->drm;
>  	struct device *device = &dev->pdev->dev;
>  
>  	pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index b83ad62c1273..3aee03e0b178 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -1471,7 +1471,7 @@ static void intel_disable_sdvo(struct intel_encoder *encoder)
>  		temp &= ~SDVO_ENABLE;
>  		intel_sdvo_write_sdvox(intel_sdvo, temp);
>  
> -		intel_wait_for_vblank_if_active(dev_priv->dev, PIPE_A);
> +		intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A);
>  		intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
>  		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
> index c1ca458d688e..58ac3f975180 100644
> --- a/drivers/gpu/drm/i915/intel_uncore.c
> +++ b/drivers/gpu/drm/i915/intel_uncore.c
> @@ -1469,7 +1469,7 @@ static int i915_reset_complete(struct pci_dev *pdev)
>  
>  static int i915_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask)
>  {
> -	struct pci_dev *pdev = dev_priv->dev->pdev;
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
>  
>  	/* assert reset for at least 20 usec */
>  	pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE);
> @@ -1488,14 +1488,14 @@ static int g4x_reset_complete(struct pci_dev *pdev)
>  
>  static int g33_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask)
>  {
> -	struct pci_dev *pdev = dev_priv->dev->pdev;
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE);
>  	return wait_for(g4x_reset_complete(pdev), 500);
>  }
>  
>  static int g4x_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask)
>  {
> -	struct pci_dev *pdev = dev_priv->dev->pdev;
> +	struct pci_dev *pdev = dev_priv->drm.pdev;
>  	int ret;
>  
>  	pci_write_config_byte(pdev, I915_GDRST,
-- 
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 11/11] drm/i915: Move module init/exit to i915_pci.c
  2016-05-30  6:44   ` Joonas Lahtinen
@ 2016-05-30  7:55     ` Chris Wilson
  0 siblings, 0 replies; 28+ messages in thread
From: Chris Wilson @ 2016-05-30  7:55 UTC (permalink / raw)
  To: Joonas Lahtinen; +Cc: Daniel Vetter, intel-gfx

On Mon, May 30, 2016 at 09:44:34AM +0300, Joonas Lahtinen wrote:
> On pe, 2016-05-27 at 15:00 +0100, Chris Wilson wrote:
> > The module init/exit routines are a wrapper around the PCI device
> > init/exit, so move them across.
> > 
> 
> This is not a simple move operation (i915_init), this should be noted
> in the commit message or preferably split into two commits, first move,
> then restructure.

It can't be simply moved due to the static driver that I don't want
to export. When atomic is complete we can get back to a rodata driver.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] drm/i915: Remove drm_i915_private->dev backpointer
  2016-05-30  6:58       ` Joonas Lahtinen
@ 2016-05-30  8:21         ` Chris Wilson
  0 siblings, 0 replies; 28+ messages in thread
From: Chris Wilson @ 2016-05-30  8:21 UTC (permalink / raw)
  To: Joonas Lahtinen; +Cc: intel-gfx

On Mon, May 30, 2016 at 09:58:15AM +0300, Joonas Lahtinen wrote:
> On pe, 2016-05-27 at 15:46 +0100, Chris Wilson wrote:
> > Now that drm_i915_private contains drm_device, we can directly go to the
> > drm_device as required:
> > 
> >    text	   data	    bss	    dec	    hex	filename
> > 1105153	  23207	    416	1128776	 113948	i915.ko (before)
> > 1102849	  23207	    416	1126472	 113048	i915.ko (after)
> > 
> > s/dev_priv->dev->/dev_priv->drm./
> > s/dev_priv->dev/\&dev_priv->drm./
> 
> Lose the dot from last replaement pattern, and I'm also pretty sure \
> is not needed in front of &

It's a vim sed line, since I was working inside vim checking the
results. (Hand copied, hence the extra .)

A bigger change that I think Dave Gordon has the coccinelle scripts for
is s/dev->dev_private/to_i915(dev)/ . We still have something like 600
sites that we can fix up.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 02/11] drm: Add a callback from connector registering
  2016-05-27 14:00 ` [PATCH 02/11] drm: Add a callback from connector registering Chris Wilson
@ 2016-05-30  8:49   ` Daniel Vetter
  2016-05-30  8:57     ` Chris Wilson
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Vetter @ 2016-05-30  8:49 UTC (permalink / raw)
  To: Chris Wilson; +Cc: Daniel Vetter, intel-gfx, dri-devel

On Fri, May 27, 2016 at 03:00:35PM +0100, Chris Wilson wrote:
> If a driver wants to more precisely control its initialisation and in
> particular, defer registering its interfaces with userspace until after
> everything is setup, it also needs to defer registering the connectors.
> As some devices need more work during registration, add a callback so
> that drivers can do additional work if required for a connector.
> 
> Correspondingly, we also require an unregister callback.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: dri-devel@lists.freedesktop.org

Smells a bit too much like midlayer too me ;-) Imo perfectly fine to have
a driver loop besides the register_all which registers stuff like
backlights and similar things. But otoh this is a bit a high-grade
bikeshed ...
-Daniel

> ---
>  drivers/gpu/drm/drm_crtc.c | 18 ++++++++++++++++--
>  include/drm/drm_crtc.h     | 21 +++++++++++++++++++++
>  2 files changed, 37 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index d2a6d958ca76..81641544ac3e 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -1036,13 +1036,24 @@ int drm_connector_register(struct drm_connector *connector)
>  
>  	ret = drm_debugfs_connector_add(connector);
>  	if (ret) {
> -		drm_sysfs_connector_remove(connector);
> -		return ret;
> +		goto err_sysfs;
> +	}
> +
> +	if (connector->funcs->late_register) {
> +		ret = connector->funcs->late_register(connector);
> +		if (ret)
> +			goto err_debugfs;
>  	}
>  
>  	drm_mode_object_register(connector->dev, &connector->base);
>  
>  	return 0;
> +
> +err_debugfs:
> +	drm_debugfs_connector_remove(connector);
> +err_sysfs:
> +	drm_sysfs_connector_remove(connector);
> +	return ret;
>  }
>  EXPORT_SYMBOL(drm_connector_register);
>  
> @@ -1054,6 +1065,9 @@ EXPORT_SYMBOL(drm_connector_register);
>   */
>  void drm_connector_unregister(struct drm_connector *connector)
>  {
> +	if (connector->funcs->early_unregister)
> +		connector->funcs->early_unregister(connector);
> +
>  	drm_sysfs_connector_remove(connector);
>  	drm_debugfs_connector_remove(connector);
>  }
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index d1559cd04e3d..0f7425444a44 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -926,6 +926,27 @@ struct drm_connector_funcs {
>  			     uint64_t val);
>  
>  	/**
> +	 * @late_register:
> +	 *
> +	 * Register the connector with userspace, called from
> +	 * drm_connector_register. This should be called after driver
> +	 * load during its registration phase. All actions such as registering
> +	 * with auxiliary devices (such as drm_dp_aux_register) should be done
> +	 * during this callback.
> +	 */
> +	int (*late_register)(struct drm_connector *connector);
> +
> +	/**
> +	 * @early_unregister:
> +	 *
> +	 * Unregister the connector with userspace, called from
> +	 * drm_connector_unregister. This is called early in the driver
> +	 * unload sequence to disable userspace access before data
> +	 * structures are torndown.
> +	 */
> +	void (*early_unregister)(struct drm_connector *connector);
> +
> +	/**
>  	 * @destroy:
>  	 *
>  	 * Clean up connector resources. This is called at driver unload time
> -- 
> 2.8.1
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 02/11] drm: Add a callback from connector registering
  2016-05-30  8:49   ` Daniel Vetter
@ 2016-05-30  8:57     ` Chris Wilson
  0 siblings, 0 replies; 28+ messages in thread
From: Chris Wilson @ 2016-05-30  8:57 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, intel-gfx, dri-devel

On Mon, May 30, 2016 at 10:49:43AM +0200, Daniel Vetter wrote:
> On Fri, May 27, 2016 at 03:00:35PM +0100, Chris Wilson wrote:
> > If a driver wants to more precisely control its initialisation and in
> > particular, defer registering its interfaces with userspace until after
> > everything is setup, it also needs to defer registering the connectors.
> > As some devices need more work during registration, add a callback so
> > that drivers can do additional work if required for a connector.
> > 
> > Correspondingly, we also require an unregister callback.
> > 
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: dri-devel@lists.freedesktop.org
> 
> Smells a bit too much like midlayer too me ;-) Imo perfectly fine to have
> a driver loop besides the register_all which registers stuff like
> backlights and similar things. But otoh this is a bit a high-grade
> bikeshed ...

We either:

intel_connector_register()
{
	drm_connector_register()
	intel_connector->register();
}

intel_connector_unregister()
{
	intel_connector->unregister();
	drm_connector_unregister()
}

or

drm_connector_register()
{
	/*blah*/
	connector->func->register();
}

drm_connector_unregister()
{
	connector->func->unregister();
	/*blah*/
}

We still get to drive the registration (hence why it doesn't smell too
much like midlayer just a vfunc wrapper), just the second is a tad more
generic and we aren't the only ones who require the calback.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2016-05-30  8:57 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-27 14:00 Reordering debugfs registration vs driver loading Chris Wilson
2016-05-27 14:00 ` [PATCH 01/11] drm: Export drm_dev_init() for subclassing Chris Wilson
2016-05-27 15:29   ` Nils Wallménius
2016-05-27 15:36     ` Chris Wilson
2016-05-27 15:54       ` Emil Velikov
2016-05-27 16:08         ` [Intel-gfx] " Chris Wilson
2016-05-27 16:11           ` Emil Velikov
2016-05-27 14:00 ` [PATCH 02/11] drm: Add a callback from connector registering Chris Wilson
2016-05-30  8:49   ` Daniel Vetter
2016-05-30  8:57     ` Chris Wilson
2016-05-27 14:00 ` [PATCH 03/11] drm/i915: Perform async fbdev initialisation much later Chris Wilson
2016-05-27 14:00 ` [PATCH 04/11] drm/i915: Move connector registration to driver registration phase Chris Wilson
2016-05-27 14:00 ` [PATCH 05/11] drm/i915: Register debugfs interface last Chris Wilson
2016-05-27 14:00 ` [PATCH 06/11] drm/i915: Demidlayer driver loading Chris Wilson
2016-05-27 14:00 ` [PATCH 07/11] drm/i915: Demidlayer driver unloading Chris Wilson
2016-05-27 14:00 ` [PATCH 08/11] drm/i915: Start exploiting drm_device subclassing Chris Wilson
2016-05-27 14:15   ` Tvrtko Ursulin
2016-05-27 14:46     ` [PATCH] drm/i915: Remove drm_i915_private->dev backpointer Chris Wilson
2016-05-30  6:58       ` Joonas Lahtinen
2016-05-30  8:21         ` Chris Wilson
2016-05-27 14:00 ` [PATCH 09/11] drm/i915: Merge i915_dma.c into i915_drv.c Chris Wilson
2016-05-30  6:30   ` Joonas Lahtinen
2016-05-27 14:00 ` [PATCH 10/11] drm/i915: Split out the PCI driver interface to i915_pci.c Chris Wilson
2016-05-30  6:36   ` Joonas Lahtinen
2016-05-27 14:00 ` [PATCH 11/11] drm/i915: Move module init/exit " Chris Wilson
2016-05-30  6:44   ` Joonas Lahtinen
2016-05-30  7:55     ` Chris Wilson
2016-05-27 14:58 ` ✗ Ro.CI.BAT: failure for series starting with [01/11] drm: Export drm_dev_init() for subclassing (rev2) Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.