diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 90e47a9..8d6deaa 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -667,6 +667,12 @@ struct intel_uncore {
 #define for_each_fw_domain(domain__, dev_priv__, i__) \
 	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
 
+enum csr_states {
+	FW_LOADED = 0,
+	FW_LOADING,
+	FW_FAILED
+};
+
 struct intel_csr {
 	const char *fw_path;
 	__be32 *dmc_payload;
@@ -674,6 +680,7 @@ struct intel_csr {
 	uint32_t mmio_count;
 	uint32_t mmioaddr[8];
 	uint32_t mmiodata[8];
+	enum csr_states states;
 };
 
 #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
index ab9b16b..6d08a41 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -49,6 +49,25 @@ static char intel_get_substepping(struct drm_device *dev)
 	else
 		return -ENODATA;
 }
+
+bool intel_csr_load_status_get(struct drm_i915_private *dev_priv)
+{
+	bool val = false;
+
+	mutex_lock(&dev_priv->csr_lock);
+	val = dev_priv->csr.states;
+	mutex_unlock(&dev_priv->csr_lock);
+
+	return val;
+}
+
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val)
+{
+	mutex_lock(&dev_priv->csr_lock);
+	dev_priv->csr.states = val;
+	mutex_unlock(&dev_priv->csr_lock);
+}
+
 void intel_csr_load_program(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -71,6 +90,8 @@ void intel_csr_load_program(struct drm_device *dev)
 		I915_WRITE(dev_priv->csr.mmioaddr[i],
 			dev_priv->csr.mmiodata[i]);
 	}
+
+	intel_csr_load_status_set(dev_priv, FW_LOADED);
 	mutex_unlock(&dev_priv->csr_lock);
 }
 
@@ -90,11 +111,13 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 
 	if (!fw) {
 		i915_firmware_load_error_print(csr->fw_path, 0);
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 
 	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
 		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 
@@ -104,6 +127,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 		(css_header->header_len * 4)) {
 		DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
 			(css_header->header_len * 4));
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 	readcount += sizeof(struct intel_css_header);
@@ -115,6 +139,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 		(package_header->header_len * 4)) {
 		DRM_ERROR("Firmware has wrong package header length %u bytes\n",
 			(package_header->header_len * 4));
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 	readcount += sizeof(struct intel_package_header);
@@ -135,6 +160,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	}
 	if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
 		DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 	readcount += dmc_offset;
@@ -144,6 +170,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
 		DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
 				(dmc_header->header_len));
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 	readcount += sizeof(struct intel_dmc_header);
@@ -152,6 +179,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
 		DRM_ERROR("Firmware has wrong mmio count %u\n",
 						dmc_header->mmio_count);
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 	csr->mmio_count = dmc_header->mmio_count;
@@ -160,6 +188,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 			dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
 			DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
 						dmc_header->mmioaddr[i]);
+			intel_csr_load_status_set(dev_priv, FW_FAILED);
 			goto out;
 		}
 		csr->mmioaddr[i] = dmc_header->mmioaddr[i];
@@ -170,6 +199,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	nbytes = dmc_header->fw_size * 4;
 	if (nbytes > CSR_MAX_FW_SIZE) {
 		DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 	csr->dmc_fw_size = dmc_header->fw_size;
@@ -177,6 +207,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL);
 	if (!csr->dmc_payload) {
 		DRM_ERROR("Memory allocation failed for dmc payload\n");
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 
@@ -194,6 +225,11 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	/* load csr program during system boot, as needed for DC states */
 	intel_csr_load_program(dev);
 out:
+	/*
+	 * Release the runtime pm reference obtained when
+	 * CSR wasn't loaded.
+	 */
+	intel_runtime_pm_put(dev_priv);
 	release_firmware(fw);
 }
 
@@ -210,17 +246,27 @@ void intel_csr_ucode_init(struct drm_device *dev)
 		csr->fw_path = I915_CSR_SKL;
 	else {
 		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		return;
 	}
 
+	/*
+	 * Obtain a runtime pm reference, until CSR is loaded,
+	 * to avoid entering runtime-suspend.
+	 */
+	intel_runtime_pm_get(dev_priv);
+
+	intel_csr_load_status_set(dev_priv, FW_LOADING);
+
 	/* CSR supported for platform, load firmware */
 	ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
 				&dev_priv->dev->pdev->dev,
 				GFP_KERNEL, dev_priv,
 				finish_csr_load);
-	if (ret)
+	if (ret) {
 		i915_firmware_load_error_print(csr->fw_path, ret);
-
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
+	}
 }
 
 void intel_csr_ucode_fini(struct drm_device *dev)
@@ -230,5 +276,6 @@ void intel_csr_ucode_fini(struct drm_device *dev)
 	if (!HAS_CSR(dev))
 		return;
 
+	intel_csr_load_status_set(dev_priv, FW_FAILED);
 	kfree(dev_priv->csr.dmc_payload);
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f3a2d88..3fc2473 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1064,6 +1064,8 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
 
 /* intel_csr.c */
 void intel_csr_ucode_init(struct drm_device *dev);
+bool intel_csr_load_status_get(struct drm_i915_private *dev_priv);
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val);
 void intel_csr_load_program(struct drm_device *dev);
 void intel_csr_ucode_fini(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index bc6cee9..0750191 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -49,6 +49,8 @@
  * present for a given platform.
  */
 
+#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev))
+
 #define for_each_power_well(i, power_well, domain_mask, power_domains)	\
 	for (i = 0;							\
 	     i < (power_domains)->power_well_count &&			\
@@ -369,6 +371,7 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
 static void skl_set_power_well(struct drm_i915_private *dev_priv,
 			struct i915_power_well *power_well, bool enable)
 {
+	struct drm_device *dev = dev_priv->dev;
 	uint32_t tmp, fuse_status;
 	uint32_t req_mask, state_mask;
 	bool is_enabled, enable_requested, check_fuse_status = false;
@@ -408,6 +411,13 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
 
 	if (enable) {
 		if (!enable_requested) {
+			WARN((tmp & state_mask) &&
+				!I915_READ(HSW_PWR_WELL_BIOS),
+				"Invalid for power well status to be enabled, unless done by the BIOS, \
+				when request is to disable!\n");
+			if (GEN9_ENABLE_DC5(dev) &&
+				power_well->data == SKL_DISP_PW_2)
+				gen9_disable_dc5(dev_priv);
 			I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
 		}
 
@@ -424,6 +434,25 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
 			I915_WRITE(HSW_PWR_WELL_DRIVER,	tmp & ~req_mask);
 			POSTING_READ(HSW_PWR_WELL_DRIVER);
 			DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
+
+			if (GEN9_ENABLE_DC5(dev) &&
+				power_well->data == SKL_DISP_PW_2) {
+				if (dev_priv->csr.states <= FW_LOADING) {
+					/*
+					* TODO: wait for a completion event or
+					* similar here instead of busy
+					* waiting using wait_for function.
+					*/
+					if (wait_for(
+						intel_csr_load_status_get(
+							dev_priv), 1000))
+						DRM_ERROR("Timed out waiting for CSR to be loaded!");
+					else
+						gen9_enable_dc5(dev_priv);
+				} else {
+					DRM_ERROR("Cannot enable DC5 as CSR failed to load!");
+				}
+			}
 		}
 	}
 
