summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_drv.c')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c194
1 files changed, 104 insertions, 90 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index f8cfd16be534..5dd7fc582e6f 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -373,7 +373,7 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data,
value = 2;
break;
case I915_PARAM_HAS_RESOURCE_STREAMER:
- value = HAS_RESOURCE_STREAMER(dev_priv);
+ value = 0;
break;
case I915_PARAM_HAS_POOLED_EU:
value = HAS_POOLED_EU(dev_priv);
@@ -441,6 +441,9 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data,
case I915_PARAM_CS_TIMESTAMP_FREQUENCY:
value = 1000 * INTEL_INFO(dev_priv)->cs_timestamp_frequency_khz;
break;
+ case I915_PARAM_MMAP_GTT_COHERENT:
+ value = INTEL_INFO(dev_priv)->has_coherent_ggtt;
+ break;
default:
DRM_DEBUG("Unknown parameter %d\n", param->param);
return -EINVAL;
@@ -709,7 +712,7 @@ cleanup_irq:
intel_teardown_gmbus(dev_priv);
cleanup_csr:
intel_csr_ucode_fini(dev_priv);
- intel_power_domains_fini(dev_priv);
+ intel_power_domains_fini_hw(dev_priv);
vga_switcheroo_unregister_client(pdev);
cleanup_vga_client:
vga_client_register(pdev, NULL, NULL, NULL);
@@ -867,7 +870,6 @@ static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv)
/**
* i915_driver_init_early - setup state not requiring device access
* @dev_priv: device private
- * @ent: the matching pci_device_id
*
* Initialize everything that is a "SW-only" state, that is state not
* requiring accessing the device or exposing the driver via kernel internal
@@ -875,25 +877,13 @@ static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv)
* 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)
+static int i915_driver_init_early(struct drm_i915_private *dev_priv)
{
- 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 = mkwrite_device_info(dev_priv);
- memcpy(device_info, match_info, sizeof(*device_info));
- device_info->device_id = dev_priv->drm.pdev->device;
-
- BUILD_BUG_ON(INTEL_MAX_PLATFORMS >
- sizeof(device_info->platform_mask) * BITS_PER_BYTE);
- BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE);
spin_lock_init(&dev_priv->irq_lock);
spin_lock_init(&dev_priv->gpu_error.lock);
mutex_init(&dev_priv->backlight_lock);
@@ -921,7 +911,9 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
intel_uc_init_early(dev_priv);
intel_pm_setup(dev_priv);
intel_init_dpio(dev_priv);
- intel_power_domains_init(dev_priv);
+ ret = intel_power_domains_init(dev_priv);
+ if (ret < 0)
+ goto err_uc;
intel_irq_init(dev_priv);
intel_hangcheck_init(dev_priv);
intel_init_display_hooks(dev_priv);
@@ -933,6 +925,9 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
return 0;
+err_uc:
+ intel_uc_cleanup_early(dev_priv);
+ i915_gem_cleanup_early(dev_priv);
err_workqueues:
i915_workqueues_cleanup(dev_priv);
err_engines:
@@ -947,6 +942,7 @@ err_engines:
static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
{
intel_irq_fini(dev_priv);
+ intel_power_domains_cleanup(dev_priv);
intel_uc_cleanup_early(dev_priv);
i915_gem_cleanup_early(dev_priv);
i915_workqueues_cleanup(dev_priv);
@@ -1272,6 +1268,9 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
*/
if (INTEL_INFO(dev_priv)->num_pipes)
drm_kms_helper_poll_init(dev);
+
+ intel_power_domains_enable(dev_priv);
+ intel_runtime_pm_enable(dev_priv);
}
/**
@@ -1280,6 +1279,9 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
*/
static void i915_driver_unregister(struct drm_i915_private *dev_priv)
{
+ intel_runtime_pm_disable(dev_priv);
+ intel_power_domains_disable(dev_priv);
+
intel_fbdev_unregister(dev_priv);
intel_audio_deinit(dev_priv);
@@ -1316,6 +1318,52 @@ static void i915_welcome_messages(struct drm_i915_private *dev_priv)
DRM_INFO("DRM_I915_DEBUG enabled\n");
if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
DRM_INFO("DRM_I915_DEBUG_GEM enabled\n");
+ if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM))
+ DRM_INFO("DRM_I915_DEBUG_RUNTIME_PM enabled\n");
+}
+
+static struct drm_i915_private *
+i915_driver_create(struct pci_dev *pdev, 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;
+ struct drm_i915_private *i915;
+
+ i915 = kzalloc(sizeof(*i915), GFP_KERNEL);
+ if (!i915)
+ return NULL;
+
+ if (drm_dev_init(&i915->drm, &driver, &pdev->dev)) {
+ kfree(i915);
+ return NULL;
+ }
+
+ i915->drm.pdev = pdev;
+ i915->drm.dev_private = i915;
+ pci_set_drvdata(pdev, &i915->drm);
+
+ /* Setup the write-once "constant" device info */
+ device_info = mkwrite_device_info(i915);
+ memcpy(device_info, match_info, sizeof(*device_info));
+ device_info->device_id = pdev->device;
+
+ BUILD_BUG_ON(INTEL_MAX_PLATFORMS >
+ sizeof(device_info->platform_mask) * BITS_PER_BYTE);
+ BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE);
+
+ return i915;
+}
+
+static void i915_driver_destroy(struct drm_i915_private *i915)
+{
+ struct pci_dev *pdev = i915->drm.pdev;
+
+ drm_dev_fini(&i915->drm);
+ kfree(i915);
+
+ /* And make sure we never chase our dangling pointer from pci_dev */
+ pci_set_drvdata(pdev, NULL);
}
/**
@@ -1340,38 +1388,19 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!i915_modparams.nuclear_pageflip && match_info->gen < 5)
driver.driver_features &= ~DRIVER_ATOMIC;
- ret = -ENOMEM;
- dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
- if (dev_priv)
- ret = drm_dev_init(&dev_priv->drm, &driver, &pdev->dev);
- if (ret) {
- DRM_DEV_ERROR(&pdev->dev, "allocation failed\n");
- goto out_free;
- }
-
- dev_priv->drm.pdev = pdev;
- dev_priv->drm.dev_private = dev_priv;
+ dev_priv = i915_driver_create(pdev, ent);
+ if (!dev_priv)
+ return -ENOMEM;
ret = pci_enable_device(pdev);
if (ret)
goto out_fini;
- pci_set_drvdata(pdev, &dev_priv->drm);
- /*
- * Disable the system suspend direct complete optimization, which can
- * leave the device suspended skipping the driver's suspend handlers
- * if the device was already runtime suspended. This is needed due to
- * the difference in our runtime and system suspend sequence and
- * becaue the HDA driver may require us to enable the audio power
- * domain during system suspend.
- */
- dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NEVER_SKIP);
-
- ret = i915_driver_init_early(dev_priv, ent);
+ ret = i915_driver_init_early(dev_priv);
if (ret < 0)
goto out_pci_disable;
- intel_runtime_pm_get(dev_priv);
+ disable_rpm_wakeref_asserts(dev_priv);
ret = i915_driver_init_mmio(dev_priv);
if (ret < 0)
@@ -1399,11 +1428,9 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
i915_driver_register(dev_priv);
- intel_runtime_pm_enable(dev_priv);
-
intel_init_ipc(dev_priv);
- intel_runtime_pm_put(dev_priv);
+ enable_rpm_wakeref_asserts(dev_priv);
i915_welcome_messages(dev_priv);
@@ -1414,16 +1441,13 @@ out_cleanup_hw:
out_cleanup_mmio:
i915_driver_cleanup_mmio(dev_priv);
out_runtime_pm_put:
- intel_runtime_pm_put(dev_priv);
+ enable_rpm_wakeref_asserts(dev_priv);
i915_driver_cleanup_early(dev_priv);
out_pci_disable:
pci_disable_device(pdev);
out_fini:
i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret);
- drm_dev_fini(&dev_priv->drm);
-out_free:
- kfree(dev_priv);
- pci_set_drvdata(pdev, NULL);
+ i915_driver_destroy(dev_priv);
return ret;
}
@@ -1432,13 +1456,13 @@ void i915_driver_unload(struct drm_device *dev)
struct drm_i915_private *dev_priv = to_i915(dev);
struct pci_dev *pdev = dev_priv->drm.pdev;
+ disable_rpm_wakeref_asserts(dev_priv);
+
i915_driver_unregister(dev_priv);
if (i915_gem_suspend(dev_priv))
DRM_ERROR("failed to idle hardware; continuing to unload!\n");
- intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
-
drm_atomic_helper_shutdown(dev);
intel_gvt_cleanup(dev_priv);
@@ -1459,12 +1483,14 @@ void i915_driver_unload(struct drm_device *dev)
i915_gem_fini(dev_priv);
intel_fbc_cleanup_cfb(dev_priv);
- intel_power_domains_fini(dev_priv);
+ intel_power_domains_fini_hw(dev_priv);
i915_driver_cleanup_hw(dev_priv);
i915_driver_cleanup_mmio(dev_priv);
- intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+ enable_rpm_wakeref_asserts(dev_priv);
+
+ WARN_ON(atomic_read(&dev_priv->runtime_pm.wakeref_count));
}
static void i915_driver_release(struct drm_device *dev)
@@ -1472,9 +1498,7 @@ static void i915_driver_release(struct drm_device *dev)
struct drm_i915_private *dev_priv = to_i915(dev);
i915_driver_cleanup_early(dev_priv);
- drm_dev_fini(&dev_priv->drm);
-
- kfree(dev_priv);
+ i915_driver_destroy(dev_priv);
}
static int i915_driver_open(struct drm_device *dev, struct drm_file *file)
@@ -1573,7 +1597,7 @@ static int i915_drm_suspend(struct drm_device *dev)
/* We do a lot of poking in a lot of registers, make sure they work
* properly. */
- intel_display_set_init_power(dev_priv, true);
+ intel_power_domains_disable(dev_priv);
drm_kms_helper_poll_disable(dev);
@@ -1610,6 +1634,18 @@ static int i915_drm_suspend(struct drm_device *dev)
return 0;
}
+static enum i915_drm_suspend_mode
+get_suspend_mode(struct drm_i915_private *dev_priv, bool hibernate)
+{
+ if (hibernate)
+ return I915_DRM_SUSPEND_HIBERNATE;
+
+ if (suspend_to_idle(dev_priv))
+ return I915_DRM_SUSPEND_IDLE;
+
+ return I915_DRM_SUSPEND_MEM;
+}
+
static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
{
struct drm_i915_private *dev_priv = to_i915(dev);
@@ -1620,21 +1656,10 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
i915_gem_suspend_late(dev_priv);
- intel_display_set_init_power(dev_priv, false);
intel_uncore_suspend(dev_priv);
- /*
- * In case of firmware assisted context save/restore don't manually
- * deinit the power domains. This also means the CSR/DMC firmware will
- * stay active, it will power down any HW resources as required and
- * also enable deeper system power states that would be blocked if the
- * firmware was inactive.
- */
- if (IS_GEN9_LP(dev_priv) || hibernation || !suspend_to_idle(dev_priv) ||
- dev_priv->csr.dmc_payload == NULL) {
- intel_power_domains_suspend(dev_priv);
- dev_priv->power_domains_suspended = true;
- }
+ intel_power_domains_suspend(dev_priv,
+ get_suspend_mode(dev_priv, hibernation));
ret = 0;
if (IS_GEN9_LP(dev_priv))
@@ -1646,10 +1671,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
if (ret) {
DRM_ERROR("Suspend complete failed: %d\n", ret);
- if (dev_priv->power_domains_suspended) {
- intel_power_domains_init_hw(dev_priv, true);
- dev_priv->power_domains_suspended = false;
- }
+ intel_power_domains_resume(dev_priv);
goto out;
}
@@ -1755,7 +1777,7 @@ static int i915_drm_resume(struct drm_device *dev)
/*
* ... but also need to make sure that hotplug processing
* doesn't cause havoc. Like in the driver load code we don't
- * bother with the tiny race here where we might loose hotplug
+ * bother with the tiny race here where we might lose hotplug
* notifications.
* */
intel_hpd_init(dev_priv);
@@ -1766,6 +1788,8 @@ static int i915_drm_resume(struct drm_device *dev)
intel_opregion_notify_adapter(dev_priv, PCI_D0);
+ intel_power_domains_enable(dev_priv);
+
enable_rpm_wakeref_asserts(dev_priv);
return 0;
@@ -1800,7 +1824,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
ret = pci_set_power_state(pdev, PCI_D0);
if (ret) {
DRM_ERROR("failed to set PCI D0 power state (%d)\n", ret);
- goto out;
+ return ret;
}
/*
@@ -1816,10 +1840,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
* depend on the device enable refcount we can't anyway depend on them
* disabling/enabling the device.
*/
- if (pci_enable_device(pdev)) {
- ret = -EIO;
- goto out;
- }
+ if (pci_enable_device(pdev))
+ return -EIO;
pci_set_master(pdev);
@@ -1842,18 +1864,12 @@ static int i915_drm_resume_early(struct drm_device *dev)
intel_uncore_sanitize(dev_priv);
- if (dev_priv->power_domains_suspended)
- intel_power_domains_init_hw(dev_priv, true);
- else
- intel_display_set_init_power(dev_priv, true);
+ intel_power_domains_resume(dev_priv);
intel_engines_sanitize(dev_priv);
enable_rpm_wakeref_asserts(dev_priv);
-out:
- dev_priv->power_domains_suspended = false;
-
return ret;
}
@@ -1915,7 +1931,6 @@ void i915_reset(struct drm_i915_private *i915,
dev_notice(i915->drm.dev, "Resetting chip for %s\n", reason);
error->reset_count++;
- disable_irq(i915->drm.irq);
ret = i915_gem_reset_prepare(i915);
if (ret) {
dev_err(i915->drm.dev, "GPU recovery failed\n");
@@ -1977,8 +1992,6 @@ void i915_reset(struct drm_i915_private *i915,
finish:
i915_gem_reset_finish(i915);
- enable_irq(i915->drm.irq);
-
wakeup:
clear_bit(I915_RESET_HANDOFF, &error->flags);
wake_up_bit(&error->flags, I915_RESET_HANDOFF);
@@ -2073,6 +2086,7 @@ int i915_reset_engine(struct intel_engine_cs *engine, const char *msg)
goto out;
out:
+ intel_engine_cancel_stop_cs(engine);
i915_gem_reset_finish_engine(engine);
return ret;
}