diff options
author | Dave Airlie <airlied@redhat.com> | 2018-03-01 07:07:22 +0300 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-03-01 07:07:22 +0300 |
commit | f073d78eeb8efd85718e611c15f9a78647751dea (patch) | |
tree | 7ae17810b85416c173fac5bb52f3b7575d969f14 /drivers/gpu | |
parent | 0feeb106c79532074b370c3cb45f742ef4302cc6 (diff) | |
parent | fed8165851e262575585b22055ff5dba7d91b0e5 (diff) | |
download | linux-f073d78eeb8efd85718e611c15f9a78647751dea.tar.xz |
Merge tag 'drm-intel-next-2018-02-21' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
Driver Changes:
- Lift alpha_support protection from Cannonlake (Rodrigo)
* Meaning the driver should mostly work for the hardware we had
at our disposal when testing
* Used to be preliminary_hw_support
- Add missing Cannonlake PCI device ID of 0x5A4C (Rodrigo)
- Cannonlake port register fix (Mahesh)
- Fix Dell Venue 8 Pro black screen after modeset (Hans)
- Fix for always returning zero out-fence from execbuf (Daniele)
- Fix HDMI audio when no no relevant video output is active (Jani)
- Fix memleak of VBT data on driver_unload (Hans)
- Fix for KASAN found locking issue (Maarten)
- RCU barrier consolidation to improve igt/gem_sync/idle (Chris)
- Optimizations to IRQ handlers (Chris)
- vblank tracking improvements (64-bit resolution, PM) (Dhinakaran)
- Pipe select bit corrections (Ville)
- Reduce runtime computed device_info fields (Chris)
- Tune down some WARN_ONs to GEM_BUG_ON now that CI has good coverage (Chris)
- A bunch of kerneldoc warning fixes (Chris)
* tag 'drm-intel-next-2018-02-21' of git://anongit.freedesktop.org/drm/drm-intel: (113 commits)
drm/i915: Update DRIVER_DATE to 20180221
drm/i915/fbc: Use PLANE_HAS_FENCE to determine if the plane is fenced
drm/i915/fbdev: Use the PLANE_HAS_FENCE flags from the time of pinning
drm/i915: Move the policy for placement of the GGTT vma into the caller
drm/i915: Also check view->type for a normal GGTT view
drm/i915: Drop WaDoubleCursorLP3Latency:ivb
drm/i915: Set the primary plane pipe select bits on gen4
drm/i915: Don't set cursor pipe select bits on g4x+
drm/i915: Assert that we don't overflow frontbuffer tracking bits
drm/i915: Track number of pending freed objects
drm/i915/: Initialise trans_min for skl_compute_transition_wm()
drm/i915: Clear the in-use marker on execbuf failure
drm/i915: Prune gen8_gt_irq_handler
drm/i915: Track GT interrupt handling using the master iir
drm/i915: Remove WARN_ONCE for failing to pm_runtime_if_in_use
drm: intel_dpio_phy: fix kernel-doc comments at nested struct
drm/i915: Release connector iterator on a digital port conflict.
drm/i915/execlists: Remove too early assert
drm/i915: Assert that we always complete a submission to guc/execlists
drm: move read_domains and write_domain into i915
...
Diffstat (limited to 'drivers/gpu')
79 files changed, 1855 insertions, 932 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 1eb0861c9147..93f700ab1bfb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -210,7 +210,7 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc, amdgpu_bo_unreserve(new_abo); work->base = base; - work->target_vblank = target - drm_crtc_vblank_count(crtc) + + work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) + amdgpu_get_vblank_counter_kms(dev, work->crtc_id); /* we borrow the event spin lock for protecting flip_wrok */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 84f6fe9a448b..246fff33c7bf 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3842,7 +3842,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, /* Prepare wait for target vblank early - before the fence-waits */ - target_vblank = target - drm_crtc_vblank_count(crtc) + + target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) + amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); /* TODO This might fail and hence better not used, wait @@ -3988,7 +3988,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, amdgpu_dm_do_flip( crtc, fb, - drm_crtc_vblank_count(crtc) + *wait_for_vblank, + (uint32_t)drm_crtc_vblank_count(crtc) + *wait_for_vblank, dm_state->context); } diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 22b54663b6e7..09de6ecb3968 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -948,7 +948,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, if (r) return r; - current_vblank = drm_crtc_vblank_count(crtc); + current_vblank = (u32)drm_crtc_vblank_count(crtc); switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) { case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE: diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 32d9bcf5be7f..c781cb426bf1 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -271,7 +271,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, store_vblank(dev, pipe, diff, t_vblank, cur_vblank); } -static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) +static u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; @@ -292,11 +292,11 @@ static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) * This is mostly useful for hardware that can obtain the scanout position, but * doesn't have a hardware frame counter. */ -u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) +u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = drm_crtc_index(crtc); - u32 vblank; + u64 vblank; unsigned long flags; WARN_ONCE(drm_debug & DRM_UT_VBL && !dev->driver->get_vblank_timestamp, @@ -347,23 +347,25 @@ void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) spin_lock_irqsave(&dev->vblank_time_lock, irqflags); /* - * Only disable vblank interrupts if they're enabled. This avoids - * calling the ->disable_vblank() operation in atomic context with the - * hardware potentially runtime suspended. + * Update vblank count and disable vblank interrupts only if the + * interrupts were enabled. This avoids calling the ->disable_vblank() + * operation in atomic context with the hardware potentially runtime + * suspended. */ - if (vblank->enabled) { - __disable_vblank(dev, pipe); - vblank->enabled = false; - } + if (!vblank->enabled) + goto out; /* - * Always update the count and timestamp to maintain the + * Update the count and timestamp to maintain the * appearance that the counter has been ticking all along until * this time. This makes the count account for the entire time * between drm_crtc_vblank_on() and drm_crtc_vblank_off(). */ drm_update_vblank_count(dev, pipe, false); + __disable_vblank(dev, pipe); + vblank->enabled = false; +out: spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); } @@ -1055,7 +1057,7 @@ void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; int ret; - u32 last; + u64 last; if (WARN_ON(pipe >= dev->num_crtcs)) return; @@ -1235,6 +1237,65 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_vblank_on); +/** + * drm_vblank_restore - estimated vblanks using timestamps and update it. + * + * Power manamement features can cause frame counter resets between vblank + * disable and enable. Drivers can then use this function in their + * &drm_crtc_funcs.enable_vblank implementation to estimate the vblanks since + * the last &drm_crtc_funcs.disable_vblank. + * + * This function is the legacy version of drm_crtc_vblank_restore(). + */ +void drm_vblank_restore(struct drm_device *dev, unsigned int pipe) +{ + ktime_t t_vblank; + struct drm_vblank_crtc *vblank; + int framedur_ns; + u64 diff_ns; + u32 cur_vblank, diff = 1; + int count = DRM_TIMESTAMP_MAXRETRIES; + + if (WARN_ON(pipe >= dev->num_crtcs)) + return; + + assert_spin_locked(&dev->vbl_lock); + assert_spin_locked(&dev->vblank_time_lock); + + vblank = &dev->vblank[pipe]; + WARN_ONCE((drm_debug & DRM_UT_VBL) && !vblank->framedur_ns, + "Cannot compute missed vblanks without frame duration\n"); + framedur_ns = vblank->framedur_ns; + + do { + cur_vblank = __get_vblank_counter(dev, pipe); + drm_get_last_vbltimestamp(dev, pipe, &t_vblank, false); + } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0); + + diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time)); + if (framedur_ns) + diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); + + + DRM_DEBUG_VBL("missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n", + diff, diff_ns, framedur_ns, cur_vblank - vblank->last); + store_vblank(dev, pipe, diff, t_vblank, cur_vblank); +} +EXPORT_SYMBOL(drm_vblank_restore); + +/** + * drm_crtc_vblank_restore - estimate vblanks using timestamps and update it. + * Power manamement features can cause frame counter resets between vblank + * disable and enable. Drivers can then use this function in their + * &drm_crtc_funcs.enable_vblank implementation to estimate the vblanks since + * the last &drm_crtc_funcs.disable_vblank. + */ +void drm_crtc_vblank_restore(struct drm_crtc *crtc) +{ + drm_vblank_restore(crtc->dev, drm_crtc_index(crtc)); +} +EXPORT_SYMBOL(drm_crtc_vblank_restore); + static void drm_legacy_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe) { diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 3bddd8a06806..f55cc028b2eb 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -17,6 +17,7 @@ subdir-ccflags-y += $(call cc-disable-warning, unused-parameter) subdir-ccflags-y += $(call cc-disable-warning, type-limits) subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers) subdir-ccflags-y += $(call cc-disable-warning, implicit-fallthrough) +subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable) subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror # Fine grained warnings disable diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c index 4950b82f5b49..c73aff163908 100644 --- a/drivers/gpu/drm/i915/dvo_ivch.c +++ b/drivers/gpu/drm/i915/dvo_ivch.c @@ -59,28 +59,28 @@ * This must not be set while VR01_DVO_BYPASS_ENABLE is set. */ # define VR01_LCD_ENABLE (1 << 2) -/** Enables the DVO repeater. */ +/* Enables the DVO repeater. */ # define VR01_DVO_BYPASS_ENABLE (1 << 1) -/** Enables the DVO clock */ +/* Enables the DVO clock */ # define VR01_DVO_ENABLE (1 << 0) -/** Enable dithering for 18bpp panels. Not documented. */ +/* Enable dithering for 18bpp panels. Not documented. */ # define VR01_DITHER_ENABLE (1 << 4) /* * LCD Interface Format */ #define VR10 0x10 -/** Enables LVDS output instead of CMOS */ +/* Enables LVDS output instead of CMOS */ # define VR10_LVDS_ENABLE (1 << 4) -/** Enables 18-bit LVDS output. */ +/* Enables 18-bit LVDS output. */ # define VR10_INTERFACE_1X18 (0 << 2) -/** Enables 24-bit LVDS or CMOS output */ +/* Enables 24-bit LVDS or CMOS output */ # define VR10_INTERFACE_1X24 (1 << 2) -/** Enables 2x18-bit LVDS or CMOS output. */ +/* Enables 2x18-bit LVDS or CMOS output. */ # define VR10_INTERFACE_2X18 (2 << 2) -/** Enables 2x24-bit LVDS output */ +/* Enables 2x24-bit LVDS output */ # define VR10_INTERFACE_2X24 (3 << 2) -/** Mask that defines the depth of the pipeline */ +/* Mask that defines the depth of the pipeline */ # define VR10_INTERFACE_DEPTH_MASK (3 << 2) /* @@ -97,7 +97,7 @@ * Panel power down status */ #define VR30 0x30 -/** Read only bit indicating that the panel is not in a safe poweroff state. */ +/* Read only bit indicating that the panel is not in a safe poweroff state. */ # define VR30_PANEL_ON (1 << 15) #define VR40 0x40 @@ -183,7 +183,7 @@ struct ivch_priv { static void ivch_dump_regs(struct intel_dvo_device *dvo); -/** +/* * Reads a register on the ivch. * * Each of the 256 registers are 16 bits long. @@ -230,7 +230,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) return false; } -/** Writes a 16-bit register on the ivch */ +/* Writes a 16-bit register on the ivch */ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) { struct ivch_priv *priv = dvo->dev_priv; @@ -258,7 +258,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) return false; } -/** Probes the given bus and slave address for an ivch */ +/* Probes the given bus and slave address for an ivch */ static bool ivch_init(struct intel_dvo_device *dvo, struct i2c_adapter *adapter) { @@ -338,7 +338,7 @@ static void ivch_reset(struct intel_dvo_device *dvo) ivch_write(dvo, backup_addresses[i], priv->reg_backup[i]); } -/** Sets the power state of the panel connected to the ivch */ +/* Sets the power state of the panel connected to the ivch */ static void ivch_dpms(struct intel_dvo_device *dvo, bool enable) { int i; diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c index 2fb7b34ef561..9a471b0afb15 100644 --- a/drivers/gpu/drm/i915/gvt/dmabuf.c +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c @@ -162,8 +162,8 @@ static struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev, info->size << PAGE_SHIFT); i915_gem_object_init(obj, &intel_vgpu_gem_ops); - obj->base.read_domains = I915_GEM_DOMAIN_GTT; - obj->base.write_domain = 0; + obj->read_domains = I915_GEM_DOMAIN_GTT; + obj->write_domain = 0; if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { unsigned int tiling_mode = 0; unsigned int stride = 0; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3849ded354e3..05b41045b8f9 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -49,6 +49,7 @@ static int i915_capabilities(struct seq_file *m, void *data) intel_device_info_dump_flags(info, &p); intel_device_info_dump_runtime(info, &p); + intel_driver_caps_print(&dev_priv->caps, &p); kernel_param_lock(THIS_MODULE); i915_params_dump(&i915_modparams, &p); @@ -149,8 +150,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) get_global_flag(obj), get_pin_mapped_flag(obj), obj->base.size / 1024, - obj->base.read_domains, - obj->base.write_domain, + obj->read_domains, + obj->write_domain, i915_cache_level_str(dev_priv, obj->cache_level), obj->mm.dirty ? " dirty" : "", obj->mm.madv == I915_MADV_DONTNEED ? " purgeable" : ""); @@ -1460,19 +1461,6 @@ static int gen6_drpc_info(struct seq_file *m) struct drm_i915_private *dev_priv = node_to_i915(m->private); u32 gt_core_status, rcctl1, rc6vids = 0; u32 gen9_powergate_enable = 0, gen9_powergate_status = 0; - unsigned forcewake_count; - int count = 0; - - forcewake_count = READ_ONCE(dev_priv->uncore.fw_domain[FW_DOMAIN_ID_RENDER].wake_count); - if (forcewake_count) { - seq_puts(m, "RC information inaccurate because somebody " - "holds a forcewake reference \n"); - } else { - /* NB: we cannot use forcewake, else we read the wrong values */ - while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1)) - udelay(10); - seq_printf(m, "RC information accurate: %s\n", yesno(count < 51)); - } gt_core_status = I915_READ_FW(GEN6_GT_CORE_STATUS); trace_i915_reg_rw(false, GEN6_GT_CORE_STATUS, gt_core_status, 4, true); @@ -1483,9 +1471,12 @@ static int gen6_drpc_info(struct seq_file *m) gen9_powergate_status = I915_READ(GEN9_PWRGT_DOMAIN_STATUS); } - mutex_lock(&dev_priv->pcu_lock); - sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids); - mutex_unlock(&dev_priv->pcu_lock); + if (INTEL_GEN(dev_priv) <= 7) { + mutex_lock(&dev_priv->pcu_lock); + sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, + &rc6vids); + mutex_unlock(&dev_priv->pcu_lock); + } seq_printf(m, "RC1e Enabled: %s\n", yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE)); @@ -1541,12 +1532,15 @@ static int gen6_drpc_info(struct seq_file *m) print_rc6_res(m, "RC6+ residency since boot:", GEN6_GT_GFX_RC6p); print_rc6_res(m, "RC6++ residency since boot:", GEN6_GT_GFX_RC6pp); - seq_printf(m, "RC6 voltage: %dmV\n", - GEN6_DECODE_RC6_VID(((rc6vids >> 0) & 0xff))); - seq_printf(m, "RC6+ voltage: %dmV\n", - GEN6_DECODE_RC6_VID(((rc6vids >> 8) & 0xff))); - seq_printf(m, "RC6++ voltage: %dmV\n", - GEN6_DECODE_RC6_VID(((rc6vids >> 16) & 0xff))); + if (INTEL_GEN(dev_priv) <= 7) { + seq_printf(m, "RC6 voltage: %dmV\n", + GEN6_DECODE_RC6_VID(((rc6vids >> 0) & 0xff))); + seq_printf(m, "RC6+ voltage: %dmV\n", + GEN6_DECODE_RC6_VID(((rc6vids >> 8) & 0xff))); + seq_printf(m, "RC6++ voltage: %dmV\n", + GEN6_DECODE_RC6_VID(((rc6vids >> 16) & 0xff))); + } + return i915_forcewake_domains(m, NULL); } @@ -1599,7 +1593,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused) seq_printf(m, "FBC disabled: %s\n", fbc->no_fbc_reason); if (fbc->work.scheduled) - seq_printf(m, "FBC worker scheduled on vblank %u, now %llu\n", + seq_printf(m, "FBC worker scheduled on vblank %llu, now %llu\n", fbc->work.scheduled_vblank, drm_crtc_vblank_count(&fbc->crtc->base)); @@ -2338,7 +2332,6 @@ static int i915_guc_info(struct seq_file *m, void *data) return -ENODEV; GEM_BUG_ON(!guc->execbuf_client); - GEM_BUG_ON(!guc->preempt_client); seq_printf(m, "Doorbell map:\n"); seq_printf(m, "\t%*pb\n", GUC_NUM_DOORBELLS, guc->doorbell_bitmap); @@ -2346,8 +2339,11 @@ static int i915_guc_info(struct seq_file *m, void *data) seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client); i915_guc_client_info(m, dev_priv, guc->execbuf_client); - seq_printf(m, "\nGuC preempt client @ %p:\n", guc->preempt_client); - i915_guc_client_info(m, dev_priv, guc->preempt_client); + if (guc->preempt_client) { + seq_printf(m, "\nGuC preempt client @ %p:\n", + guc->preempt_client); + i915_guc_client_info(m, dev_priv, guc->preempt_client); + } i915_guc_log_info(m, dev_priv); @@ -4083,10 +4079,8 @@ i915_drop_caches_set(void *data, u64 val) if (val & DROP_IDLE) drain_delayed_work(&dev_priv->gt.idle_work); - if (val & DROP_FREED) { - synchronize_rcu(); + if (val & DROP_FREED) i915_gem_drain_freed_objects(dev_priv); - } return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e9f1daf258fe..d09f8e661fbd 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -122,10 +122,90 @@ static bool i915_error_injected(struct drm_i915_private *dev_priv) i915_error_injected(dev_priv) ? KERN_DEBUG : KERN_ERR, \ fmt, ##__VA_ARGS__) +/* Map PCH device id to PCH type, or PCH_NONE if unknown. */ +static enum intel_pch +intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) +{ + switch (id) { + case INTEL_PCH_IBX_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found Ibex Peak PCH\n"); + WARN_ON(!IS_GEN5(dev_priv)); + return PCH_IBX; + case INTEL_PCH_CPT_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found CougarPoint PCH\n"); + WARN_ON(!IS_GEN6(dev_priv) && !IS_IVYBRIDGE(dev_priv)); + return PCH_CPT; + case INTEL_PCH_PPT_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found PantherPoint PCH\n"); + WARN_ON(!IS_GEN6(dev_priv) && !IS_IVYBRIDGE(dev_priv)); + /* PantherPoint is CPT compatible */ + return PCH_CPT; + case INTEL_PCH_LPT_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found LynxPoint PCH\n"); + WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); + WARN_ON(IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); + return PCH_LPT; + case INTEL_PCH_LPT_LP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); + WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); + WARN_ON(!IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); + return PCH_LPT; + case INTEL_PCH_WPT_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found WildcatPoint PCH\n"); + WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); + WARN_ON(IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); + /* WildcatPoint is LPT compatible */ + return PCH_LPT; + case INTEL_PCH_WPT_LP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found WildcatPoint LP PCH\n"); + WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); + WARN_ON(!IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); + /* WildcatPoint is LPT compatible */ + return PCH_LPT; + case INTEL_PCH_SPT_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); + WARN_ON(!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)); + return PCH_SPT; + case INTEL_PCH_SPT_LP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n"); + WARN_ON(!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)); + return PCH_SPT; + case INTEL_PCH_KBP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found Kaby Lake PCH (KBP)\n"); + WARN_ON(!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv) && + !IS_COFFEELAKE(dev_priv)); + return PCH_KBP; + case INTEL_PCH_CNP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found Cannon Lake PCH (CNP)\n"); + WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv)); + return PCH_CNP; + case INTEL_PCH_CNP_LP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found Cannon Lake LP PCH (CNP-LP)\n"); + WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv)); + return PCH_CNP; + case INTEL_PCH_ICP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found Ice Lake PCH\n"); + WARN_ON(!IS_ICELAKE(dev_priv)); + return PCH_ICP; + default: + return PCH_NONE; + } +} -static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv) +static bool intel_is_virt_pch(unsigned short id, + unsigned short svendor, unsigned short sdevice) { - enum intel_pch ret = PCH_NOP; + return (id == INTEL_PCH_P2X_DEVICE_ID_TYPE || + id == INTEL_PCH_P3X_DEVICE_ID_TYPE || + (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE && + svendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET && + sdevice == PCI_SUBDEVICE_ID_QEMU)); +} + +static unsigned short +intel_virt_detect_pch(const struct drm_i915_private *dev_priv) +{ + unsigned short id = 0; /* * In a virtualized passthrough environment we can be in a @@ -134,28 +214,25 @@ static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv) * make an educated guess as to which PCH is really there. */ - if (IS_GEN5(dev_priv)) { - ret = PCH_IBX; - DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n"); - } else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) { - ret = PCH_CPT; - DRM_DEBUG_KMS("Assuming CougarPoint PCH\n"); - } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - ret = PCH_LPT; - if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) - dev_priv->pch_id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; - else - dev_priv->pch_id = INTEL_PCH_LPT_DEVICE_ID_TYPE; - DRM_DEBUG_KMS("Assuming LynxPoint PCH\n"); - } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { - ret = PCH_SPT; - DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n"); - } else if (IS_COFFEELAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) { - ret = PCH_CNP; - DRM_DEBUG_KMS("Assuming CannonPoint PCH\n"); - } + if (IS_GEN5(dev_priv)) + id = INTEL_PCH_IBX_DEVICE_ID_TYPE; + else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) + id = INTEL_PCH_CPT_DEVICE_ID_TYPE; + else if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) + id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; + else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) + id = INTEL_PCH_LPT_DEVICE_ID_TYPE; + else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) + id = INTEL_PCH_SPT_DEVICE_ID_TYPE; + else if (IS_COFFEELAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) + id = INTEL_PCH_CNP_DEVICE_ID_TYPE; + + if (id) + DRM_DEBUG_KMS("Assuming PCH ID %04x\n", id); + else + DRM_DEBUG_KMS("Assuming no PCH\n"); - return ret; + return id; } static void intel_detect_pch(struct drm_i915_private *dev_priv) @@ -183,102 +260,32 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) */ while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) { unsigned short id; + enum intel_pch pch_type; if (pch->vendor != PCI_VENDOR_ID_INTEL) continue; 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_priv)); - } 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_priv) && - !IS_IVYBRIDGE(dev_priv)); - } 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_priv) && - !IS_IVYBRIDGE(dev_priv)); - } 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_priv) && - !IS_BROADWELL(dev_priv)); - WARN_ON(IS_HSW_ULT(dev_priv) || - IS_BDW_ULT(dev_priv)); - } 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_priv) && - !IS_BROADWELL(dev_priv)); - WARN_ON(!IS_HSW_ULT(dev_priv) && - !IS_BDW_ULT(dev_priv)); - } else if (id == INTEL_PCH_WPT_DEVICE_ID_TYPE) { - /* WildcatPoint is LPT compatible */ - dev_priv->pch_type = PCH_LPT; - DRM_DEBUG_KMS("Found WildcatPoint PCH\n"); - WARN_ON(!IS_HASWELL(dev_priv) && - !IS_BROADWELL(dev_priv)); - WARN_ON(IS_HSW_ULT(dev_priv) || - IS_BDW_ULT(dev_priv)); - } else if (id == INTEL_PCH_WPT_LP_DEVICE_ID_TYPE) { - /* WildcatPoint is LPT compatible */ - dev_priv->pch_type = PCH_LPT; - DRM_DEBUG_KMS("Found WildcatPoint LP PCH\n"); - WARN_ON(!IS_HASWELL(dev_priv) && - !IS_BROADWELL(dev_priv)); - WARN_ON(!IS_HSW_ULT(dev_priv) && - !IS_BDW_ULT(dev_priv)); - } 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_priv) && - !IS_KABYLAKE(dev_priv)); - } 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_priv) && - !IS_KABYLAKE(dev_priv)); - } else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_KBP; - DRM_DEBUG_KMS("Found Kaby Lake PCH (KBP)\n"); - WARN_ON(!IS_SKYLAKE(dev_priv) && - !IS_KABYLAKE(dev_priv) && - !IS_COFFEELAKE(dev_priv)); - } else if (id == INTEL_PCH_CNP_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_CNP; - DRM_DEBUG_KMS("Found Cannon Lake PCH (CNP)\n"); - WARN_ON(!IS_CANNONLAKE(dev_priv) && - !IS_COFFEELAKE(dev_priv)); - } else if (id == INTEL_PCH_CNP_LP_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_CNP; - DRM_DEBUG_KMS("Found Cannon Lake LP PCH (CNP-LP)\n"); - WARN_ON(!IS_CANNONLAKE(dev_priv) && - !IS_COFFEELAKE(dev_priv)); - } else if (id == INTEL_PCH_ICP_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_ICP; - DRM_DEBUG_KMS("Found Ice Lake PCH\n"); - WARN_ON(!IS_ICELAKE(dev_priv)); - } 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 == - PCI_SUBVENDOR_ID_REDHAT_QUMRANET && - pch->subsystem_device == - PCI_SUBDEVICE_ID_QEMU)) { - dev_priv->pch_type = intel_virt_detect_pch(dev_priv); - } else { - continue; + pch_type = intel_pch_type(dev_priv, id); + if (pch_type != PCH_NONE) { + dev_priv->pch_type = pch_type; + dev_priv->pch_id = id; + break; + } else if (intel_is_virt_pch(id, pch->subsystem_vendor, + pch->subsystem_device)) { + id = intel_virt_detect_pch(dev_priv); + if (id) { + pch_type = intel_pch_type(dev_priv, id); + if (WARN_ON(pch_type == PCH_NONE)) + pch_type = PCH_NOP; + } else { + pch_type = PCH_NOP; + } + dev_priv->pch_type = pch_type; + dev_priv->pch_id = id; + break; } - - break; } if (!pch) DRM_DEBUG_KMS("No PCH found.\n"); @@ -286,8 +293,8 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) pci_dev_put(pch); } -static int i915_getparam(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i915_getparam_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_i915_private *dev_priv = to_i915(dev); struct pci_dev *pdev = dev_priv->drm.pdev; @@ -381,13 +388,7 @@ static int i915_getparam(struct drm_device *dev, void *data, value = i915_gem_mmap_gtt_version(); break; case I915_PARAM_HAS_SCHEDULER: - value = 0; - if (dev_priv->engine[RCS] && dev_priv->engine[RCS]->schedule) { - value |= I915_SCHEDULER_CAP_ENABLED; - value |= I915_SCHEDULER_CAP_PRIORITY; - if (HAS_LOGICAL_RING_PREEMPTION(dev_priv)) - value |= I915_SCHEDULER_CAP_PREEMPTION; - } + value = dev_priv->caps.scheduler; break; case I915_PARAM_MMAP_VERSION: @@ -879,6 +880,7 @@ 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 @@ -904,11 +906,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, BUILD_BUG_ON(INTEL_MAX_PLATFORMS > sizeof(device_info->platform_mask) * BITS_PER_BYTE); - device_info->platform_mask = BIT(device_info->platform); - 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); @@ -1446,19 +1444,7 @@ void i915_driver_unload(struct drm_device *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; + intel_bios_cleanup(dev_priv); vga_switcheroo_unregister_client(pdev); vga_client_register(pdev, NULL, NULL, NULL); @@ -1925,7 +1911,6 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags) ret = i915_gem_reset_prepare(i915); if (ret) { dev_err(i915->drm.dev, "GPU recovery failed\n"); - intel_gpu_reset(i915, ALL_ENGINES); goto taint; } @@ -1957,7 +1942,8 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags) */ ret = i915_ggtt_enable_hw(i915); if (ret) { - DRM_ERROR("Failed to re-enable GGTT following reset %d\n", ret); + DRM_ERROR("Failed to re-enable GGTT following reset (%d)\n", + ret); goto error; } @@ -1974,7 +1960,8 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags) */ ret = i915_gem_init_hw(i915); if (ret) { - DRM_ERROR("Failed hw init on reset %d\n", ret); + DRM_ERROR("Failed to initialise HW following reset (%d)\n", + ret); goto error; } @@ -2006,6 +1993,7 @@ taint: error: i915_gem_set_wedged(i915); i915_gem_retire_requests(i915); + intel_gpu_reset(i915, ALL_ENGINES); goto finish; } @@ -2795,7 +2783,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = { 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_GETPARAM, i915_getparam_ioctl, 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), @@ -2807,8 +2795,8 @@ static const struct drm_ioctl_desc i915_ioctls[] = { 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_WR, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer_ioctl, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2_WR, i915_gem_execbuffer2_ioctl, 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), @@ -2827,11 +2815,11 @@ static const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling_ioctl, 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_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id_ioctl, 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_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey_ioctl, 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), diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ad1fc845cd1b..92883a40bdd5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -83,8 +83,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20180207" -#define DRIVER_TIMESTAMP 1517988364 +#define DRIVER_DATE "20180221" +#define DRIVER_TIMESTAMP 1519219289 /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and * WARN_ON()) for hw state sanity checks to check for unexpected conditions @@ -472,6 +472,7 @@ struct i915_gpu_state { u32 reset_count; u32 suspend_count; struct intel_device_info device_info; + struct intel_driver_caps driver_caps; struct i915_params params; struct i915_error_uc { @@ -666,6 +667,7 @@ struct intel_fbc { */ struct intel_fbc_state_cache { struct i915_vma *vma; + unsigned long flags; struct { unsigned int mode_flags; @@ -704,6 +706,7 @@ struct intel_fbc { */ struct intel_fbc_reg_params { struct i915_vma *vma; + unsigned long flags; struct { enum pipe pipe; @@ -722,7 +725,7 @@ struct intel_fbc { struct intel_fbc_work { bool scheduled; - u32 scheduled_vblank; + u64 scheduled_vblank; struct work_struct work; } work; @@ -946,6 +949,8 @@ struct intel_rps { struct intel_rc6 { bool enabled; + u64 prev_hw_residency[4]; + u64 cur_residency[4]; }; struct intel_llc_pstate { @@ -1092,6 +1097,11 @@ struct i915_gem_mm { struct llist_head free_list; struct work_struct free_work; spinlock_t free_lock; + /** + * Count of objects pending destructions. Used to skip needlessly + * waiting on an RCU barrier if no objects are waiting to be freed. + */ + atomic_t free_count; /** * Small stash of WC pages @@ -1356,6 +1366,7 @@ struct intel_vbt_data { u32 size; u8 *data; const u8 *sequence[MIPI_SEQ_MAX]; + u8 *deassert_seq; /* Used by fixup_mipi_sequences() */ } dsi; int crt_ddc_pin; @@ -1815,6 +1826,7 @@ struct drm_i915_private { struct kmem_cache *priorities; const struct intel_device_info info; + struct intel_driver_caps caps; /** * Data Stolen Memory - aka "i915 stolen memory" gives us the start and @@ -2419,12 +2431,16 @@ enum hdmi_force_audio { * We have one bit per pipe and per scanout plane type. */ #define INTEL_FRONTBUFFER_BITS_PER_PIPE 8 -#define INTEL_FRONTBUFFER(pipe, plane_id) \ - (1 << ((plane_id) + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) +#define INTEL_FRONTBUFFER(pipe, plane_id) ({ \ + BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES > 32); \ + BUILD_BUG_ON(I915_MAX_PLANES > INTEL_FRONTBUFFER_BITS_PER_PIPE); \ + BIT((plane_id) + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)); \ +}) #define INTEL_FRONTBUFFER_OVERLAY(pipe) \ - (1 << (INTEL_FRONTBUFFER_BITS_PER_PIPE - 1 + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) + BIT(INTEL_FRONTBUFFER_BITS_PER_PIPE - 1 + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)) #define INTEL_FRONTBUFFER_ALL_MASK(pipe) \ - (0xff << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) + GENMASK(INTEL_FRONTBUFFER_BITS_PER_PIPE * ((pipe) + 1) - 1, \ + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)) /* * Optimised SGL iterator for GEM objects @@ -2799,7 +2815,7 @@ intel_info(const struct drm_i915_private *dev_priv) #define HAS_FW_BLC(dev_priv) (INTEL_GEN(dev_priv) > 2) #define HAS_FBC(dev_priv) ((dev_priv)->info.has_fbc) -#define HAS_CUR_FBC(dev_priv) (!HAS_GMCH_DISPLAY(dev_priv) && INTEL_INFO(dev_priv)->gen >= 7) +#define HAS_CUR_FBC(dev_priv) (!HAS_GMCH_DISPLAY(dev_priv) && INTEL_GEN(dev_priv) >= 7) #define HAS_IPS(dev_priv) (IS_HSW_ULT(dev_priv) || IS_BROADWELL(dev_priv)) @@ -2862,19 +2878,20 @@ intel_info(const struct drm_i915_private *dev_priv) #define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */ #define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type) +#define INTEL_PCH_ID(dev_priv) ((dev_priv)->pch_id) #define HAS_PCH_ICP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ICP) #define HAS_PCH_CNP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CNP) #define HAS_PCH_CNP_LP(dev_priv) \ - ((dev_priv)->pch_id == INTEL_PCH_CNP_LP_DEVICE_ID_TYPE) + (INTEL_PCH_ID(dev_priv) == INTEL_PCH_CNP_LP_DEVICE_ID_TYPE) #define HAS_PCH_KBP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_KBP) #define HAS_PCH_SPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_SPT) #define HAS_PCH_LPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LPT) #define HAS_PCH_LPT_LP(dev_priv) \ - ((dev_priv)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE || \ - (dev_priv)->pch_id == INTEL_PCH_WPT_LP_DEVICE_ID_TYPE) + (INTEL_PCH_ID(dev_priv) == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE || \ + INTEL_PCH_ID(dev_priv) == INTEL_PCH_WPT_LP_DEVICE_ID_TYPE) #define HAS_PCH_LPT_H(dev_priv) \ - ((dev_priv)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE || \ - (dev_priv)->pch_id == INTEL_PCH_WPT_DEVICE_ID_TYPE) + (INTEL_PCH_ID(dev_priv) == INTEL_PCH_LPT_DEVICE_ID_TYPE || \ + INTEL_PCH_ID(dev_priv) == INTEL_PCH_WPT_DEVICE_ID_TYPE) #define HAS_PCH_CPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CPT) #define HAS_PCH_IBX(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_IBX) #define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP) @@ -3081,10 +3098,10 @@ int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -int i915_gem_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file_priv); -int i915_gem_execbuffer2(struct drm_device *dev, void *data, - struct drm_file *file_priv); +int i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); int i915_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data, @@ -3128,6 +3145,9 @@ void i915_gem_free_object(struct drm_gem_object *obj); static inline void i915_gem_drain_freed_objects(struct drm_i915_private *i915) { + if (!atomic_read(&i915->mm.free_count)) + return; + /* A single pass should suffice to release all the freed objects (along * most call paths) , but be a little more paranoid in that freeing * the objects does take a little amount of time, during which the rcu @@ -3399,7 +3419,8 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write); struct i915_vma * __must_check i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, u32 alignment, - const struct i915_ggtt_view *view); + const struct i915_ggtt_view *view, + unsigned int flags); void i915_gem_object_unpin_from_display_plane(struct i915_vma *vma); int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align); @@ -3675,6 +3696,7 @@ extern void intel_i2c_reset(struct drm_i915_private *dev_priv); /* intel_bios.c */ void intel_bios_init(struct drm_i915_private *dev_priv); +void intel_bios_cleanup(struct drm_i915_private *dev_priv); bool intel_bios_is_valid_vbt(const void *buf, size_t size); bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1632f18e6a64..43afa1c1b14f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -240,8 +240,8 @@ err_phys: static void __start_cpu_write(struct drm_i915_gem_object *obj) { - obj->base.read_domains = I915_GEM_DOMAIN_CPU; - obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; if (cpu_write_needs_clflush(obj)) obj->cache_dirty = true; } @@ -257,7 +257,7 @@ __i915_gem_object_release_shmem(struct drm_i915_gem_object *obj, obj->mm.dirty = false; if (needs_clflush && - (obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0 && + (obj->read_domains & I915_GEM_DOMAIN_CPU) == 0 && !(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ)) drm_clflush_sg(pages); @@ -703,10 +703,10 @@ flush_write_domain(struct drm_i915_gem_object *obj, unsigned int flush_domains) struct drm_i915_private *dev_priv = to_i915(obj->base.dev); struct i915_vma *vma; - if (!(obj->base.write_domain & flush_domains)) + if (!(obj->write_domain & flush_domains)) return; - switch (obj->base.write_domain) { + switch (obj->write_domain) { case I915_GEM_DOMAIN_GTT: i915_gem_flush_ggtt_writes(dev_priv); @@ -731,7 +731,7 @@ flush_write_domain(struct drm_i915_gem_object *obj, unsigned int flush_domains) break; } - obj->base.write_domain = 0; + obj->write_domain = 0; } static inline int @@ -831,7 +831,7 @@ int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj, * anyway again before the next pread happens. */ if (!obj->cache_dirty && - !(obj->base.read_domains & I915_GEM_DOMAIN_CPU)) + !(obj->read_domains & I915_GEM_DOMAIN_CPU)) *needs_clflush = CLFLUSH_BEFORE; out: @@ -890,7 +890,7 @@ int i915_gem_obj_prepare_shmem_write(struct drm_i915_gem_object *obj, * Same trick applies to invalidate partially written * cachelines read before writing. */ - if (!(obj->base.read_domains & I915_GEM_DOMAIN_CPU)) + if (!(obj->read_domains & I915_GEM_DOMAIN_CPU)) *needs_clflush |= CLFLUSH_BEFORE; } @@ -2391,8 +2391,8 @@ static int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) * wasn't in the GTT, there shouldn't be any way it could have been in * a GPU cache */ - GEM_BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS); - GEM_BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS); + GEM_BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS); + GEM_BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS); st = kmalloc(sizeof(*st), GFP_KERNEL); if (st == NULL) @@ -3205,6 +3205,9 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) intel_engine_dump(engine, &p, "%s\n", engine->name); } + set_bit(I915_WEDGED, &i915->gpu_error.flags); + smp_mb__after_atomic(); + /* * First, stop submission to hw, but do not yet complete requests by * rolling the global seqno forward (since this would complete requests @@ -3229,8 +3232,11 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) * start to complete all requests. */ engine->submit_request = nop_complete_submit_request; + engine->schedule = NULL; } + i915->caps.scheduler = 0; + /* * Make sure no request can slip through without getting completed by * either this call here to intel_engine_init_global_seqno, or the one @@ -3241,7 +3247,8 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) for_each_engine(engine, i915, id) { unsigned long flags; - /* Mark all pending requests as complete so that any concurrent + /* + * Mark all pending requests as complete so that any concurrent * (lockless) lookup doesn't try and wait upon the request as we * reset it. */ @@ -3251,7 +3258,6 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) spin_unlock_irqrestore(&engine->timeline->lock, flags); } - set_bit(I915_WEDGED, &i915->gpu_error.flags); wake_up_all(&i915->gpu_error.reset_queue); } @@ -3697,7 +3703,7 @@ static void __i915_gem_object_flush_for_display(struct drm_i915_gem_object *obj) flush_write_domain(obj, ~I915_GEM_DOMAIN_CPU); if (obj->cache_dirty) i915_gem_clflush_object(obj, I915_CLFLUSH_FORCE); - obj->base.write_domain = 0; + obj->write_domain = 0; } void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj) @@ -3734,7 +3740,7 @@ i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write) if (ret) return ret; - if (obj->base.write_domain == I915_GEM_DOMAIN_WC) + if (obj->write_domain == I915_GEM_DOMAIN_WC) return 0; /* Flush and acquire obj->pages so that we are coherent through @@ -3755,17 +3761,17 @@ i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write) * coherent writes from the GPU, by effectively invalidating the * WC domain upon first access. */ - if ((obj->base.read_domains & I915_GEM_DOMAIN_WC) == 0) + if ((obj->read_domains & I915_GEM_DOMAIN_WC) == 0) mb(); /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - GEM_BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_WC) != 0); - obj->base.read_domains |= I915_GEM_DOMAIN_WC; + GEM_BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_WC) != 0); + obj->read_domains |= I915_GEM_DOMAIN_WC; if (write) { - obj->base.read_domains = I915_GEM_DOMAIN_WC; - obj->base.write_domain = I915_GEM_DOMAIN_WC; + obj->read_domains = I915_GEM_DOMAIN_WC; + obj->write_domain = I915_GEM_DOMAIN_WC; obj->mm.dirty = true; } @@ -3797,7 +3803,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) if (ret) return ret; - if (obj->base.write_domain == I915_GEM_DOMAIN_GTT) + if (obj->write_domain == I915_GEM_DOMAIN_GTT) return 0; /* Flush and acquire obj->pages so that we are coherent through @@ -3818,17 +3824,17 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) * coherent writes from the GPU, by effectively invalidating the * GTT domain upon first access. */ - if ((obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0) + if ((obj->read_domains & I915_GEM_DOMAIN_GTT) == 0) mb(); /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - GEM_BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0); - obj->base.read_domains |= I915_GEM_DOMAIN_GTT; + GEM_BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); + obj->read_domains |= I915_GEM_DOMAIN_GTT; if (write) { - obj->base.read_domains = I915_GEM_DOMAIN_GTT; - obj->base.write_domain = I915_GEM_DOMAIN_GTT; + obj->read_domains = I915_GEM_DOMAIN_GTT; + obj->write_domain = I915_GEM_DOMAIN_GTT; obj->mm.dirty = true; } @@ -4072,7 +4078,8 @@ out: struct i915_vma * i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, u32 alignment, - const struct i915_ggtt_view *view) + const struct i915_ggtt_view *view, + unsigned int flags) { struct i915_vma *vma; int ret; @@ -4109,25 +4116,14 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, * try to preserve the existing ABI). */ vma = ERR_PTR(-ENOSPC); - if (!view || view->type == I915_GGTT_VIEW_NORMAL) + if ((flags & PIN_MAPPABLE) == 0 && + (!view || view->type == I915_GGTT_VIEW_NORMAL)) vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, - PIN_MAPPABLE | PIN_NONBLOCK); - if (IS_ERR(vma)) { - struct drm_i915_private *i915 = to_i915(obj->base.dev); - unsigned int flags; - - /* Valleyview is definitely limited to scanning out the first - * 512MiB. Lets presume this behaviour was inherited from the - * g4x display engine and that all earlier gen are similarly - * limited. Testing suggests that it is a little more - * complicated than this. For example, Cherryview appears quite - * happy to scanout from anywhere within its global aperture. - */ - flags = 0; - if (HAS_GMCH_DISPLAY(i915)) - flags = PIN_MAPPABLE; + flags | + PIN_MAPPABLE | + PIN_NONBLOCK); + if (IS_ERR(vma)) vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, flags); - } if (IS_ERR(vma)) goto err_unpin_global; @@ -4140,7 +4136,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - obj->base.read_domains |= I915_GEM_DOMAIN_GTT; + obj->read_domains |= I915_GEM_DOMAIN_GTT; return vma; @@ -4193,15 +4189,15 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write) flush_write_domain(obj, ~I915_GEM_DOMAIN_CPU); /* Flush the CPU cache if it's still invalid. */ - if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0) { + if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0) { i915_gem_clflush_object(obj, I915_CLFLUSH_SYNC); - obj->base.read_domains |= I915_GEM_DOMAIN_CPU; + obj->read_domains |= I915_GEM_DOMAIN_CPU; } /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - GEM_BUG_ON(obj->base.write_domain & ~I915_GEM_DOMAIN_CPU); + GEM_BUG_ON(obj->write_domain & ~I915_GEM_DOMAIN_CPU); /* If we're writing through the CPU, then the GPU read domains will * need to be invalidated at next use. @@ -4276,7 +4272,8 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, lockdep_assert_held(&obj->base.dev->struct_mutex); - if (!view && flags & PIN_MAPPABLE) { + if (flags & PIN_MAPPABLE && + (!view || view->type == I915_GGTT_VIEW_NORMAL)) { /* If the required space is larger than the available * aperture, we will not able to find a slot for the * object and unbinding the object now will be in @@ -4637,8 +4634,8 @@ i915_gem_object_create(struct drm_i915_private *dev_priv, u64 size) i915_gem_object_init(obj, &i915_gem_object_ops); - obj->base.write_domain = I915_GEM_DOMAIN_CPU; - obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; if (HAS_LLC(dev_priv)) /* On some devices, we can have the GPU use the LLC (the CPU @@ -4752,6 +4749,9 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, kfree(obj->bit_17); i915_gem_object_free(obj); + GEM_BUG_ON(!atomic_read(&i915->mm.free_count)); + atomic_dec(&i915->mm.free_count); + if (on) cond_resched(); } @@ -4840,6 +4840,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) * i915_gem_busy_ioctl(). For the corresponding synchronized * lookup see i915_gem_object_lookup_rcu(). */ + atomic_inc(&to_i915(obj->base.dev)->mm.free_count); call_rcu(&obj->rcu, __i915_gem_free_object_rcu); } @@ -4882,10 +4883,8 @@ void i915_gem_sanitize(struct drm_i915_private *i915) * it may impact the display and we are uncertain about the stability * of the reset, so this could be applied to even earlier gen. */ - if (INTEL_GEN(i915) >= 5) { - int reset = intel_gpu_reset(i915, ALL_ENGINES); - WARN_ON(reset && reset != -ENODEV); - } + if (INTEL_GEN(i915) >= 5 && intel_has_gpu_reset(i915)) + WARN_ON(intel_gpu_reset(i915, ALL_ENGINES)); } int i915_gem_suspend(struct drm_i915_private *dev_priv) @@ -5065,8 +5064,11 @@ static int __i915_gem_restart_engines(void *data) for_each_engine(engine, i915, id) { err = engine->init_hw(engine); - if (err) + if (err) { + DRM_ERROR("Failed to restart %s (%d)\n", + engine->name, err); return err; + } } return 0; @@ -5118,14 +5120,16 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv) ret = i915_ppgtt_init_hw(dev_priv); if (ret) { - DRM_ERROR("PPGTT enable HW failed %d\n", ret); + DRM_ERROR("Enabling PPGTT failed (%d)\n", ret); goto out; } /* We can't enable contexts until all firmware is loaded */ ret = intel_uc_init_hw(dev_priv); - if (ret) + if (ret) { + DRM_ERROR("Enabling uc failed (%d)\n", ret); goto out; + } intel_mocs_init_l3cc_table(dev_priv); @@ -5415,10 +5419,10 @@ i915_gem_load_init_fences(struct drm_i915_private *dev_priv) { int i; - if (INTEL_INFO(dev_priv)->gen >= 7 && !IS_VALLEYVIEW(dev_priv) && + if (INTEL_GEN(dev_priv) >= 7 && !IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) dev_priv->num_fence_regs = 32; - else if (INTEL_INFO(dev_priv)->gen >= 4 || + else if (INTEL_GEN(dev_priv) >= 4 || IS_I945G(dev_priv) || IS_I945GM(dev_priv) || IS_G33(dev_priv) || IS_PINEVIEW(dev_priv)) dev_priv->num_fence_regs = 16; @@ -5537,7 +5541,8 @@ err_out: void i915_gem_load_cleanup(struct drm_i915_private *dev_priv) { i915_gem_drain_freed_objects(dev_priv); - WARN_ON(!llist_empty(&dev_priv->mm.free_list)); + GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); + GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count)); WARN_ON(dev_priv->mm.object_count); mutex_lock(&dev_priv->drm.struct_mutex); @@ -5693,7 +5698,7 @@ i915_gem_object_create_from_data(struct drm_i915_private *dev_priv, if (IS_ERR(obj)) return obj; - GEM_BUG_ON(obj->base.write_domain != I915_GEM_DOMAIN_CPU); + GEM_BUG_ON(obj->write_domain != I915_GEM_DOMAIN_CPU); file = obj->base.filp; offset = 0; diff --git a/drivers/gpu/drm/i915/i915_gem_clflush.c b/drivers/gpu/drm/i915/i915_gem_clflush.c index b9b53ac14176..f5c570d35b2a 100644 --- a/drivers/gpu/drm/i915/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/i915_gem_clflush.c @@ -177,7 +177,7 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, } else if (obj->mm.pages) { __i915_do_clflush(obj); } else { - GEM_BUG_ON(obj->base.write_domain != I915_GEM_DOMAIN_CPU); + GEM_BUG_ON(obj->write_domain != I915_GEM_DOMAIN_CPU); } obj->cache_dirty = false; diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 648e7536ff51..3d75f484f6e5 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -338,11 +338,6 @@ static void __destroy_hw_context(struct i915_gem_context *ctx, context_close(ctx); } -/** - * The default context needs to exist per ring that uses contexts. It stores the - * context state of the GPU for applications that don't utilize HW contexts, as - * well as an idle case. - */ static struct i915_gem_context * i915_gem_create_context(struct drm_i915_private *dev_priv, struct drm_i915_file_private *file_priv) @@ -449,12 +444,18 @@ destroy_kernel_context(struct i915_gem_context **ctxp) i915_gem_context_free(ctx); } +static bool needs_preempt_context(struct drm_i915_private *i915) +{ + return HAS_LOGICAL_RING_PREEMPTION(i915); +} + int i915_gem_contexts_init(struct drm_i915_private *dev_priv) { struct i915_gem_context *ctx; - int err; + /* Reassure ourselves we are only called once */ GEM_BUG_ON(dev_priv->kernel_context); + GEM_BUG_ON(dev_priv->preempt_context); INIT_LIST_HEAD(&dev_priv->contexts.list); INIT_WORK(&dev_priv->contexts.free_work, contexts_free_worker); @@ -468,8 +469,7 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) ctx = i915_gem_context_create_kernel(dev_priv, I915_PRIORITY_MIN); if (IS_ERR(ctx)) { DRM_ERROR("Failed to create default global context\n"); - err = PTR_ERR(ctx); - goto err; + return PTR_ERR(ctx); } /* * For easy recognisablity, we want the kernel context to be 0 and then @@ -479,23 +479,18 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) dev_priv->kernel_context = ctx; /* highest priority; preempting task */ - ctx = i915_gem_context_create_kernel(dev_priv, INT_MAX); - if (IS_ERR(ctx)) { - DRM_ERROR("Failed to create default preempt context\n"); - err = PTR_ERR(ctx); - goto err_kernel_context; + if (needs_preempt_context(dev_priv)) { + ctx = i915_gem_context_create_kernel(dev_priv, INT_MAX); + if (!IS_ERR(ctx)) + dev_priv->preempt_context = ctx; + else + DRM_ERROR("Failed to create preempt context; disabling preemption\n"); } - dev_priv->preempt_context = ctx; DRM_DEBUG_DRIVER("%s context support initialized\n", dev_priv->engine[RCS]->context_size ? "logical" : "fake"); return 0; - -err_kernel_context: - destroy_kernel_context(&dev_priv->kernel_context); -err: - return err; } void i915_gem_contexts_lost(struct drm_i915_private *dev_priv) @@ -521,7 +516,8 @@ void i915_gem_contexts_fini(struct drm_i915_private *i915) { lockdep_assert_held(&i915->drm.struct_mutex); - destroy_kernel_context(&i915->preempt_context); + if (i915->preempt_context) + destroy_kernel_context(&i915->preempt_context); destroy_kernel_context(&i915->kernel_context); /* Must free all deferred contexts (via flush_workqueue) first */ @@ -803,11 +799,11 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, case I915_CONTEXT_PARAM_PRIORITY: { - int priority = args->value; + s64 priority = args->value; if (args->size) ret = -EINVAL; - else if (!to_i915(dev)->engine[RCS]->schedule) + else if (!(to_i915(dev)->caps.scheduler & I915_SCHEDULER_CAP_PRIORITY)) ret = -ENODEV; else if (priority > I915_CONTEXT_MAX_USER_PRIORITY || priority < I915_CONTEXT_MIN_USER_PRIORITY) diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h index 4bfb72f8e1cb..a681c5b891ff 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.h +++ b/drivers/gpu/drm/i915/i915_gem_context.h @@ -29,6 +29,8 @@ #include <linux/list.h> #include <linux/radix-tree.h> +#include "i915_gem.h" + struct pid; struct drm_device; @@ -36,6 +38,7 @@ struct drm_file; struct drm_i915_private; struct drm_i915_file_private; +struct drm_i915_gem_request; struct i915_hw_ppgtt; struct i915_vma; struct intel_ring; diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 864439a214c8..69a7aec49e84 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -330,8 +330,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, * write-combined buffer or a delay through the chipset for GTT * writes that do require us to treat GTT as a separate cache domain.) */ - obj->base.read_domains = I915_GEM_DOMAIN_GTT; - obj->base.write_domain = 0; + obj->read_domains = I915_GEM_DOMAIN_GTT; + obj->write_domain = 0; return &obj->base; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 4401068ff468..4eb28e84fda4 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -505,6 +505,8 @@ eb_add_vma(struct i915_execbuffer *eb, unsigned int i, struct i915_vma *vma) list_add_tail(&vma->exec_link, &eb->unbound); if (drm_mm_node_allocated(&vma->node)) err = i915_vma_unbind(vma); + if (unlikely(err)) + vma->exec_flags = NULL; } return err; } @@ -1073,7 +1075,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, u32 *cmd; int err; - GEM_BUG_ON(vma->obj->base.write_domain & I915_GEM_DOMAIN_CPU); + GEM_BUG_ON(vma->obj->write_domain & I915_GEM_DOMAIN_CPU); obj = i915_gem_batch_pool_get(&eb->engine->batch_pool, PAGE_SIZE); if (IS_ERR(obj)) @@ -1861,16 +1863,16 @@ void i915_vma_move_to_active(struct i915_vma *vma, i915_gem_active_set(&vma->last_read[idx], req); list_move_tail(&vma->vm_link, &vma->vm->active_list); - obj->base.write_domain = 0; + obj->write_domain = 0; if (flags & EXEC_OBJECT_WRITE) { - obj->base.write_domain = I915_GEM_DOMAIN_RENDER; + obj->write_domain = I915_GEM_DOMAIN_RENDER; if (intel_fb_obj_invalidate(obj, ORIGIN_CS)) i915_gem_active_set(&obj->frontbuffer_write, req); - obj->base.read_domains = 0; + obj->read_domains = 0; } - obj->base.read_domains |= I915_GEM_GPU_DOMAINS; + obj->read_domains |= I915_GEM_GPU_DOMAINS; if (flags & EXEC_OBJECT_NEEDS_FENCE) i915_gem_active_set(&vma->last_fence, req); @@ -1973,7 +1975,7 @@ static int eb_submit(struct i915_execbuffer *eb) return 0; } -/** +/* * Find one BSD ring to dispatch the corresponding BSD command. * The engine index is returned. */ @@ -2410,7 +2412,7 @@ err_request: if (out_fence) { if (err == 0) { fd_install(out_fence_fd, out_fence->file); - args->rsvd2 &= GENMASK_ULL(0, 31); /* keep in-fence */ + args->rsvd2 &= GENMASK_ULL(31, 0); /* keep in-fence */ args->rsvd2 |= (u64)out_fence_fd << 32; out_fence_fd = -1; } else { @@ -2463,8 +2465,8 @@ static bool check_buffer_count(size_t count) * list array and passes it to the real function. */ int -i915_gem_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file) +i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) { struct drm_i915_gem_execbuffer *args = data; struct drm_i915_gem_execbuffer2 exec2; @@ -2554,8 +2556,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, } int -i915_gem_execbuffer2(struct drm_device *dev, void *data, - struct drm_file *file) +i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) { struct drm_i915_gem_execbuffer2 *args = data; struct drm_i915_gem_exec_object2 *exec2_list; diff --git a/drivers/gpu/drm/i915/i915_gem_fence_reg.c b/drivers/gpu/drm/i915/i915_gem_fence_reg.c index b8338d75c6f3..d548ac05ccd7 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence_reg.c +++ b/drivers/gpu/drm/i915/i915_gem_fence_reg.c @@ -64,7 +64,7 @@ static void i965_write_fence_reg(struct drm_i915_fence_reg *fence, int fence_pitch_shift; u64 val; - if (INTEL_INFO(fence->i915)->gen >= 6) { + if (INTEL_GEN(fence->i915) >= 6) { fence_reg_lo = FENCE_REG_GEN6_LO(fence->id); fence_reg_hi = FENCE_REG_GEN6_HI(fence->id); fence_pitch_shift = GEN6_FENCE_PITCH_SHIFT; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 955ce7bee448..cd5984246bc3 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -673,27 +673,22 @@ static void free_pd(struct i915_address_space *vm, static void gen8_initialize_pd(struct i915_address_space *vm, struct i915_page_directory *pd) { - unsigned int i; - fill_px(vm, pd, gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC)); - for (i = 0; i < I915_PDES; i++) - pd->page_table[i] = vm->scratch_pt; + memset_p((void **)pd->page_table, vm->scratch_pt, I915_PDES); } static int __pdp_init(struct i915_address_space *vm, struct i915_page_directory_pointer *pdp) { const unsigned int pdpes = i915_pdpes_per_pdp(vm); - unsigned int i; pdp->page_directory = kmalloc_array(pdpes, sizeof(*pdp->page_directory), GFP_KERNEL | __GFP_NOWARN); if (unlikely(!pdp->page_directory)) return -ENOMEM; - for (i = 0; i < pdpes; i++) - pdp->page_directory[i] = vm->scratch_pd; + memset_p((void **)pdp->page_directory, vm->scratch_pd, pdpes); return 0; } @@ -715,7 +710,7 @@ alloc_pdp(struct i915_address_space *vm) struct i915_page_directory_pointer *pdp; int ret = -ENOMEM; - WARN_ON(!use_4lvl(vm)); + GEM_BUG_ON(!use_4lvl(vm)); pdp = kzalloc(sizeof(*pdp), GFP_KERNEL); if (!pdp) @@ -764,12 +759,9 @@ static void gen8_initialize_pdp(struct i915_address_space *vm, static void gen8_initialize_pml4(struct i915_address_space *vm, struct i915_pml4 *pml4) { - unsigned int i; - fill_px(vm, pml4, gen8_pml4e_encode(px_dma(vm->scratch_pdp), I915_CACHE_LLC)); - for (i = 0; i < GEN8_PML4ES_PER_PML4; i++) - pml4->pdps[i] = vm->scratch_pdp; + memset_p((void **)pml4->pdps, vm->scratch_pdp, GEN8_PML4ES_PER_PML4); } /* Broadwell Page Directory Pointer Descriptors */ @@ -2109,7 +2101,7 @@ static int __hw_ppgtt_init(struct i915_hw_ppgtt *ppgtt, ppgtt->base.i915 = dev_priv; ppgtt->base.dma = &dev_priv->drm.pdev->dev; - if (INTEL_INFO(dev_priv)->gen < 8) + if (INTEL_GEN(dev_priv) < 8) return gen6_ppgtt_init(ppgtt); else return gen8_ppgtt_init(ppgtt); @@ -2257,9 +2249,9 @@ void i915_ppgtt_release(struct kref *kref) trace_i915_ppgtt_release(&ppgtt->base); /* vmas should already be unbound and destroyed */ - WARN_ON(!list_empty(&ppgtt->base.active_list)); - WARN_ON(!list_empty(&ppgtt->base.inactive_list)); - WARN_ON(!list_empty(&ppgtt->base.unbound_list)); + GEM_BUG_ON(!list_empty(&ppgtt->base.active_list)); + GEM_BUG_ON(!list_empty(&ppgtt->base.inactive_list)); + GEM_BUG_ON(!list_empty(&ppgtt->base.unbound_list)); ppgtt->base.cleanup(&ppgtt->base); i915_address_space_fini(&ppgtt->base); @@ -2822,10 +2814,10 @@ int i915_gem_init_aliasing_ppgtt(struct drm_i915_private *i915) i915->mm.aliasing_ppgtt = ppgtt; - WARN_ON(ggtt->base.bind_vma != ggtt_bind_vma); + GEM_BUG_ON(ggtt->base.bind_vma != ggtt_bind_vma); ggtt->base.bind_vma = aliasing_gtt_bind_vma; - WARN_ON(ggtt->base.unbind_vma != ggtt_unbind_vma); + GEM_BUG_ON(ggtt->base.unbind_vma != ggtt_unbind_vma); ggtt->base.unbind_vma = aliasing_gtt_unbind_vma; return 0; @@ -2916,7 +2908,7 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv) ggtt->base.closed = true; mutex_lock(&dev_priv->drm.struct_mutex); - WARN_ON(!list_empty(&ggtt->base.active_list)); + GEM_BUG_ON(!list_empty(&ggtt->base.active_list)); list_for_each_entry_safe(vma, vn, &ggtt->base.inactive_list, vm_link) WARN_ON(i915_vma_unbind(vma)); mutex_unlock(&dev_priv->drm.struct_mutex); @@ -3809,6 +3801,9 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma) GEM_BUG_ON(!i915_gem_object_has_pinned_pages(vma->obj)); switch (vma->ggtt_view.type) { + default: + GEM_BUG_ON(vma->ggtt_view.type); + /* fall through */ case I915_GGTT_VIEW_NORMAL: vma->pages = vma->obj->mm.pages; return 0; @@ -3821,11 +3816,6 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma) case I915_GGTT_VIEW_PARTIAL: vma->pages = intel_partial_pages(&vma->ggtt_view, vma->obj); break; - - default: - WARN_ONCE(1, "GGTT view %u not implemented!\n", - vma->ggtt_view.type); - return -EINVAL; } ret = 0; diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c b/drivers/gpu/drm/i915/i915_gem_internal.c index a1d6956734f7..0d0144b2104c 100644 --- a/drivers/gpu/drm/i915/i915_gem_internal.c +++ b/drivers/gpu/drm/i915/i915_gem_internal.c @@ -167,6 +167,10 @@ static const struct drm_i915_gem_object_ops i915_gem_object_internal_ops = { }; /** + * i915_gem_object_create_internal: create an object with volatile pages + * @i915: the i915 device + * @size: the size in bytes of backing storage to allocate for the object + * * Creates a new object that wraps some internal memory for private use. * This object is not backed by swappable storage, and as such its contents * are volatile and only valid whilst pinned. If the object is reaped by the @@ -197,8 +201,8 @@ i915_gem_object_create_internal(struct drm_i915_private *i915, drm_gem_private_object_init(&i915->drm, &obj->base, size); i915_gem_object_init(obj, &i915_gem_object_internal_ops); - obj->base.read_domains = I915_GEM_DOMAIN_CPU; - obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE; i915_gem_object_set_cache_coherency(obj, cache_level); diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h index 05e89e1c0a08..ca2b3b62569d 100644 --- a/drivers/gpu/drm/i915/i915_gem_object.h +++ b/drivers/gpu/drm/i915/i915_gem_object.h @@ -148,6 +148,21 @@ struct drm_i915_gem_object { #define I915_BO_CACHE_COHERENT_FOR_WRITE BIT(1) unsigned int cache_dirty:1; + /** + * @read_domains: Read memory domains. + * + * These monitor which caches contain read/write data related to the + * object. When transitioning from one set of domains to another, + * the driver is called to ensure that caches are suitably flushed and + * invalidated. + */ + u16 read_domains; + + /** + * @write_domain: Corresponding unique write memory domain. + */ + u16 write_domain; + atomic_t frontbuffer_bits; unsigned int frontbuffer_ggtt_origin; /* write once */ struct i915_gem_active frontbuffer_write; diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 8efa9e7a9e46..8bc7c50b8418 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -443,12 +443,14 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) engine->last_retired_context = request->ctx; spin_lock_irq(&request->lock); - if (request->waitboost) - atomic_dec(&request->i915->gt_pm.rps.num_waiters); if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &request->fence.flags)) dma_fence_signal_locked(&request->fence); if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags)) intel_engine_cancel_signaling(request); + if (request->waitboost) { + GEM_BUG_ON(!atomic_read(&request->i915->gt_pm.rps.num_waiters)); + atomic_dec(&request->i915->gt_pm.rps.num_waiters); + } spin_unlock_irq(&request->lock); i915_priotree_fini(request->i915, &request->priotree); @@ -916,9 +918,9 @@ i915_gem_request_await_dma_fence(struct drm_i915_gem_request *req, /** * i915_gem_request_await_object - set this request to (async) wait upon a bo - * * @to: request we are wishing to use * @obj: object which may be in use on another ring. + * @write: whether the wait is on behalf of a writer * * This code is meant to abstract object synchronization with the GPU. * Conceptually we serialise writes between engines inside the GPU. @@ -993,7 +995,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) lockdep_assert_held(&request->i915->drm.struct_mutex); trace_i915_gem_request_add(request); - /* Make sure that no request gazumped us - if it was allocated after + /* + * Make sure that no request gazumped us - if it was allocated after * our i915_gem_request_alloc() and called __i915_add_request() before * us, the timeline will hold its seqno which is later than ours. */ @@ -1020,7 +1023,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) WARN(err, "engine->emit_flush() failed: %d!\n", err); } - /* Record the position of the start of the breadcrumb so that + /* + * Record the position of the start of the breadcrumb so that * should we detect the updated seqno part-way through the * GPU processing the request, we never over-estimate the * position of the ring's HEAD. @@ -1029,7 +1033,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) GEM_BUG_ON(IS_ERR(cs)); request->postfix = intel_ring_offset(request, cs); - /* Seal the request and mark it as pending execution. Note that + /* + * Seal the request and mark it as pending execution. Note that * we may inspect this state, without holding any locks, during * hangcheck. Hence we apply the barrier to ensure that we do not * see a more recent value in the hws than we are tracking. @@ -1037,7 +1042,7 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) prev = i915_gem_active_raw(&timeline->last_request, &request->i915->drm.struct_mutex); - if (prev) { + if (prev && !i915_gem_request_completed(prev)) { i915_sw_fence_await_sw_fence(&request->submit, &prev->submit, &request->submitq); if (engine->schedule) @@ -1057,7 +1062,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) list_add_tail(&request->ring_link, &ring->request_list); request->emitted_jiffies = jiffies; - /* Let the backend know a new request has arrived that may need + /* + * Let the backend know a new request has arrived that may need * to adjust the existing execution schedule due to a high priority * request - i.e. we may want to preempt the current request in order * to run a high priority dependency chain *before* we can execute this @@ -1073,6 +1079,26 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) local_bh_disable(); i915_sw_fence_commit(&request->submit); local_bh_enable(); /* Kick the execlists tasklet if just scheduled */ + + /* + * In typical scenarios, we do not expect the previous request on + * the timeline to be still tracked by timeline->last_request if it + * has been completed. If the completed request is still here, that + * implies that request retirement is a long way behind submission, + * suggesting that we haven't been retiring frequently enough from + * the combination of retire-before-alloc, waiters and the background + * retirement worker. So if the last request on this timeline was + * already completed, do a catch up pass, flushing the retirement queue + * up to this client. Since we have now moved the heaviest operations + * during retirement onto secondary workers, such as freeing objects + * or contexts, retiring a bunch of requests is mostly list management + * (and cache misses), and so we should not be overly penalizing this + * client by performing excess work, though we may still performing + * work on behalf of others -- but instead we should benefit from + * improved resource management. (Well, that's the theory at least.) + */ + if (prev && i915_gem_request_completed(prev)) + i915_gem_request_retire_upto(prev); } static unsigned long local_clock_us(unsigned int *cpu) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index d3f222fa6356..62aa67960bf4 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -356,7 +356,7 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) reserved_base = 0; reserved_size = 0; - switch (INTEL_INFO(dev_priv)->gen) { + switch (INTEL_GEN(dev_priv)) { case 2: case 3: break; @@ -516,7 +516,7 @@ _i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, i915_gem_object_init(obj, &i915_gem_object_stolen_ops); obj->stolen = stolen; - obj->base.read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT; + obj->read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT; cache_level = HAS_LLC(dev_priv) ? I915_CACHE_LLC : I915_CACHE_NONE; i915_gem_object_set_cache_coherency(obj, cache_level); diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 382a77a1097e..d596a8302ca3 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -721,7 +721,7 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = { .release = i915_gem_userptr_release, }; -/** +/* * Creates a new mm object that wraps some normal memory from the process * context - user memory. * @@ -757,7 +757,9 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = { * dma-buf instead. */ int -i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +i915_gem_userptr_ioctl(struct drm_device *dev, + void *data, + struct drm_file *file) { struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_gem_userptr *args = data; @@ -796,8 +798,8 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file drm_gem_private_object_init(dev, &obj->base, args->user_size); i915_gem_object_init(obj, &i915_gem_userptr_ops); - obj->base.read_domains = I915_GEM_DOMAIN_CPU; - obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; i915_gem_object_set_cache_coherency(obj, I915_CACHE_LLC); obj->userptr.ptr = args->user_ptr; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 67c902412193..65c0bef73ee5 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -579,11 +579,13 @@ static void print_error_obj(struct drm_i915_error_state_buf *m, } static void err_print_capabilities(struct drm_i915_error_state_buf *m, - const struct intel_device_info *info) + const struct intel_device_info *info, + const struct intel_driver_caps *caps) { struct drm_printer p = i915_error_printer(m); intel_device_info_dump_flags(info, &p); + intel_driver_caps_print(caps, &p); } static void err_print_params(struct drm_i915_error_state_buf *m, @@ -808,7 +810,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, if (error->display) intel_display_print_error_state(m, error->display); - err_print_capabilities(m, &error->device_info); + err_print_capabilities(m, &error->device_info, &error->driver_caps); err_print_params(m, &error->params); err_print_uc(m, &error->uc); @@ -1019,8 +1021,8 @@ static void capture_bo(struct drm_i915_error_buffer *err, err->engine = __active_get_engine_id(&obj->frontbuffer_write); err->gtt_offset = vma->node.start; - err->read_domains = obj->base.read_domains; - err->write_domain = obj->base.write_domain; + err->read_domains = obj->read_domains; + err->write_domain = obj->write_domain; err->fence_reg = vma->fence ? vma->fence->id : -1; err->tiling = i915_gem_object_get_tiling(obj); err->dirty = obj->mm.dirty; @@ -1740,6 +1742,7 @@ static void i915_capture_gen_state(struct drm_i915_private *dev_priv, memcpy(&error->device_info, INTEL_INFO(dev_priv), sizeof(error->device_info)); + error->driver_caps = dev_priv->caps; } static __always_inline void dup_param(const char *type, void *x) @@ -1802,14 +1805,16 @@ i915_capture_gpu_state(struct drm_i915_private *i915) /** * i915_capture_error_state - capture an error record for later analysis - * @dev: drm device + * @i915: i915 device + * @engine_mask: the mask of engines triggering the hang + * @error_msg: a message to insert into the error capture header * * Should be called when an error is detected (either a hang or an error * interrupt) to capture error state from the time of the error. Fills * out a structure which becomes available in debugfs for user level tools * to pick up. */ -void i915_capture_error_state(struct drm_i915_private *dev_priv, +void i915_capture_error_state(struct drm_i915_private *i915, u32 engine_mask, const char *error_msg) { @@ -1820,25 +1825,25 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv, if (!i915_modparams.error_capture) return; - if (READ_ONCE(dev_priv->gpu_error.first_error)) + if (READ_ONCE(i915->gpu_error.first_error)) return; - error = i915_capture_gpu_state(dev_priv); + error = i915_capture_gpu_state(i915); if (!error) { DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); return; } - i915_error_capture_msg(dev_priv, error, engine_mask, error_msg); + i915_error_capture_msg(i915, error, engine_mask, error_msg); DRM_INFO("%s\n", error->error_msg); if (!error->simulated) { - spin_lock_irqsave(&dev_priv->gpu_error.lock, flags); - if (!dev_priv->gpu_error.first_error) { - dev_priv->gpu_error.first_error = error; + spin_lock_irqsave(&i915->gpu_error.lock, flags); + if (!i915->gpu_error.first_error) { + i915->gpu_error.first_error = error; error = NULL; } - spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags); + spin_unlock_irqrestore(&i915->gpu_error.lock, flags); } if (error) { @@ -1853,7 +1858,7 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv, 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->drm.primary->index); + i915->drm.primary->index); warned = true; } } diff --git a/drivers/gpu/drm/i915/i915_ioc32.c b/drivers/gpu/drm/i915/i915_ioc32.c index 97f3a5640289..0e5c580d117c 100644 --- a/drivers/gpu/drm/i915/i915_ioc32.c +++ b/drivers/gpu/drm/i915/i915_ioc32.c @@ -1,11 +1,6 @@ -/** - * \file i915_ioc32.c - * +/* * 32-bit ioctl compatibility routines for the i915 DRM. * - * \author Alan Hourihane <alanh@fairlite.demon.co.uk> - * - * * Copyright (C) Paul Mackerras 2005 * Copyright (C) Alan Hourihane 2005 * All Rights Reserved. @@ -28,6 +23,8 @@ * 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. + * + * Author: Alan Hourihane <alanh@fairlite.demon.co.uk> */ #include <linux/compat.h> @@ -55,10 +52,10 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd, return -EFAULT; request = compat_alloc_user_space(sizeof(*request)); - if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) - || __put_user(req32.param, &request->param) - || __put_user((void __user *)(unsigned long)req32.value, - &request->value)) + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) || + __put_user(req32.param, &request->param) || + __put_user((void __user *)(unsigned long)req32.value, + &request->value)) return -EFAULT; return drm_ioctl(file, DRM_IOCTL_I915_GETPARAM, @@ -70,13 +67,13 @@ static drm_ioctl_compat_t *i915_compat_ioctls[] = { }; /** + * i915_compat_ioctl - handle the mistakes of the past + * @filp: the file pointer + * @cmd: the ioctl command (and encoded flags) + * @arg: the ioctl argument (from userspace) + * * Called whenever a 32-bit process running under a 64-bit kernel * performs an ioctl on /dev/dri/card<n>. - * - * \param filp file pointer. - * \param cmd command. - * \param arg user argument. - * \return zero on success or negative number on failure. */ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b886bd459acc..17de6cef2a30 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1413,64 +1413,73 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) tasklet_hi_schedule(&execlists->tasklet); } -static void gen8_gt_irq_ack(struct drm_i915_private *dev_priv, +static void gen8_gt_irq_ack(struct drm_i915_private *i915, u32 master_ctl, u32 gt_iir[4]) { + void __iomem * const regs = i915->regs; + +#define GEN8_GT_IRQS (GEN8_GT_RCS_IRQ | \ + GEN8_GT_BCS_IRQ | \ + GEN8_GT_VCS1_IRQ | \ + GEN8_GT_VCS2_IRQ | \ + GEN8_GT_VECS_IRQ | \ + GEN8_GT_PM_IRQ | \ + GEN8_GT_GUC_IRQ) + if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { - gt_iir[0] = I915_READ_FW(GEN8_GT_IIR(0)); - if (gt_iir[0]) - I915_WRITE_FW(GEN8_GT_IIR(0), gt_iir[0]); + gt_iir[0] = raw_reg_read(regs, GEN8_GT_IIR(0)); + if (likely(gt_iir[0])) + raw_reg_write(regs, GEN8_GT_IIR(0), gt_iir[0]); } if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) { - gt_iir[1] = I915_READ_FW(GEN8_GT_IIR(1)); - if (gt_iir[1]) - I915_WRITE_FW(GEN8_GT_IIR(1), gt_iir[1]); + gt_iir[1] = raw_reg_read(regs, GEN8_GT_IIR(1)); + if (likely(gt_iir[1])) + raw_reg_write(regs, GEN8_GT_IIR(1), gt_iir[1]); } - if (master_ctl & GEN8_GT_VECS_IRQ) { - gt_iir[3] = I915_READ_FW(GEN8_GT_IIR(3)); - if (gt_iir[3]) - I915_WRITE_FW(GEN8_GT_IIR(3), gt_iir[3]); + if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { + gt_iir[2] = raw_reg_read(regs, GEN8_GT_IIR(2)); + if (likely(gt_iir[2] & (i915->pm_rps_events | + i915->pm_guc_events))) + raw_reg_write(regs, GEN8_GT_IIR(2), + gt_iir[2] & (i915->pm_rps_events | + i915->pm_guc_events)); } - if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { - gt_iir[2] = I915_READ_FW(GEN8_GT_IIR(2)); - if (gt_iir[2] & (dev_priv->pm_rps_events | - dev_priv->pm_guc_events)) { - I915_WRITE_FW(GEN8_GT_IIR(2), - gt_iir[2] & (dev_priv->pm_rps_events | - dev_priv->pm_guc_events)); - } + if (master_ctl & GEN8_GT_VECS_IRQ) { + gt_iir[3] = raw_reg_read(regs, GEN8_GT_IIR(3)); + if (likely(gt_iir[3])) + raw_reg_write(regs, GEN8_GT_IIR(3), gt_iir[3]); } } -static void gen8_gt_irq_handler(struct drm_i915_private *dev_priv, - u32 gt_iir[4]) +static void gen8_gt_irq_handler(struct drm_i915_private *i915, + u32 master_ctl, u32 gt_iir[4]) { - if (gt_iir[0]) { - gen8_cs_irq_handler(dev_priv->engine[RCS], + if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { + gen8_cs_irq_handler(i915->engine[RCS], gt_iir[0], GEN8_RCS_IRQ_SHIFT); - gen8_cs_irq_handler(dev_priv->engine[BCS], + gen8_cs_irq_handler(i915->engine[BCS], gt_iir[0], GEN8_BCS_IRQ_SHIFT); } - if (gt_iir[1]) { - gen8_cs_irq_handler(dev_priv->engine[VCS], + if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) { + gen8_cs_irq_handler(i915->engine[VCS], gt_iir[1], GEN8_VCS1_IRQ_SHIFT); - gen8_cs_irq_handler(dev_priv->engine[VCS2], + gen8_cs_irq_handler(i915->engine[VCS2], gt_iir[1], GEN8_VCS2_IRQ_SHIFT); } - if (gt_iir[3]) - gen8_cs_irq_handler(dev_priv->engine[VECS], + if (master_ctl & GEN8_GT_VECS_IRQ) { + gen8_cs_irq_handler(i915->engine[VECS], gt_iir[3], GEN8_VECS_IRQ_SHIFT); + } - if (gt_iir[2] & dev_priv->pm_rps_events) - gen6_rps_irq_handler(dev_priv, gt_iir[2]); - - if (gt_iir[2] & dev_priv->pm_guc_events) - gen9_guc_irq_handler(dev_priv, gt_iir[2]); + if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { + gen6_rps_irq_handler(i915, gt_iir[2]); + gen9_guc_irq_handler(i915, gt_iir[2]); + } } static bool bxt_port_hotplug_long_detect(enum port port, u32 val) @@ -2085,9 +2094,9 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) do { u32 master_ctl, iir; - u32 gt_iir[4] = {}; u32 pipe_stats[I915_MAX_PIPES] = {}; u32 hotplug_status = 0; + u32 gt_iir[4]; u32 ier = 0; master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; @@ -2140,7 +2149,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); POSTING_READ(GEN8_MASTER_IRQ); - gen8_gt_irq_handler(dev_priv, gt_iir); + gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir); if (hotplug_status) i9xx_hpd_irq_handler(dev_priv, hotplug_status); @@ -2675,10 +2684,9 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) static irqreturn_t gen8_irq_handler(int irq, void *arg) { - struct drm_device *dev = arg; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(arg); u32 master_ctl; - u32 gt_iir[4] = {}; + u32 gt_iir[4]; if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; @@ -2690,18 +2698,19 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) I915_WRITE_FW(GEN8_MASTER_IRQ, 0); - /* IRQs are synced during runtime_suspend, we don't require a wakeref */ - disable_rpm_wakeref_asserts(dev_priv); - /* Find, clear, then process each source of interrupt */ gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir); - gen8_gt_irq_handler(dev_priv, gt_iir); - gen8_de_irq_handler(dev_priv, master_ctl); + + /* IRQs are synced during runtime_suspend, we don't require a wakeref */ + if (master_ctl & ~GEN8_GT_IRQS) { + disable_rpm_wakeref_asserts(dev_priv); + gen8_de_irq_handler(dev_priv, master_ctl); + enable_rpm_wakeref_asserts(dev_priv); + } I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); - POSTING_READ_FW(GEN8_MASTER_IRQ); - enable_rpm_wakeref_asserts(dev_priv); + gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir); return IRQ_HANDLED; } @@ -2951,6 +2960,12 @@ static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe) ilk_enable_display_irq(dev_priv, bit); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + /* Even though there is no DMC, frame counter can get stuck when + * PSR is active as no frames are generated. + */ + if (HAS_PSR(dev_priv)) + drm_vblank_restore(dev, pipe); + return 0; } @@ -2963,6 +2978,12 @@ static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe) bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + /* Even if there is no DMC, frame counter can get stuck when + * PSR is active as no frames are generated, so check only for PSR. + */ + if (HAS_PSR(dev_priv)) + drm_vblank_restore(dev, pipe); + return 0; } diff --git a/drivers/gpu/drm/i915/i915_oa_cflgt3.c b/drivers/gpu/drm/i915/i915_oa_cflgt3.c index 42ff06fe54a3..792facdb6702 100644 --- a/drivers/gpu/drm/i915/i915_oa_cflgt3.c +++ b/drivers/gpu/drm/i915/i915_oa_cflgt3.c @@ -84,9 +84,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) void i915_perf_load_test_config_cflgt3(struct drm_i915_private *dev_priv) { - strncpy(dev_priv->perf.oa.test_config.uuid, + strlcpy(dev_priv->perf.oa.test_config.uuid, "577e8e2c-3fa0-4875-8743-3538d585e3b0", - UUID_STRING_LEN); + sizeof(dev_priv->perf.oa.test_config.uuid)); dev_priv->perf.oa.test_config.id = 1; dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; diff --git a/drivers/gpu/drm/i915/i915_oa_cnl.c b/drivers/gpu/drm/i915/i915_oa_cnl.c index ff0ac3627cc4..ba9140c87cc0 100644 --- a/drivers/gpu/drm/i915/i915_oa_cnl.c +++ b/drivers/gpu/drm/i915/i915_oa_cnl.c @@ -96,9 +96,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) void i915_perf_load_test_config_cnl(struct drm_i915_private *dev_priv) { - strncpy(dev_priv->perf.oa.test_config.uuid, + strlcpy(dev_priv->perf.oa.test_config.uuid, "db41edd4-d8e7-4730-ad11-b9a2d6833503", - UUID_STRING_LEN); + sizeof(dev_priv->perf.oa.test_config.uuid)); dev_priv->perf.oa.test_config.id = 1; dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 4e7a10c89782..1eaabf28d7b7 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -29,6 +29,9 @@ #include "i915_drv.h" #include "i915_selftest.h" +#define PLATFORM(x) .platform = (x), .platform_mask = BIT(x) +#define GEN(x) .gen = (x), .gen_mask = BIT((x) - 1) + #define GEN_DEFAULT_PIPEOFFSETS \ .pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \ PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \ @@ -63,7 +66,8 @@ .page_sizes = I915_GTT_PAGE_SIZE_4K #define GEN2_FEATURES \ - .gen = 2, .num_pipes = 1, \ + GEN(2), \ + .num_pipes = 1, \ .has_overlay = 1, .overlay_needs_physical = 1, \ .has_gmch_display = 1, \ .hws_needs_physical = 1, \ @@ -76,19 +80,20 @@ static const struct intel_device_info intel_i830_info = { GEN2_FEATURES, - .platform = INTEL_I830, + PLATFORM(INTEL_I830), .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2, /* legal, last one wins */ }; static const struct intel_device_info intel_i845g_info = { GEN2_FEATURES, - .platform = INTEL_I845G, + PLATFORM(INTEL_I845G), }; static const struct intel_device_info intel_i85x_info = { GEN2_FEATURES, - .platform = INTEL_I85X, .is_mobile = 1, + PLATFORM(INTEL_I85X), + .is_mobile = 1, .num_pipes = 2, /* legal, last one wins */ .cursor_needs_physical = 1, .has_fbc = 1, @@ -96,11 +101,12 @@ static const struct intel_device_info intel_i85x_info = { static const struct intel_device_info intel_i865g_info = { GEN2_FEATURES, - .platform = INTEL_I865G, + PLATFORM(INTEL_I865G), }; #define GEN3_FEATURES \ - .gen = 3, .num_pipes = 2, \ + GEN(3), \ + .num_pipes = 2, \ .has_gmch_display = 1, \ .ring_mask = RENDER_RING, \ .has_snoop = true, \ @@ -110,7 +116,8 @@ static const struct intel_device_info intel_i865g_info = { static const struct intel_device_info intel_i915g_info = { GEN3_FEATURES, - .platform = INTEL_I915G, .cursor_needs_physical = 1, + PLATFORM(INTEL_I915G), + .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .hws_needs_physical = 1, .unfenced_needs_alignment = 1, @@ -118,7 +125,7 @@ static const struct intel_device_info intel_i915g_info = { static const struct intel_device_info intel_i915gm_info = { GEN3_FEATURES, - .platform = INTEL_I915GM, + PLATFORM(INTEL_I915GM), .is_mobile = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, @@ -130,7 +137,7 @@ static const struct intel_device_info intel_i915gm_info = { static const struct intel_device_info intel_i945g_info = { GEN3_FEATURES, - .platform = INTEL_I945G, + PLATFORM(INTEL_I945G), .has_hotplug = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .hws_needs_physical = 1, @@ -139,7 +146,8 @@ static const struct intel_device_info intel_i945g_info = { static const struct intel_device_info intel_i945gm_info = { GEN3_FEATURES, - .platform = INTEL_I945GM, .is_mobile = 1, + PLATFORM(INTEL_I945GM), + .is_mobile = 1, .has_hotplug = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .supports_tv = 1, @@ -150,20 +158,22 @@ static const struct intel_device_info intel_i945gm_info = { static const struct intel_device_info intel_g33_info = { GEN3_FEATURES, - .platform = INTEL_G33, + PLATFORM(INTEL_G33), .has_hotplug = 1, .has_overlay = 1, }; static const struct intel_device_info intel_pineview_info = { GEN3_FEATURES, - .platform = INTEL_PINEVIEW, .is_mobile = 1, + PLATFORM(INTEL_PINEVIEW), + .is_mobile = 1, .has_hotplug = 1, .has_overlay = 1, }; #define GEN4_FEATURES \ - .gen = 4, .num_pipes = 2, \ + GEN(4), \ + .num_pipes = 2, \ .has_hotplug = 1, \ .has_gmch_display = 1, \ .ring_mask = RENDER_RING, \ @@ -174,7 +184,7 @@ static const struct intel_device_info intel_pineview_info = { static const struct intel_device_info intel_i965g_info = { GEN4_FEATURES, - .platform = INTEL_I965G, + PLATFORM(INTEL_I965G), .has_overlay = 1, .hws_needs_physical = 1, .has_snoop = false, @@ -182,7 +192,7 @@ static const struct intel_device_info intel_i965g_info = { static const struct intel_device_info intel_i965gm_info = { GEN4_FEATURES, - .platform = INTEL_I965GM, + PLATFORM(INTEL_I965GM), .is_mobile = 1, .has_fbc = 1, .has_overlay = 1, .supports_tv = 1, @@ -192,20 +202,21 @@ static const struct intel_device_info intel_i965gm_info = { static const struct intel_device_info intel_g45_info = { GEN4_FEATURES, - .platform = INTEL_G45, + PLATFORM(INTEL_G45), .ring_mask = RENDER_RING | BSD_RING, }; static const struct intel_device_info intel_gm45_info = { GEN4_FEATURES, - .platform = INTEL_GM45, + PLATFORM(INTEL_GM45), .is_mobile = 1, .has_fbc = 1, .supports_tv = 1, .ring_mask = RENDER_RING | BSD_RING, }; #define GEN5_FEATURES \ - .gen = 5, .num_pipes = 2, \ + GEN(5), \ + .num_pipes = 2, \ .has_hotplug = 1, \ .ring_mask = RENDER_RING | BSD_RING, \ .has_snoop = true, \ @@ -217,17 +228,18 @@ static const struct intel_device_info intel_gm45_info = { static const struct intel_device_info intel_ironlake_d_info = { GEN5_FEATURES, - .platform = INTEL_IRONLAKE, + PLATFORM(INTEL_IRONLAKE), }; static const struct intel_device_info intel_ironlake_m_info = { GEN5_FEATURES, - .platform = INTEL_IRONLAKE, + PLATFORM(INTEL_IRONLAKE), .is_mobile = 1, .has_fbc = 1, }; #define GEN6_FEATURES \ - .gen = 6, .num_pipes = 2, \ + GEN(6), \ + .num_pipes = 2, \ .has_hotplug = 1, \ .has_fbc = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ @@ -241,7 +253,7 @@ static const struct intel_device_info intel_ironlake_m_info = { #define SNB_D_PLATFORM \ GEN6_FEATURES, \ - .platform = INTEL_SANDYBRIDGE + PLATFORM(INTEL_SANDYBRIDGE) static const struct intel_device_info intel_sandybridge_d_gt1_info = { SNB_D_PLATFORM, @@ -255,7 +267,7 @@ static const struct intel_device_info intel_sandybridge_d_gt2_info = { #define SNB_M_PLATFORM \ GEN6_FEATURES, \ - .platform = INTEL_SANDYBRIDGE, \ + PLATFORM(INTEL_SANDYBRIDGE), \ .is_mobile = 1 @@ -270,7 +282,8 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info = { }; #define GEN7_FEATURES \ - .gen = 7, .num_pipes = 3, \ + GEN(7), \ + .num_pipes = 3, \ .has_hotplug = 1, \ .has_fbc = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ @@ -285,7 +298,7 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info = { #define IVB_D_PLATFORM \ GEN7_FEATURES, \ - .platform = INTEL_IVYBRIDGE, \ + PLATFORM(INTEL_IVYBRIDGE), \ .has_l3_dpf = 1 static const struct intel_device_info intel_ivybridge_d_gt1_info = { @@ -300,7 +313,7 @@ static const struct intel_device_info intel_ivybridge_d_gt2_info = { #define IVB_M_PLATFORM \ GEN7_FEATURES, \ - .platform = INTEL_IVYBRIDGE, \ + PLATFORM(INTEL_IVYBRIDGE), \ .is_mobile = 1, \ .has_l3_dpf = 1 @@ -316,15 +329,15 @@ static const struct intel_device_info intel_ivybridge_m_gt2_info = { static const struct intel_device_info intel_ivybridge_q_info = { GEN7_FEATURES, - .platform = INTEL_IVYBRIDGE, + PLATFORM(INTEL_IVYBRIDGE), .gt = 2, .num_pipes = 0, /* legal, last one wins */ .has_l3_dpf = 1, }; static const struct intel_device_info intel_valleyview_info = { - .platform = INTEL_VALLEYVIEW, - .gen = 7, + PLATFORM(INTEL_VALLEYVIEW), + GEN(7), .is_lp = 1, .num_pipes = 2, .has_psr = 1, @@ -355,7 +368,7 @@ static const struct intel_device_info intel_valleyview_info = { #define HSW_PLATFORM \ G75_FEATURES, \ - .platform = INTEL_HASWELL, \ + PLATFORM(INTEL_HASWELL), \ .has_l3_dpf = 1 static const struct intel_device_info intel_haswell_gt1_info = { @@ -375,6 +388,7 @@ static const struct intel_device_info intel_haswell_gt3_info = { #define GEN8_FEATURES \ G75_FEATURES, \ + GEN(8), \ BDW_COLORS, \ .page_sizes = I915_GTT_PAGE_SIZE_4K | \ I915_GTT_PAGE_SIZE_2M, \ @@ -385,8 +399,7 @@ static const struct intel_device_info intel_haswell_gt3_info = { #define BDW_PLATFORM \ GEN8_FEATURES, \ - .gen = 8, \ - .platform = INTEL_BROADWELL + PLATFORM(INTEL_BROADWELL) static const struct intel_device_info intel_broadwell_gt1_info = { BDW_PLATFORM, @@ -413,11 +426,12 @@ static const struct intel_device_info intel_broadwell_gt3_info = { }; static const struct intel_device_info intel_cherryview_info = { - .gen = 8, .num_pipes = 3, + PLATFORM(INTEL_CHERRYVIEW), + GEN(8), + .num_pipes = 3, .has_hotplug = 1, .is_lp = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, - .platform = INTEL_CHERRYVIEW, .has_64bit_reloc = 1, .has_psr = 1, .has_runtime_pm = 1, @@ -443,6 +457,7 @@ static const struct intel_device_info intel_cherryview_info = { #define GEN9_FEATURES \ GEN8_FEATURES, \ + GEN(9), \ GEN9_DEFAULT_PAGE_SIZES, \ .has_logical_ring_preemption = 1, \ .has_csr = 1, \ @@ -452,8 +467,7 @@ static const struct intel_device_info intel_cherryview_info = { #define SKL_PLATFORM \ GEN9_FEATURES, \ - .gen = 9, \ - .platform = INTEL_SKYLAKE + PLATFORM(INTEL_SKYLAKE) static const struct intel_device_info intel_skylake_gt1_info = { SKL_PLATFORM, @@ -481,7 +495,7 @@ static const struct intel_device_info intel_skylake_gt4_info = { }; #define GEN9_LP_FEATURES \ - .gen = 9, \ + GEN(9), \ .is_lp = 1, \ .has_hotplug = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \ @@ -513,21 +527,20 @@ static const struct intel_device_info intel_skylake_gt4_info = { static const struct intel_device_info intel_broxton_info = { GEN9_LP_FEATURES, - .platform = INTEL_BROXTON, + PLATFORM(INTEL_BROXTON), .ddb_size = 512, }; static const struct intel_device_info intel_geminilake_info = { GEN9_LP_FEATURES, - .platform = INTEL_GEMINILAKE, + PLATFORM(INTEL_GEMINILAKE), .ddb_size = 1024, GLK_COLORS, }; #define KBL_PLATFORM \ GEN9_FEATURES, \ - .gen = 9, \ - .platform = INTEL_KABYLAKE + PLATFORM(INTEL_KABYLAKE) static const struct intel_device_info intel_kabylake_gt1_info = { KBL_PLATFORM, @@ -547,8 +560,7 @@ static const struct intel_device_info intel_kabylake_gt3_info = { #define CFL_PLATFORM \ GEN9_FEATURES, \ - .gen = 9, \ - .platform = INTEL_COFFEELAKE + PLATFORM(INTEL_COFFEELAKE) static const struct intel_device_info intel_coffeelake_gt1_info = { CFL_PLATFORM, @@ -568,30 +580,32 @@ static const struct intel_device_info intel_coffeelake_gt3_info = { #define GEN10_FEATURES \ GEN9_FEATURES, \ + GEN(10), \ .ddb_size = 1024, \ GLK_COLORS static const struct intel_device_info intel_cannonlake_info = { GEN10_FEATURES, - .is_alpha_support = 1, - .platform = INTEL_CANNONLAKE, - .gen = 10, + PLATFORM(INTEL_CANNONLAKE), .gt = 2, }; #define GEN11_FEATURES \ GEN10_FEATURES, \ - .gen = 11, \ + GEN(11), \ .ddb_size = 2048, \ .has_csr = 0 static const struct intel_device_info intel_icelake_11_info = { GEN11_FEATURES, - .platform = INTEL_ICELAKE, + PLATFORM(INTEL_ICELAKE), .is_alpha_support = 1, .has_resource_streamer = 0, }; +#undef GEN +#undef PLATFORM + /* * Make sure any device matches here are from most specific to most * general. For example, since the Quanta match is based on the subsystem diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 1c440460255d..964467b03e4d 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -415,7 +415,94 @@ static int i915_pmu_event_init(struct perf_event *event) return 0; } -static u64 __i915_pmu_event_read(struct perf_event *event) +static u64 __get_rc6(struct drm_i915_private *i915) +{ + u64 val; + + val = intel_rc6_residency_ns(i915, + IS_VALLEYVIEW(i915) ? + VLV_GT_RENDER_RC6 : + GEN6_GT_GFX_RC6); + + if (HAS_RC6p(i915)) + val += intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6p); + + if (HAS_RC6pp(i915)) + val += intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6pp); + + return val; +} + +static u64 get_rc6(struct drm_i915_private *i915, bool locked) +{ +#if IS_ENABLED(CONFIG_PM) + unsigned long flags; + u64 val; + + if (intel_runtime_pm_get_if_in_use(i915)) { + val = __get_rc6(i915); + intel_runtime_pm_put(i915); + + /* + * If we are coming back from being runtime suspended we must + * be careful not to report a larger value than returned + * previously. + */ + + if (!locked) + spin_lock_irqsave(&i915->pmu.lock, flags); + + if (val >= i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) { + i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = 0; + i915->pmu.sample[__I915_SAMPLE_RC6].cur = val; + } else { + val = i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur; + } + + if (!locked) + spin_unlock_irqrestore(&i915->pmu.lock, flags); + } else { + struct pci_dev *pdev = i915->drm.pdev; + struct device *kdev = &pdev->dev; + unsigned long flags2; + + /* + * We are runtime suspended. + * + * Report the delta from when the device was suspended to now, + * on top of the last known real value, as the approximated RC6 + * counter value. + */ + if (!locked) + spin_lock_irqsave(&i915->pmu.lock, flags); + + spin_lock_irqsave(&kdev->power.lock, flags2); + + if (!i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) + i915->pmu.suspended_jiffies_last = + kdev->power.suspended_jiffies; + + val = kdev->power.suspended_jiffies - + i915->pmu.suspended_jiffies_last; + val += jiffies - kdev->power.accounting_timestamp; + + spin_unlock_irqrestore(&kdev->power.lock, flags2); + + val = jiffies_to_nsecs(val); + val += i915->pmu.sample[__I915_SAMPLE_RC6].cur; + i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val; + + if (!locked) + spin_unlock_irqrestore(&i915->pmu.lock, flags); + } + + return val; +#else + return __get_rc6(i915); +#endif +} + +static u64 __i915_pmu_event_read(struct perf_event *event, bool locked) { struct drm_i915_private *i915 = container_of(event->pmu, typeof(*i915), pmu.base); @@ -453,18 +540,7 @@ static u64 __i915_pmu_event_read(struct perf_event *event) val = count_interrupts(i915); break; case I915_PMU_RC6_RESIDENCY: - intel_runtime_pm_get(i915); - val = intel_rc6_residency_ns(i915, - IS_VALLEYVIEW(i915) ? - VLV_GT_RENDER_RC6 : - GEN6_GT_GFX_RC6); - if (HAS_RC6p(i915)) - val += intel_rc6_residency_ns(i915, - GEN6_GT_GFX_RC6p); - if (HAS_RC6pp(i915)) - val += intel_rc6_residency_ns(i915, - GEN6_GT_GFX_RC6pp); - intel_runtime_pm_put(i915); + val = get_rc6(i915, locked); break; } } @@ -479,7 +555,7 @@ static void i915_pmu_event_read(struct perf_event *event) again: prev = local64_read(&hwc->prev_count); - new = __i915_pmu_event_read(event); + new = __i915_pmu_event_read(event, false); if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev) goto again; @@ -534,7 +610,7 @@ static void i915_pmu_enable(struct perf_event *event) * for all listeners. Even when the event was already enabled and has * an existing non-zero value. */ - local64_set(&event->hw.prev_count, __i915_pmu_event_read(event)); + local64_set(&event->hw.prev_count, __i915_pmu_event_read(event, true)); spin_unlock_irqrestore(&i915->pmu.lock, flags); } diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h index 5a2e013a56bb..aa1b1a987ea1 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h @@ -27,6 +27,8 @@ enum { __I915_SAMPLE_FREQ_ACT = 0, __I915_SAMPLE_FREQ_REQ, + __I915_SAMPLE_RC6, + __I915_SAMPLE_RC6_ESTIMATED, __I915_NUM_PMU_SAMPLERS }; @@ -95,6 +97,10 @@ struct i915_pmu { */ struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS]; /** + * @suspended_jiffies_last: Cached suspend time from PM core. + */ + unsigned long suspended_jiffies_last; + /** * @i915_attr: Memory block holding device attributes. */ void *i915_attr; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e9c79b560823..1412abcb27d4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1906,6 +1906,11 @@ enum i915_power_well_id { #define CL_POWER_DOWN_ENABLE (1 << 4) #define SUS_CLOCK_CONFIG (3 << 0) +#define _ICL_PORT_CL_DW5_A 0x162014 +#define _ICL_PORT_CL_DW5_B 0x6C014 +#define ICL_PORT_CL_DW5(port) _MMIO_PORT(port, _ICL_PORT_CL_DW5_A, \ + _ICL_PORT_CL_DW5_B) + #define _PORT_CL1CM_DW9_A 0x162024 #define _PORT_CL1CM_DW9_BC 0x6C024 #define IREF0RC_OFFSET_SHIFT 8 @@ -2029,7 +2034,7 @@ enum i915_power_well_id { #define _CNL_PORT_TX_DW5_LN0_AE 0x162454 #define _CNL_PORT_TX_DW5_LN0_B 0x162654 #define _CNL_PORT_TX_DW5_LN0_C 0x162C54 -#define _CNL_PORT_TX_DW5_LN0_D 0x162ED4 +#define _CNL_PORT_TX_DW5_LN0_D 0x162E54 #define _CNL_PORT_TX_DW5_LN0_F 0x162854 #define CNL_PORT_TX_DW5_GRP(port) _MMIO_PORT6(port, \ _CNL_PORT_TX_DW5_GRP_AE, \ @@ -2060,7 +2065,7 @@ enum i915_power_well_id { #define _CNL_PORT_TX_DW7_LN0_AE 0x16245C #define _CNL_PORT_TX_DW7_LN0_B 0x16265C #define _CNL_PORT_TX_DW7_LN0_C 0x162C5C -#define _CNL_PORT_TX_DW7_LN0_D 0x162EDC +#define _CNL_PORT_TX_DW7_LN0_D 0x162E5C #define _CNL_PORT_TX_DW7_LN0_F 0x16285C #define CNL_PORT_TX_DW7_GRP(port) _MMIO_PORT6(port, \ _CNL_PORT_TX_DW7_GRP_AE, \ @@ -2104,6 +2109,28 @@ enum i915_power_well_id { #define CNL_PORT_COMP_DW9 _MMIO(0x162124) #define CNL_PORT_COMP_DW10 _MMIO(0x162128) +#define _ICL_PORT_COMP_DW0_A 0x162100 +#define _ICL_PORT_COMP_DW0_B 0x6C100 +#define ICL_PORT_COMP_DW0(port) _MMIO_PORT(port, _ICL_PORT_COMP_DW0_A, \ + _ICL_PORT_COMP_DW0_B) +#define _ICL_PORT_COMP_DW1_A 0x162104 +#define _ICL_PORT_COMP_DW1_B 0x6C104 +#define ICL_PORT_COMP_DW1(port) _MMIO_PORT(port, _ICL_PORT_COMP_DW1_A, \ + _ICL_PORT_COMP_DW1_B) +#define _ICL_PORT_COMP_DW3_A 0x16210C +#define _ICL_PORT_COMP_DW3_B 0x6C10C +#define ICL_PORT_COMP_DW3(port) _MMIO_PORT(port, _ICL_PORT_COMP_DW3_A, \ + _ICL_PORT_COMP_DW3_B) +#define _ICL_PORT_COMP_DW9_A 0x162124 +#define _ICL_PORT_COMP_DW9_B 0x6C124 +#define ICL_PORT_COMP_DW9(port) _MMIO_PORT(port, _ICL_PORT_COMP_DW9_A, \ + _ICL_PORT_COMP_DW9_B) +#define _ICL_PORT_COMP_DW10_A 0x162128 +#define _ICL_PORT_COMP_DW10_B 0x6C128 +#define ICL_PORT_COMP_DW10(port) _MMIO_PORT(port, \ + _ICL_PORT_COMP_DW10_A, \ + _ICL_PORT_COMP_DW10_B) + /* BXT PHY Ref registers */ #define _PORT_REF_DW3_A 0x16218C #define _PORT_REF_DW3_BC 0x6C18C @@ -7138,6 +7165,8 @@ enum { #define DISP_DATA_PARTITION_5_6 (1<<6) #define DISP_IPC_ENABLE (1<<3) #define DBUF_CTL _MMIO(0x45008) +#define DBUF_CTL_S1 _MMIO(0x45008) +#define DBUF_CTL_S2 _MMIO(0x44FE8) #define DBUF_POWER_REQUEST (1<<31) #define DBUF_POWER_STATE (1<<30) #define GEN7_MSG_CTL _MMIO(0x45010) @@ -7147,8 +7176,9 @@ enum { #define RESET_PCH_HANDSHAKE_ENABLE (1<<4) #define GEN8_CHICKEN_DCPR_1 _MMIO(0x46430) -#define SKL_SELECT_ALTERNATE_DC_EXIT (1<<30) -#define MASK_WAKEMEM (1<<13) +#define SKL_SELECT_ALTERNATE_DC_EXIT (1 << 30) +#define MASK_WAKEMEM (1 << 13) +#define CNL_DDI_CLOCK_REG_ACCESS_ON (1 << 7) #define SKL_DFSM _MMIO(0x51000) #define SKL_DFSM_CDCLK_LIMIT_MASK (3 << 23) @@ -7160,8 +7190,12 @@ enum { #define SKL_DFSM_PIPE_B_DISABLE (1 << 21) #define SKL_DFSM_PIPE_C_DISABLE (1 << 28) -#define SKL_DSSM _MMIO(0x51004) -#define CNL_DSSM_CDCLK_PLL_REFCLK_24MHz (1 << 31) +#define SKL_DSSM _MMIO(0x51004) +#define CNL_DSSM_CDCLK_PLL_REFCLK_24MHz (1 << 31) +#define ICL_DSSM_CDCLK_PLL_REFCLK_MASK (7 << 29) +#define ICL_DSSM_CDCLK_PLL_REFCLK_24MHz (0 << 29) +#define ICL_DSSM_CDCLK_PLL_REFCLK_19_2MHz (1 << 29) +#define ICL_DSSM_CDCLK_PLL_REFCLK_38_4MHz (2 << 29) #define GEN7_FF_SLICE_CS_CHICKEN1 _MMIO(0x20e0) #define GEN9_FFSC_PERCTX_PREEMPT_CTRL (1<<14) @@ -8794,20 +8828,21 @@ enum skl_power_gate { /* CDCLK_CTL */ #define CDCLK_CTL _MMIO(0x46000) -#define CDCLK_FREQ_SEL_MASK (3<<26) -#define CDCLK_FREQ_450_432 (0<<26) -#define CDCLK_FREQ_540 (1<<26) -#define CDCLK_FREQ_337_308 (2<<26) -#define CDCLK_FREQ_675_617 (3<<26) -#define BXT_CDCLK_CD2X_DIV_SEL_MASK (3<<22) -#define BXT_CDCLK_CD2X_DIV_SEL_1 (0<<22) -#define BXT_CDCLK_CD2X_DIV_SEL_1_5 (1<<22) -#define BXT_CDCLK_CD2X_DIV_SEL_2 (2<<22) -#define BXT_CDCLK_CD2X_DIV_SEL_4 (3<<22) -#define BXT_CDCLK_CD2X_PIPE(pipe) ((pipe)<<20) -#define CDCLK_DIVMUX_CD_OVERRIDE (1<<19) +#define CDCLK_FREQ_SEL_MASK (3 << 26) +#define CDCLK_FREQ_450_432 (0 << 26) +#define CDCLK_FREQ_540 (1 << 26) +#define CDCLK_FREQ_337_308 (2 << 26) +#define CDCLK_FREQ_675_617 (3 << 26) +#define BXT_CDCLK_CD2X_DIV_SEL_MASK (3 << 22) +#define BXT_CDCLK_CD2X_DIV_SEL_1 (0 << 22) +#define BXT_CDCLK_CD2X_DIV_SEL_1_5 (1 << 22) +#define BXT_CDCLK_CD2X_DIV_SEL_2 (2 << 22) +#define BXT_CDCLK_CD2X_DIV_SEL_4 (3 << 22) +#define BXT_CDCLK_CD2X_PIPE(pipe) ((pipe) << 20) +#define CDCLK_DIVMUX_CD_OVERRIDE (1 << 19) #define BXT_CDCLK_CD2X_PIPE_NONE BXT_CDCLK_CD2X_PIPE(3) -#define BXT_CDCLK_SSA_PRECHARGE_ENABLE (1<<16) +#define ICL_CDCLK_CD2X_PIPE_NONE (7 << 19) +#define BXT_CDCLK_SSA_PRECHARGE_ENABLE (1 << 16) #define CDCLK_FREQ_DECIMAL_MASK (0x7ff) /* LCPLL_CTL */ @@ -9716,4 +9751,10 @@ enum skl_power_gate { #define MMCD_PCLA (1 << 31) #define MMCD_HOTSPOT_EN (1 << 27) +#define _ICL_PHY_MISC_A 0x64C00 +#define _ICL_PHY_MISC_B 0x64C04 +#define ICL_PHY_MISC(port) _MMIO_PORT(port, _ICL_PHY_MISC_A, \ + _ICL_PHY_MISC_B) +#define ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN (1 << 23) + #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/i915_syncmap.c b/drivers/gpu/drm/i915/i915_syncmap.c index 0087acf731a8..58f8d0cc125c 100644 --- a/drivers/gpu/drm/i915/i915_syncmap.c +++ b/drivers/gpu/drm/i915/i915_syncmap.c @@ -86,7 +86,7 @@ struct i915_syncmap { /** * i915_syncmap_init -- initialise the #i915_syncmap - * @root - pointer to the #i915_syncmap + * @root: pointer to the #i915_syncmap */ void i915_syncmap_init(struct i915_syncmap **root) { @@ -139,9 +139,9 @@ static inline bool seqno_later(u32 a, u32 b) /** * i915_syncmap_is_later -- compare against the last know sync point - * @root - pointer to the #i915_syncmap - * @id - the context id (other timeline) we are synchronising to - * @seqno - the sequence number along the other timeline + * @root: pointer to the #i915_syncmap + * @id: the context id (other timeline) we are synchronising to + * @seqno: the sequence number along the other timeline * * If we have already synchronised this @root timeline with another (@id) then * we can omit any repeated or earlier synchronisation requests. If the two @@ -339,9 +339,9 @@ found: /** * i915_syncmap_set -- mark the most recent syncpoint between contexts - * @root - pointer to the #i915_syncmap - * @id - the context id (other timeline) we have synchronised to - * @seqno - the sequence number along the other timeline + * @root: pointer to the #i915_syncmap + * @id: the context id (other timeline) we have synchronised to + * @seqno: the sequence number along the other timeline * * When we synchronise this @root timeline with another (@id), we also know * that we have synchronized with all previous seqno along that timeline. If @@ -382,7 +382,7 @@ static void __sync_free(struct i915_syncmap *p) /** * i915_syncmap_free -- free all memory associated with the syncmap - * @root - pointer to the #i915_syncmap + * @root: pointer to the #i915_syncmap * * Either when the timeline is to be freed and we no longer need the sync * point tracking, or when the fences are all known to be signaled and the diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index d452c327dc1d..e9fb692076d7 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -188,13 +188,14 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) /** * intel_crtc_destroy_state - destroy crtc state * @crtc: drm crtc + * @state: the state to destroy * * Destroys the crtc state (both common and Intel-specific) for the * specified crtc. */ void intel_crtc_destroy_state(struct drm_crtc *crtc, - struct drm_crtc_state *state) + struct drm_crtc_state *state) { drm_atomic_helper_crtc_destroy_state(crtc, state); } @@ -202,7 +203,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc, /** * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests * @dev_priv: i915 device - * @crtc: intel crtc + * @intel_crtc: intel crtc * @crtc_state: incoming crtc_state to validate and setup scalers * * This function sets up scalers based on staged scaling requests for diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 0ee32275994a..7481ce85746b 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -85,6 +85,7 @@ intel_plane_duplicate_state(struct drm_plane *plane) __drm_atomic_helper_plane_duplicate_state(plane, state); intel_state->vma = NULL; + intel_state->flags = 0; return state; } diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 522d54fecb53..709d6ca68074 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -704,7 +704,7 @@ void intel_init_audio_hooks(struct drm_i915_private *dev_priv) } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { dev_priv->display.audio_codec_enable = ilk_audio_codec_enable; dev_priv->display.audio_codec_disable = ilk_audio_codec_disable; - } else if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8) { + } else if (IS_HASWELL(dev_priv) || INTEL_GEN(dev_priv) >= 8) { dev_priv->display.audio_codec_enable = hsw_audio_codec_enable; dev_priv->display.audio_codec_disable = hsw_audio_codec_disable; } else if (HAS_PCH_SPLIT(dev_priv)) { @@ -779,11 +779,11 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, { struct intel_encoder *encoder; - if (WARN_ON(pipe >= ARRAY_SIZE(dev_priv->av_enc_map))) - return NULL; - /* MST */ if (pipe >= 0) { + if (WARN_ON(pipe >= ARRAY_SIZE(dev_priv->av_enc_map))) + return NULL; + encoder = dev_priv->av_enc_map[pipe]; /* * when bootup, audio driver may not know it is diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 4e74aa2f16bc..c5c7530ba157 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -391,7 +391,7 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, static int intel_bios_ssc_frequency(struct drm_i915_private *dev_priv, bool alternate) { - switch (INTEL_INFO(dev_priv)->gen) { + switch (INTEL_GEN(dev_priv)) { case 2: return alternate ? 66667 : 48000; case 3: @@ -947,6 +947,86 @@ static int goto_next_sequence_v3(const u8 *data, int index, int total) return 0; } +/* + * Get len of pre-fixed deassert fragment from a v1 init OTP sequence, + * skip all delay + gpio operands and stop at the first DSI packet op. + */ +static int get_init_otp_deassert_fragment_len(struct drm_i915_private *dev_priv) +{ + const u8 *data = dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; + int index, len; + + if (WARN_ON(!data || dev_priv->vbt.dsi.seq_version != 1)) + return 0; + + /* index = 1 to skip sequence byte */ + for (index = 1; data[index] != MIPI_SEQ_ELEM_END; index += len) { + switch (data[index]) { + case MIPI_SEQ_ELEM_SEND_PKT: + return index == 1 ? 0 : index; + case MIPI_SEQ_ELEM_DELAY: + len = 5; /* 1 byte for operand + uint32 */ + break; + case MIPI_SEQ_ELEM_GPIO: + len = 3; /* 1 byte for op, 1 for gpio_nr, 1 for value */ + break; + default: + return 0; + } + } + + return 0; +} + +/* + * Some v1 VBT MIPI sequences do the deassert in the init OTP sequence. + * The deassert must be done before calling intel_dsi_device_ready, so for + * these devices we split the init OTP sequence into a deassert sequence and + * the actual init OTP part. + */ +static void fixup_mipi_sequences(struct drm_i915_private *dev_priv) +{ + u8 *init_otp; + int len; + + /* Limit this to VLV for now. */ + if (!IS_VALLEYVIEW(dev_priv)) + return; + + /* Limit this to v1 vid-mode sequences */ + if (dev_priv->vbt.dsi.config->is_cmd_mode || + dev_priv->vbt.dsi.seq_version != 1) + return; + + /* Only do this if there are otp and assert seqs and no deassert seq */ + if (!dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] || + !dev_priv->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET] || + dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET]) + return; + + /* The deassert-sequence ends at the first DSI packet */ + len = get_init_otp_deassert_fragment_len(dev_priv); + if (!len) + return; + + DRM_DEBUG_KMS("Using init OTP fragment to deassert reset\n"); + + /* Copy the fragment, update seq byte and terminate it */ + init_otp = (u8 *)dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; + dev_priv->vbt.dsi.deassert_seq = kmemdup(init_otp, len + 1, GFP_KERNEL); + if (!dev_priv->vbt.dsi.deassert_seq) + return; + dev_priv->vbt.dsi.deassert_seq[0] = MIPI_SEQ_DEASSERT_RESET; + dev_priv->vbt.dsi.deassert_seq[len] = MIPI_SEQ_ELEM_END; + /* Use the copy for deassert */ + dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET] = + dev_priv->vbt.dsi.deassert_seq; + /* Replace the last byte of the fragment with init OTP seq byte */ + init_otp[len - 1] = MIPI_SEQ_INIT_OTP; + /* And make MIPI_MIPI_SEQ_INIT_OTP point to it */ + dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] = init_otp + len - 1; +} + static void parse_mipi_sequence(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) @@ -1016,6 +1096,8 @@ parse_mipi_sequence(struct drm_i915_private *dev_priv, dev_priv->vbt.dsi.size = seq_size; dev_priv->vbt.dsi.seq_version = sequence->version; + fixup_mipi_sequences(dev_priv); + DRM_DEBUG_DRIVER("MIPI related VBT parsing complete\n"); return; @@ -1611,6 +1693,29 @@ out: } /** + * intel_bios_cleanup - Free any resources allocated by intel_bios_init() + * @dev_priv: i915 device instance + */ +void intel_bios_cleanup(struct drm_i915_private *dev_priv) +{ + 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; + kfree(dev_priv->vbt.dsi.data); + dev_priv->vbt.dsi.data = NULL; + kfree(dev_priv->vbt.dsi.pps); + dev_priv->vbt.dsi.pps = NULL; + kfree(dev_priv->vbt.dsi.config); + dev_priv->vbt.dsi.config = NULL; + kfree(dev_priv->vbt.dsi.deassert_seq); + dev_priv->vbt.dsi.deassert_seq = NULL; +} + +/** * intel_bios_is_tv_present - is integrated TV present in VBT * @dev_priv: i915 device instance * diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index efbc627a2a25..b955f7d7bd0f 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -588,29 +588,16 @@ void intel_engine_remove_wait(struct intel_engine_cs *engine, spin_unlock_irq(&b->rb_lock); } -static bool signal_valid(const struct drm_i915_gem_request *request) -{ - return intel_wait_check_request(&request->signaling.wait, request); -} - static bool signal_complete(const struct drm_i915_gem_request *request) { if (!request) return false; - /* If another process served as the bottom-half it may have already - * signalled that this wait is already completed. - */ - if (intel_wait_complete(&request->signaling.wait)) - return signal_valid(request); - - /* Carefully check if the request is complete, giving time for the + /* + * Carefully check if the request is complete, giving time for the * seqno to be visible or if the GPU hung. */ - if (__i915_request_irq_complete(request)) - return true; - - return false; + return __i915_request_irq_complete(request); } static struct drm_i915_gem_request *to_signaler(struct rb_node *rb) @@ -712,6 +699,7 @@ static int intel_breadcrumbs_signaler(void *arg) &request->fence.flags)) { local_bh_disable(); dma_fence_signal(&request->fence); + GEM_BUG_ON(!i915_gem_request_completed(request)); local_bh_enable(); /* kick start the tasklets */ } diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index ee788d5be5e3..dc7db8a2caf8 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -1778,6 +1778,199 @@ sanitize: dev_priv->cdclk.hw.vco = -1; } +static int icl_calc_cdclk(int min_cdclk, unsigned int ref) +{ + int ranges_24[] = { 312000, 552000, 648000 }; + int ranges_19_38[] = { 307200, 556800, 652800 }; + int *ranges; + + switch (ref) { + default: + MISSING_CASE(ref); + case 24000: + ranges = ranges_24; + break; + case 19200: + case 38400: + ranges = ranges_19_38; + break; + } + + if (min_cdclk > ranges[1]) + return ranges[2]; + else if (min_cdclk > ranges[0]) + return ranges[1]; + else + return ranges[0]; +} + +static int icl_calc_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk) +{ + int ratio; + + if (cdclk == dev_priv->cdclk.hw.bypass) + return 0; + + switch (cdclk) { + default: + MISSING_CASE(cdclk); + case 307200: + case 556800: + case 652800: + WARN_ON(dev_priv->cdclk.hw.ref != 19200 && + dev_priv->cdclk.hw.ref != 38400); + break; + case 312000: + case 552000: + case 648000: + WARN_ON(dev_priv->cdclk.hw.ref != 24000); + } + + ratio = cdclk / (dev_priv->cdclk.hw.ref / 2); + + return dev_priv->cdclk.hw.ref * ratio; +} + +static void icl_set_cdclk(struct drm_i915_private *dev_priv, + const struct intel_cdclk_state *cdclk_state) +{ + unsigned int cdclk = cdclk_state->cdclk; + unsigned int vco = cdclk_state->vco; + int ret; + + mutex_lock(&dev_priv->pcu_lock); + ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL, + SKL_CDCLK_PREPARE_FOR_CHANGE, + SKL_CDCLK_READY_FOR_CHANGE, + SKL_CDCLK_READY_FOR_CHANGE, 3); + mutex_unlock(&dev_priv->pcu_lock); + if (ret) { + DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n", + ret); + return; + } + + if (dev_priv->cdclk.hw.vco != 0 && + dev_priv->cdclk.hw.vco != vco) + cnl_cdclk_pll_disable(dev_priv); + + if (dev_priv->cdclk.hw.vco != vco) + cnl_cdclk_pll_enable(dev_priv, vco); + + I915_WRITE(CDCLK_CTL, ICL_CDCLK_CD2X_PIPE_NONE | + skl_cdclk_decimal(cdclk)); + + mutex_lock(&dev_priv->pcu_lock); + /* TODO: add proper DVFS support. */ + sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, 2); + mutex_unlock(&dev_priv->pcu_lock); + + intel_update_cdclk(dev_priv); +} + +static void icl_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) +{ + u32 val; + + cdclk_state->bypass = 50000; + + val = I915_READ(SKL_DSSM); + switch (val & ICL_DSSM_CDCLK_PLL_REFCLK_MASK) { + default: + MISSING_CASE(val); + case ICL_DSSM_CDCLK_PLL_REFCLK_24MHz: + cdclk_state->ref = 24000; + break; + case ICL_DSSM_CDCLK_PLL_REFCLK_19_2MHz: + cdclk_state->ref = 19200; + break; + case ICL_DSSM_CDCLK_PLL_REFCLK_38_4MHz: + cdclk_state->ref = 38400; + break; + } + + val = I915_READ(BXT_DE_PLL_ENABLE); + if ((val & BXT_DE_PLL_PLL_ENABLE) == 0 || + (val & BXT_DE_PLL_LOCK) == 0) { + /* + * CDCLK PLL is disabled, the VCO/ratio doesn't matter, but + * setting it to zero is a way to signal that. + */ + cdclk_state->vco = 0; + cdclk_state->cdclk = cdclk_state->bypass; + return; + } + + cdclk_state->vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->ref; + + val = I915_READ(CDCLK_CTL); + WARN_ON((val & BXT_CDCLK_CD2X_DIV_SEL_MASK) != 0); + + cdclk_state->cdclk = cdclk_state->vco / 2; +} + +/** + * icl_init_cdclk - Initialize CDCLK on ICL + * @dev_priv: i915 device + * + * Initialize CDCLK for ICL. This consists mainly of initializing + * dev_priv->cdclk.hw and sanitizing the state of the hardware if needed. This + * is generally done only during the display core initialization sequence, after + * which the DMC will take care of turning CDCLK off/on as needed. + */ +void icl_init_cdclk(struct drm_i915_private *dev_priv) +{ + struct intel_cdclk_state sanitized_state; + u32 val; + + /* This sets dev_priv->cdclk.hw. */ + intel_update_cdclk(dev_priv); + intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK"); + + /* This means CDCLK disabled. */ + if (dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.bypass) + goto sanitize; + + val = I915_READ(CDCLK_CTL); + + if ((val & BXT_CDCLK_CD2X_DIV_SEL_MASK) != 0) + goto sanitize; + + if ((val & CDCLK_FREQ_DECIMAL_MASK) != + skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk)) + goto sanitize; + + return; + +sanitize: + DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n"); + + sanitized_state.ref = dev_priv->cdclk.hw.ref; + sanitized_state.cdclk = icl_calc_cdclk(0, sanitized_state.ref); + sanitized_state.vco = icl_calc_cdclk_pll_vco(dev_priv, + sanitized_state.cdclk); + + icl_set_cdclk(dev_priv, &sanitized_state); +} + +/** + * icl_uninit_cdclk - Uninitialize CDCLK on ICL + * @dev_priv: i915 device + * + * Uninitialize CDCLK for ICL. This is done only during the display core + * uninitialization sequence. + */ +void icl_uninit_cdclk(struct drm_i915_private *dev_priv) +{ + struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw; + + cdclk_state.cdclk = cdclk_state.bypass; + cdclk_state.vco = 0; + + icl_set_cdclk(dev_priv, &cdclk_state); +} + /** * cnl_init_cdclk - Initialize CDCLK on CNL * @dev_priv: i915 device @@ -2216,6 +2409,36 @@ static int cnl_modeset_calc_cdclk(struct drm_atomic_state *state) return 0; } +static int icl_modeset_calc_cdclk(struct drm_atomic_state *state) +{ + struct drm_i915_private *dev_priv = to_i915(state->dev); + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + unsigned int ref = intel_state->cdclk.logical.ref; + int min_cdclk, cdclk, vco; + + min_cdclk = intel_compute_min_cdclk(state); + if (min_cdclk < 0) + return min_cdclk; + + cdclk = icl_calc_cdclk(min_cdclk, ref); + vco = icl_calc_cdclk_pll_vco(dev_priv, cdclk); + + intel_state->cdclk.logical.vco = vco; + intel_state->cdclk.logical.cdclk = cdclk; + + if (!intel_state->active_crtcs) { + cdclk = icl_calc_cdclk(0, ref); + vco = icl_calc_cdclk_pll_vco(dev_priv, cdclk); + + intel_state->cdclk.actual.vco = vco; + intel_state->cdclk.actual.cdclk = cdclk; + } else { + intel_state->cdclk.actual = intel_state->cdclk.logical; + } + + return 0; +} + static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv) { int max_cdclk_freq = dev_priv->max_cdclk_freq; @@ -2233,7 +2456,7 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv) return max_cdclk_freq; else if (IS_CHERRYVIEW(dev_priv)) return max_cdclk_freq*95/100; - else if (INTEL_INFO(dev_priv)->gen < 4) + else if (INTEL_GEN(dev_priv) < 4) return 2*max_cdclk_freq*90/100; else return max_cdclk_freq*90/100; @@ -2249,7 +2472,12 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv) */ void intel_update_max_cdclk(struct drm_i915_private *dev_priv) { - if (IS_CANNONLAKE(dev_priv)) { + if (IS_ICELAKE(dev_priv)) { + if (dev_priv->cdclk.hw.ref == 24000) + dev_priv->max_cdclk_freq = 648000; + else + dev_priv->max_cdclk_freq = 652800; + } else if (IS_CANNONLAKE(dev_priv)) { dev_priv->max_cdclk_freq = 528000; } else if (IS_GEN9_BC(dev_priv)) { u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK; @@ -2473,9 +2701,14 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) dev_priv->display.set_cdclk = cnl_set_cdclk; dev_priv->display.modeset_calc_cdclk = cnl_modeset_calc_cdclk; + } else if (IS_ICELAKE(dev_priv)) { + dev_priv->display.set_cdclk = icl_set_cdclk; + dev_priv->display.modeset_calc_cdclk = icl_modeset_calc_cdclk; } - if (IS_CANNONLAKE(dev_priv)) + if (IS_ICELAKE(dev_priv)) + dev_priv->display.get_cdclk = icl_get_cdclk; + else if (IS_CANNONLAKE(dev_priv)) dev_priv->display.get_cdclk = cnl_get_cdclk; else if (IS_GEN9_BC(dev_priv)) dev_priv->display.get_cdclk = skl_get_cdclk; diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 1cd4a7c22bd5..391dd69ae0a4 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -474,14 +474,6 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) return ret; } -/** - * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. - * - * Not for i915G/i915GM - * - * \return true if CRT is connected. - * \return false if CRT is disconnected. - */ static bool intel_crt_detect_hotplug(struct drm_connector *connector) { struct drm_device *dev = connector->dev; @@ -807,10 +799,11 @@ intel_crt_detect(struct drm_connector *connector, else status = connector_status_unknown; intel_release_load_detect_pipe(connector, &tmp, ctx); - } else if (ret == 0) + } else if (ret == 0) { status = connector_status_unknown; - else if (ret < 0) + } else { status = ret; + } out: intel_display_power_put(dev_priv, intel_encoder->power_domain); diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index cfcd9cb37d5d..8ca376aca8bd 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2152,7 +2152,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder, I915_WRITE(DPLL_CTRL2, val); - } else if (INTEL_INFO(dev_priv)->gen < 9) { + } else if (INTEL_GEN(dev_priv) < 9) { I915_WRITE(PORT_CLK_SEL(port), hsw_pll_to_ddi_pll_sel(pll)); } diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index a2c16140169f..298f8996cc54 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -586,3 +586,9 @@ void intel_device_info_runtime_init(struct intel_device_info *info) /* Initialize command stream timestamp frequency */ info->cs_timestamp_frequency_khz = read_timestamp_frequency(dev_priv); } + +void intel_driver_caps_print(const struct intel_driver_caps *caps, + struct drm_printer *p) +{ + drm_printf(p, "scheduler: %x\n", caps->scheduler); +} diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index 9542018d11d0..71fdfb0451ef 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -167,6 +167,10 @@ struct intel_device_info { } color; }; +struct intel_driver_caps { + unsigned int scheduler; +}; + static inline unsigned int sseu_subslice_total(const struct sseu_dev_info *sseu) { return hweight8(sseu->slice_mask) * hweight8(sseu->subslice_mask); @@ -182,4 +186,7 @@ void intel_device_info_dump_flags(const struct intel_device_info *info, void intel_device_info_dump_runtime(const struct intel_device_info *info, struct drm_printer *p); +void intel_driver_caps_print(const struct intel_driver_caps *caps, + struct drm_printer *p); + #endif diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 60ba5bb3f34c..5d46771d58f6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -558,11 +558,11 @@ int chv_calc_dpll_params(int refclk, struct dpll *clock) } #define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) -/** + +/* * Returns whether the given set of divisors are valid for a given refclk with * the given connectors. */ - static bool intel_PLL_is_valid(struct drm_i915_private *dev_priv, const struct intel_limit *limit, const struct dpll *clock) @@ -2029,12 +2029,12 @@ static unsigned int intel_cursor_alignment(const struct drm_i915_private *dev_pr static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv) { - if (INTEL_INFO(dev_priv)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) return 256 * 1024; else if (IS_I965G(dev_priv) || IS_I965GM(dev_priv) || IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) return 128 * 1024; - else if (INTEL_INFO(dev_priv)->gen >= 4) + else if (INTEL_GEN(dev_priv) >= 4) return 4 * 1024; else return 0; @@ -2068,13 +2068,16 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, } struct i915_vma * -intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) +intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, + unsigned int rotation, + unsigned long *out_flags) { struct drm_device *dev = fb->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct i915_ggtt_view view; struct i915_vma *vma; + unsigned int pinctl; u32 alignment; WARN_ON(!mutex_is_locked(&dev->struct_mutex)); @@ -2102,7 +2105,20 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) atomic_inc(&dev_priv->gpu_error.pending_fb_pin); - vma = i915_gem_object_pin_to_display_plane(obj, alignment, &view); + pinctl = 0; + + /* Valleyview is definitely limited to scanning out the first + * 512MiB. Lets presume this behaviour was inherited from the + * g4x display engine and that all earlier gen are similarly + * limited. Testing suggests that it is a little more + * complicated than this. For example, Cherryview appears quite + * happy to scanout from anywhere within its global aperture. + */ + if (HAS_GMCH_DISPLAY(dev_priv)) + pinctl |= PIN_MAPPABLE; + + vma = i915_gem_object_pin_to_display_plane(obj, + alignment, &view, pinctl); if (IS_ERR(vma)) goto err; @@ -2123,7 +2139,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) * something and try to run the system in a "less than optimal" * mode that matches the user configuration. */ - i915_vma_pin_fence(vma); + if (i915_vma_pin_fence(vma) == 0 && vma->fence) + *out_flags |= PLANE_HAS_FENCE; } i915_vma_get(vma); @@ -2134,11 +2151,12 @@ err: return vma; } -void intel_unpin_fb_vma(struct i915_vma *vma) +void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags) { lockdep_assert_held(&vma->vm->i915->drm.struct_mutex); - i915_vma_unpin_fence(vma); + if (flags & PLANE_HAS_FENCE) + i915_vma_unpin_fence(vma); i915_gem_object_unpin_from_display_plane(vma); i915_vma_put(vma); } @@ -2808,7 +2826,9 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, valid_fb: mutex_lock(&dev->struct_mutex); intel_state->vma = - intel_pin_and_fence_fb_obj(fb, primary->state->rotation); + intel_pin_and_fence_fb_obj(fb, + primary->state->rotation, + &intel_state->flags); mutex_unlock(&dev->struct_mutex); if (IS_ERR(intel_state->vma)) { DRM_ERROR("failed to pin boot fb on pipe %d: %li\n", @@ -3163,7 +3183,7 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; - if (INTEL_GEN(dev_priv) < 4) + if (INTEL_GEN(dev_priv) < 5) dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe); switch (fb->format->format) { @@ -4756,8 +4776,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state) /** * skl_update_scaler_plane - Stages update to scaler state for a given plane. - * - * @state: crtc's scaler state + * @crtc_state: crtc's scaler state * @plane_state: atomic plane state to update * * Return @@ -4954,6 +4973,7 @@ static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc) /** * intel_post_enable_primary - Perform operations after enabling primary plane * @crtc: the CRTC whose primary plane was just enabled + * @new_crtc_state: the enabling state * * Performs potentially sleeping operations that must be done after the primary * plane is enabled, such as updating FBC and IPS. Note that this may be @@ -5418,6 +5438,20 @@ static void glk_pipe_scaler_clock_gating_wa(struct drm_i915_private *dev_priv, I915_WRITE(CLKGATE_DIS_PSL(pipe), val); } +static void icl_pipe_mbus_enable(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + uint32_t val; + + val = MBUS_DBOX_BW_CREDIT(1) | MBUS_DBOX_A_CREDIT(2); + + /* Program B credit equally to all pipes */ + val |= MBUS_DBOX_B_CREDIT(24 / INTEL_INFO(dev_priv)->num_pipes); + + I915_WRITE(PIPE_MBUS_DBOX_CTL(pipe), val); +} + static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, struct drm_atomic_state *old_state) { @@ -5495,6 +5529,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, if (dev_priv->display.initial_watermarks != NULL) dev_priv->display.initial_watermarks(old_intel_state, pipe_config); + if (INTEL_GEN(dev_priv) >= 11) + icl_pipe_mbus_enable(intel_crtc); + /* XXX: Do the pipe assertions at the right place for BXT DSI. */ if (!transcoder_is_dsi(cpu_transcoder)) intel_enable_pipe(pipe_config); @@ -6307,7 +6344,7 @@ static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc) const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); /* GDG double wide on either pipe, otherwise pipe A only */ - return INTEL_INFO(dev_priv)->gen < 4 && + return INTEL_GEN(dev_priv) < 4 && (crtc->pipe == PIPE_A || IS_I915G(dev_priv)); } @@ -8194,7 +8231,7 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc_state *config = intel_crtc->config; - if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) { + if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) { u32 val = 0; switch (intel_crtc->config->pipe_bpp) { @@ -9537,7 +9574,8 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, if (HAS_DDI(dev_priv)) cntl |= CURSOR_PIPE_CSC_ENABLE; - cntl |= MCURSOR_PIPE_SELECT(crtc->pipe); + if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv)) + cntl |= MCURSOR_PIPE_SELECT(crtc->pipe); switch (plane_state->base.crtc_w) { case 64: @@ -10702,6 +10740,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state) struct drm_connector_list_iter conn_iter; unsigned int used_ports = 0; unsigned int used_mst_ports = 0; + bool ret = true; /* * Walk the connector list instead of the encoder @@ -10736,7 +10775,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state) /* the same port mustn't appear more than once */ if (used_ports & port_mask) - return false; + ret = false; used_ports |= port_mask; break; @@ -10754,7 +10793,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state) if (used_ports & used_mst_ports) return false; - return true; + return ret; } static void @@ -12075,7 +12114,7 @@ u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) struct drm_device *dev = crtc->base.dev; if (!dev->max_vblank_count) - return drm_crtc_accurate_vblank_count(&crtc->base); + return (u32)drm_crtc_accurate_vblank_count(&crtc->base); return dev->driver->get_vblank_counter(dev, crtc->pipe); } @@ -12616,7 +12655,7 @@ static void add_rps_boost_after_vblank(struct drm_crtc *crtc, /** * intel_prepare_plane_fb - Prepare fb for usage on plane * @plane: drm plane to prepare for - * @fb: framebuffer to prepare for presentation + * @new_state: the plane state being prepared * * Prepares a framebuffer for usage on a display plane. Generally this * involves pinning the underlying object and updating the frontbuffer tracking @@ -12695,7 +12734,9 @@ intel_prepare_plane_fb(struct drm_plane *plane, } else { struct i915_vma *vma; - vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation); + vma = intel_pin_and_fence_fb_obj(fb, + new_state->rotation, + &to_intel_plane_state(new_state)->flags); if (!IS_ERR(vma)) to_intel_plane_state(new_state)->vma = vma; else @@ -12734,7 +12775,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, /** * intel_cleanup_plane_fb - Cleans up an fb after plane use * @plane: drm plane to clean up for - * @fb: old framebuffer that was on plane + * @old_state: the state from the previous modeset * * Cleans up a framebuffer that has just been removed from a plane. * @@ -12750,7 +12791,7 @@ intel_cleanup_plane_fb(struct drm_plane *plane, vma = fetch_and_zero(&to_intel_plane_state(old_state)->vma); if (vma) { mutex_lock(&plane->dev->struct_mutex); - intel_unpin_fb_vma(vma); + intel_unpin_fb_vma(vma, to_intel_plane_state(old_state)->flags); mutex_unlock(&plane->dev->struct_mutex); } } @@ -13111,7 +13152,9 @@ intel_legacy_cursor_update(struct drm_plane *plane, goto out_unlock; } } else { - vma = intel_pin_and_fence_fb_obj(fb, new_plane_state->rotation); + vma = intel_pin_and_fence_fb_obj(fb, + new_plane_state->rotation, + &to_intel_plane_state(new_plane_state)->flags); if (IS_ERR(vma)) { DRM_DEBUG_KMS("failed to pin object\n"); @@ -13142,7 +13185,8 @@ intel_legacy_cursor_update(struct drm_plane *plane, old_vma = fetch_and_zero(&to_intel_plane_state(old_plane_state)->vma); if (old_vma) - intel_unpin_fb_vma(old_vma); + intel_unpin_fb_vma(old_vma, + to_intel_plane_state(old_plane_state)->flags); out_unlock: mutex_unlock(&dev_priv->drm.struct_mutex); @@ -13498,8 +13542,8 @@ enum pipe intel_get_pipe_from_connector(struct intel_connector *connector) return to_intel_crtc(connector->base.state->crtc)->pipe; } -int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, - struct drm_file *file) +int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) { struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data; struct drm_crtc *drmmode_crtc; @@ -13947,7 +13991,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, * gen2/3 display engine uses the fence if present, * so the tiling mode must match the fb modifier exactly. */ - if (INTEL_INFO(dev_priv)->gen < 4 && + if (INTEL_GEN(dev_priv) < 4 && tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) { DRM_DEBUG_KMS("tiling_mode must match fb modifier exactly on gen2/3\n"); goto err; @@ -14162,7 +14206,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) { intel_init_cdclk_hooks(dev_priv); - if (INTEL_INFO(dev_priv)->gen >= 9) { + if (INTEL_GEN(dev_priv) >= 9) { dev_priv->display.get_pipe_config = haswell_get_pipe_config; dev_priv->display.get_initial_plane_config = skylake_get_initial_plane_config; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f10a14330e7c..f20b25f98e5a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -258,7 +258,7 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp) if (IS_CNL_WITH_PORT_F(dev_priv)) return 810000; - /* For other SKUs, max rate on ports A and B is 5.4G */ + /* For other SKUs, max rate on ports A and D is 5.4G */ if (port == PORT_A || port == PORT_D) return 540000; @@ -1467,7 +1467,7 @@ static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv, static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv, enum port port) { - if (INTEL_INFO(dev_priv)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) return skl_aux_ctl_reg(dev_priv, port); else if (HAS_PCH_SPLIT(dev_priv)) return ilk_aux_ctl_reg(dev_priv, port); @@ -1478,7 +1478,7 @@ static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv, static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv, enum port port, int index) { - if (INTEL_INFO(dev_priv)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) return skl_aux_data_reg(dev_priv, port, index); else if (HAS_PCH_SPLIT(dev_priv)) return ilk_aux_data_reg(dev_priv, port, index); diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index 76473e9836c6..c8e9e44e5981 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c @@ -147,7 +147,7 @@ struct bxt_ddi_phy_info { */ struct { /** - * @port: which port maps to this channel. + * @channel.port: which port maps to this channel. */ enum port port; } channel[2]; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 468ec1e90e16..50874f4035cf 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -204,6 +204,7 @@ struct intel_fbdev { struct drm_fb_helper helper; struct intel_framebuffer *fb; struct i915_vma *vma; + unsigned long vma_flags; async_cookie_t cookie; int preferred_bpp; }; @@ -490,6 +491,8 @@ struct intel_atomic_state { struct intel_plane_state { struct drm_plane_state base; struct i915_vma *vma; + unsigned long flags; +#define PLANE_HAS_FENCE BIT(0) struct { u32 offset; @@ -1407,6 +1410,8 @@ void cnl_init_cdclk(struct drm_i915_private *dev_priv); void cnl_uninit_cdclk(struct drm_i915_private *dev_priv); void bxt_init_cdclk(struct drm_i915_private *dev_priv); void bxt_uninit_cdclk(struct drm_i915_private *dev_priv); +void icl_init_cdclk(struct drm_i915_private *dev_priv); +void icl_uninit_cdclk(struct drm_i915_private *dev_priv); void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv); void intel_update_max_cdclk(struct drm_i915_private *dev_priv); void intel_update_cdclk(struct drm_i915_private *dev_priv); @@ -1455,8 +1460,8 @@ struct drm_display_mode * intel_encoder_current_mode(struct intel_encoder *encoder); enum pipe intel_get_pipe_from_connector(struct intel_connector *connector); -int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, - struct drm_file *file_priv); +int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe); static inline bool @@ -1501,8 +1506,10 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, struct intel_load_detect_pipe *old, struct drm_modeset_acquire_ctx *ctx); struct i915_vma * -intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation); -void intel_unpin_fb_vma(struct i915_vma *vma); +intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, + unsigned int rotation, + unsigned long *out_flags); +void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags); struct drm_framebuffer * intel_framebuffer_create(struct drm_i915_gem_object *obj, struct drm_mode_fb_cmd2 *mode_cmd); @@ -2018,8 +2025,8 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, int usecs); struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe, int plane); -int intel_sprite_set_colorkey(struct drm_device *dev, void *data, - struct drm_file *file_priv); +int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state); void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state); void skl_update_plane(struct intel_plane *plane, diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 59c066ca14e5..eb0c559b2715 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -245,7 +245,8 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder, intel_dvo->attached_connector->panel.fixed_mode; struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; - /* If we have timings from the BIOS for the panel, put them in + /* + * If we have timings from the BIOS for the panel, put them in * to the adjusted mode. The CRTC will be set up for this mode, * with the panel scaling set up to source from the H/VDisplay * of the original mode. @@ -293,11 +294,6 @@ static void intel_dvo_pre_enable(struct intel_encoder *encoder, I915_WRITE(dvo_reg, dvo_val); } -/** - * Detect the output connection on our DVO device. - * - * Unimplemented. - */ static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector, bool force) { @@ -313,7 +309,8 @@ static int intel_dvo_get_modes(struct drm_connector *connector) const struct drm_display_mode *fixed_mode = to_intel_connector(connector)->panel.fixed_mode; - /* We should probably have an i2c driver get_modes function for those + /* + * We should probably have an i2c driver get_modes function for those * devices which will have a fixed set of modes determined by the chip * (TV-out, for example), but for now with just TMDS and LVDS, * that's not the case. @@ -371,7 +368,7 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = { .destroy = intel_dvo_enc_destroy, }; -/** +/* * Attempts to get a fixed panel timing for LVDS (currently only the i830). * * Other chips with DVO LVDS will need to extend this to deal with the LVDS @@ -443,7 +440,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) uint32_t dpll[I915_MAX_PIPES]; enum port port; - /* Allow the I2C driver info to specify the GPIO to be used in + /* + * Allow the I2C driver info to specify the GPIO to be used in * special cases, but otherwise default to what's defined * in the spec. */ @@ -454,7 +452,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) else gpio = GMBUS_PIN_DPB; - /* Set up the I2C bus necessary for the chip we're probing. + /* + * Set up the I2C bus necessary for the chip we're probing. * It appears that everything is on GPIOE except for panels * on i830 laptops, which are on GPIOB (DVOA). */ @@ -462,12 +461,14 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) intel_dvo->dev = *dvo; - /* GMBUS NAK handling seems to be unstable, hence let the + /* + * GMBUS NAK handling seems to be unstable, hence let the * transmitter detection run in bit banging mode for now. */ intel_gmbus_force_bit(i2c, true); - /* ns2501 requires the DVO 2x clock before it will + /* + * ns2501 requires the DVO 2x clock before it will * respond to i2c accesses, so make sure we have * have the clock enabled before we attempt to * initialize the device. @@ -525,7 +526,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) intel_connector_attach_encoder(intel_connector, intel_encoder); if (dvo->type == INTEL_DVO_CHIP_LVDS) { - /* For our LVDS chipsets, we should hopefully be able + /* + * For our LVDS chipsets, we should hopefully be able * to dig the fixed panel mode out of the BIOS data. * However, it's in a different format from the BIOS * data on chipsets with integrated LVDS (stored in AIM diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 7eebfbb95e89..f3c5100d629e 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -631,7 +631,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine) * Similarly the preempt context must always be available so that * we can interrupt the engine at any time. */ - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) { + if (engine->i915->preempt_context) { ring = engine->context_pin(engine, engine->i915->preempt_context); if (IS_ERR(ring)) { @@ -656,7 +656,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine) err_breadcrumbs: intel_engine_fini_breadcrumbs(engine); err_unpin_preempt: - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) + if (engine->i915->preempt_context) engine->context_unpin(engine, engine->i915->preempt_context); err_unpin_kernel: engine->context_unpin(engine, engine->i915->kernel_context); @@ -686,12 +686,12 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) if (engine->default_state) i915_gem_object_put(engine->default_state); - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) + if (engine->i915->preempt_context) engine->context_unpin(engine, engine->i915->preempt_context); engine->context_unpin(engine, engine->i915->kernel_context); } -u64 intel_engine_get_active_head(struct intel_engine_cs *engine) +u64 intel_engine_get_active_head(const struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; u64 acthd; @@ -707,7 +707,7 @@ u64 intel_engine_get_active_head(struct intel_engine_cs *engine) return acthd; } -u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine) +u64 intel_engine_get_last_batch_head(const struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; u64 bbaddr; @@ -1464,7 +1464,9 @@ static bool ring_is_idle(struct intel_engine_cs *engine) struct drm_i915_private *dev_priv = engine->i915; bool idle = true; - intel_runtime_pm_get(dev_priv); + /* If the whole device is asleep, the engine must be idle */ + if (!intel_runtime_pm_get_if_in_use(dev_priv)) + return true; /* First check that no commands are left in the ring */ if ((I915_READ_HEAD(engine) & HEAD_ADDR) != @@ -1503,10 +1505,6 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine) if (I915_SELFTEST_ONLY(engine->breadcrumbs.mock)) return true; - /* Interrupt/tasklet pending? */ - if (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted)) - return false; - /* Waiting to drain ELSP? */ if (READ_ONCE(engine->execlists.active)) return false; @@ -1707,73 +1705,20 @@ static void hexdump(struct drm_printer *m, const void *buf, size_t len) } } -void intel_engine_dump(struct intel_engine_cs *engine, - struct drm_printer *m, - const char *header, ...) +static void intel_engine_print_registers(const struct intel_engine_cs *engine, + struct drm_printer *m) { - struct intel_breadcrumbs * const b = &engine->breadcrumbs; - const struct intel_engine_execlists * const execlists = &engine->execlists; - struct i915_gpu_error * const error = &engine->i915->gpu_error; struct drm_i915_private *dev_priv = engine->i915; - struct drm_i915_gem_request *rq; - struct rb_node *rb; - char hdr[80]; + const struct intel_engine_execlists * const execlists = + &engine->execlists; u64 addr; - if (header) { - va_list ap; - - va_start(ap, header); - drm_vprintf(m, header, &ap); - va_end(ap); - } - - if (i915_terminally_wedged(&engine->i915->gpu_error)) - drm_printf(m, "*** WEDGED ***\n"); - - drm_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms], inflight %d\n", - intel_engine_get_seqno(engine), - intel_engine_last_submit(engine), - engine->hangcheck.seqno, - jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp), - engine->timeline->inflight_seqnos); - drm_printf(m, "\tReset count: %d (global %d)\n", - i915_reset_engine_count(error, engine), - i915_reset_count(error)); - - rcu_read_lock(); - - drm_printf(m, "\tRequests:\n"); - - rq = list_first_entry(&engine->timeline->requests, - struct drm_i915_gem_request, link); - if (&rq->link != &engine->timeline->requests) - print_request(m, rq, "\t\tfirst "); - - rq = list_last_entry(&engine->timeline->requests, - struct drm_i915_gem_request, link); - if (&rq->link != &engine->timeline->requests) - print_request(m, rq, "\t\tlast "); - - rq = i915_gem_find_active_request(engine); - if (rq) { - print_request(m, rq, "\t\tactive "); - drm_printf(m, - "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n", - rq->head, rq->postfix, rq->tail, - rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u, - rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u); - } - - drm_printf(m, "\tRING_START: 0x%08x [0x%08x]\n", - I915_READ(RING_START(engine->mmio_base)), - rq ? i915_ggtt_offset(rq->ring->vma) : 0); - drm_printf(m, "\tRING_HEAD: 0x%08x [0x%08x]\n", - I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR, - rq ? rq->ring->head : 0); - drm_printf(m, "\tRING_TAIL: 0x%08x [0x%08x]\n", - I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR, - rq ? rq->ring->tail : 0); + drm_printf(m, "\tRING_START: 0x%08x\n", + I915_READ(RING_START(engine->mmio_base))); + drm_printf(m, "\tRING_HEAD: 0x%08x\n", + I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR); + drm_printf(m, "\tRING_TAIL: 0x%08x\n", + I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR); drm_printf(m, "\tRING_CTL: 0x%08x%s\n", I915_READ(RING_CTL(engine->mmio_base)), I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? " [waiting]" : ""); @@ -1782,6 +1727,11 @@ void intel_engine_dump(struct intel_engine_cs *engine, I915_READ(RING_MI_MODE(engine->mmio_base)), I915_READ(RING_MI_MODE(engine->mmio_base)) & (MODE_IDLE) ? " [idle]" : ""); } + + if (INTEL_GEN(dev_priv) >= 6) { + drm_printf(m, "\tRING_IMR: %08x\n", I915_READ_IMR(engine)); + } + if (HAS_LEGACY_SEMAPHORES(dev_priv)) { drm_printf(m, "\tSYNC_0: 0x%08x\n", I915_READ(RING_SYNC_0(engine->mmio_base))); @@ -1792,8 +1742,6 @@ void intel_engine_dump(struct intel_engine_cs *engine, I915_READ(RING_SYNC_2(engine->mmio_base))); } - rcu_read_unlock(); - addr = intel_engine_get_active_head(engine); drm_printf(m, "\tACTHD: 0x%08x_%08x\n", upper_32_bits(addr), lower_32_bits(addr)); @@ -1855,10 +1803,13 @@ void intel_engine_dump(struct intel_engine_cs *engine, rcu_read_lock(); for (idx = 0; idx < execlists_num_ports(execlists); idx++) { + struct drm_i915_gem_request *rq; unsigned int count; rq = port_unpack(&execlists->port[idx], &count); if (rq) { + char hdr[80]; + snprintf(hdr, sizeof(hdr), "\t\tELSP[%d] count=%d, rq: ", idx, count); @@ -1877,6 +1828,77 @@ void intel_engine_dump(struct intel_engine_cs *engine, drm_printf(m, "\tPP_DIR_DCLV: 0x%08x\n", I915_READ(RING_PP_DIR_DCLV(engine))); } +} + +void intel_engine_dump(struct intel_engine_cs *engine, + struct drm_printer *m, + const char *header, ...) +{ + struct intel_breadcrumbs * const b = &engine->breadcrumbs; + const struct intel_engine_execlists * const execlists = &engine->execlists; + struct i915_gpu_error * const error = &engine->i915->gpu_error; + struct drm_i915_gem_request *rq; + struct rb_node *rb; + + if (header) { + va_list ap; + + va_start(ap, header); + drm_vprintf(m, header, &ap); + va_end(ap); + } + + if (i915_terminally_wedged(&engine->i915->gpu_error)) + drm_printf(m, "*** WEDGED ***\n"); + + drm_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms], inflight %d\n", + intel_engine_get_seqno(engine), + intel_engine_last_submit(engine), + engine->hangcheck.seqno, + jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp), + engine->timeline->inflight_seqnos); + drm_printf(m, "\tReset count: %d (global %d)\n", + i915_reset_engine_count(error, engine), + i915_reset_count(error)); + + rcu_read_lock(); + + drm_printf(m, "\tRequests:\n"); + + rq = list_first_entry(&engine->timeline->requests, + struct drm_i915_gem_request, link); + if (&rq->link != &engine->timeline->requests) + print_request(m, rq, "\t\tfirst "); + + rq = list_last_entry(&engine->timeline->requests, + struct drm_i915_gem_request, link); + if (&rq->link != &engine->timeline->requests) + print_request(m, rq, "\t\tlast "); + + rq = i915_gem_find_active_request(engine); + if (rq) { + print_request(m, rq, "\t\tactive "); + drm_printf(m, + "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n", + rq->head, rq->postfix, rq->tail, + rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u, + rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u); + drm_printf(m, "\t\tring->start: 0x%08x\n", + i915_ggtt_offset(rq->ring->vma)); + drm_printf(m, "\t\tring->head: 0x%08x\n", + rq->ring->head); + drm_printf(m, "\t\tring->tail: 0x%08x\n", + rq->ring->tail); + } + + rcu_read_unlock(); + + if (intel_runtime_pm_get_if_in_use(engine->i915)) { + intel_engine_print_registers(engine, m); + intel_runtime_pm_put(engine->i915); + } else { + drm_printf(m, "\tDevice is asleep; skipping register dump\n"); + } spin_lock_irq(&engine->timeline->lock); list_for_each_entry(rq, &engine->timeline->requests, link) @@ -1899,10 +1921,6 @@ void intel_engine_dump(struct intel_engine_cs *engine, } spin_unlock_irq(&b->rb_lock); - if (INTEL_GEN(dev_priv) >= 6) { - drm_printf(m, "\tRING_IMR: %08x\n", I915_READ_IMR(engine)); - } - drm_printf(m, "IRQ? 0x%lx (breadcrumbs? %s) (execlists? %s)\n", engine->irq_posted, yesno(test_bit(ENGINE_IRQ_BREADCRUMB, diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index d7d1ac79c38a..f66f6fb5743d 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -183,7 +183,7 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv) else dpfc_ctl |= DPFC_CTL_LIMIT_1X; - if (params->vma->fence) { + if (params->flags & PLANE_HAS_FENCE) { dpfc_ctl |= DPFC_CTL_FENCE_EN | params->vma->fence->id; I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset); } else { @@ -241,7 +241,7 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv) break; } - if (params->vma->fence) { + if (params->flags & PLANE_HAS_FENCE) { dpfc_ctl |= DPFC_CTL_FENCE_EN; if (IS_GEN5(dev_priv)) dpfc_ctl |= params->vma->fence->id; @@ -324,7 +324,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) break; } - if (params->vma->fence) { + if (params->flags & PLANE_HAS_FENCE) { dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN; I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | @@ -753,6 +753,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, struct drm_framebuffer *fb = plane_state->base.fb; cache->vma = NULL; + cache->flags = 0; cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags; if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) @@ -778,6 +779,9 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->fb.stride = fb->pitches[0]; cache->vma = plane_state->vma; + cache->flags = plane_state->flags; + if (WARN_ON(cache->flags & PLANE_HAS_FENCE && !cache->vma->fence)) + cache->flags &= ~PLANE_HAS_FENCE; } static bool intel_fbc_can_activate(struct intel_crtc *crtc) @@ -816,7 +820,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * so have no fence associated with it) due to aperture constaints * at the time of pinning. */ - if (!cache->vma->fence) { + if (!(cache->flags & PLANE_HAS_FENCE)) { fbc->no_fbc_reason = "framebuffer not tiled or fenced"; return false; } @@ -897,6 +901,7 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, memset(params, 0, sizeof(*params)); params->vma = cache->vma; + params->flags = cache->flags; params->crtc.pipe = crtc->pipe; params->crtc.i9xx_plane = to_intel_plane(crtc->base.primary)->i9xx_plane; diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index da48af11eb6b..055f409f8b75 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -48,7 +48,8 @@ static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev) { struct drm_i915_gem_object *obj = ifbdev->fb->obj; - unsigned int origin = ifbdev->vma->fence ? ORIGIN_GTT : ORIGIN_CPU; + unsigned int origin = + ifbdev->vma_flags & PLANE_HAS_FENCE ? ORIGIN_GTT : ORIGIN_CPU; intel_fb_obj_invalidate(obj, origin); } @@ -177,6 +178,7 @@ static int intelfb_create(struct drm_fb_helper *helper, struct fb_info *info; struct drm_framebuffer *fb; struct i915_vma *vma; + unsigned long flags = 0; bool prealloc = false; void __iomem *vaddr; int ret; @@ -211,7 +213,9 @@ static int intelfb_create(struct drm_fb_helper *helper, * This also validates that any existing fb inherited from the * BIOS is suitable for own access. */ - vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, DRM_MODE_ROTATE_0); + vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, + DRM_MODE_ROTATE_0, + &flags); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto out_unlock; @@ -268,6 +272,7 @@ static int intelfb_create(struct drm_fb_helper *helper, DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x\n", fb->width, fb->height, i915_ggtt_offset(vma)); ifbdev->vma = vma; + ifbdev->vma_flags = flags; intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); @@ -275,7 +280,7 @@ static int intelfb_create(struct drm_fb_helper *helper, return 0; out_unpin: - intel_unpin_fb_vma(vma); + intel_unpin_fb_vma(vma, flags); out_unlock: intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); @@ -513,7 +518,7 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev) if (ifbdev->vma) { mutex_lock(&ifbdev->helper.dev->struct_mutex); - intel_unpin_fb_vma(ifbdev->vma); + intel_unpin_fb_vma(ifbdev->vma, ifbdev->vma_flags); mutex_unlock(&ifbdev->helper.dev->struct_mutex); } diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c index 1f3a8786bbdc..946766b62459 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/intel_guc_submission.c @@ -688,7 +688,7 @@ static void guc_dequeue(struct intel_engine_cs *engine) goto unlock; if (port_isset(port)) { - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) { + if (engine->i915->preempt_context) { struct guc_preempt_work *preempt_work = &engine->i915->guc.preempt_work[engine->id]; @@ -747,6 +747,12 @@ done: execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); guc_submit(engine); } + + /* We must always keep the beast fed if we have work piled up */ + GEM_BUG_ON(port_isset(execlists->port) && + !execlists_is_active(execlists, EXECLISTS_ACTIVE_USER)); + GEM_BUG_ON(execlists->first && !port_isset(execlists->port)); + unlock: spin_unlock_irq(&engine->timeline->lock); } @@ -832,10 +838,12 @@ static int guc_clients_doorbell_init(struct intel_guc *guc) if (ret) return ret; - ret = create_doorbell(guc->preempt_client); - if (ret) { - destroy_doorbell(guc->execbuf_client); - return ret; + if (guc->preempt_client) { + ret = create_doorbell(guc->preempt_client); + if (ret) { + destroy_doorbell(guc->execbuf_client); + return ret; + } } return 0; @@ -848,8 +856,11 @@ static void guc_clients_doorbell_fini(struct intel_guc *guc) * Instead of trying (in vain) to communicate with it, let's just * cleanup the doorbell HW and our internal state. */ - __destroy_doorbell(guc->preempt_client); - __update_doorbell_desc(guc->preempt_client, GUC_DOORBELL_INVALID); + if (guc->preempt_client) { + __destroy_doorbell(guc->preempt_client); + __update_doorbell_desc(guc->preempt_client, + GUC_DOORBELL_INVALID); + } __destroy_doorbell(guc->execbuf_client); __update_doorbell_desc(guc->execbuf_client, GUC_DOORBELL_INVALID); } @@ -979,17 +990,19 @@ static int guc_clients_create(struct intel_guc *guc) } guc->execbuf_client = client; - client = guc_client_alloc(dev_priv, - INTEL_INFO(dev_priv)->ring_mask, - GUC_CLIENT_PRIORITY_KMD_HIGH, - dev_priv->preempt_context); - if (IS_ERR(client)) { - DRM_ERROR("Failed to create GuC client for preemption!\n"); - guc_client_free(guc->execbuf_client); - guc->execbuf_client = NULL; - return PTR_ERR(client); + if (dev_priv->preempt_context) { + client = guc_client_alloc(dev_priv, + INTEL_INFO(dev_priv)->ring_mask, + GUC_CLIENT_PRIORITY_KMD_HIGH, + dev_priv->preempt_context); + if (IS_ERR(client)) { + DRM_ERROR("Failed to create GuC client for preemption!\n"); + guc_client_free(guc->execbuf_client); + guc->execbuf_client = NULL; + return PTR_ERR(client); + } + guc->preempt_client = client; } - guc->preempt_client = client; return 0; } @@ -998,10 +1011,11 @@ static void guc_clients_destroy(struct intel_guc *guc) { struct intel_guc_client *client; - client = fetch_and_zero(&guc->execbuf_client); - guc_client_free(client); - client = fetch_and_zero(&guc->preempt_client); + if (client) + guc_client_free(client); + + client = fetch_and_zero(&guc->execbuf_client); guc_client_free(client); } @@ -1160,7 +1174,8 @@ int intel_guc_submission_enable(struct intel_guc *guc) GEM_BUG_ON(!guc->execbuf_client); guc_reset_wq(guc->execbuf_client); - guc_reset_wq(guc->preempt_client); + if (guc->preempt_client) + guc_reset_wq(guc->preempt_client); err = intel_guc_sample_forcewake(guc); if (err) diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c index 8ed05182f944..ef9a05d8e5a9 100644 --- a/drivers/gpu/drm/i915/intel_huc.c +++ b/drivers/gpu/drm/i915/intel_huc.c @@ -118,7 +118,8 @@ void intel_huc_init_early(struct intel_huc *huc) /** * huc_ucode_xfer() - DMA's the firmware - * @dev_priv: the drm_i915_private device + * @huc_fw: the firmware descriptor + * @vma: the firmware image (bound into the GGTT) * * Transfer the firmware image to RAM for execution by the microcontroller. * diff --git a/drivers/gpu/drm/i915/intel_lpe_audio.c b/drivers/gpu/drm/i915/intel_lpe_audio.c index 5809b29044fc..6269750e2b54 100644 --- a/drivers/gpu/drm/i915/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/intel_lpe_audio.c @@ -74,7 +74,6 @@ static struct platform_device * lpe_audio_platdev_create(struct drm_i915_private *dev_priv) { - int ret; struct drm_device *dev = &dev_priv->drm; struct platform_device_info pinfo = {}; struct resource *rsc; @@ -119,24 +118,19 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv) spin_lock_init(&pdata->lpe_audio_slock); platdev = platform_device_register_full(&pinfo); + kfree(rsc); + kfree(pdata); + if (IS_ERR(platdev)) { - ret = PTR_ERR(platdev); DRM_ERROR("Failed to allocate LPE audio platform device\n"); - goto err; + return platdev; } - kfree(rsc); - pm_runtime_forbid(&platdev->dev); pm_runtime_set_active(&platdev->dev); pm_runtime_enable(&platdev->dev); return platdev; - -err: - kfree(rsc); - kfree(pdata); - return ERR_PTR(ret); } static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 380c0838d8b3..9b6d781b22ec 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -161,7 +161,6 @@ #define EXECLISTS_REQUEST_SIZE 64 /* bytes */ #define WA_TAIL_DWORDS 2 #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS) -#define PREEMPT_ID 0x1 static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, struct intel_engine_cs *engine); @@ -448,7 +447,8 @@ static void inject_preempt_context(struct intel_engine_cs *engine) &engine->i915->preempt_context->engine[engine->id]; unsigned int n; - GEM_BUG_ON(engine->i915->preempt_context->hw_id != PREEMPT_ID); + GEM_BUG_ON(engine->execlists.preempt_complete_status != + upper_32_bits(ce->lrc_desc)); GEM_BUG_ON(!IS_ALIGNED(ce->ring->size, WA_TAIL_BYTES)); memset(ce->ring->vaddr + ce->ring->tail, 0, WA_TAIL_BYTES); @@ -528,7 +528,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_HWACK)) goto unlock; - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915) && + if (engine->i915->preempt_context && rb_entry(rb, struct i915_priolist, node)->priority > max(last->priotree.priority, 0)) { /* @@ -642,6 +642,10 @@ done: execlists->first = rb; if (submit) port_assign(port, last); + + /* We must always keep the beast fed if we have work piled up */ + GEM_BUG_ON(execlists->first && !port_isset(execlists->port)); + unlock: spin_unlock_irq(&engine->timeline->lock); @@ -649,6 +653,9 @@ unlock: execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); execlists_submit_ports(engine); } + + GEM_BUG_ON(port_isset(execlists->port) && + !execlists_is_active(execlists, EXECLISTS_ACTIVE_USER)); } void @@ -844,7 +851,7 @@ static void execlists_submission_tasklet(unsigned long data) GEM_BUG_ON(status & GEN8_CTX_STATUS_IDLE_ACTIVE); if (status & GEN8_CTX_STATUS_COMPLETE && - buf[2*head + 1] == PREEMPT_ID) { + buf[2*head + 1] == execlists->preempt_complete_status) { GEM_TRACE("%s preempt-idle\n", engine->name); execlists_cancel_port_requests(execlists); @@ -1963,6 +1970,12 @@ static void execlists_set_default_submission(struct intel_engine_cs *engine) engine->unpark = NULL; engine->flags |= I915_ENGINE_SUPPORTS_STATS; + + engine->i915->caps.scheduler = + I915_SCHEDULER_CAP_ENABLED | + I915_SCHEDULER_CAP_PRIORITY; + if (engine->i915->preempt_context) + engine->i915->caps.scheduler |= I915_SCHEDULER_CAP_PREEMPTION; } static void @@ -2039,6 +2052,11 @@ static int logical_ring_init(struct intel_engine_cs *engine) engine->execlists.elsp = engine->i915->regs + i915_mmio_reg_offset(RING_ELSP(engine)); + engine->execlists.preempt_complete_status = ~0u; + if (engine->i915->preempt_context) + engine->execlists.preempt_complete_status = + upper_32_bits(engine->i915->preempt_context->engine[engine->id].lrc_desc); + return 0; error: @@ -2301,7 +2319,7 @@ populate_lr_context(struct i915_gem_context *ctx, if (!engine->default_state) regs[CTX_CONTEXT_CONTROL + 1] |= _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); - if (ctx->hw_id == PREEMPT_ID) + if (ctx == ctx->i915->preempt_context) regs[CTX_CONTEXT_CONTROL + 1] |= _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index ef80499113ee..d35d2d50f595 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -189,7 +189,7 @@ static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv, /* Convert from 100ms to 100us units */ pps->t4 = val * 1000; - if (INTEL_INFO(dev_priv)->gen <= 4 && + if (INTEL_GEN(dev_priv) <= 4 && pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) { DRM_DEBUG_KMS("Panel power timings uninitialized, " "setting defaults\n"); @@ -268,7 +268,9 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, /* set the corresponsding LVDS_BORDER bit */ temp &= ~LVDS_BORDER_ENABLE; temp |= pipe_config->gmch_pfit.lvds_border_bits; - /* Set the B0-B3 data pairs corresponding to whether we're going to + + /* + * Set the B0-B3 data pairs corresponding to whether we're going to * set the DPLLs for dual-channel mode or not. */ if (lvds_encoder->is_dual_link) @@ -276,7 +278,8 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, else temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); - /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) + /* + * It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) * appropriately here, but we need to look more thoroughly into how * panels behave in the two modes. For now, let's just maintain the * value we got from the BIOS. @@ -284,12 +287,16 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, temp &= ~LVDS_A3_POWER_MASK; temp |= lvds_encoder->a3_power; - /* Set the dithering flag on LVDS as needed, note that there is no + /* + * Set the dithering flag on LVDS as needed, note that there is no * special lvds dither control bit on pch-split platforms, dithering is - * only controlled through the PIPECONF reg. */ + * only controlled through the PIPECONF reg. + */ if (IS_GEN4(dev_priv)) { - /* Bspec wording suggests that LVDS port dithering only exists - * for 18bpp panels. */ + /* + * Bspec wording suggests that LVDS port dithering only exists + * for 18bpp panels. + */ if (pipe_config->dither && pipe_config->pipe_bpp == 18) temp |= LVDS_ENABLE_DITHER; else @@ -304,7 +311,7 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, I915_WRITE(lvds_encoder->reg, temp); } -/** +/* * Sets the power state for the panel. */ static void intel_enable_lvds(struct intel_encoder *encoder, @@ -441,7 +448,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, return true; } -/** +/* * Detect the LVDS connection. * * Since LVDS doesn't have hotlug, we use the lid as a proxy. Open means @@ -464,7 +471,7 @@ intel_lvds_detect(struct drm_connector *connector, bool force) return connector_status_connected; } -/** +/* * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. */ static int intel_lvds_get_modes(struct drm_connector *connector) @@ -893,7 +900,8 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) if (dmi_check_system(intel_dual_link_lvds)) return true; - /* BIOS should set the proper LVDS register value at boot, but + /* + * BIOS should set the proper LVDS register value at boot, but * in reality, it doesn't set the value when the lid is closed; * we need to check "the value to be set" in VBT when LVDS * register is uninitialized. @@ -907,13 +915,17 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) static bool intel_lvds_supported(struct drm_i915_private *dev_priv) { - /* With the introduction of the PCH we gained a dedicated - * LVDS presence pin, use it. */ + /* + * With the introduction of the PCH we gained a dedicated + * LVDS presence pin, use it. + */ if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) return true; - /* Otherwise LVDS was only attached to mobile products, - * except for the inglorious 830gm */ + /* + * Otherwise LVDS was only attached to mobile products, + * except for the inglorious 830gm + */ if (INTEL_GEN(dev_priv) <= 4 && IS_MOBILE(dev_priv) && !IS_I830(dev_priv)) return true; @@ -923,7 +935,7 @@ static bool intel_lvds_supported(struct drm_i915_private *dev_priv) /** * intel_lvds_init - setup LVDS connectors on this device - * @dev: drm device + * @dev_priv: i915 device * * Create the connector, register the LVDS DDC bus, and try to figure out what * modes we can display on the LVDS panel (if present). diff --git a/drivers/gpu/drm/i915/intel_mocs.c b/drivers/gpu/drm/i915/intel_mocs.c index f4c46b0b8f0a..abb7a8c1e340 100644 --- a/drivers/gpu/drm/i915/intel_mocs.c +++ b/drivers/gpu/drm/i915/intel_mocs.c @@ -187,7 +187,7 @@ static bool get_mocs_settings(struct drm_i915_private *dev_priv, table->table = broxton_mocs_table; result = true; } else { - WARN_ONCE(INTEL_INFO(dev_priv)->gen >= 9, + WARN_ONCE(INTEL_GEN(dev_priv) >= 9, "Platform that should have a MOCS table does not.\n"); } diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 41e9465d44a8..89f568e739ee 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -801,7 +801,8 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, atomic_inc(&dev_priv->gpu_error.pending_fb_pin); - vma = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL); + vma = i915_gem_object_pin_to_display_plane(new_bo, + 0, NULL, PIN_MAPPABLE); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto out_pin_section; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index e702a6487aa9..41d00b1603e3 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -397,8 +397,11 @@ intel_panel_detect(struct drm_i915_private *dev_priv) /** * scale - scale values from one range to another - * * @source_val: value in range [@source_min..@source_max] + * @source_min: minimum legal value for @source_val + * @source_max: maximum legal value for @source_val + * @target_min: corresponding target value for @source_min + * @target_max: corresponding target value for @source_max * * Return @source_val in range [@source_min..@source_max] scaled to range * [@target_min..@target_max]. @@ -416,8 +419,9 @@ static uint32_t scale(uint32_t source_val, source_val = clamp(source_val, source_min, source_max); /* avoid overflows */ - target_val = DIV_ROUND_CLOSEST_ULL((uint64_t)(source_val - source_min) * - (target_max - target_min), source_max - source_min); + target_val = mul_u32_u32(source_val - source_min, + target_max - target_min); + target_val = DIV_ROUND_CLOSEST_ULL(target_val, source_max - source_min); target_val += target_min; return target_val; @@ -497,7 +501,7 @@ static u32 i9xx_get_backlight(struct intel_connector *connector) u32 val; val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - if (INTEL_INFO(dev_priv)->gen < 4) + if (INTEL_GEN(dev_priv) < 4) val >>= 1; if (panel->backlight.combination_mode) { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index eb68abf6a8e9..abf80e462833 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -729,6 +729,7 @@ static unsigned int intel_wm_method2(unsigned int pixel_rate, * intel_calculate_wm - calculate watermark level * @pixel_rate: pixel clock * @wm: chip FIFO params + * @fifo_size: size of the FIFO buffer * @cpp: bytes per pixel * @latency_ns: memory latency for the platform * @@ -2916,10 +2917,6 @@ static void intel_fixup_cur_wm_latency(struct drm_i915_private *dev_priv, /* ILK cursor LP0 latency is 1300 ns */ if (IS_GEN5(dev_priv)) wm[0] = 13; - - /* WaDoubleCursorLP3Latency:ivb */ - if (IS_IVYBRIDGE(dev_priv)) - wm[3] *= 2; } int ilk_wm_max_level(const struct drm_i915_private *dev_priv) @@ -4596,7 +4593,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, min_disp_buf_needed = res_blocks; } - if (res_blocks >= ddb_allocation || res_lines > 31 || + if ((level > 0 && res_lines > 31) || + res_blocks >= ddb_allocation || min_disp_buf_needed >= ddb_allocation) { *enabled = false; @@ -4617,8 +4615,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, } } + /* The number of lines are ignored for the level 0 watermark. */ + *out_lines = level ? res_lines : 0; *out_blocks = res_blocks; - *out_lines = res_lines; *enabled = true; return 0; @@ -4710,6 +4709,7 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate, if (!dev_priv->ipc_enabled) goto exit; + trans_min = 0; if (INTEL_GEN(dev_priv) >= 10) trans_min = 4; @@ -5864,6 +5864,7 @@ void ilk_wm_get_hw_state(struct drm_device *dev) /** * intel_update_watermarks - update FIFO watermark values based on current modes + * @crtc: the #intel_crtc on which to compute the WM * * Calculate watermark values for the various WM regs based on current mode * and plane configuration. @@ -6372,12 +6373,15 @@ void gen6_rps_boost(struct drm_i915_gem_request *rq, if (!rps->enabled) return; + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags)) + return; + + /* Serializes with i915_gem_request_retire() */ boost = false; spin_lock_irqsave(&rq->lock, flags); - if (!rq->waitboost && !i915_gem_request_completed(rq)) { - atomic_inc(&rps->num_waiters); + if (!rq->waitboost && !dma_fence_is_signaled_locked(&rq->fence)) { + boost = !atomic_fetch_inc(&rps->num_waiters); rq->waitboost = true; - boost = true; } spin_unlock_irqrestore(&rq->lock, flags); if (!boost) @@ -6938,7 +6942,7 @@ static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) * No floor required for ring frequency on SKL. */ ring_freq = gpu_freq; - } else if (INTEL_INFO(dev_priv)->gen >= 8) { + } else if (INTEL_GEN(dev_priv) >= 8) { /* max(2 * GT, DDR). NB: GT is 50MHz units */ ring_freq = max(min_ring_freq, gpu_freq); } else if (IS_HASWELL(dev_priv)) { @@ -7549,7 +7553,7 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) { unsigned long val; - if (INTEL_INFO(dev_priv)->gen != 5) + if (!IS_GEN5(dev_priv)) return 0; spin_lock_irq(&mchdev_lock); @@ -7633,7 +7637,7 @@ static void __i915_update_gfx_val(struct drm_i915_private *dev_priv) void i915_update_gfx_val(struct drm_i915_private *dev_priv) { - if (INTEL_INFO(dev_priv)->gen != 5) + if (!IS_GEN5(dev_priv)) return; spin_lock_irq(&mchdev_lock); @@ -7684,7 +7688,7 @@ unsigned long i915_gfx_val(struct drm_i915_private *dev_priv) { unsigned long val; - if (INTEL_INFO(dev_priv)->gen != 5) + if (!IS_GEN5(dev_priv)) return 0; spin_lock_irq(&mchdev_lock); @@ -9415,15 +9419,16 @@ static u64 vlv_residency_raw(struct drm_i915_private *dev_priv, const i915_reg_t reg) { u32 lower, upper, tmp; - unsigned long flags; int loop = 2; - /* The register accessed do not need forcewake. We borrow + /* + * The register accessed do not need forcewake. We borrow * uncore lock to prevent concurrent access to range reg. */ - spin_lock_irqsave(&dev_priv->uncore.lock, flags); + lockdep_assert_held(&dev_priv->uncore.lock); - /* vlv and chv residency counters are 40 bits in width. + /* + * vlv and chv residency counters are 40 bits in width. * With a control bit, we can choose between upper or lower * 32bit window into this counter. * @@ -9447,29 +9452,49 @@ static u64 vlv_residency_raw(struct drm_i915_private *dev_priv, upper = I915_READ_FW(reg); } while (upper != tmp && --loop); - /* Everywhere else we always use VLV_COUNTER_CONTROL with the + /* + * Everywhere else we always use VLV_COUNTER_CONTROL with the * VLV_COUNT_RANGE_HIGH bit set - so it is safe to leave it set * now. */ - spin_unlock_irqrestore(&dev_priv->uncore.lock, flags); - return lower | (u64)upper << 8; } u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv, const i915_reg_t reg) { - u64 time_hw; + u64 time_hw, prev_hw, overflow_hw; + unsigned int fw_domains; + unsigned long flags; + unsigned int i; u32 mul, div; if (!HAS_RC6(dev_priv)) return 0; + /* + * Store previous hw counter values for counter wrap-around handling. + * + * There are only four interesting registers and they live next to each + * other so we can use the relative address, compared to the smallest + * one as the index into driver storage. + */ + i = (i915_mmio_reg_offset(reg) - + i915_mmio_reg_offset(GEN6_GT_GFX_RC6_LOCKED)) / sizeof(u32); + if (WARN_ON_ONCE(i >= ARRAY_SIZE(dev_priv->gt_pm.rc6.cur_residency))) + return 0; + + fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, FW_REG_READ); + + spin_lock_irqsave(&dev_priv->uncore.lock, flags); + intel_uncore_forcewake_get__locked(dev_priv, fw_domains); + /* On VLV and CHV, residency time is in CZ units rather than 1.28us */ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { mul = 1000000; div = dev_priv->czclk_freq; + overflow_hw = BIT_ULL(40); time_hw = vlv_residency_raw(dev_priv, reg); } else { /* 833.33ns units on Gen9LP, 1.28us elsewhere. */ @@ -9481,10 +9506,33 @@ u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv, div = 1; } - time_hw = I915_READ(reg); + overflow_hw = BIT_ULL(32); + time_hw = I915_READ_FW(reg); } - return DIV_ROUND_UP_ULL(time_hw * mul, div); + /* + * Counter wrap handling. + * + * But relying on a sufficient frequency of queries otherwise counters + * can still wrap. + */ + prev_hw = dev_priv->gt_pm.rc6.prev_hw_residency[i]; + dev_priv->gt_pm.rc6.prev_hw_residency[i] = time_hw; + + /* RC6 delta from last sample. */ + if (time_hw >= prev_hw) + time_hw -= prev_hw; + else + time_hw += overflow_hw - prev_hw; + + /* Add delta to RC6 extended raw driver copy. */ + time_hw += dev_priv->gt_pm.rc6.cur_residency[i]; + dev_priv->gt_pm.rc6.cur_residency[i] = time_hw; + + intel_uncore_forcewake_put__locked(dev_priv, fw_domains); + spin_unlock_irqrestore(&dev_priv->uncore.lock, flags); + + return mul_u64_u32_div(time_hw, mul, div); } u32 intel_get_cagf(struct drm_i915_private *dev_priv, u32 rpstat) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index e9feffdea899..2ef374f936b9 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -126,7 +126,7 @@ static void vlv_psr_enable_sink(struct intel_dp *intel_dp) static i915_reg_t psr_aux_ctl_reg(struct drm_i915_private *dev_priv, enum port port) { - if (INTEL_INFO(dev_priv)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) return DP_AUX_CH_CTL(port); else return EDP_PSR_AUX_CTL; @@ -135,7 +135,7 @@ static i915_reg_t psr_aux_ctl_reg(struct drm_i915_private *dev_priv, static i915_reg_t psr_aux_data_reg(struct drm_i915_private *dev_priv, enum port port, int index) { - if (INTEL_INFO(dev_priv)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) return DP_AUX_CH_DATA(port, index); else return EDP_PSR_AUX_DATA(index); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e2085820b586..5718f37160c5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -137,7 +137,7 @@ gen4_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) return 0; } -/** +/* * Emits a PIPE_CONTROL with a non-zero post-sync operation, for * implementing two workarounds on gen6. From section 1.4.7.1 * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: @@ -453,13 +453,13 @@ static int init_ring_common(struct intel_engine_cs *engine) if (!stop_ring(engine)) { /* G45 ring initialization often fails to reset head to zero */ - DRM_DEBUG_KMS("%s head not reset to zero " - "ctl %08x head %08x tail %08x start %08x\n", - engine->name, - I915_READ_CTL(engine), - I915_READ_HEAD(engine), - I915_READ_TAIL(engine), - I915_READ_START(engine)); + DRM_DEBUG_DRIVER("%s head not reset to zero " + "ctl %08x head %08x tail %08x start %08x\n", + engine->name, + I915_READ_CTL(engine), + I915_READ_HEAD(engine), + I915_READ_TAIL(engine), + I915_READ_START(engine)); if (!stop_ring(engine)) { DRM_ERROR("failed to set %s head to zero " @@ -492,8 +492,8 @@ static int init_ring_common(struct intel_engine_cs *engine) /* WaClearRingBufHeadRegAtInit:ctg,elk */ if (I915_READ_HEAD(engine)) - DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", - engine->name, I915_READ_HEAD(engine)); + DRM_DEBUG_DRIVER("%s initialization failed [head=%08x], fudging\n", + engine->name, I915_READ_HEAD(engine)); intel_ring_update_space(ring); I915_WRITE_HEAD(engine, ring->head); @@ -655,7 +655,7 @@ static int init_render_ring(struct intel_engine_cs *engine) if (IS_GEN(dev_priv, 6, 7)) I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); - if (INTEL_INFO(dev_priv)->gen >= 6) + if (INTEL_GEN(dev_priv) >= 6) I915_WRITE_IMR(engine, ~engine->irq_keep_mask); return init_workarounds_ring(engine); @@ -729,14 +729,6 @@ static void i9xx_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs) static const int i9xx_emit_breadcrumb_sz = 4; -/** - * gen6_sema_emit_breadcrumb - Update the semaphore mailbox registers - * - * @request - request to write to the ring - * - * Update the mailbox registers in the *other* rings with the current seqno. - * This acts like a signal in the canonical semaphore. - */ static void gen6_sema_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs) { return i9xx_emit_breadcrumb(req, diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index a0e7a6c2a57c..51523ad049de 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -279,6 +279,11 @@ struct intel_engine_execlists { * @csb_use_mmio: access csb through mmio, instead of hwsp */ bool csb_use_mmio; + + /** + * @preempt_complete_status: expected CSB upon completing preemption + */ + u32 preempt_complete_status; }; #define INTEL_ENGINE_CS_MAX_NAME 8 @@ -654,7 +659,7 @@ intel_engine_flag(const struct intel_engine_cs *engine) } static inline u32 -intel_read_status_page(struct intel_engine_cs *engine, int reg) +intel_read_status_page(const struct intel_engine_cs *engine, int reg) { /* Ensure that the compiler doesn't optimize away the load. */ return READ_ONCE(engine->status_page.page_addr[reg]); @@ -812,8 +817,8 @@ int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine); int intel_init_blt_ring_buffer(struct intel_engine_cs *engine); int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine); -u64 intel_engine_get_active_head(struct intel_engine_cs *engine); -u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine); +u64 intel_engine_get_active_head(const struct intel_engine_cs *engine); +u64 intel_engine_get_last_batch_head(const struct intel_engine_cs *engine); static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine) { diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 70e659772a7a..b7924feb9f27 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2646,6 +2646,48 @@ static void gen9_dbuf_disable(struct drm_i915_private *dev_priv) DRM_ERROR("DBuf power disable timeout!\n"); } +/* + * TODO: we shouldn't always enable DBUF_CTL_S2, we should only enable it when + * needed and keep it disabled as much as possible. + */ +static void icl_dbuf_enable(struct drm_i915_private *dev_priv) +{ + I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) | DBUF_POWER_REQUEST); + I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) | DBUF_POWER_REQUEST); + POSTING_READ(DBUF_CTL_S2); + + udelay(10); + + if (!(I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) || + !(I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)) + DRM_ERROR("DBuf power enable timeout\n"); +} + +static void icl_dbuf_disable(struct drm_i915_private *dev_priv) +{ + I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) & ~DBUF_POWER_REQUEST); + I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) & ~DBUF_POWER_REQUEST); + POSTING_READ(DBUF_CTL_S2); + + udelay(10); + + if ((I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) || + (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)) + DRM_ERROR("DBuf power disable timeout!\n"); +} + +static void icl_mbus_init(struct drm_i915_private *dev_priv) +{ + uint32_t val; + + val = MBUS_ABOX_BT_CREDIT_POOL1(16) | + MBUS_ABOX_BT_CREDIT_POOL2(16) | + MBUS_ABOX_B_CREDIT(1) | + MBUS_ABOX_BW_CREDIT(1); + + I915_WRITE(MBUS_ABOX_CTL, val); +} + static void skl_display_core_init(struct drm_i915_private *dev_priv, bool resume) { @@ -2794,12 +2836,19 @@ static const struct cnl_procmon { { .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, }, }; -static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv) +/* + * CNL has just one set of registers, while ICL has two sets: one for port A and + * the other for port B. The CNL registers are equivalent to the ICL port A + * registers, that's why we call the ICL macros even though the function has CNL + * on its name. + */ +static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv, + enum port port) { const struct cnl_procmon *procmon; u32 val; - val = I915_READ(CNL_PORT_COMP_DW3); + val = I915_READ(ICL_PORT_COMP_DW3(port)); switch (val & (PROCESS_INFO_MASK | VOLTAGE_INFO_MASK)) { default: MISSING_CASE(val); @@ -2820,13 +2869,13 @@ static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv) break; } - val = I915_READ(CNL_PORT_COMP_DW1); + val = I915_READ(ICL_PORT_COMP_DW1(port)); val &= ~((0xff << 16) | 0xff); val |= procmon->dw1; - I915_WRITE(CNL_PORT_COMP_DW1, val); + I915_WRITE(ICL_PORT_COMP_DW1(port), val); - I915_WRITE(CNL_PORT_COMP_DW9, procmon->dw9); - I915_WRITE(CNL_PORT_COMP_DW10, procmon->dw10); + I915_WRITE(ICL_PORT_COMP_DW9(port), procmon->dw9); + I915_WRITE(ICL_PORT_COMP_DW10(port), procmon->dw10); } static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume) @@ -2847,7 +2896,8 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume val &= ~CNL_COMP_PWR_DOWN; I915_WRITE(CHICKEN_MISC_2, val); - cnl_set_procmon_ref_values(dev_priv); + /* Dummy PORT_A to get the correct CNL register from the ICL macro */ + cnl_set_procmon_ref_values(dev_priv, PORT_A); val = I915_READ(CNL_PORT_COMP_DW0); val |= COMP_INIT; @@ -2911,6 +2961,80 @@ static void cnl_display_core_uninit(struct drm_i915_private *dev_priv) I915_WRITE(CHICKEN_MISC_2, val); } +static void icl_display_core_init(struct drm_i915_private *dev_priv, + bool resume) +{ + enum port port; + u32 val; + + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); + + /* 1. Enable PCH reset handshake. */ + val = I915_READ(HSW_NDE_RSTWRN_OPT); + val |= RESET_PCH_HANDSHAKE_ENABLE; + I915_WRITE(HSW_NDE_RSTWRN_OPT, val); + + for (port = PORT_A; port <= PORT_B; port++) { + /* 2. Enable DDI combo PHY comp. */ + val = I915_READ(ICL_PHY_MISC(port)); + val &= ~ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN; + I915_WRITE(ICL_PHY_MISC(port), val); + + cnl_set_procmon_ref_values(dev_priv, port); + + val = I915_READ(ICL_PORT_COMP_DW0(port)); + val |= COMP_INIT; + I915_WRITE(ICL_PORT_COMP_DW0(port), val); + + /* 3. Set power down enable. */ + val = I915_READ(ICL_PORT_CL_DW5(port)); + val |= CL_POWER_DOWN_ENABLE; + I915_WRITE(ICL_PORT_CL_DW5(port), val); + } + + /* 4. Enable power well 1 (PG1) and aux IO power. */ + /* FIXME: ICL power wells code not here yet. */ + + /* 5. Enable CDCLK. */ + icl_init_cdclk(dev_priv); + + /* 6. Enable DBUF. */ + icl_dbuf_enable(dev_priv); + + /* 7. Setup MBUS. */ + icl_mbus_init(dev_priv); + + /* 8. CHICKEN_DCPR_1 */ + I915_WRITE(GEN8_CHICKEN_DCPR_1, I915_READ(GEN8_CHICKEN_DCPR_1) | + CNL_DDI_CLOCK_REG_ACCESS_ON); +} + +static void icl_display_core_uninit(struct drm_i915_private *dev_priv) +{ + enum port port; + u32 val; + + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); + + /* 1. Disable all display engine functions -> aready done */ + + /* 2. Disable DBUF */ + icl_dbuf_disable(dev_priv); + + /* 3. Disable CD clock */ + icl_uninit_cdclk(dev_priv); + + /* 4. Disable Power Well 1 (PG1) and Aux IO Power */ + /* FIXME: ICL power wells code not here yet. */ + + /* 5. Disable Comp */ + for (port = PORT_A; port <= PORT_B; port++) { + val = I915_READ(ICL_PHY_MISC(port)); + val |= ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN; + I915_WRITE(ICL_PHY_MISC(port), val); + } +} + static void chv_phy_control_init(struct drm_i915_private *dev_priv) { struct i915_power_well *cmn_bc = @@ -3043,7 +3167,9 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) power_domains->initializing = true; - if (IS_CANNONLAKE(dev_priv)) { + if (IS_ICELAKE(dev_priv)) { + icl_display_core_init(dev_priv, resume); + } else if (IS_CANNONLAKE(dev_priv)) { cnl_display_core_init(dev_priv, resume); } else if (IS_GEN9_BC(dev_priv)) { skl_display_core_init(dev_priv, resume); @@ -3084,7 +3210,9 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv) if (!i915_modparams.disable_power_well) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); - if (IS_CANNONLAKE(dev_priv)) + if (IS_ICELAKE(dev_priv)) + icl_display_core_uninit(dev_priv); + else if (IS_CANNONLAKE(dev_priv)) cnl_display_core_uninit(dev_priv); else if (IS_GEN9_BC(dev_priv)) skl_display_core_uninit(dev_priv); @@ -3200,18 +3328,19 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv) * @dev_priv: i915 device instance * * This function grabs a device-level runtime pm reference if the device is - * already in use and ensures that it is powered up. + * already in use and ensures that it is powered up. It is illegal to try + * and access the HW should intel_runtime_pm_get_if_in_use() report failure. * * Any runtime pm reference obtained by this function must have a symmetric * call to intel_runtime_pm_put() to release the reference again. + * + * Returns: True if the wakeref was acquired, or False otherwise. */ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv) { - struct pci_dev *pdev = dev_priv->drm.pdev; - struct device *kdev = &pdev->dev; - if (IS_ENABLED(CONFIG_PM)) { - int ret = pm_runtime_get_if_in_use(kdev); + struct pci_dev *pdev = dev_priv->drm.pdev; + struct device *kdev = &pdev->dev; /* * In cases runtime PM is disabled by the RPM core and we get @@ -3219,9 +3348,7 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv) * function, since the power state is undefined. This applies * atm to the late/early system suspend/resume handlers. */ - WARN_ONCE(ret < 0, - "pm_runtime_get_if_in_use() failed: %d\n", ret); - if (ret <= 0) + if (pm_runtime_get_if_in_use(kdev) <= 0) return false; } diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 0bf97ed5ffac..0c14d1c04cbd 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -214,7 +214,7 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, struct intel_sdvo_connector *intel_sdvo_connector); -/** +/* * Writes the SDVOB or SDVOC with the given value, but always writes both * SDVOB and SDVOC to work around apparent hardware issues (according to * comments in the BIOS). @@ -250,10 +250,10 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) * writing them only once doesn't appear to 'stick'. * The BIOS does this too. Yay, magic */ - for (i = 0; i < 2; i++) - { + for (i = 0; i < 2; i++) { I915_WRITE(GEN3_SDVOB, bval); POSTING_READ(GEN3_SDVOB); + I915_WRITE(GEN3_SDVOC, cval); POSTING_READ(GEN3_SDVOC); } @@ -643,7 +643,7 @@ static bool intel_sdvo_set_target_input(struct intel_sdvo *intel_sdvo) &targets, sizeof(targets)); } -/** +/* * Return whether each input is trained. * * This function is making an assumption about the layout of the response, @@ -1061,8 +1061,10 @@ intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, return true; } -/* Asks the sdvo controller for the preferred input mode given the output mode. - * Unfortunately we have to set up the full output mode to do that. */ +/* + * Asks the sdvo controller for the preferred input mode given the output mode. + * Unfortunately we have to set up the full output mode to do that. + */ static bool intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, const struct drm_display_mode *mode, @@ -1095,8 +1097,10 @@ static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config) unsigned dotclock = pipe_config->port_clock; struct dpll *clock = &pipe_config->dpll; - /* SDVO TV has fixed PLL values depend on its clock range, - this mirrors vbios setting. */ + /* + * SDVO TV has fixed PLL values depend on its clock range, + * this mirrors vbios setting. + */ if (dotclock >= 100000 && dotclock < 140500) { clock->p1 = 2; clock->p2 = 10; @@ -1132,7 +1136,8 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, if (HAS_PCH_SPLIT(to_i915(encoder->base.dev))) pipe_config->has_pch_encoder = true; - /* We need to construct preferred input timings based on our + /* + * We need to construct preferred input timings based on our * output timings. To do that, we have to set the output * timings, even though this isn't really the right place in * the sequence to do it. Oh well. @@ -1155,7 +1160,8 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, adjusted_mode); } - /* Make the CRTC code factor in the SDVO pixel multiplier. The + /* + * Make the CRTC code factor in the SDVO pixel multiplier. The * SDVO device will factor out the multiplier during mode_set. */ pipe_config->pixel_multiplier = @@ -1169,9 +1175,12 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, pipe_config->has_audio = true; if (intel_sdvo_state->base.broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) { - /* See CEA-861-E - 5.1 Default Encoding Parameters */ - /* FIXME: This bit is only valid when using TMDS encoding and 8 - * bit per color mode. */ + /* + * See CEA-861-E - 5.1 Default Encoding Parameters + * + * FIXME: This bit is only valid when using TMDS encoding and 8 + * bit per color mode. + */ if (pipe_config->has_hdmi_sink && drm_match_cea_mode(adjusted_mode) > 1) pipe_config->limited_color_range = true; @@ -1272,7 +1281,8 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, intel_sdvo_update_props(intel_sdvo, sdvo_state); - /* First, set the input mapping for the first input to our controlled + /* + * First, set the input mapping for the first input to our controlled * output. This is only correct if we're a single-input device, in * which case the first input is the output from the appropriate SDVO * channel on the motherboard. In a two-input device, the first input @@ -1435,8 +1445,10 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd); if (!ret) { - /* Some sdvo encoders are not spec compliant and don't - * implement the mandatory get_timings function. */ + /* + * Some sdvo encoders are not spec compliant and don't + * implement the mandatory get_timings function. + */ DRM_DEBUG_DRIVER("failed to retrieve SDVO DTD\n"); pipe_config->quirks |= PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS; } else { @@ -1585,7 +1597,9 @@ static void intel_enable_sdvo(struct intel_encoder *encoder, intel_wait_for_vblank(dev_priv, intel_crtc->pipe); success = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2); - /* Warn if the device reported failure to sync. + /* + * Warn if the device reported failure to sync. + * * A lot of SDVO devices fail to notify of sync, but it's * a given it the status is a success, we succeeded. */ @@ -1672,8 +1686,10 @@ static uint16_t intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo) if (!I915_HAS_HOTPLUG(dev_priv)) return 0; - /* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise - * on the line. */ + /* + * HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise + * on the line. + */ if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) return 0; @@ -1957,7 +1973,8 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector) DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); - /* Read the list of supported input resolutions for the selected TV + /* + * Read the list of supported input resolutions for the selected TV * format. */ format_map = 1 << conn_state->tv.mode; @@ -2268,7 +2285,8 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo) uint16_t mask = 0; unsigned int num_bits; - /* Make a mask of outputs less than or equal to our own priority in the + /* + * Make a mask of outputs less than or equal to our own priority in the * list. */ switch (sdvo->controlled_output) { @@ -2298,7 +2316,7 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo) sdvo->ddc_bus = 1 << num_bits; } -/** +/* * Choose the appropriate DDC bus for control bus switch command for this * SDVO output based on the controlled output. * @@ -2342,9 +2360,11 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, sdvo->i2c = intel_gmbus_get_adapter(dev_priv, pin); - /* With gmbus we should be able to drive sdvo i2c at 2MHz, but somehow + /* + * With gmbus we should be able to drive sdvo i2c at 2MHz, but somehow * our code totally fails once we start using gmbus. Hence fall back to - * bit banging for now. */ + * bit banging for now. + */ intel_gmbus_force_bit(sdvo->i2c, true); } @@ -2379,7 +2399,8 @@ intel_sdvo_get_slave_addr(struct drm_i915_private *dev_priv, if (my_mapping->slave_addr) return my_mapping->slave_addr; - /* If the BIOS only described a different SDVO device, use the + /* + * If the BIOS only described a different SDVO device, use the * address that it isn't using. */ if (other_mapping->slave_addr) { @@ -2389,7 +2410,8 @@ intel_sdvo_get_slave_addr(struct drm_i915_private *dev_priv, return 0x70; } - /* No SDVO device info is found for another DVO port, + /* + * No SDVO device info is found for another DVO port, * so use mapping assumption we had before BIOS parsing. */ if (sdvo->port == PORT_B) @@ -2490,7 +2512,8 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) if (intel_sdvo_get_hotplug_support(intel_sdvo) & intel_sdvo_connector->output_flag) { intel_sdvo->hotplug_active |= intel_sdvo_connector->output_flag; - /* Some SDVO devices have one-shot hotplug interrupts. + /* + * Some SDVO devices have one-shot hotplug interrupts. * Ensure that they get re-enabled when an interrupt happens. */ intel_encoder->hot_plug = intel_sdvo_enable_hotplug; @@ -2789,7 +2812,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, to_intel_sdvo_connector_state(conn_state); uint16_t response, data_value[2]; - /* when horizontal overscan is supported, Add the left/right property */ + /* when horizontal overscan is supported, Add the left/right property */ if (enhancements.overscan_h) { if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_MAX_OVERSCAN_H, @@ -3074,7 +3097,8 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv, goto err_output; } - /* Only enable the hotplug irq if we need it, to work around noisy + /* + * Only enable the hotplug irq if we need it, to work around noisy * hotplug lines. */ if (intel_sdvo->hotplug_active) { diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 3be22c0fcfb5..e098e4b2c85c 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1063,8 +1063,8 @@ intel_check_sprite_plane(struct intel_plane *plane, return 0; } -int intel_sprite_set_colorkey(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_i915_private *dev_priv = to_i915(dev); struct drm_intel_sprite_colorkey *set = data; @@ -1077,6 +1077,9 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, /* ignore the pointless "none" flag */ set->flags &= ~I915_SET_COLORKEY_NONE; + if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) + return -EINVAL; + /* Make sure we don't try to enable both src & dest simultaneously */ if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) return -EINVAL; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index b3dabc219e6a..885fc3809f7f 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -43,7 +43,6 @@ enum tv_margin { TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM }; -/** Private structure for the integrated TV support */ struct intel_tv { struct intel_encoder base; @@ -370,12 +369,11 @@ struct tv_mode { * The constants below were all computed using a 107.520MHz clock */ -/** +/* * Register programming values for TV modes. * * These values account for -1s required. */ - static const struct tv_mode tv_modes[] = { { .name = "NTSC-M", @@ -1126,14 +1124,6 @@ static const struct drm_display_mode reported_modes[] = { }, }; -/** - * Detects TV presence by checking for load. - * - * Requires that the current pipe's DPLL is active. - - * \return true if TV is connected. - * \return false if TV is disconnected. - */ static int intel_tv_detect_type(struct intel_tv *intel_tv, struct drm_connector *connector) @@ -1259,12 +1249,6 @@ static void intel_tv_find_better_format(struct drm_connector *connector) connector->state->tv.mode = i; } -/** - * Detect the TV connection. - * - * Currently this always returns CONNECTOR_STATUS_UNKNOWN, as we need to be sure - * we have a pipe programmed in order to probe the TV. - */ static int intel_tv_detect(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx, @@ -1339,13 +1323,6 @@ intel_tv_choose_preferred_modes(const struct tv_mode *tv_mode, } } -/** - * Stub get_modes function. - * - * This should probably return a set of fixed modes, unless we can figure out - * how to probe modes off of TV connections. - */ - static int intel_tv_get_modes(struct drm_connector *connector) { @@ -1512,7 +1489,8 @@ intel_tv_init(struct drm_i915_private *dev_priv) connector = &intel_connector->base; state = connector->state; - /* The documentation, for the older chipsets at least, recommend + /* + * The documentation, for the older chipsets at least, recommend * using a polling method rather than hotplug detection for TVs. * This is because in order to perform the hotplug detection, the PLLs * for the TV must be kept alive increasing power drain and starving diff --git a/drivers/gpu/drm/i915/intel_uc_fw.c b/drivers/gpu/drm/i915/intel_uc_fw.c index 784eff9cdfc8..3ec0ce505b76 100644 --- a/drivers/gpu/drm/i915/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/intel_uc_fw.c @@ -197,11 +197,12 @@ fail: /** * intel_uc_fw_upload - load uC firmware using custom loader - * * @uc_fw: uC firmware - * @loader: custom uC firmware loader function + * @xfer: custom uC firmware loader function * * Loads uC firmware using custom loader and updates internal flags. + * + * Return: 0 on success, non-zero on failure. */ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, int (*xfer)(struct intel_uc_fw *uc_fw, diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 164dbb8cfa36..5ae9a62712ca 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1522,9 +1522,11 @@ static void gen3_stop_engine(struct intel_engine_cs *engine) engine->name); I915_WRITE_FW(RING_HEAD(base), I915_READ_FW(RING_TAIL(base))); + POSTING_READ_FW(RING_HEAD(base)); /* paranoia */ I915_WRITE_FW(RING_HEAD(base), 0); I915_WRITE_FW(RING_TAIL(base), 0); + POSTING_READ_FW(RING_TAIL(base)); /* The ring must be empty before it is disabled */ I915_WRITE_FW(RING_CTL(base), 0); @@ -1548,24 +1550,31 @@ static void i915_stop_engines(struct drm_i915_private *dev_priv, gen3_stop_engine(engine); } -static bool i915_reset_complete(struct pci_dev *pdev) +static bool i915_in_reset(struct pci_dev *pdev) { u8 gdrst; pci_read_config_byte(pdev, I915_GDRST, &gdrst); - return (gdrst & GRDOM_RESET_STATUS) == 0; + return gdrst & GRDOM_RESET_STATUS; } static int i915_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask) { struct pci_dev *pdev = dev_priv->drm.pdev; + int err; - /* assert reset for at least 20 usec */ + /* Assert reset for at least 20 usec, and wait for acknowledgement. */ pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE); usleep_range(50, 200); + err = wait_for(i915_in_reset(pdev), 500); + + /* Clear the reset request. */ pci_write_config_byte(pdev, I915_GDRST, 0); + usleep_range(50, 200); + if (!err) + err = wait_for(!i915_in_reset(pdev), 500); - return wait_for(i915_reset_complete(pdev), 500); + return err; } static bool g4x_reset_complete(struct pci_dev *pdev) @@ -1874,9 +1883,9 @@ static reset_func intel_get_gpu_reset(struct drm_i915_private *dev_priv) if (!i915_modparams.reset) return NULL; - if (INTEL_INFO(dev_priv)->gen >= 8) + if (INTEL_GEN(dev_priv) >= 8) return gen8_reset_engines; - else if (INTEL_INFO(dev_priv)->gen >= 6) + else if (INTEL_GEN(dev_priv) >= 6) return gen6_reset_engines; else if (IS_GEN5(dev_priv)) return ironlake_do_reset; @@ -1884,7 +1893,7 @@ static reset_func intel_get_gpu_reset(struct drm_i915_private *dev_priv) return g4x_do_reset; else if (IS_G33(dev_priv) || IS_PINEVIEW(dev_priv)) return g33_do_reset; - else if (INTEL_INFO(dev_priv)->gen >= 3) + else if (INTEL_GEN(dev_priv) >= 3) return i915_do_reset; else return NULL; diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h index bed019ef000f..53ef77d0c97c 100644 --- a/drivers/gpu/drm/i915/intel_uncore.h +++ b/drivers/gpu/drm/i915/intel_uncore.h @@ -198,4 +198,9 @@ int intel_wait_for_register_fw(struct drm_i915_private *dev_priv, 2, timeout_ms, NULL); } +#define raw_reg_read(base, reg) \ + readl(base + i915_mmio_reg_offset(reg)) +#define raw_reg_write(base, reg, value) \ + writel(value, base + i915_mmio_reg_offset(reg)) + #endif /* !__INTEL_UNCORE_H__ */ diff --git a/drivers/gpu/drm/i915/selftests/huge_gem_object.c b/drivers/gpu/drm/i915/selftests/huge_gem_object.c index a2632df39173..391f3d9ffdf1 100644 --- a/drivers/gpu/drm/i915/selftests/huge_gem_object.c +++ b/drivers/gpu/drm/i915/selftests/huge_gem_object.c @@ -129,8 +129,8 @@ huge_gem_object(struct drm_i915_private *i915, drm_gem_private_object_init(&i915->drm, &obj->base, dma_size); i915_gem_object_init(obj, &huge_ops); - obj->base.read_domains = I915_GEM_DOMAIN_CPU; - obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE; i915_gem_object_set_cache_coherency(obj, cache_level); obj->scratch = phys_size; diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c index 2ea69394f428..52b1bd17bf46 100644 --- a/drivers/gpu/drm/i915/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c @@ -178,8 +178,8 @@ huge_pages_object(struct drm_i915_private *i915, drm_gem_private_object_init(&i915->drm, &obj->base, size); i915_gem_object_init(obj, &huge_page_ops); - obj->base.write_domain = I915_GEM_DOMAIN_CPU; - obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; obj->cache_level = I915_CACHE_NONE; obj->mm.page_mask = page_mask; @@ -329,8 +329,8 @@ fake_huge_pages_object(struct drm_i915_private *i915, u64 size, bool single) else i915_gem_object_init(obj, &fake_ops); - obj->base.write_domain = I915_GEM_DOMAIN_CPU; - obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; obj->cache_level = I915_CACHE_NONE; return obj; diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index 56a803d11916..6da2a2f29c54 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -215,8 +215,8 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value) } i915_gem_obj_finish_shmem_access(obj); - obj->base.read_domains = I915_GEM_DOMAIN_GTT | I915_GEM_DOMAIN_CPU; - obj->base.write_domain = 0; + obj->read_domains = I915_GEM_DOMAIN_GTT | I915_GEM_DOMAIN_CPU; + obj->write_domain = 0; return 0; } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index d8064276431c..f7dc926f4ef1 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -113,8 +113,8 @@ fake_dma_object(struct drm_i915_private *i915, u64 size) drm_gem_private_object_init(&i915->drm, &obj->base, size); i915_gem_object_init(obj, &fake_ops); - obj->base.write_domain = I915_GEM_DOMAIN_CPU; - obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; obj->cache_level = I915_CACHE_NONE; /* Preallocate the "backing storage" */ @@ -927,7 +927,7 @@ static int shrink_boom(struct drm_i915_private *i915, explode = fake_dma_object(i915, size); if (IS_ERR(explode)) { - err = PTR_ERR(purge); + err = PTR_ERR(explode); goto err_purge; } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c index f32aa6bb79e2..3c64815e910b 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c @@ -212,8 +212,11 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj, return -EINTR; err = i915_gem_object_set_tiling(obj, tile->tiling, tile->stride); - if (err) + if (err) { + pr_err("Failed to set tiling mode=%u, stride=%u, err=%d\n", + tile->tiling, tile->stride, err); return err; + } GEM_BUG_ON(i915_gem_object_get_tiling(obj) != tile->tiling); GEM_BUG_ON(i915_gem_object_get_stride(obj) != tile->stride); @@ -230,13 +233,16 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj, GEM_BUG_ON(view.partial.size > nreal); err = i915_gem_object_set_to_gtt_domain(obj, true); - if (err) + if (err) { + pr_err("Failed to flush to GTT write domain; err=%d\n", + err); return err; + } vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE); if (IS_ERR(vma)) { - pr_err("Failed to pin partial view: offset=%lu\n", - page); + pr_err("Failed to pin partial view: offset=%lu; err=%d\n", + page, (int)PTR_ERR(vma)); return PTR_ERR(vma); } @@ -246,8 +252,8 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj, io = i915_vma_pin_iomap(vma); i915_vma_unpin(vma); if (IS_ERR(io)) { - pr_err("Failed to iomap partial view: offset=%lu\n", - page); + pr_err("Failed to iomap partial view: offset=%lu; err=%d\n", + page, (int)PTR_ERR(io)); return PTR_ERR(io); } diff --git a/drivers/gpu/drm/i915/selftests/intel_guc.c b/drivers/gpu/drm/i915/selftests/intel_guc.c index 3f9016466dea..fb74e2cf8a0a 100644 --- a/drivers/gpu/drm/i915/selftests/intel_guc.c +++ b/drivers/gpu/drm/i915/selftests/intel_guc.c @@ -87,7 +87,7 @@ static int validate_client(struct intel_guc_client *client, static bool client_doorbell_in_sync(struct intel_guc_client *client) { - return doorbell_ok(client->guc, client->doorbell_id); + return !client || doorbell_ok(client->guc, client->doorbell_id); } /* @@ -137,7 +137,6 @@ static int igt_guc_clients(void *args) goto unlock; } GEM_BUG_ON(!guc->execbuf_client); - GEM_BUG_ON(!guc->preempt_client); err = validate_client(guc->execbuf_client, GUC_CLIENT_PRIORITY_KMD_NORMAL, false); @@ -146,16 +145,18 @@ static int igt_guc_clients(void *args) goto out; } - err = validate_client(guc->preempt_client, - GUC_CLIENT_PRIORITY_KMD_HIGH, true); - if (err) { - pr_err("preempt client validation failed\n"); - goto out; + if (guc->preempt_client) { + err = validate_client(guc->preempt_client, + GUC_CLIENT_PRIORITY_KMD_HIGH, true); + if (err) { + pr_err("preempt client validation failed\n"); + goto out; + } } /* each client should now have reserved a doorbell */ if (!has_doorbell(guc->execbuf_client) || - !has_doorbell(guc->preempt_client)) { + (guc->preempt_client && !has_doorbell(guc->preempt_client))) { pr_err("guc_clients_create didn't reserve doorbells\n"); err = -EINVAL; goto out; @@ -224,7 +225,8 @@ out: * clients during unload. */ destroy_doorbell(guc->execbuf_client); - destroy_doorbell(guc->preempt_client); + if (guc->preempt_client) + destroy_doorbell(guc->preempt_client); guc_clients_destroy(guc); guc_clients_create(guc); guc_clients_doorbell_init(guc); diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 1bc61f3f76fc..3175db70cc6e 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -243,16 +243,10 @@ struct drm_i915_private *mock_gem_device(void) if (!i915->kernel_context) goto err_engine; - i915->preempt_context = mock_context(i915, NULL); - if (!i915->preempt_context) - goto err_kernel_context; - WARN_ON(i915_gemfs_init(i915)); return i915; -err_kernel_context: - i915_gem_context_put(i915->kernel_context); err_engine: for_each_engine(engine, i915, id) mock_engine_free(engine); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index dfda5e0ed166..26129b2b082d 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -570,7 +570,7 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc, base &= ~7; } work->base = base; - work->target_vblank = target - drm_crtc_vblank_count(crtc) + + work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) + dev->driver->get_vblank_counter(dev, work->crtc_id); /* We borrow the event spin lock for protecting flip_work */ diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index b8403ed48285..49df2db2ad46 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1359,7 +1359,7 @@ static u32 tegra_dc_get_vblank_counter(struct drm_crtc *crtc) return host1x_syncpt_read(dc->syncpt); /* fallback to software emulated VBLANK counter */ - return drm_crtc_vblank_count(&dc->base); + return (u32)drm_crtc_vblank_count(&dc->base); } static int tegra_dc_enable_vblank(struct drm_crtc *crtc) |