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
  ...
This commit is contained in:
Dave Airlie 2018-03-01 14:07:22 +10:00
commit f073d78eeb
83 changed files with 1872 additions and 961 deletions

View file

@ -210,7 +210,7 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
amdgpu_bo_unreserve(new_abo); amdgpu_bo_unreserve(new_abo);
work->base = base; 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); amdgpu_get_vblank_counter_kms(dev, work->crtc_id);
/* we borrow the event spin lock for protecting flip_wrok */ /* we borrow the event spin lock for protecting flip_wrok */

View file

@ -3842,7 +3842,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
/* Prepare wait for target vblank early - before the fence-waits */ /* 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); amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id);
/* TODO This might fail and hence better not used, wait /* 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( amdgpu_dm_do_flip(
crtc, crtc,
fb, fb,
drm_crtc_vblank_count(crtc) + *wait_for_vblank, (uint32_t)drm_crtc_vblank_count(crtc) + *wait_for_vblank,
dm_state->context); dm_state->context);
} }

View file

@ -948,7 +948,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
if (r) if (r)
return 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) { switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) {
case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE: case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE:

View file

@ -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); 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]; 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 * This is mostly useful for hardware that can obtain the scanout position, but
* doesn't have a hardware frame counter. * 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; struct drm_device *dev = crtc->dev;
unsigned int pipe = drm_crtc_index(crtc); unsigned int pipe = drm_crtc_index(crtc);
u32 vblank; u64 vblank;
unsigned long flags; unsigned long flags;
WARN_ONCE(drm_debug & DRM_UT_VBL && !dev->driver->get_vblank_timestamp, 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); spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
/* /*
* Only disable vblank interrupts if they're enabled. This avoids * Update vblank count and disable vblank interrupts only if the
* calling the ->disable_vblank() operation in atomic context with the * interrupts were enabled. This avoids calling the ->disable_vblank()
* hardware potentially runtime suspended. * operation in atomic context with the hardware potentially runtime
* suspended.
*/ */
if (vblank->enabled) { if (!vblank->enabled)
__disable_vblank(dev, pipe); goto out;
vblank->enabled = false;
}
/* /*
* 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 * appearance that the counter has been ticking all along until
* this time. This makes the count account for the entire time * this time. This makes the count account for the entire time
* between drm_crtc_vblank_on() and drm_crtc_vblank_off(). * between drm_crtc_vblank_on() and drm_crtc_vblank_off().
*/ */
drm_update_vblank_count(dev, pipe, false); drm_update_vblank_count(dev, pipe, false);
__disable_vblank(dev, pipe);
vblank->enabled = false;
out:
spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); 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]; struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
int ret; int ret;
u32 last; u64 last;
if (WARN_ON(pipe >= dev->num_crtcs)) if (WARN_ON(pipe >= dev->num_crtcs))
return; return;
@ -1235,6 +1237,65 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc)
} }
EXPORT_SYMBOL(drm_crtc_vblank_on); 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, static void drm_legacy_vblank_pre_modeset(struct drm_device *dev,
unsigned int pipe) unsigned int pipe)
{ {

View file

@ -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, type-limits)
subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers) 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, implicit-fallthrough)
subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable)
subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror
# Fine grained warnings disable # Fine grained warnings disable

View file

@ -59,28 +59,28 @@
* This must not be set while VR01_DVO_BYPASS_ENABLE is set. * This must not be set while VR01_DVO_BYPASS_ENABLE is set.
*/ */
# define VR01_LCD_ENABLE (1 << 2) # define VR01_LCD_ENABLE (1 << 2)
/** Enables the DVO repeater. */ /* Enables the DVO repeater. */
# define VR01_DVO_BYPASS_ENABLE (1 << 1) # define VR01_DVO_BYPASS_ENABLE (1 << 1)
/** Enables the DVO clock */ /* Enables the DVO clock */
# define VR01_DVO_ENABLE (1 << 0) # 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) # define VR01_DITHER_ENABLE (1 << 4)
/* /*
* LCD Interface Format * LCD Interface Format
*/ */
#define VR10 0x10 #define VR10 0x10
/** Enables LVDS output instead of CMOS */ /* Enables LVDS output instead of CMOS */
# define VR10_LVDS_ENABLE (1 << 4) # define VR10_LVDS_ENABLE (1 << 4)
/** Enables 18-bit LVDS output. */ /* Enables 18-bit LVDS output. */
# define VR10_INTERFACE_1X18 (0 << 2) # 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) # 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) # define VR10_INTERFACE_2X18 (2 << 2)
/** Enables 2x24-bit LVDS output */ /* Enables 2x24-bit LVDS output */
# define VR10_INTERFACE_2X24 (3 << 2) # 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) # define VR10_INTERFACE_DEPTH_MASK (3 << 2)
/* /*
@ -97,7 +97,7 @@
* Panel power down status * Panel power down status
*/ */
#define VR30 0x30 #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 VR30_PANEL_ON (1 << 15)
#define VR40 0x40 #define VR40 0x40
@ -183,7 +183,7 @@ struct ivch_priv {
static void ivch_dump_regs(struct intel_dvo_device *dvo); static void ivch_dump_regs(struct intel_dvo_device *dvo);
/** /*
* Reads a register on the ivch. * Reads a register on the ivch.
* *
* Each of the 256 registers are 16 bits long. * 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; 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) static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
{ {
struct ivch_priv *priv = dvo->dev_priv; 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; 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, static bool ivch_init(struct intel_dvo_device *dvo,
struct i2c_adapter *adapter) 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]); 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) static void ivch_dpms(struct intel_dvo_device *dvo, bool enable)
{ {
int i; int i;

View file

@ -162,8 +162,8 @@ static struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev,
info->size << PAGE_SHIFT); info->size << PAGE_SHIFT);
i915_gem_object_init(obj, &intel_vgpu_gem_ops); i915_gem_object_init(obj, &intel_vgpu_gem_ops);
obj->base.read_domains = I915_GEM_DOMAIN_GTT; obj->read_domains = I915_GEM_DOMAIN_GTT;
obj->base.write_domain = 0; obj->write_domain = 0;
if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
unsigned int tiling_mode = 0; unsigned int tiling_mode = 0;
unsigned int stride = 0; unsigned int stride = 0;

View file

@ -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_flags(info, &p);
intel_device_info_dump_runtime(info, &p); intel_device_info_dump_runtime(info, &p);
intel_driver_caps_print(&dev_priv->caps, &p);
kernel_param_lock(THIS_MODULE); kernel_param_lock(THIS_MODULE);
i915_params_dump(&i915_modparams, &p); 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_global_flag(obj),
get_pin_mapped_flag(obj), get_pin_mapped_flag(obj),
obj->base.size / 1024, obj->base.size / 1024,
obj->base.read_domains, obj->read_domains,
obj->base.write_domain, obj->write_domain,
i915_cache_level_str(dev_priv, obj->cache_level), i915_cache_level_str(dev_priv, obj->cache_level),
obj->mm.dirty ? " dirty" : "", obj->mm.dirty ? " dirty" : "",
obj->mm.madv == I915_MADV_DONTNEED ? " purgeable" : ""); 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); struct drm_i915_private *dev_priv = node_to_i915(m->private);
u32 gt_core_status, rcctl1, rc6vids = 0; u32 gt_core_status, rcctl1, rc6vids = 0;
u32 gen9_powergate_enable = 0, gen9_powergate_status = 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); gt_core_status = I915_READ_FW(GEN6_GT_CORE_STATUS);
trace_i915_reg_rw(false, GEN6_GT_CORE_STATUS, gt_core_status, 4, true); 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); gen9_powergate_status = I915_READ(GEN9_PWRGT_DOMAIN_STATUS);
} }
mutex_lock(&dev_priv->pcu_lock); if (INTEL_GEN(dev_priv) <= 7) {
sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids); mutex_lock(&dev_priv->pcu_lock);
mutex_unlock(&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", seq_printf(m, "RC1e Enabled: %s\n",
yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE)); 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_RC6p);
print_rc6_res(m, "RC6++ residency since boot:", GEN6_GT_GFX_RC6pp); print_rc6_res(m, "RC6++ residency since boot:", GEN6_GT_GFX_RC6pp);
seq_printf(m, "RC6 voltage: %dmV\n", if (INTEL_GEN(dev_priv) <= 7) {
GEN6_DECODE_RC6_VID(((rc6vids >> 0) & 0xff))); seq_printf(m, "RC6 voltage: %dmV\n",
seq_printf(m, "RC6+ voltage: %dmV\n", GEN6_DECODE_RC6_VID(((rc6vids >> 0) & 0xff)));
GEN6_DECODE_RC6_VID(((rc6vids >> 8) & 0xff))); seq_printf(m, "RC6+ voltage: %dmV\n",
seq_printf(m, "RC6++ voltage: %dmV\n", GEN6_DECODE_RC6_VID(((rc6vids >> 8) & 0xff)));
GEN6_DECODE_RC6_VID(((rc6vids >> 16) & 0xff))); seq_printf(m, "RC6++ voltage: %dmV\n",
GEN6_DECODE_RC6_VID(((rc6vids >> 16) & 0xff)));
}
return i915_forcewake_domains(m, NULL); 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); seq_printf(m, "FBC disabled: %s\n", fbc->no_fbc_reason);
if (fbc->work.scheduled) 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, fbc->work.scheduled_vblank,
drm_crtc_vblank_count(&fbc->crtc->base)); drm_crtc_vblank_count(&fbc->crtc->base));
@ -2338,7 +2332,6 @@ static int i915_guc_info(struct seq_file *m, void *data)
return -ENODEV; return -ENODEV;
GEM_BUG_ON(!guc->execbuf_client); GEM_BUG_ON(!guc->execbuf_client);
GEM_BUG_ON(!guc->preempt_client);
seq_printf(m, "Doorbell map:\n"); seq_printf(m, "Doorbell map:\n");
seq_printf(m, "\t%*pb\n", GUC_NUM_DOORBELLS, guc->doorbell_bitmap); 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); seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client);
i915_guc_client_info(m, dev_priv, guc->execbuf_client); i915_guc_client_info(m, dev_priv, guc->execbuf_client);
seq_printf(m, "\nGuC preempt client @ %p:\n", guc->preempt_client); if (guc->preempt_client) {
i915_guc_client_info(m, dev_priv, 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); i915_guc_log_info(m, dev_priv);
@ -4083,10 +4079,8 @@ i915_drop_caches_set(void *data, u64 val)
if (val & DROP_IDLE) if (val & DROP_IDLE)
drain_delayed_work(&dev_priv->gt.idle_work); drain_delayed_work(&dev_priv->gt.idle_work);
if (val & DROP_FREED) { if (val & DROP_FREED)
synchronize_rcu();
i915_gem_drain_freed_objects(dev_priv); i915_gem_drain_freed_objects(dev_priv);
}
return ret; return ret;
} }

View file

@ -122,10 +122,90 @@ static bool i915_error_injected(struct drm_i915_private *dev_priv)
i915_error_injected(dev_priv) ? KERN_DEBUG : KERN_ERR, \ i915_error_injected(dev_priv) ? KERN_DEBUG : KERN_ERR, \
fmt, ##__VA_ARGS__) fmt, ##__VA_ARGS__)
/* Map PCH device id to PCH type, or PCH_NONE if unknown. */
static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv) static enum intel_pch
intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id)
{ {
enum intel_pch ret = PCH_NOP; 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 bool intel_is_virt_pch(unsigned short id,
unsigned short svendor, unsigned short sdevice)
{
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 * 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. * make an educated guess as to which PCH is really there.
*/ */
if (IS_GEN5(dev_priv)) { if (IS_GEN5(dev_priv))
ret = PCH_IBX; id = INTEL_PCH_IBX_DEVICE_ID_TYPE;
DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n"); else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
} else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) { id = INTEL_PCH_CPT_DEVICE_ID_TYPE;
ret = PCH_CPT; else if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv))
DRM_DEBUG_KMS("Assuming CougarPoint PCH\n"); id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE;
} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
ret = PCH_LPT; id = INTEL_PCH_LPT_DEVICE_ID_TYPE;
if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
dev_priv->pch_id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; id = INTEL_PCH_SPT_DEVICE_ID_TYPE;
else else if (IS_COFFEELAKE(dev_priv) || IS_CANNONLAKE(dev_priv))
dev_priv->pch_id = INTEL_PCH_LPT_DEVICE_ID_TYPE; id = INTEL_PCH_CNP_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");
}
return ret; if (id)
DRM_DEBUG_KMS("Assuming PCH ID %04x\n", id);
else
DRM_DEBUG_KMS("Assuming no PCH\n");
return id;
} }
static void intel_detect_pch(struct drm_i915_private *dev_priv) 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))) { while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) {
unsigned short id; unsigned short id;
enum intel_pch pch_type;
if (pch->vendor != PCI_VENDOR_ID_INTEL) if (pch->vendor != PCI_VENDOR_ID_INTEL)
continue; continue;
id = pch->device & INTEL_PCH_DEVICE_ID_MASK; id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
dev_priv->pch_id = id; pch_type = intel_pch_type(dev_priv, id);
if (pch_type != PCH_NONE) {
if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) { dev_priv->pch_type = pch_type;
dev_priv->pch_type = PCH_IBX; dev_priv->pch_id = id;
DRM_DEBUG_KMS("Found Ibex Peak PCH\n"); break;
WARN_ON(!IS_GEN5(dev_priv)); } else if (intel_is_virt_pch(id, pch->subsystem_vendor,
} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) { pch->subsystem_device)) {
dev_priv->pch_type = PCH_CPT; id = intel_virt_detect_pch(dev_priv);
DRM_DEBUG_KMS("Found CougarPoint PCH\n"); if (id) {
WARN_ON(!IS_GEN6(dev_priv) && pch_type = intel_pch_type(dev_priv, id);
!IS_IVYBRIDGE(dev_priv)); if (WARN_ON(pch_type == PCH_NONE))
} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) { pch_type = PCH_NOP;
/* PantherPoint is CPT compatible */ } else {
dev_priv->pch_type = PCH_CPT; pch_type = PCH_NOP;
DRM_DEBUG_KMS("Found PantherPoint PCH\n"); }
WARN_ON(!IS_GEN6(dev_priv) && dev_priv->pch_type = pch_type;
!IS_IVYBRIDGE(dev_priv)); dev_priv->pch_id = id;
} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { break;
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;
} }
break;
} }
if (!pch) if (!pch)
DRM_DEBUG_KMS("No PCH found.\n"); 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); pci_dev_put(pch);
} }
static int i915_getparam(struct drm_device *dev, void *data, static int i915_getparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct pci_dev *pdev = dev_priv->drm.pdev; 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(); value = i915_gem_mmap_gtt_version();
break; break;
case I915_PARAM_HAS_SCHEDULER: case I915_PARAM_HAS_SCHEDULER:
value = 0; value = dev_priv->caps.scheduler;
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;
}
break; break;
case I915_PARAM_MMAP_VERSION: 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 * i915_driver_init_early - setup state not requiring device access
* @dev_priv: device private * @dev_priv: device private
* @ent: the matching pci_device_id
* *
* Initialize everything that is a "SW-only" state, that is state not * Initialize everything that is a "SW-only" state, that is state not
* requiring accessing the device or exposing the driver via kernel internal * 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 > BUILD_BUG_ON(INTEL_MAX_PLATFORMS >
sizeof(device_info->platform_mask) * BITS_PER_BYTE); 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); 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->irq_lock);
spin_lock_init(&dev_priv->gpu_error.lock); spin_lock_init(&dev_priv->gpu_error.lock);
mutex_init(&dev_priv->backlight_lock); mutex_init(&dev_priv->backlight_lock);
@ -1446,19 +1444,7 @@ void i915_driver_unload(struct drm_device *dev)
intel_modeset_cleanup(dev); intel_modeset_cleanup(dev);
/* intel_bios_cleanup(dev_priv);
* free the memory space allocated for the child device
* config parsed from VBT
*/
if (dev_priv->vbt.child_dev && dev_priv->vbt.child_dev_num) {
kfree(dev_priv->vbt.child_dev);
dev_priv->vbt.child_dev = NULL;
dev_priv->vbt.child_dev_num = 0;
}
kfree(dev_priv->vbt.sdvo_lvds_vbt_mode);
dev_priv->vbt.sdvo_lvds_vbt_mode = NULL;
kfree(dev_priv->vbt.lfp_lvds_vbt_mode);
dev_priv->vbt.lfp_lvds_vbt_mode = NULL;
vga_switcheroo_unregister_client(pdev); vga_switcheroo_unregister_client(pdev);
vga_client_register(pdev, NULL, NULL, NULL); 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); ret = i915_gem_reset_prepare(i915);
if (ret) { if (ret) {
dev_err(i915->drm.dev, "GPU recovery failed\n"); dev_err(i915->drm.dev, "GPU recovery failed\n");
intel_gpu_reset(i915, ALL_ENGINES);
goto taint; goto taint;
} }
@ -1957,7 +1942,8 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags)
*/ */
ret = i915_ggtt_enable_hw(i915); ret = i915_ggtt_enable_hw(i915);
if (ret) { 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; goto error;
} }
@ -1974,7 +1960,8 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags)
*/ */
ret = i915_gem_init_hw(i915); ret = i915_gem_init_hw(i915);
if (ret) { 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; goto error;
} }
@ -2006,6 +1993,7 @@ taint:
error: error:
i915_gem_set_wedged(i915); i915_gem_set_wedged(i915);
i915_gem_retire_requests(i915); i915_gem_retire_requests(i915);
intel_gpu_reset(i915, ALL_ENGINES);
goto finish; 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_BATCHBUFFER, drm_noop, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_IRQ_EMIT, 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_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_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_ALLOC, drm_noop, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_FREE, 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_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_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_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_EXECBUFFER, i915_gem_execbuffer_ioctl, DRM_AUTH),
DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2_WR, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW), 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_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_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_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_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_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_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_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_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_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_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_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_RENDER_ALLOW),

View file

@ -83,8 +83,8 @@
#define DRIVER_NAME "i915" #define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics" #define DRIVER_DESC "Intel Graphics"
#define DRIVER_DATE "20180207" #define DRIVER_DATE "20180221"
#define DRIVER_TIMESTAMP 1517988364 #define DRIVER_TIMESTAMP 1519219289
/* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and /* 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 * WARN_ON()) for hw state sanity checks to check for unexpected conditions
@ -472,6 +472,7 @@ struct i915_gpu_state {
u32 reset_count; u32 reset_count;
u32 suspend_count; u32 suspend_count;
struct intel_device_info device_info; struct intel_device_info device_info;
struct intel_driver_caps driver_caps;
struct i915_params params; struct i915_params params;
struct i915_error_uc { struct i915_error_uc {
@ -666,6 +667,7 @@ struct intel_fbc {
*/ */
struct intel_fbc_state_cache { struct intel_fbc_state_cache {
struct i915_vma *vma; struct i915_vma *vma;
unsigned long flags;
struct { struct {
unsigned int mode_flags; unsigned int mode_flags;
@ -704,6 +706,7 @@ struct intel_fbc {
*/ */
struct intel_fbc_reg_params { struct intel_fbc_reg_params {
struct i915_vma *vma; struct i915_vma *vma;
unsigned long flags;
struct { struct {
enum pipe pipe; enum pipe pipe;
@ -722,7 +725,7 @@ struct intel_fbc {
struct intel_fbc_work { struct intel_fbc_work {
bool scheduled; bool scheduled;
u32 scheduled_vblank; u64 scheduled_vblank;
struct work_struct work; struct work_struct work;
} work; } work;
@ -946,6 +949,8 @@ struct intel_rps {
struct intel_rc6 { struct intel_rc6 {
bool enabled; bool enabled;
u64 prev_hw_residency[4];
u64 cur_residency[4];
}; };
struct intel_llc_pstate { struct intel_llc_pstate {
@ -1092,6 +1097,11 @@ struct i915_gem_mm {
struct llist_head free_list; struct llist_head free_list;
struct work_struct free_work; struct work_struct free_work;
spinlock_t free_lock; 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 * Small stash of WC pages
@ -1356,6 +1366,7 @@ struct intel_vbt_data {
u32 size; u32 size;
u8 *data; u8 *data;
const u8 *sequence[MIPI_SEQ_MAX]; const u8 *sequence[MIPI_SEQ_MAX];
u8 *deassert_seq; /* Used by fixup_mipi_sequences() */
} dsi; } dsi;
int crt_ddc_pin; int crt_ddc_pin;
@ -1815,6 +1826,7 @@ struct drm_i915_private {
struct kmem_cache *priorities; struct kmem_cache *priorities;
const struct intel_device_info info; const struct intel_device_info info;
struct intel_driver_caps caps;
/** /**
* Data Stolen Memory - aka "i915 stolen memory" gives us the start and * 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. * We have one bit per pipe and per scanout plane type.
*/ */
#define INTEL_FRONTBUFFER_BITS_PER_PIPE 8 #define INTEL_FRONTBUFFER_BITS_PER_PIPE 8
#define INTEL_FRONTBUFFER(pipe, plane_id) \ #define INTEL_FRONTBUFFER(pipe, plane_id) ({ \
(1 << ((plane_id) + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) 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) \ #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) \ #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 * 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_FW_BLC(dev_priv) (INTEL_GEN(dev_priv) > 2)
#define HAS_FBC(dev_priv) ((dev_priv)->info.has_fbc) #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)) #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_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */
#define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type) #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_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(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CNP)
#define HAS_PCH_CNP_LP(dev_priv) \ #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_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_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(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LPT)
#define HAS_PCH_LPT_LP(dev_priv) \ #define HAS_PCH_LPT_LP(dev_priv) \
((dev_priv)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE || \ (INTEL_PCH_ID(dev_priv) == 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_WPT_LP_DEVICE_ID_TYPE)
#define HAS_PCH_LPT_H(dev_priv) \ #define HAS_PCH_LPT_H(dev_priv) \
((dev_priv)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE || \ (INTEL_PCH_ID(dev_priv) == INTEL_PCH_LPT_DEVICE_ID_TYPE || \
(dev_priv)->pch_id == INTEL_PCH_WPT_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_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_IBX(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_IBX)
#define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP) #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); struct drm_file *file_priv);
int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int i915_gem_execbuffer(struct drm_device *dev, void *data, int i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int i915_gem_execbuffer2(struct drm_device *dev, void *data, int i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int i915_gem_busy_ioctl(struct drm_device *dev, void *data, int i915_gem_busy_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data, 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) 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 /* A single pass should suffice to release all the freed objects (along
* most call paths) , but be a little more paranoid in that freeing * 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 * 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 struct i915_vma * __must_check
i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
u32 alignment, 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); 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 i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
int align); int align);
@ -3675,6 +3696,7 @@ extern void intel_i2c_reset(struct drm_i915_private *dev_priv);
/* intel_bios.c */ /* intel_bios.c */
void intel_bios_init(struct drm_i915_private *dev_priv); 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_valid_vbt(const void *buf, size_t size);
bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); 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); bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin);

View file

@ -240,8 +240,8 @@ err_phys:
static void __start_cpu_write(struct drm_i915_gem_object *obj) static void __start_cpu_write(struct drm_i915_gem_object *obj)
{ {
obj->base.read_domains = I915_GEM_DOMAIN_CPU; obj->read_domains = I915_GEM_DOMAIN_CPU;
obj->base.write_domain = I915_GEM_DOMAIN_CPU; obj->write_domain = I915_GEM_DOMAIN_CPU;
if (cpu_write_needs_clflush(obj)) if (cpu_write_needs_clflush(obj))
obj->cache_dirty = true; obj->cache_dirty = true;
} }
@ -257,7 +257,7 @@ __i915_gem_object_release_shmem(struct drm_i915_gem_object *obj,
obj->mm.dirty = false; obj->mm.dirty = false;
if (needs_clflush && 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)) !(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
drm_clflush_sg(pages); 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 drm_i915_private *dev_priv = to_i915(obj->base.dev);
struct i915_vma *vma; struct i915_vma *vma;
if (!(obj->base.write_domain & flush_domains)) if (!(obj->write_domain & flush_domains))
return; return;
switch (obj->base.write_domain) { switch (obj->write_domain) {
case I915_GEM_DOMAIN_GTT: case I915_GEM_DOMAIN_GTT:
i915_gem_flush_ggtt_writes(dev_priv); 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; break;
} }
obj->base.write_domain = 0; obj->write_domain = 0;
} }
static inline int 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. * anyway again before the next pread happens.
*/ */
if (!obj->cache_dirty && if (!obj->cache_dirty &&
!(obj->base.read_domains & I915_GEM_DOMAIN_CPU)) !(obj->read_domains & I915_GEM_DOMAIN_CPU))
*needs_clflush = CLFLUSH_BEFORE; *needs_clflush = CLFLUSH_BEFORE;
out: 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 * Same trick applies to invalidate partially written
* cachelines read before writing. * 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; *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 * wasn't in the GTT, there shouldn't be any way it could have been in
* a GPU cache * a GPU cache
*/ */
GEM_BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS); GEM_BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS);
GEM_BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS); GEM_BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS);
st = kmalloc(sizeof(*st), GFP_KERNEL); st = kmalloc(sizeof(*st), GFP_KERNEL);
if (st == NULL) 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); 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 * First, stop submission to hw, but do not yet complete requests by
* rolling the global seqno forward (since this would complete requests * 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. * start to complete all requests.
*/ */
engine->submit_request = nop_complete_submit_request; 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 * Make sure no request can slip through without getting completed by
* either this call here to intel_engine_init_global_seqno, or the one * 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) { for_each_engine(engine, i915, id) {
unsigned long flags; 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 * (lockless) lookup doesn't try and wait upon the request as we
* reset it. * reset it.
*/ */
@ -3251,7 +3258,6 @@ void i915_gem_set_wedged(struct drm_i915_private *i915)
spin_unlock_irqrestore(&engine->timeline->lock, flags); spin_unlock_irqrestore(&engine->timeline->lock, flags);
} }
set_bit(I915_WEDGED, &i915->gpu_error.flags);
wake_up_all(&i915->gpu_error.reset_queue); 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); flush_write_domain(obj, ~I915_GEM_DOMAIN_CPU);
if (obj->cache_dirty) if (obj->cache_dirty)
i915_gem_clflush_object(obj, I915_CLFLUSH_FORCE); 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) 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) if (ret)
return ret; return ret;
if (obj->base.write_domain == I915_GEM_DOMAIN_WC) if (obj->write_domain == I915_GEM_DOMAIN_WC)
return 0; return 0;
/* Flush and acquire obj->pages so that we are coherent through /* 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 * coherent writes from the GPU, by effectively invalidating the
* WC domain upon first access. * 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(); mb();
/* It should now be out of any other write domains, and we can update /* It should now be out of any other write domains, and we can update
* the domain values for our changes. * the domain values for our changes.
*/ */
GEM_BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_WC) != 0); GEM_BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_WC) != 0);
obj->base.read_domains |= I915_GEM_DOMAIN_WC; obj->read_domains |= I915_GEM_DOMAIN_WC;
if (write) { if (write) {
obj->base.read_domains = I915_GEM_DOMAIN_WC; obj->read_domains = I915_GEM_DOMAIN_WC;
obj->base.write_domain = I915_GEM_DOMAIN_WC; obj->write_domain = I915_GEM_DOMAIN_WC;
obj->mm.dirty = true; 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) if (ret)
return ret; return ret;
if (obj->base.write_domain == I915_GEM_DOMAIN_GTT) if (obj->write_domain == I915_GEM_DOMAIN_GTT)
return 0; return 0;
/* Flush and acquire obj->pages so that we are coherent through /* 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 * coherent writes from the GPU, by effectively invalidating the
* GTT domain upon first access. * 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(); mb();
/* It should now be out of any other write domains, and we can update /* It should now be out of any other write domains, and we can update
* the domain values for our changes. * the domain values for our changes.
*/ */
GEM_BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0); GEM_BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
obj->base.read_domains |= I915_GEM_DOMAIN_GTT; obj->read_domains |= I915_GEM_DOMAIN_GTT;
if (write) { if (write) {
obj->base.read_domains = I915_GEM_DOMAIN_GTT; obj->read_domains = I915_GEM_DOMAIN_GTT;
obj->base.write_domain = I915_GEM_DOMAIN_GTT; obj->write_domain = I915_GEM_DOMAIN_GTT;
obj->mm.dirty = true; obj->mm.dirty = true;
} }
@ -4072,7 +4078,8 @@ out:
struct i915_vma * struct i915_vma *
i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
u32 alignment, u32 alignment,
const struct i915_ggtt_view *view) const struct i915_ggtt_view *view,
unsigned int flags)
{ {
struct i915_vma *vma; struct i915_vma *vma;
int ret; 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). * try to preserve the existing ABI).
*/ */
vma = ERR_PTR(-ENOSPC); 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, vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment,
PIN_MAPPABLE | PIN_NONBLOCK); flags |
if (IS_ERR(vma)) { PIN_MAPPABLE |
struct drm_i915_private *i915 = to_i915(obj->base.dev); PIN_NONBLOCK);
unsigned int flags; if (IS_ERR(vma))
/* 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;
vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, flags); vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, flags);
}
if (IS_ERR(vma)) if (IS_ERR(vma))
goto err_unpin_global; 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 /* It should now be out of any other write domains, and we can update
* the domain values for our changes. * the domain values for our changes.
*/ */
obj->base.read_domains |= I915_GEM_DOMAIN_GTT; obj->read_domains |= I915_GEM_DOMAIN_GTT;
return vma; 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_write_domain(obj, ~I915_GEM_DOMAIN_CPU);
/* Flush the CPU cache if it's still invalid. */ /* 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); 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 /* It should now be out of any other write domains, and we can update
* the domain values for our changes. * 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 /* If we're writing through the CPU, then the GPU read domains will
* need to be invalidated at next use. * 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); 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 /* If the required space is larger than the available
* aperture, we will not able to find a slot for the * aperture, we will not able to find a slot for the
* object and unbinding the object now will be in * 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); i915_gem_object_init(obj, &i915_gem_object_ops);
obj->base.write_domain = I915_GEM_DOMAIN_CPU; obj->write_domain = I915_GEM_DOMAIN_CPU;
obj->base.read_domains = I915_GEM_DOMAIN_CPU; obj->read_domains = I915_GEM_DOMAIN_CPU;
if (HAS_LLC(dev_priv)) if (HAS_LLC(dev_priv))
/* On some devices, we can have the GPU use the LLC (the CPU /* 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); kfree(obj->bit_17);
i915_gem_object_free(obj); i915_gem_object_free(obj);
GEM_BUG_ON(!atomic_read(&i915->mm.free_count));
atomic_dec(&i915->mm.free_count);
if (on) if (on)
cond_resched(); 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 * i915_gem_busy_ioctl(). For the corresponding synchronized
* lookup see i915_gem_object_lookup_rcu(). * 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); 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 * it may impact the display and we are uncertain about the stability
* of the reset, so this could be applied to even earlier gen. * of the reset, so this could be applied to even earlier gen.
*/ */
if (INTEL_GEN(i915) >= 5) { if (INTEL_GEN(i915) >= 5 && intel_has_gpu_reset(i915))
int reset = intel_gpu_reset(i915, ALL_ENGINES); WARN_ON(intel_gpu_reset(i915, ALL_ENGINES));
WARN_ON(reset && reset != -ENODEV);
}
} }
int i915_gem_suspend(struct drm_i915_private *dev_priv) 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) { for_each_engine(engine, i915, id) {
err = engine->init_hw(engine); err = engine->init_hw(engine);
if (err) if (err) {
DRM_ERROR("Failed to restart %s (%d)\n",
engine->name, err);
return err; return err;
}
} }
return 0; return 0;
@ -5118,14 +5120,16 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
ret = i915_ppgtt_init_hw(dev_priv); ret = i915_ppgtt_init_hw(dev_priv);
if (ret) { if (ret) {
DRM_ERROR("PPGTT enable HW failed %d\n", ret); DRM_ERROR("Enabling PPGTT failed (%d)\n", ret);
goto out; goto out;
} }
/* We can't enable contexts until all firmware is loaded */ /* We can't enable contexts until all firmware is loaded */
ret = intel_uc_init_hw(dev_priv); ret = intel_uc_init_hw(dev_priv);
if (ret) if (ret) {
DRM_ERROR("Enabling uc failed (%d)\n", ret);
goto out; goto out;
}
intel_mocs_init_l3cc_table(dev_priv); intel_mocs_init_l3cc_table(dev_priv);
@ -5415,10 +5419,10 @@ i915_gem_load_init_fences(struct drm_i915_private *dev_priv)
{ {
int i; 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)) !IS_CHERRYVIEW(dev_priv))
dev_priv->num_fence_regs = 32; 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_I945G(dev_priv) || IS_I945GM(dev_priv) ||
IS_G33(dev_priv) || IS_PINEVIEW(dev_priv)) IS_G33(dev_priv) || IS_PINEVIEW(dev_priv))
dev_priv->num_fence_regs = 16; dev_priv->num_fence_regs = 16;
@ -5537,7 +5541,8 @@ err_out:
void i915_gem_load_cleanup(struct drm_i915_private *dev_priv) void i915_gem_load_cleanup(struct drm_i915_private *dev_priv)
{ {
i915_gem_drain_freed_objects(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); WARN_ON(dev_priv->mm.object_count);
mutex_lock(&dev_priv->drm.struct_mutex); 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)) if (IS_ERR(obj))
return 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; file = obj->base.filp;
offset = 0; offset = 0;

View file

@ -177,7 +177,7 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj,
} else if (obj->mm.pages) { } else if (obj->mm.pages) {
__i915_do_clflush(obj); __i915_do_clflush(obj);
} else { } 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; obj->cache_dirty = false;

View file

@ -338,11 +338,6 @@ static void __destroy_hw_context(struct i915_gem_context *ctx,
context_close(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 * static struct i915_gem_context *
i915_gem_create_context(struct drm_i915_private *dev_priv, i915_gem_create_context(struct drm_i915_private *dev_priv,
struct drm_i915_file_private *file_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); 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) int i915_gem_contexts_init(struct drm_i915_private *dev_priv)
{ {
struct i915_gem_context *ctx; 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->kernel_context);
GEM_BUG_ON(dev_priv->preempt_context);
INIT_LIST_HEAD(&dev_priv->contexts.list); INIT_LIST_HEAD(&dev_priv->contexts.list);
INIT_WORK(&dev_priv->contexts.free_work, contexts_free_worker); 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); ctx = i915_gem_context_create_kernel(dev_priv, I915_PRIORITY_MIN);
if (IS_ERR(ctx)) { if (IS_ERR(ctx)) {
DRM_ERROR("Failed to create default global context\n"); DRM_ERROR("Failed to create default global context\n");
err = PTR_ERR(ctx); return PTR_ERR(ctx);
goto err;
} }
/* /*
* For easy recognisablity, we want the kernel context to be 0 and then * 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; dev_priv->kernel_context = ctx;
/* highest priority; preempting task */ /* highest priority; preempting task */
ctx = i915_gem_context_create_kernel(dev_priv, INT_MAX); if (needs_preempt_context(dev_priv)) {
if (IS_ERR(ctx)) { ctx = i915_gem_context_create_kernel(dev_priv, INT_MAX);
DRM_ERROR("Failed to create default preempt context\n"); if (!IS_ERR(ctx))
err = PTR_ERR(ctx); dev_priv->preempt_context = ctx;
goto err_kernel_context; else
DRM_ERROR("Failed to create preempt context; disabling preemption\n");
} }
dev_priv->preempt_context = ctx;
DRM_DEBUG_DRIVER("%s context support initialized\n", DRM_DEBUG_DRIVER("%s context support initialized\n",
dev_priv->engine[RCS]->context_size ? "logical" : dev_priv->engine[RCS]->context_size ? "logical" :
"fake"); "fake");
return 0; 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) 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); 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); destroy_kernel_context(&i915->kernel_context);
/* Must free all deferred contexts (via flush_workqueue) first */ /* 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: case I915_CONTEXT_PARAM_PRIORITY:
{ {
int priority = args->value; s64 priority = args->value;
if (args->size) if (args->size)
ret = -EINVAL; ret = -EINVAL;
else if (!to_i915(dev)->engine[RCS]->schedule) else if (!(to_i915(dev)->caps.scheduler & I915_SCHEDULER_CAP_PRIORITY))
ret = -ENODEV; ret = -ENODEV;
else if (priority > I915_CONTEXT_MAX_USER_PRIORITY || else if (priority > I915_CONTEXT_MAX_USER_PRIORITY ||
priority < I915_CONTEXT_MIN_USER_PRIORITY) priority < I915_CONTEXT_MIN_USER_PRIORITY)

View file

@ -29,6 +29,8 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/radix-tree.h> #include <linux/radix-tree.h>
#include "i915_gem.h"
struct pid; struct pid;
struct drm_device; struct drm_device;
@ -36,6 +38,7 @@ struct drm_file;
struct drm_i915_private; struct drm_i915_private;
struct drm_i915_file_private; struct drm_i915_file_private;
struct drm_i915_gem_request;
struct i915_hw_ppgtt; struct i915_hw_ppgtt;
struct i915_vma; struct i915_vma;
struct intel_ring; struct intel_ring;

View file

@ -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 * write-combined buffer or a delay through the chipset for GTT
* writes that do require us to treat GTT as a separate cache domain.) * writes that do require us to treat GTT as a separate cache domain.)
*/ */
obj->base.read_domains = I915_GEM_DOMAIN_GTT; obj->read_domains = I915_GEM_DOMAIN_GTT;
obj->base.write_domain = 0; obj->write_domain = 0;
return &obj->base; return &obj->base;

View file

@ -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); list_add_tail(&vma->exec_link, &eb->unbound);
if (drm_mm_node_allocated(&vma->node)) if (drm_mm_node_allocated(&vma->node))
err = i915_vma_unbind(vma); err = i915_vma_unbind(vma);
if (unlikely(err))
vma->exec_flags = NULL;
} }
return err; return err;
} }
@ -1073,7 +1075,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb,
u32 *cmd; u32 *cmd;
int err; 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); obj = i915_gem_batch_pool_get(&eb->engine->batch_pool, PAGE_SIZE);
if (IS_ERR(obj)) 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); i915_gem_active_set(&vma->last_read[idx], req);
list_move_tail(&vma->vm_link, &vma->vm->active_list); list_move_tail(&vma->vm_link, &vma->vm->active_list);
obj->base.write_domain = 0; obj->write_domain = 0;
if (flags & EXEC_OBJECT_WRITE) { 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)) if (intel_fb_obj_invalidate(obj, ORIGIN_CS))
i915_gem_active_set(&obj->frontbuffer_write, req); 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) if (flags & EXEC_OBJECT_NEEDS_FENCE)
i915_gem_active_set(&vma->last_fence, req); i915_gem_active_set(&vma->last_fence, req);
@ -1973,7 +1975,7 @@ static int eb_submit(struct i915_execbuffer *eb)
return 0; return 0;
} }
/** /*
* Find one BSD ring to dispatch the corresponding BSD command. * Find one BSD ring to dispatch the corresponding BSD command.
* The engine index is returned. * The engine index is returned.
*/ */
@ -2410,7 +2412,7 @@ err_request:
if (out_fence) { if (out_fence) {
if (err == 0) { if (err == 0) {
fd_install(out_fence_fd, out_fence->file); 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; args->rsvd2 |= (u64)out_fence_fd << 32;
out_fence_fd = -1; out_fence_fd = -1;
} else { } else {
@ -2463,8 +2465,8 @@ static bool check_buffer_count(size_t count)
* list array and passes it to the real function. * list array and passes it to the real function.
*/ */
int int
i915_gem_execbuffer(struct drm_device *dev, void *data, i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data,
struct drm_file *file) struct drm_file *file)
{ {
struct drm_i915_gem_execbuffer *args = data; struct drm_i915_gem_execbuffer *args = data;
struct drm_i915_gem_execbuffer2 exec2; struct drm_i915_gem_execbuffer2 exec2;
@ -2554,8 +2556,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
} }
int int
i915_gem_execbuffer2(struct drm_device *dev, void *data, i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data,
struct drm_file *file) struct drm_file *file)
{ {
struct drm_i915_gem_execbuffer2 *args = data; struct drm_i915_gem_execbuffer2 *args = data;
struct drm_i915_gem_exec_object2 *exec2_list; struct drm_i915_gem_exec_object2 *exec2_list;

View file

@ -64,7 +64,7 @@ static void i965_write_fence_reg(struct drm_i915_fence_reg *fence,
int fence_pitch_shift; int fence_pitch_shift;
u64 val; 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_lo = FENCE_REG_GEN6_LO(fence->id);
fence_reg_hi = FENCE_REG_GEN6_HI(fence->id); fence_reg_hi = FENCE_REG_GEN6_HI(fence->id);
fence_pitch_shift = GEN6_FENCE_PITCH_SHIFT; fence_pitch_shift = GEN6_FENCE_PITCH_SHIFT;

View file

@ -673,27 +673,22 @@ static void free_pd(struct i915_address_space *vm,
static void gen8_initialize_pd(struct i915_address_space *vm, static void gen8_initialize_pd(struct i915_address_space *vm,
struct i915_page_directory *pd) struct i915_page_directory *pd)
{ {
unsigned int i;
fill_px(vm, pd, fill_px(vm, pd,
gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC)); gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC));
for (i = 0; i < I915_PDES; i++) memset_p((void **)pd->page_table, vm->scratch_pt, I915_PDES);
pd->page_table[i] = vm->scratch_pt;
} }
static int __pdp_init(struct i915_address_space *vm, static int __pdp_init(struct i915_address_space *vm,
struct i915_page_directory_pointer *pdp) struct i915_page_directory_pointer *pdp)
{ {
const unsigned int pdpes = i915_pdpes_per_pdp(vm); const unsigned int pdpes = i915_pdpes_per_pdp(vm);
unsigned int i;
pdp->page_directory = kmalloc_array(pdpes, sizeof(*pdp->page_directory), pdp->page_directory = kmalloc_array(pdpes, sizeof(*pdp->page_directory),
GFP_KERNEL | __GFP_NOWARN); GFP_KERNEL | __GFP_NOWARN);
if (unlikely(!pdp->page_directory)) if (unlikely(!pdp->page_directory))
return -ENOMEM; return -ENOMEM;
for (i = 0; i < pdpes; i++) memset_p((void **)pdp->page_directory, vm->scratch_pd, pdpes);
pdp->page_directory[i] = vm->scratch_pd;
return 0; return 0;
} }
@ -715,7 +710,7 @@ alloc_pdp(struct i915_address_space *vm)
struct i915_page_directory_pointer *pdp; struct i915_page_directory_pointer *pdp;
int ret = -ENOMEM; int ret = -ENOMEM;
WARN_ON(!use_4lvl(vm)); GEM_BUG_ON(!use_4lvl(vm));
pdp = kzalloc(sizeof(*pdp), GFP_KERNEL); pdp = kzalloc(sizeof(*pdp), GFP_KERNEL);
if (!pdp) 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, static void gen8_initialize_pml4(struct i915_address_space *vm,
struct i915_pml4 *pml4) struct i915_pml4 *pml4)
{ {
unsigned int i;
fill_px(vm, pml4, fill_px(vm, pml4,
gen8_pml4e_encode(px_dma(vm->scratch_pdp), I915_CACHE_LLC)); gen8_pml4e_encode(px_dma(vm->scratch_pdp), I915_CACHE_LLC));
for (i = 0; i < GEN8_PML4ES_PER_PML4; i++) memset_p((void **)pml4->pdps, vm->scratch_pdp, GEN8_PML4ES_PER_PML4);
pml4->pdps[i] = vm->scratch_pdp;
} }
/* Broadwell Page Directory Pointer Descriptors */ /* 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.i915 = dev_priv;
ppgtt->base.dma = &dev_priv->drm.pdev->dev; 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); return gen6_ppgtt_init(ppgtt);
else else
return gen8_ppgtt_init(ppgtt); return gen8_ppgtt_init(ppgtt);
@ -2257,9 +2249,9 @@ void i915_ppgtt_release(struct kref *kref)
trace_i915_ppgtt_release(&ppgtt->base); trace_i915_ppgtt_release(&ppgtt->base);
/* vmas should already be unbound and destroyed */ /* vmas should already be unbound and destroyed */
WARN_ON(!list_empty(&ppgtt->base.active_list)); GEM_BUG_ON(!list_empty(&ppgtt->base.active_list));
WARN_ON(!list_empty(&ppgtt->base.inactive_list)); GEM_BUG_ON(!list_empty(&ppgtt->base.inactive_list));
WARN_ON(!list_empty(&ppgtt->base.unbound_list)); GEM_BUG_ON(!list_empty(&ppgtt->base.unbound_list));
ppgtt->base.cleanup(&ppgtt->base); ppgtt->base.cleanup(&ppgtt->base);
i915_address_space_fini(&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; 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; 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; ggtt->base.unbind_vma = aliasing_gtt_unbind_vma;
return 0; return 0;
@ -2916,7 +2908,7 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv)
ggtt->base.closed = true; ggtt->base.closed = true;
mutex_lock(&dev_priv->drm.struct_mutex); 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) list_for_each_entry_safe(vma, vn, &ggtt->base.inactive_list, vm_link)
WARN_ON(i915_vma_unbind(vma)); WARN_ON(i915_vma_unbind(vma));
mutex_unlock(&dev_priv->drm.struct_mutex); 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)); GEM_BUG_ON(!i915_gem_object_has_pinned_pages(vma->obj));
switch (vma->ggtt_view.type) { switch (vma->ggtt_view.type) {
default:
GEM_BUG_ON(vma->ggtt_view.type);
/* fall through */
case I915_GGTT_VIEW_NORMAL: case I915_GGTT_VIEW_NORMAL:
vma->pages = vma->obj->mm.pages; vma->pages = vma->obj->mm.pages;
return 0; return 0;
@ -3821,11 +3816,6 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma)
case I915_GGTT_VIEW_PARTIAL: case I915_GGTT_VIEW_PARTIAL:
vma->pages = intel_partial_pages(&vma->ggtt_view, vma->obj); vma->pages = intel_partial_pages(&vma->ggtt_view, vma->obj);
break; break;
default:
WARN_ONCE(1, "GGTT view %u not implemented!\n",
vma->ggtt_view.type);
return -EINVAL;
} }
ret = 0; ret = 0;

View file

@ -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. * 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 * 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 * 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); drm_gem_private_object_init(&i915->drm, &obj->base, size);
i915_gem_object_init(obj, &i915_gem_object_internal_ops); i915_gem_object_init(obj, &i915_gem_object_internal_ops);
obj->base.read_domains = I915_GEM_DOMAIN_CPU; obj->read_domains = I915_GEM_DOMAIN_CPU;
obj->base.write_domain = I915_GEM_DOMAIN_CPU; obj->write_domain = I915_GEM_DOMAIN_CPU;
cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE; cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE;
i915_gem_object_set_cache_coherency(obj, cache_level); i915_gem_object_set_cache_coherency(obj, cache_level);

View file

@ -148,6 +148,21 @@ struct drm_i915_gem_object {
#define I915_BO_CACHE_COHERENT_FOR_WRITE BIT(1) #define I915_BO_CACHE_COHERENT_FOR_WRITE BIT(1)
unsigned int cache_dirty: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; atomic_t frontbuffer_bits;
unsigned int frontbuffer_ggtt_origin; /* write once */ unsigned int frontbuffer_ggtt_origin; /* write once */
struct i915_gem_active frontbuffer_write; struct i915_gem_active frontbuffer_write;

View file

@ -443,12 +443,14 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
engine->last_retired_context = request->ctx; engine->last_retired_context = request->ctx;
spin_lock_irq(&request->lock); 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)) if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &request->fence.flags))
dma_fence_signal_locked(&request->fence); dma_fence_signal_locked(&request->fence);
if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags)) if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags))
intel_engine_cancel_signaling(request); 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); spin_unlock_irq(&request->lock);
i915_priotree_fini(request->i915, &request->priotree); 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 * i915_gem_request_await_object - set this request to (async) wait upon a bo
*
* @to: request we are wishing to use * @to: request we are wishing to use
* @obj: object which may be in use on another ring. * @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. * This code is meant to abstract object synchronization with the GPU.
* Conceptually we serialise writes between engines inside 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); lockdep_assert_held(&request->i915->drm.struct_mutex);
trace_i915_gem_request_add(request); 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 * our i915_gem_request_alloc() and called __i915_add_request() before
* us, the timeline will hold its seqno which is later than ours. * 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); 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 * should we detect the updated seqno part-way through the
* GPU processing the request, we never over-estimate the * GPU processing the request, we never over-estimate the
* position of the ring's HEAD. * 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)); GEM_BUG_ON(IS_ERR(cs));
request->postfix = intel_ring_offset(request, 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 * we may inspect this state, without holding any locks, during
* hangcheck. Hence we apply the barrier to ensure that we do not * hangcheck. Hence we apply the barrier to ensure that we do not
* see a more recent value in the hws than we are tracking. * 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, prev = i915_gem_active_raw(&timeline->last_request,
&request->i915->drm.struct_mutex); &request->i915->drm.struct_mutex);
if (prev) { if (prev && !i915_gem_request_completed(prev)) {
i915_sw_fence_await_sw_fence(&request->submit, &prev->submit, i915_sw_fence_await_sw_fence(&request->submit, &prev->submit,
&request->submitq); &request->submitq);
if (engine->schedule) 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); list_add_tail(&request->ring_link, &ring->request_list);
request->emitted_jiffies = jiffies; 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 * to adjust the existing execution schedule due to a high priority
* request - i.e. we may want to preempt the current request in order * 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 * 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(); local_bh_disable();
i915_sw_fence_commit(&request->submit); i915_sw_fence_commit(&request->submit);
local_bh_enable(); /* Kick the execlists tasklet if just scheduled */ 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) static unsigned long local_clock_us(unsigned int *cpu)

View file

@ -356,7 +356,7 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv)
reserved_base = 0; reserved_base = 0;
reserved_size = 0; reserved_size = 0;
switch (INTEL_INFO(dev_priv)->gen) { switch (INTEL_GEN(dev_priv)) {
case 2: case 2:
case 3: case 3:
break; 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); i915_gem_object_init(obj, &i915_gem_object_stolen_ops);
obj->stolen = stolen; 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; cache_level = HAS_LLC(dev_priv) ? I915_CACHE_LLC : I915_CACHE_NONE;
i915_gem_object_set_cache_coherency(obj, cache_level); i915_gem_object_set_cache_coherency(obj, cache_level);

View file

@ -721,7 +721,7 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
.release = i915_gem_userptr_release, .release = i915_gem_userptr_release,
}; };
/** /*
* Creates a new mm object that wraps some normal memory from the process * Creates a new mm object that wraps some normal memory from the process
* context - user memory. * context - user memory.
* *
@ -757,7 +757,9 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
* dma-buf instead. * dma-buf instead.
*/ */
int 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_private *dev_priv = to_i915(dev);
struct drm_i915_gem_userptr *args = data; 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); drm_gem_private_object_init(dev, &obj->base, args->user_size);
i915_gem_object_init(obj, &i915_gem_userptr_ops); i915_gem_object_init(obj, &i915_gem_userptr_ops);
obj->base.read_domains = I915_GEM_DOMAIN_CPU; obj->read_domains = I915_GEM_DOMAIN_CPU;
obj->base.write_domain = I915_GEM_DOMAIN_CPU; obj->write_domain = I915_GEM_DOMAIN_CPU;
i915_gem_object_set_cache_coherency(obj, I915_CACHE_LLC); i915_gem_object_set_cache_coherency(obj, I915_CACHE_LLC);
obj->userptr.ptr = args->user_ptr; obj->userptr.ptr = args->user_ptr;

View file

@ -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, 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); struct drm_printer p = i915_error_printer(m);
intel_device_info_dump_flags(info, &p); 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, 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) if (error->display)
intel_display_print_error_state(m, 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_params(m, &error->params);
err_print_uc(m, &error->uc); 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->engine = __active_get_engine_id(&obj->frontbuffer_write);
err->gtt_offset = vma->node.start; err->gtt_offset = vma->node.start;
err->read_domains = obj->base.read_domains; err->read_domains = obj->read_domains;
err->write_domain = obj->base.write_domain; err->write_domain = obj->write_domain;
err->fence_reg = vma->fence ? vma->fence->id : -1; err->fence_reg = vma->fence ? vma->fence->id : -1;
err->tiling = i915_gem_object_get_tiling(obj); err->tiling = i915_gem_object_get_tiling(obj);
err->dirty = obj->mm.dirty; 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, memcpy(&error->device_info,
INTEL_INFO(dev_priv), INTEL_INFO(dev_priv),
sizeof(error->device_info)); sizeof(error->device_info));
error->driver_caps = dev_priv->caps;
} }
static __always_inline void dup_param(const char *type, void *x) 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 * 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 * 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 * interrupt) to capture error state from the time of the error. Fills
* out a structure which becomes available in debugfs for user level tools * out a structure which becomes available in debugfs for user level tools
* to pick up. * 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, u32 engine_mask,
const char *error_msg) const char *error_msg)
{ {
@ -1820,25 +1825,25 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv,
if (!i915_modparams.error_capture) if (!i915_modparams.error_capture)
return; return;
if (READ_ONCE(dev_priv->gpu_error.first_error)) if (READ_ONCE(i915->gpu_error.first_error))
return; return;
error = i915_capture_gpu_state(dev_priv); error = i915_capture_gpu_state(i915);
if (!error) { if (!error) {
DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
return; 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); DRM_INFO("%s\n", error->error_msg);
if (!error->simulated) { if (!error->simulated) {
spin_lock_irqsave(&dev_priv->gpu_error.lock, flags); spin_lock_irqsave(&i915->gpu_error.lock, flags);
if (!dev_priv->gpu_error.first_error) { if (!i915->gpu_error.first_error) {
dev_priv->gpu_error.first_error = error; i915->gpu_error.first_error = error;
error = NULL; error = NULL;
} }
spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags); spin_unlock_irqrestore(&i915->gpu_error.lock, flags);
} }
if (error) { 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("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("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", 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; warned = true;
} }
} }

View file

@ -1,11 +1,6 @@
/** /*
* \file i915_ioc32.c
*
* 32-bit ioctl compatibility routines for the i915 DRM. * 32-bit ioctl compatibility routines for the i915 DRM.
* *
* \author Alan Hourihane <alanh@fairlite.demon.co.uk>
*
*
* Copyright (C) Paul Mackerras 2005 * Copyright (C) Paul Mackerras 2005
* Copyright (C) Alan Hourihane 2005 * Copyright (C) Alan Hourihane 2005
* All Rights Reserved. * All Rights Reserved.
@ -28,6 +23,8 @@
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE. * IN THE SOFTWARE.
*
* Author: Alan Hourihane <alanh@fairlite.demon.co.uk>
*/ */
#include <linux/compat.h> #include <linux/compat.h>
@ -55,10 +52,10 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd,
return -EFAULT; return -EFAULT;
request = compat_alloc_user_space(sizeof(*request)); request = compat_alloc_user_space(sizeof(*request));
if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) ||
|| __put_user(req32.param, &request->param) __put_user(req32.param, &request->param) ||
|| __put_user((void __user *)(unsigned long)req32.value, __put_user((void __user *)(unsigned long)req32.value,
&request->value)) &request->value))
return -EFAULT; return -EFAULT;
return drm_ioctl(file, DRM_IOCTL_I915_GETPARAM, 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 * Called whenever a 32-bit process running under a 64-bit kernel
* performs an ioctl on /dev/dri/card<n>. * 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) long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{ {

View file

@ -1413,64 +1413,73 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift)
tasklet_hi_schedule(&execlists->tasklet); 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]) 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)) { if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
gt_iir[0] = I915_READ_FW(GEN8_GT_IIR(0)); gt_iir[0] = raw_reg_read(regs, GEN8_GT_IIR(0));
if (gt_iir[0]) if (likely(gt_iir[0]))
I915_WRITE_FW(GEN8_GT_IIR(0), 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)) { if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) {
gt_iir[1] = I915_READ_FW(GEN8_GT_IIR(1)); gt_iir[1] = raw_reg_read(regs, GEN8_GT_IIR(1));
if (gt_iir[1]) if (likely(gt_iir[1]))
I915_WRITE_FW(GEN8_GT_IIR(1), 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)) { if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) {
gt_iir[2] = I915_READ_FW(GEN8_GT_IIR(2)); gt_iir[2] = raw_reg_read(regs, GEN8_GT_IIR(2));
if (gt_iir[2] & (dev_priv->pm_rps_events | if (likely(gt_iir[2] & (i915->pm_rps_events |
dev_priv->pm_guc_events)) { i915->pm_guc_events)))
I915_WRITE_FW(GEN8_GT_IIR(2), raw_reg_write(regs, GEN8_GT_IIR(2),
gt_iir[2] & (dev_priv->pm_rps_events | gt_iir[2] & (i915->pm_rps_events |
dev_priv->pm_guc_events)); i915->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, static void gen8_gt_irq_handler(struct drm_i915_private *i915,
u32 gt_iir[4]) u32 master_ctl, u32 gt_iir[4])
{ {
if (gt_iir[0]) { if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
gen8_cs_irq_handler(dev_priv->engine[RCS], gen8_cs_irq_handler(i915->engine[RCS],
gt_iir[0], GEN8_RCS_IRQ_SHIFT); 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); gt_iir[0], GEN8_BCS_IRQ_SHIFT);
} }
if (gt_iir[1]) { if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) {
gen8_cs_irq_handler(dev_priv->engine[VCS], gen8_cs_irq_handler(i915->engine[VCS],
gt_iir[1], GEN8_VCS1_IRQ_SHIFT); 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); gt_iir[1], GEN8_VCS2_IRQ_SHIFT);
} }
if (gt_iir[3]) if (master_ctl & GEN8_GT_VECS_IRQ) {
gen8_cs_irq_handler(dev_priv->engine[VECS], gen8_cs_irq_handler(i915->engine[VECS],
gt_iir[3], GEN8_VECS_IRQ_SHIFT); gt_iir[3], GEN8_VECS_IRQ_SHIFT);
}
if (gt_iir[2] & dev_priv->pm_rps_events) if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) {
gen6_rps_irq_handler(dev_priv, gt_iir[2]); gen6_rps_irq_handler(i915, gt_iir[2]);
gen9_guc_irq_handler(i915, gt_iir[2]);
if (gt_iir[2] & dev_priv->pm_guc_events) }
gen9_guc_irq_handler(dev_priv, gt_iir[2]);
} }
static bool bxt_port_hotplug_long_detect(enum port port, u32 val) 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 { do {
u32 master_ctl, iir; u32 master_ctl, iir;
u32 gt_iir[4] = {};
u32 pipe_stats[I915_MAX_PIPES] = {}; u32 pipe_stats[I915_MAX_PIPES] = {};
u32 hotplug_status = 0; u32 hotplug_status = 0;
u32 gt_iir[4];
u32 ier = 0; u32 ier = 0;
master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; 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); I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
POSTING_READ(GEN8_MASTER_IRQ); 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) if (hotplug_status)
i9xx_hpd_irq_handler(dev_priv, 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) static irqreturn_t gen8_irq_handler(int irq, void *arg)
{ {
struct drm_device *dev = arg; struct drm_i915_private *dev_priv = to_i915(arg);
struct drm_i915_private *dev_priv = to_i915(dev);
u32 master_ctl; u32 master_ctl;
u32 gt_iir[4] = {}; u32 gt_iir[4];
if (!intel_irqs_enabled(dev_priv)) if (!intel_irqs_enabled(dev_priv))
return IRQ_NONE; return IRQ_NONE;
@ -2690,18 +2698,19 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
I915_WRITE_FW(GEN8_MASTER_IRQ, 0); 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 */ /* Find, clear, then process each source of interrupt */
gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir); 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); 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; 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); ilk_enable_display_irq(dev_priv, bit);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 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; 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); bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 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; return 0;
} }

View file

@ -84,9 +84,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
void void
i915_perf_load_test_config_cflgt3(struct drm_i915_private *dev_priv) 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", "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.id = 1;
dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;

View file

@ -96,9 +96,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf)
void void
i915_perf_load_test_config_cnl(struct drm_i915_private *dev_priv) 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", "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.id = 1;
dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa;

View file

@ -29,6 +29,9 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_selftest.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 \ #define GEN_DEFAULT_PIPEOFFSETS \
.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \ .pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \ PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \
@ -63,7 +66,8 @@
.page_sizes = I915_GTT_PAGE_SIZE_4K .page_sizes = I915_GTT_PAGE_SIZE_4K
#define GEN2_FEATURES \ #define GEN2_FEATURES \
.gen = 2, .num_pipes = 1, \ GEN(2), \
.num_pipes = 1, \
.has_overlay = 1, .overlay_needs_physical = 1, \ .has_overlay = 1, .overlay_needs_physical = 1, \
.has_gmch_display = 1, \ .has_gmch_display = 1, \
.hws_needs_physical = 1, \ .hws_needs_physical = 1, \
@ -76,19 +80,20 @@
static const struct intel_device_info intel_i830_info = { static const struct intel_device_info intel_i830_info = {
GEN2_FEATURES, GEN2_FEATURES,
.platform = INTEL_I830, PLATFORM(INTEL_I830),
.is_mobile = 1, .cursor_needs_physical = 1, .is_mobile = 1, .cursor_needs_physical = 1,
.num_pipes = 2, /* legal, last one wins */ .num_pipes = 2, /* legal, last one wins */
}; };
static const struct intel_device_info intel_i845g_info = { static const struct intel_device_info intel_i845g_info = {
GEN2_FEATURES, GEN2_FEATURES,
.platform = INTEL_I845G, PLATFORM(INTEL_I845G),
}; };
static const struct intel_device_info intel_i85x_info = { static const struct intel_device_info intel_i85x_info = {
GEN2_FEATURES, GEN2_FEATURES,
.platform = INTEL_I85X, .is_mobile = 1, PLATFORM(INTEL_I85X),
.is_mobile = 1,
.num_pipes = 2, /* legal, last one wins */ .num_pipes = 2, /* legal, last one wins */
.cursor_needs_physical = 1, .cursor_needs_physical = 1,
.has_fbc = 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 = { static const struct intel_device_info intel_i865g_info = {
GEN2_FEATURES, GEN2_FEATURES,
.platform = INTEL_I865G, PLATFORM(INTEL_I865G),
}; };
#define GEN3_FEATURES \ #define GEN3_FEATURES \
.gen = 3, .num_pipes = 2, \ GEN(3), \
.num_pipes = 2, \
.has_gmch_display = 1, \ .has_gmch_display = 1, \
.ring_mask = RENDER_RING, \ .ring_mask = RENDER_RING, \
.has_snoop = true, \ .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 = { static const struct intel_device_info intel_i915g_info = {
GEN3_FEATURES, GEN3_FEATURES,
.platform = INTEL_I915G, .cursor_needs_physical = 1, PLATFORM(INTEL_I915G),
.cursor_needs_physical = 1,
.has_overlay = 1, .overlay_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1,
.hws_needs_physical = 1, .hws_needs_physical = 1,
.unfenced_needs_alignment = 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 = { static const struct intel_device_info intel_i915gm_info = {
GEN3_FEATURES, GEN3_FEATURES,
.platform = INTEL_I915GM, PLATFORM(INTEL_I915GM),
.is_mobile = 1, .is_mobile = 1,
.cursor_needs_physical = 1, .cursor_needs_physical = 1,
.has_overlay = 1, .overlay_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 = { static const struct intel_device_info intel_i945g_info = {
GEN3_FEATURES, GEN3_FEATURES,
.platform = INTEL_I945G, PLATFORM(INTEL_I945G),
.has_hotplug = 1, .cursor_needs_physical = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
.has_overlay = 1, .overlay_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1,
.hws_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 = { static const struct intel_device_info intel_i945gm_info = {
GEN3_FEATURES, GEN3_FEATURES,
.platform = INTEL_I945GM, .is_mobile = 1, PLATFORM(INTEL_I945GM),
.is_mobile = 1,
.has_hotplug = 1, .cursor_needs_physical = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
.has_overlay = 1, .overlay_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1,
.supports_tv = 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 = { static const struct intel_device_info intel_g33_info = {
GEN3_FEATURES, GEN3_FEATURES,
.platform = INTEL_G33, PLATFORM(INTEL_G33),
.has_hotplug = 1, .has_hotplug = 1,
.has_overlay = 1, .has_overlay = 1,
}; };
static const struct intel_device_info intel_pineview_info = { static const struct intel_device_info intel_pineview_info = {
GEN3_FEATURES, GEN3_FEATURES,
.platform = INTEL_PINEVIEW, .is_mobile = 1, PLATFORM(INTEL_PINEVIEW),
.is_mobile = 1,
.has_hotplug = 1, .has_hotplug = 1,
.has_overlay = 1, .has_overlay = 1,
}; };
#define GEN4_FEATURES \ #define GEN4_FEATURES \
.gen = 4, .num_pipes = 2, \ GEN(4), \
.num_pipes = 2, \
.has_hotplug = 1, \ .has_hotplug = 1, \
.has_gmch_display = 1, \ .has_gmch_display = 1, \
.ring_mask = RENDER_RING, \ .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 = { static const struct intel_device_info intel_i965g_info = {
GEN4_FEATURES, GEN4_FEATURES,
.platform = INTEL_I965G, PLATFORM(INTEL_I965G),
.has_overlay = 1, .has_overlay = 1,
.hws_needs_physical = 1, .hws_needs_physical = 1,
.has_snoop = false, .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 = { static const struct intel_device_info intel_i965gm_info = {
GEN4_FEATURES, GEN4_FEATURES,
.platform = INTEL_I965GM, PLATFORM(INTEL_I965GM),
.is_mobile = 1, .has_fbc = 1, .is_mobile = 1, .has_fbc = 1,
.has_overlay = 1, .has_overlay = 1,
.supports_tv = 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 = { static const struct intel_device_info intel_g45_info = {
GEN4_FEATURES, GEN4_FEATURES,
.platform = INTEL_G45, PLATFORM(INTEL_G45),
.ring_mask = RENDER_RING | BSD_RING, .ring_mask = RENDER_RING | BSD_RING,
}; };
static const struct intel_device_info intel_gm45_info = { static const struct intel_device_info intel_gm45_info = {
GEN4_FEATURES, GEN4_FEATURES,
.platform = INTEL_GM45, PLATFORM(INTEL_GM45),
.is_mobile = 1, .has_fbc = 1, .is_mobile = 1, .has_fbc = 1,
.supports_tv = 1, .supports_tv = 1,
.ring_mask = RENDER_RING | BSD_RING, .ring_mask = RENDER_RING | BSD_RING,
}; };
#define GEN5_FEATURES \ #define GEN5_FEATURES \
.gen = 5, .num_pipes = 2, \ GEN(5), \
.num_pipes = 2, \
.has_hotplug = 1, \ .has_hotplug = 1, \
.ring_mask = RENDER_RING | BSD_RING, \ .ring_mask = RENDER_RING | BSD_RING, \
.has_snoop = true, \ .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 = { static const struct intel_device_info intel_ironlake_d_info = {
GEN5_FEATURES, GEN5_FEATURES,
.platform = INTEL_IRONLAKE, PLATFORM(INTEL_IRONLAKE),
}; };
static const struct intel_device_info intel_ironlake_m_info = { static const struct intel_device_info intel_ironlake_m_info = {
GEN5_FEATURES, GEN5_FEATURES,
.platform = INTEL_IRONLAKE, PLATFORM(INTEL_IRONLAKE),
.is_mobile = 1, .has_fbc = 1, .is_mobile = 1, .has_fbc = 1,
}; };
#define GEN6_FEATURES \ #define GEN6_FEATURES \
.gen = 6, .num_pipes = 2, \ GEN(6), \
.num_pipes = 2, \
.has_hotplug = 1, \ .has_hotplug = 1, \
.has_fbc = 1, \ .has_fbc = 1, \
.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .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 \ #define SNB_D_PLATFORM \
GEN6_FEATURES, \ GEN6_FEATURES, \
.platform = INTEL_SANDYBRIDGE PLATFORM(INTEL_SANDYBRIDGE)
static const struct intel_device_info intel_sandybridge_d_gt1_info = { static const struct intel_device_info intel_sandybridge_d_gt1_info = {
SNB_D_PLATFORM, SNB_D_PLATFORM,
@ -255,7 +267,7 @@ static const struct intel_device_info intel_sandybridge_d_gt2_info = {
#define SNB_M_PLATFORM \ #define SNB_M_PLATFORM \
GEN6_FEATURES, \ GEN6_FEATURES, \
.platform = INTEL_SANDYBRIDGE, \ PLATFORM(INTEL_SANDYBRIDGE), \
.is_mobile = 1 .is_mobile = 1
@ -270,7 +282,8 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info = {
}; };
#define GEN7_FEATURES \ #define GEN7_FEATURES \
.gen = 7, .num_pipes = 3, \ GEN(7), \
.num_pipes = 3, \
.has_hotplug = 1, \ .has_hotplug = 1, \
.has_fbc = 1, \ .has_fbc = 1, \
.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .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 \ #define IVB_D_PLATFORM \
GEN7_FEATURES, \ GEN7_FEATURES, \
.platform = INTEL_IVYBRIDGE, \ PLATFORM(INTEL_IVYBRIDGE), \
.has_l3_dpf = 1 .has_l3_dpf = 1
static const struct intel_device_info intel_ivybridge_d_gt1_info = { 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 \ #define IVB_M_PLATFORM \
GEN7_FEATURES, \ GEN7_FEATURES, \
.platform = INTEL_IVYBRIDGE, \ PLATFORM(INTEL_IVYBRIDGE), \
.is_mobile = 1, \ .is_mobile = 1, \
.has_l3_dpf = 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 = { static const struct intel_device_info intel_ivybridge_q_info = {
GEN7_FEATURES, GEN7_FEATURES,
.platform = INTEL_IVYBRIDGE, PLATFORM(INTEL_IVYBRIDGE),
.gt = 2, .gt = 2,
.num_pipes = 0, /* legal, last one wins */ .num_pipes = 0, /* legal, last one wins */
.has_l3_dpf = 1, .has_l3_dpf = 1,
}; };
static const struct intel_device_info intel_valleyview_info = { static const struct intel_device_info intel_valleyview_info = {
.platform = INTEL_VALLEYVIEW, PLATFORM(INTEL_VALLEYVIEW),
.gen = 7, GEN(7),
.is_lp = 1, .is_lp = 1,
.num_pipes = 2, .num_pipes = 2,
.has_psr = 1, .has_psr = 1,
@ -355,7 +368,7 @@ static const struct intel_device_info intel_valleyview_info = {
#define HSW_PLATFORM \ #define HSW_PLATFORM \
G75_FEATURES, \ G75_FEATURES, \
.platform = INTEL_HASWELL, \ PLATFORM(INTEL_HASWELL), \
.has_l3_dpf = 1 .has_l3_dpf = 1
static const struct intel_device_info intel_haswell_gt1_info = { 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 \ #define GEN8_FEATURES \
G75_FEATURES, \ G75_FEATURES, \
GEN(8), \
BDW_COLORS, \ BDW_COLORS, \
.page_sizes = I915_GTT_PAGE_SIZE_4K | \ .page_sizes = I915_GTT_PAGE_SIZE_4K | \
I915_GTT_PAGE_SIZE_2M, \ I915_GTT_PAGE_SIZE_2M, \
@ -385,8 +399,7 @@ static const struct intel_device_info intel_haswell_gt3_info = {
#define BDW_PLATFORM \ #define BDW_PLATFORM \
GEN8_FEATURES, \ GEN8_FEATURES, \
.gen = 8, \ PLATFORM(INTEL_BROADWELL)
.platform = INTEL_BROADWELL
static const struct intel_device_info intel_broadwell_gt1_info = { static const struct intel_device_info intel_broadwell_gt1_info = {
BDW_PLATFORM, 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 = { 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, .has_hotplug = 1,
.is_lp = 1, .is_lp = 1,
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
.platform = INTEL_CHERRYVIEW,
.has_64bit_reloc = 1, .has_64bit_reloc = 1,
.has_psr = 1, .has_psr = 1,
.has_runtime_pm = 1, .has_runtime_pm = 1,
@ -443,6 +457,7 @@ static const struct intel_device_info intel_cherryview_info = {
#define GEN9_FEATURES \ #define GEN9_FEATURES \
GEN8_FEATURES, \ GEN8_FEATURES, \
GEN(9), \
GEN9_DEFAULT_PAGE_SIZES, \ GEN9_DEFAULT_PAGE_SIZES, \
.has_logical_ring_preemption = 1, \ .has_logical_ring_preemption = 1, \
.has_csr = 1, \ .has_csr = 1, \
@ -452,8 +467,7 @@ static const struct intel_device_info intel_cherryview_info = {
#define SKL_PLATFORM \ #define SKL_PLATFORM \
GEN9_FEATURES, \ GEN9_FEATURES, \
.gen = 9, \ PLATFORM(INTEL_SKYLAKE)
.platform = INTEL_SKYLAKE
static const struct intel_device_info intel_skylake_gt1_info = { static const struct intel_device_info intel_skylake_gt1_info = {
SKL_PLATFORM, SKL_PLATFORM,
@ -481,7 +495,7 @@ static const struct intel_device_info intel_skylake_gt4_info = {
}; };
#define GEN9_LP_FEATURES \ #define GEN9_LP_FEATURES \
.gen = 9, \ GEN(9), \
.is_lp = 1, \ .is_lp = 1, \
.has_hotplug = 1, \ .has_hotplug = 1, \
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \ .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 = { static const struct intel_device_info intel_broxton_info = {
GEN9_LP_FEATURES, GEN9_LP_FEATURES,
.platform = INTEL_BROXTON, PLATFORM(INTEL_BROXTON),
.ddb_size = 512, .ddb_size = 512,
}; };
static const struct intel_device_info intel_geminilake_info = { static const struct intel_device_info intel_geminilake_info = {
GEN9_LP_FEATURES, GEN9_LP_FEATURES,
.platform = INTEL_GEMINILAKE, PLATFORM(INTEL_GEMINILAKE),
.ddb_size = 1024, .ddb_size = 1024,
GLK_COLORS, GLK_COLORS,
}; };
#define KBL_PLATFORM \ #define KBL_PLATFORM \
GEN9_FEATURES, \ GEN9_FEATURES, \
.gen = 9, \ PLATFORM(INTEL_KABYLAKE)
.platform = INTEL_KABYLAKE
static const struct intel_device_info intel_kabylake_gt1_info = { static const struct intel_device_info intel_kabylake_gt1_info = {
KBL_PLATFORM, KBL_PLATFORM,
@ -547,8 +560,7 @@ static const struct intel_device_info intel_kabylake_gt3_info = {
#define CFL_PLATFORM \ #define CFL_PLATFORM \
GEN9_FEATURES, \ GEN9_FEATURES, \
.gen = 9, \ PLATFORM(INTEL_COFFEELAKE)
.platform = INTEL_COFFEELAKE
static const struct intel_device_info intel_coffeelake_gt1_info = { static const struct intel_device_info intel_coffeelake_gt1_info = {
CFL_PLATFORM, CFL_PLATFORM,
@ -568,30 +580,32 @@ static const struct intel_device_info intel_coffeelake_gt3_info = {
#define GEN10_FEATURES \ #define GEN10_FEATURES \
GEN9_FEATURES, \ GEN9_FEATURES, \
GEN(10), \
.ddb_size = 1024, \ .ddb_size = 1024, \
GLK_COLORS GLK_COLORS
static const struct intel_device_info intel_cannonlake_info = { static const struct intel_device_info intel_cannonlake_info = {
GEN10_FEATURES, GEN10_FEATURES,
.is_alpha_support = 1, PLATFORM(INTEL_CANNONLAKE),
.platform = INTEL_CANNONLAKE,
.gen = 10,
.gt = 2, .gt = 2,
}; };
#define GEN11_FEATURES \ #define GEN11_FEATURES \
GEN10_FEATURES, \ GEN10_FEATURES, \
.gen = 11, \ GEN(11), \
.ddb_size = 2048, \ .ddb_size = 2048, \
.has_csr = 0 .has_csr = 0
static const struct intel_device_info intel_icelake_11_info = { static const struct intel_device_info intel_icelake_11_info = {
GEN11_FEATURES, GEN11_FEATURES,
.platform = INTEL_ICELAKE, PLATFORM(INTEL_ICELAKE),
.is_alpha_support = 1, .is_alpha_support = 1,
.has_resource_streamer = 0, .has_resource_streamer = 0,
}; };
#undef GEN
#undef PLATFORM
/* /*
* Make sure any device matches here are from most specific to most * Make sure any device matches here are from most specific to most
* general. For example, since the Quanta match is based on the subsystem * general. For example, since the Quanta match is based on the subsystem

View file

@ -415,7 +415,94 @@ static int i915_pmu_event_init(struct perf_event *event)
return 0; 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 = struct drm_i915_private *i915 =
container_of(event->pmu, typeof(*i915), pmu.base); 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); val = count_interrupts(i915);
break; break;
case I915_PMU_RC6_RESIDENCY: case I915_PMU_RC6_RESIDENCY:
intel_runtime_pm_get(i915); val = get_rc6(i915, locked);
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);
break; break;
} }
} }
@ -479,7 +555,7 @@ static void i915_pmu_event_read(struct perf_event *event)
again: again:
prev = local64_read(&hwc->prev_count); 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) if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev)
goto again; 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 * for all listeners. Even when the event was already enabled and has
* an existing non-zero value. * 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); spin_unlock_irqrestore(&i915->pmu.lock, flags);
} }

View file

@ -27,6 +27,8 @@
enum { enum {
__I915_SAMPLE_FREQ_ACT = 0, __I915_SAMPLE_FREQ_ACT = 0,
__I915_SAMPLE_FREQ_REQ, __I915_SAMPLE_FREQ_REQ,
__I915_SAMPLE_RC6,
__I915_SAMPLE_RC6_ESTIMATED,
__I915_NUM_PMU_SAMPLERS __I915_NUM_PMU_SAMPLERS
}; };
@ -94,6 +96,10 @@ struct i915_pmu {
* struct intel_engine_cs. * struct intel_engine_cs.
*/ */
struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS]; 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. * @i915_attr: Memory block holding device attributes.
*/ */

View file

@ -1906,6 +1906,11 @@ enum i915_power_well_id {
#define CL_POWER_DOWN_ENABLE (1 << 4) #define CL_POWER_DOWN_ENABLE (1 << 4)
#define SUS_CLOCK_CONFIG (3 << 0) #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_A 0x162024
#define _PORT_CL1CM_DW9_BC 0x6C024 #define _PORT_CL1CM_DW9_BC 0x6C024
#define IREF0RC_OFFSET_SHIFT 8 #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_AE 0x162454
#define _CNL_PORT_TX_DW5_LN0_B 0x162654 #define _CNL_PORT_TX_DW5_LN0_B 0x162654
#define _CNL_PORT_TX_DW5_LN0_C 0x162C54 #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_LN0_F 0x162854
#define CNL_PORT_TX_DW5_GRP(port) _MMIO_PORT6(port, \ #define CNL_PORT_TX_DW5_GRP(port) _MMIO_PORT6(port, \
_CNL_PORT_TX_DW5_GRP_AE, \ _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_AE 0x16245C
#define _CNL_PORT_TX_DW7_LN0_B 0x16265C #define _CNL_PORT_TX_DW7_LN0_B 0x16265C
#define _CNL_PORT_TX_DW7_LN0_C 0x162C5C #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_LN0_F 0x16285C
#define CNL_PORT_TX_DW7_GRP(port) _MMIO_PORT6(port, \ #define CNL_PORT_TX_DW7_GRP(port) _MMIO_PORT6(port, \
_CNL_PORT_TX_DW7_GRP_AE, \ _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_DW9 _MMIO(0x162124)
#define CNL_PORT_COMP_DW10 _MMIO(0x162128) #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 */ /* BXT PHY Ref registers */
#define _PORT_REF_DW3_A 0x16218C #define _PORT_REF_DW3_A 0x16218C
#define _PORT_REF_DW3_BC 0x6C18C #define _PORT_REF_DW3_BC 0x6C18C
@ -7138,6 +7165,8 @@ enum {
#define DISP_DATA_PARTITION_5_6 (1<<6) #define DISP_DATA_PARTITION_5_6 (1<<6)
#define DISP_IPC_ENABLE (1<<3) #define DISP_IPC_ENABLE (1<<3)
#define DBUF_CTL _MMIO(0x45008) #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_REQUEST (1<<31)
#define DBUF_POWER_STATE (1<<30) #define DBUF_POWER_STATE (1<<30)
#define GEN7_MSG_CTL _MMIO(0x45010) #define GEN7_MSG_CTL _MMIO(0x45010)
@ -7147,8 +7176,9 @@ enum {
#define RESET_PCH_HANDSHAKE_ENABLE (1<<4) #define RESET_PCH_HANDSHAKE_ENABLE (1<<4)
#define GEN8_CHICKEN_DCPR_1 _MMIO(0x46430) #define GEN8_CHICKEN_DCPR_1 _MMIO(0x46430)
#define SKL_SELECT_ALTERNATE_DC_EXIT (1<<30) #define SKL_SELECT_ALTERNATE_DC_EXIT (1 << 30)
#define MASK_WAKEMEM (1<<13) #define MASK_WAKEMEM (1 << 13)
#define CNL_DDI_CLOCK_REG_ACCESS_ON (1 << 7)
#define SKL_DFSM _MMIO(0x51000) #define SKL_DFSM _MMIO(0x51000)
#define SKL_DFSM_CDCLK_LIMIT_MASK (3 << 23) #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_B_DISABLE (1 << 21)
#define SKL_DFSM_PIPE_C_DISABLE (1 << 28) #define SKL_DFSM_PIPE_C_DISABLE (1 << 28)
#define SKL_DSSM _MMIO(0x51004) #define SKL_DSSM _MMIO(0x51004)
#define CNL_DSSM_CDCLK_PLL_REFCLK_24MHz (1 << 31) #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 GEN7_FF_SLICE_CS_CHICKEN1 _MMIO(0x20e0)
#define GEN9_FFSC_PERCTX_PREEMPT_CTRL (1<<14) #define GEN9_FFSC_PERCTX_PREEMPT_CTRL (1<<14)
@ -8794,20 +8828,21 @@ enum skl_power_gate {
/* CDCLK_CTL */ /* CDCLK_CTL */
#define CDCLK_CTL _MMIO(0x46000) #define CDCLK_CTL _MMIO(0x46000)
#define CDCLK_FREQ_SEL_MASK (3<<26) #define CDCLK_FREQ_SEL_MASK (3 << 26)
#define CDCLK_FREQ_450_432 (0<<26) #define CDCLK_FREQ_450_432 (0 << 26)
#define CDCLK_FREQ_540 (1<<26) #define CDCLK_FREQ_540 (1 << 26)
#define CDCLK_FREQ_337_308 (2<<26) #define CDCLK_FREQ_337_308 (2 << 26)
#define CDCLK_FREQ_675_617 (3<<26) #define CDCLK_FREQ_675_617 (3 << 26)
#define BXT_CDCLK_CD2X_DIV_SEL_MASK (3<<22) #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 (0 << 22)
#define BXT_CDCLK_CD2X_DIV_SEL_1_5 (1<<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_2 (2 << 22)
#define BXT_CDCLK_CD2X_DIV_SEL_4 (3<<22) #define BXT_CDCLK_CD2X_DIV_SEL_4 (3 << 22)
#define BXT_CDCLK_CD2X_PIPE(pipe) ((pipe)<<20) #define BXT_CDCLK_CD2X_PIPE(pipe) ((pipe) << 20)
#define CDCLK_DIVMUX_CD_OVERRIDE (1<<19) #define CDCLK_DIVMUX_CD_OVERRIDE (1 << 19)
#define BXT_CDCLK_CD2X_PIPE_NONE BXT_CDCLK_CD2X_PIPE(3) #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) #define CDCLK_FREQ_DECIMAL_MASK (0x7ff)
/* LCPLL_CTL */ /* LCPLL_CTL */
@ -9716,4 +9751,10 @@ enum skl_power_gate {
#define MMCD_PCLA (1 << 31) #define MMCD_PCLA (1 << 31)
#define MMCD_HOTSPOT_EN (1 << 27) #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_ */ #endif /* _I915_REG_H_ */

View file

@ -86,7 +86,7 @@ struct i915_syncmap {
/** /**
* i915_syncmap_init -- initialise the #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) 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 * i915_syncmap_is_later -- compare against the last know sync point
* @root - pointer to the #i915_syncmap * @root: pointer to the #i915_syncmap
* @id - the context id (other timeline) we are synchronising to * @id: the context id (other timeline) we are synchronising to
* @seqno - the sequence number along the other timeline * @seqno: the sequence number along the other timeline
* *
* If we have already synchronised this @root timeline with another (@id) then * If we have already synchronised this @root timeline with another (@id) then
* we can omit any repeated or earlier synchronisation requests. If the two * 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 * i915_syncmap_set -- mark the most recent syncpoint between contexts
* @root - pointer to the #i915_syncmap * @root: pointer to the #i915_syncmap
* @id - the context id (other timeline) we have synchronised to * @id: the context id (other timeline) we have synchronised to
* @seqno - the sequence number along the other timeline * @seqno: the sequence number along the other timeline
* *
* When we synchronise this @root timeline with another (@id), we also know * When we synchronise this @root timeline with another (@id), we also know
* that we have synchronized with all previous seqno along that timeline. If * 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 * 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 * 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 * point tracking, or when the fences are all known to be signaled and the

View file

@ -188,13 +188,14 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
/** /**
* intel_crtc_destroy_state - destroy crtc state * intel_crtc_destroy_state - destroy crtc state
* @crtc: drm crtc * @crtc: drm crtc
* @state: the state to destroy
* *
* Destroys the crtc state (both common and Intel-specific) for the * Destroys the crtc state (both common and Intel-specific) for the
* specified crtc. * specified crtc.
*/ */
void void
intel_crtc_destroy_state(struct drm_crtc *crtc, 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); 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 * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
* @dev_priv: i915 device * @dev_priv: i915 device
* @crtc: intel crtc * @intel_crtc: intel crtc
* @crtc_state: incoming crtc_state to validate and setup scalers * @crtc_state: incoming crtc_state to validate and setup scalers
* *
* This function sets up scalers based on staged scaling requests for * This function sets up scalers based on staged scaling requests for

View file

@ -85,6 +85,7 @@ intel_plane_duplicate_state(struct drm_plane *plane)
__drm_atomic_helper_plane_duplicate_state(plane, state); __drm_atomic_helper_plane_duplicate_state(plane, state);
intel_state->vma = NULL; intel_state->vma = NULL;
intel_state->flags = 0;
return state; return state;
} }

View file

@ -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)) { } 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_enable = ilk_audio_codec_enable;
dev_priv->display.audio_codec_disable = ilk_audio_codec_disable; 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_enable = hsw_audio_codec_enable;
dev_priv->display.audio_codec_disable = hsw_audio_codec_disable; dev_priv->display.audio_codec_disable = hsw_audio_codec_disable;
} else if (HAS_PCH_SPLIT(dev_priv)) { } 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; struct intel_encoder *encoder;
if (WARN_ON(pipe >= ARRAY_SIZE(dev_priv->av_enc_map)))
return NULL;
/* MST */ /* MST */
if (pipe >= 0) { if (pipe >= 0) {
if (WARN_ON(pipe >= ARRAY_SIZE(dev_priv->av_enc_map)))
return NULL;
encoder = dev_priv->av_enc_map[pipe]; encoder = dev_priv->av_enc_map[pipe];
/* /*
* when bootup, audio driver may not know it is * when bootup, audio driver may not know it is

View file

@ -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, static int intel_bios_ssc_frequency(struct drm_i915_private *dev_priv,
bool alternate) bool alternate)
{ {
switch (INTEL_INFO(dev_priv)->gen) { switch (INTEL_GEN(dev_priv)) {
case 2: case 2:
return alternate ? 66667 : 48000; return alternate ? 66667 : 48000;
case 3: case 3:
@ -947,6 +947,86 @@ static int goto_next_sequence_v3(const u8 *data, int index, int total)
return 0; 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 static void
parse_mipi_sequence(struct drm_i915_private *dev_priv, parse_mipi_sequence(struct drm_i915_private *dev_priv,
const struct bdb_header *bdb) 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.size = seq_size;
dev_priv->vbt.dsi.seq_version = sequence->version; dev_priv->vbt.dsi.seq_version = sequence->version;
fixup_mipi_sequences(dev_priv);
DRM_DEBUG_DRIVER("MIPI related VBT parsing complete\n"); DRM_DEBUG_DRIVER("MIPI related VBT parsing complete\n");
return; return;
@ -1610,6 +1692,29 @@ out:
pci_unmap_rom(pdev, bios); pci_unmap_rom(pdev, bios);
} }
/**
* 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 * intel_bios_is_tv_present - is integrated TV present in VBT
* @dev_priv: i915 device instance * @dev_priv: i915 device instance

View file

@ -588,29 +588,16 @@ void intel_engine_remove_wait(struct intel_engine_cs *engine,
spin_unlock_irq(&b->rb_lock); 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) static bool signal_complete(const struct drm_i915_gem_request *request)
{ {
if (!request) if (!request)
return false; return false;
/* If another process served as the bottom-half it may have already /*
* signalled that this wait is already completed. * Carefully check if the request is complete, giving time for the
*/
if (intel_wait_complete(&request->signaling.wait))
return signal_valid(request);
/* Carefully check if the request is complete, giving time for the
* seqno to be visible or if the GPU hung. * seqno to be visible or if the GPU hung.
*/ */
if (__i915_request_irq_complete(request)) return __i915_request_irq_complete(request);
return true;
return false;
} }
static struct drm_i915_gem_request *to_signaler(struct rb_node *rb) 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)) { &request->fence.flags)) {
local_bh_disable(); local_bh_disable();
dma_fence_signal(&request->fence); dma_fence_signal(&request->fence);
GEM_BUG_ON(!i915_gem_request_completed(request));
local_bh_enable(); /* kick start the tasklets */ local_bh_enable(); /* kick start the tasklets */
} }

View file

@ -1778,6 +1778,199 @@ sanitize:
dev_priv->cdclk.hw.vco = -1; 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 * cnl_init_cdclk - Initialize CDCLK on CNL
* @dev_priv: i915 device * @dev_priv: i915 device
@ -2216,6 +2409,36 @@ static int cnl_modeset_calc_cdclk(struct drm_atomic_state *state)
return 0; 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) static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
{ {
int max_cdclk_freq = dev_priv->max_cdclk_freq; 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; return max_cdclk_freq;
else if (IS_CHERRYVIEW(dev_priv)) else if (IS_CHERRYVIEW(dev_priv))
return max_cdclk_freq*95/100; 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; return 2*max_cdclk_freq*90/100;
else else
return max_cdclk_freq*90/100; 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) 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; dev_priv->max_cdclk_freq = 528000;
} else if (IS_GEN9_BC(dev_priv)) { } else if (IS_GEN9_BC(dev_priv)) {
u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK; 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.set_cdclk = cnl_set_cdclk;
dev_priv->display.modeset_calc_cdclk = dev_priv->display.modeset_calc_cdclk =
cnl_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; dev_priv->display.get_cdclk = cnl_get_cdclk;
else if (IS_GEN9_BC(dev_priv)) else if (IS_GEN9_BC(dev_priv))
dev_priv->display.get_cdclk = skl_get_cdclk; dev_priv->display.get_cdclk = skl_get_cdclk;

View file

@ -474,14 +474,6 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
return ret; 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) static bool intel_crt_detect_hotplug(struct drm_connector *connector)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
@ -807,10 +799,11 @@ intel_crt_detect(struct drm_connector *connector,
else else
status = connector_status_unknown; status = connector_status_unknown;
intel_release_load_detect_pipe(connector, &tmp, ctx); intel_release_load_detect_pipe(connector, &tmp, ctx);
} else if (ret == 0) } else if (ret == 0) {
status = connector_status_unknown; status = connector_status_unknown;
else if (ret < 0) } else {
status = ret; status = ret;
}
out: out:
intel_display_power_put(dev_priv, intel_encoder->power_domain); intel_display_power_put(dev_priv, intel_encoder->power_domain);

View file

@ -2152,7 +2152,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
I915_WRITE(DPLL_CTRL2, val); 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)); I915_WRITE(PORT_CLK_SEL(port), hsw_pll_to_ddi_pll_sel(pll));
} }

View file

@ -586,3 +586,9 @@ void intel_device_info_runtime_init(struct intel_device_info *info)
/* Initialize command stream timestamp frequency */ /* Initialize command stream timestamp frequency */
info->cs_timestamp_frequency_khz = read_timestamp_frequency(dev_priv); 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);
}

View file

@ -167,6 +167,10 @@ struct intel_device_info {
} color; } color;
}; };
struct intel_driver_caps {
unsigned int scheduler;
};
static inline unsigned int sseu_subslice_total(const struct sseu_dev_info *sseu) static inline unsigned int sseu_subslice_total(const struct sseu_dev_info *sseu)
{ {
return hweight8(sseu->slice_mask) * hweight8(sseu->subslice_mask); 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, void intel_device_info_dump_runtime(const struct intel_device_info *info,
struct drm_printer *p); struct drm_printer *p);
void intel_driver_caps_print(const struct intel_driver_caps *caps,
struct drm_printer *p);
#endif #endif

View file

@ -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) #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 * Returns whether the given set of divisors are valid for a given refclk with
* the given connectors. * the given connectors.
*/ */
static bool intel_PLL_is_valid(struct drm_i915_private *dev_priv, static bool intel_PLL_is_valid(struct drm_i915_private *dev_priv,
const struct intel_limit *limit, const struct intel_limit *limit,
const struct dpll *clock) 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) 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; return 256 * 1024;
else if (IS_I965G(dev_priv) || IS_I965GM(dev_priv) || else if (IS_I965G(dev_priv) || IS_I965GM(dev_priv) ||
IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
return 128 * 1024; return 128 * 1024;
else if (INTEL_INFO(dev_priv)->gen >= 4) else if (INTEL_GEN(dev_priv) >= 4)
return 4 * 1024; return 4 * 1024;
else else
return 0; return 0;
@ -2068,13 +2068,16 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
} }
struct i915_vma * 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_device *dev = fb->dev;
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct i915_ggtt_view view; struct i915_ggtt_view view;
struct i915_vma *vma; struct i915_vma *vma;
unsigned int pinctl;
u32 alignment; u32 alignment;
WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 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); 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)) if (IS_ERR(vma))
goto err; 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" * something and try to run the system in a "less than optimal"
* mode that matches the user configuration. * 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); i915_vma_get(vma);
@ -2134,11 +2151,12 @@ err:
return vma; 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); 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_gem_object_unpin_from_display_plane(vma);
i915_vma_put(vma); i915_vma_put(vma);
} }
@ -2808,7 +2826,9 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
valid_fb: valid_fb:
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
intel_state->vma = 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); mutex_unlock(&dev->struct_mutex);
if (IS_ERR(intel_state->vma)) { if (IS_ERR(intel_state->vma)) {
DRM_ERROR("failed to pin boot fb on pipe %d: %li\n", 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)) if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
if (INTEL_GEN(dev_priv) < 4) if (INTEL_GEN(dev_priv) < 5)
dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe); dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
switch (fb->format->format) { 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. * skl_update_scaler_plane - Stages update to scaler state for a given plane.
* * @crtc_state: crtc's scaler state
* @state: crtc's scaler state
* @plane_state: atomic plane state to update * @plane_state: atomic plane state to update
* *
* Return * 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 * intel_post_enable_primary - Perform operations after enabling primary plane
* @crtc: the CRTC whose primary plane was just enabled * @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 * 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 * 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); 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, static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
struct drm_atomic_state *old_state) 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) if (dev_priv->display.initial_watermarks != NULL)
dev_priv->display.initial_watermarks(old_intel_state, pipe_config); 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. */ /* XXX: Do the pipe assertions at the right place for BXT DSI. */
if (!transcoder_is_dsi(cpu_transcoder)) if (!transcoder_is_dsi(cpu_transcoder))
intel_enable_pipe(pipe_config); 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); const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
/* GDG double wide on either pipe, otherwise pipe A only */ /* 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)); (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 *intel_crtc = to_intel_crtc(crtc);
struct intel_crtc_state *config = intel_crtc->config; 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; u32 val = 0;
switch (intel_crtc->config->pipe_bpp) { 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)) if (HAS_DDI(dev_priv))
cntl |= CURSOR_PIPE_CSC_ENABLE; 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) { switch (plane_state->base.crtc_w) {
case 64: case 64:
@ -10702,6 +10740,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
struct drm_connector_list_iter conn_iter; struct drm_connector_list_iter conn_iter;
unsigned int used_ports = 0; unsigned int used_ports = 0;
unsigned int used_mst_ports = 0; unsigned int used_mst_ports = 0;
bool ret = true;
/* /*
* Walk the connector list instead of the encoder * 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 */ /* the same port mustn't appear more than once */
if (used_ports & port_mask) if (used_ports & port_mask)
return false; ret = false;
used_ports |= port_mask; used_ports |= port_mask;
break; break;
@ -10754,7 +10793,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
if (used_ports & used_mst_ports) if (used_ports & used_mst_ports)
return false; return false;
return true; return ret;
} }
static void static void
@ -12075,7 +12114,7 @@ u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
struct drm_device *dev = crtc->base.dev; struct drm_device *dev = crtc->base.dev;
if (!dev->max_vblank_count) 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); 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 * intel_prepare_plane_fb - Prepare fb for usage on plane
* @plane: drm plane to prepare for * @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 * Prepares a framebuffer for usage on a display plane. Generally this
* involves pinning the underlying object and updating the frontbuffer tracking * involves pinning the underlying object and updating the frontbuffer tracking
@ -12695,7 +12734,9 @@ intel_prepare_plane_fb(struct drm_plane *plane,
} else { } else {
struct i915_vma *vma; 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)) if (!IS_ERR(vma))
to_intel_plane_state(new_state)->vma = vma; to_intel_plane_state(new_state)->vma = vma;
else else
@ -12734,7 +12775,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
/** /**
* intel_cleanup_plane_fb - Cleans up an fb after plane use * intel_cleanup_plane_fb - Cleans up an fb after plane use
* @plane: drm plane to clean up for * @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. * 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); vma = fetch_and_zero(&to_intel_plane_state(old_state)->vma);
if (vma) { if (vma) {
mutex_lock(&plane->dev->struct_mutex); 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); mutex_unlock(&plane->dev->struct_mutex);
} }
} }
@ -13111,7 +13152,9 @@ intel_legacy_cursor_update(struct drm_plane *plane,
goto out_unlock; goto out_unlock;
} }
} else { } 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)) { if (IS_ERR(vma)) {
DRM_DEBUG_KMS("failed to pin object\n"); 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); old_vma = fetch_and_zero(&to_intel_plane_state(old_plane_state)->vma);
if (old_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: out_unlock:
mutex_unlock(&dev_priv->drm.struct_mutex); 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; return to_intel_crtc(connector->base.state->crtc)->pipe;
} }
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
struct drm_file *file) struct drm_file *file)
{ {
struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data; struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
struct drm_crtc *drmmode_crtc; 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, * gen2/3 display engine uses the fence if present,
* so the tiling mode must match the fb modifier exactly. * 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])) { tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
DRM_DEBUG_KMS("tiling_mode must match fb modifier exactly on gen2/3\n"); DRM_DEBUG_KMS("tiling_mode must match fb modifier exactly on gen2/3\n");
goto err; goto err;
@ -14162,7 +14206,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
{ {
intel_init_cdclk_hooks(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_pipe_config = haswell_get_pipe_config;
dev_priv->display.get_initial_plane_config = dev_priv->display.get_initial_plane_config =
skylake_get_initial_plane_config; skylake_get_initial_plane_config;

View file

@ -258,7 +258,7 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp)
if (IS_CNL_WITH_PORT_F(dev_priv)) if (IS_CNL_WITH_PORT_F(dev_priv))
return 810000; 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) if (port == PORT_A || port == PORT_D)
return 540000; 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, static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv,
enum port port) enum port port)
{ {
if (INTEL_INFO(dev_priv)->gen >= 9) if (INTEL_GEN(dev_priv) >= 9)
return skl_aux_ctl_reg(dev_priv, port); return skl_aux_ctl_reg(dev_priv, port);
else if (HAS_PCH_SPLIT(dev_priv)) else if (HAS_PCH_SPLIT(dev_priv))
return ilk_aux_ctl_reg(dev_priv, port); 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, static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv,
enum port port, int index) 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); return skl_aux_data_reg(dev_priv, port, index);
else if (HAS_PCH_SPLIT(dev_priv)) else if (HAS_PCH_SPLIT(dev_priv))
return ilk_aux_data_reg(dev_priv, port, index); return ilk_aux_data_reg(dev_priv, port, index);

View file

@ -147,7 +147,7 @@ struct bxt_ddi_phy_info {
*/ */
struct { struct {
/** /**
* @port: which port maps to this channel. * @channel.port: which port maps to this channel.
*/ */
enum port port; enum port port;
} channel[2]; } channel[2];

View file

@ -204,6 +204,7 @@ struct intel_fbdev {
struct drm_fb_helper helper; struct drm_fb_helper helper;
struct intel_framebuffer *fb; struct intel_framebuffer *fb;
struct i915_vma *vma; struct i915_vma *vma;
unsigned long vma_flags;
async_cookie_t cookie; async_cookie_t cookie;
int preferred_bpp; int preferred_bpp;
}; };
@ -490,6 +491,8 @@ struct intel_atomic_state {
struct intel_plane_state { struct intel_plane_state {
struct drm_plane_state base; struct drm_plane_state base;
struct i915_vma *vma; struct i915_vma *vma;
unsigned long flags;
#define PLANE_HAS_FENCE BIT(0)
struct { struct {
u32 offset; 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 cnl_uninit_cdclk(struct drm_i915_private *dev_priv);
void bxt_init_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 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_init_cdclk_hooks(struct drm_i915_private *dev_priv);
void intel_update_max_cdclk(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); 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); intel_encoder_current_mode(struct intel_encoder *encoder);
enum pipe intel_get_pipe_from_connector(struct intel_connector *connector); enum pipe intel_get_pipe_from_connector(struct intel_connector *connector);
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
enum pipe pipe); enum pipe pipe);
static inline bool static inline bool
@ -1501,8 +1506,10 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
struct intel_load_detect_pipe *old, struct intel_load_detect_pipe *old,
struct drm_modeset_acquire_ctx *ctx); struct drm_modeset_acquire_ctx *ctx);
struct i915_vma * 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,
void intel_unpin_fb_vma(struct i915_vma *vma); unsigned int rotation,
unsigned long *out_flags);
void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags);
struct drm_framebuffer * struct drm_framebuffer *
intel_framebuffer_create(struct drm_i915_gem_object *obj, intel_framebuffer_create(struct drm_i915_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd); 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); int usecs);
struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv, struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv,
enum pipe pipe, int plane); enum pipe pipe, int plane);
int intel_sprite_set_colorkey(struct drm_device *dev, void *data, int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state); 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 intel_pipe_update_end(struct intel_crtc_state *new_crtc_state);
void skl_update_plane(struct intel_plane *plane, void skl_update_plane(struct intel_plane *plane,

View file

@ -245,7 +245,8 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder,
intel_dvo->attached_connector->panel.fixed_mode; intel_dvo->attached_connector->panel.fixed_mode;
struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_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, * 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 * with the panel scaling set up to source from the H/VDisplay
* of the original mode. * of the original mode.
@ -293,11 +294,6 @@ static void intel_dvo_pre_enable(struct intel_encoder *encoder,
I915_WRITE(dvo_reg, dvo_val); I915_WRITE(dvo_reg, dvo_val);
} }
/**
* Detect the output connection on our DVO device.
*
* Unimplemented.
*/
static enum drm_connector_status static enum drm_connector_status
intel_dvo_detect(struct drm_connector *connector, bool force) 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 = const struct drm_display_mode *fixed_mode =
to_intel_connector(connector)->panel.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 * 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, * (TV-out, for example), but for now with just TMDS and LVDS,
* that's not the case. * that's not the case.
@ -371,7 +368,7 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = {
.destroy = intel_dvo_enc_destroy, .destroy = intel_dvo_enc_destroy,
}; };
/** /*
* Attempts to get a fixed panel timing for LVDS (currently only the i830). * 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 * 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]; uint32_t dpll[I915_MAX_PIPES];
enum port port; 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 * special cases, but otherwise default to what's defined
* in the spec. * in the spec.
*/ */
@ -454,7 +452,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv)
else else
gpio = GMBUS_PIN_DPB; 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 * It appears that everything is on GPIOE except for panels
* on i830 laptops, which are on GPIOB (DVOA). * 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; 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. * transmitter detection run in bit banging mode for now.
*/ */
intel_gmbus_force_bit(i2c, true); 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 * respond to i2c accesses, so make sure we have
* have the clock enabled before we attempt to * have the clock enabled before we attempt to
* initialize the device. * 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); intel_connector_attach_encoder(intel_connector, intel_encoder);
if (dvo->type == INTEL_DVO_CHIP_LVDS) { 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. * to dig the fixed panel mode out of the BIOS data.
* However, it's in a different format from the BIOS * However, it's in a different format from the BIOS
* data on chipsets with integrated LVDS (stored in AIM * data on chipsets with integrated LVDS (stored in AIM

View file

@ -631,7 +631,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine)
* Similarly the preempt context must always be available so that * Similarly the preempt context must always be available so that
* we can interrupt the engine at any time. * 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, ring = engine->context_pin(engine,
engine->i915->preempt_context); engine->i915->preempt_context);
if (IS_ERR(ring)) { if (IS_ERR(ring)) {
@ -656,7 +656,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine)
err_breadcrumbs: err_breadcrumbs:
intel_engine_fini_breadcrumbs(engine); intel_engine_fini_breadcrumbs(engine);
err_unpin_preempt: err_unpin_preempt:
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->preempt_context);
err_unpin_kernel: err_unpin_kernel:
engine->context_unpin(engine, engine->i915->kernel_context); 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) if (engine->default_state)
i915_gem_object_put(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->preempt_context);
engine->context_unpin(engine, engine->i915->kernel_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; struct drm_i915_private *dev_priv = engine->i915;
u64 acthd; u64 acthd;
@ -707,7 +707,7 @@ u64 intel_engine_get_active_head(struct intel_engine_cs *engine)
return acthd; 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; struct drm_i915_private *dev_priv = engine->i915;
u64 bbaddr; u64 bbaddr;
@ -1464,7 +1464,9 @@ static bool ring_is_idle(struct intel_engine_cs *engine)
struct drm_i915_private *dev_priv = engine->i915; struct drm_i915_private *dev_priv = engine->i915;
bool idle = true; 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 */ /* First check that no commands are left in the ring */
if ((I915_READ_HEAD(engine) & HEAD_ADDR) != 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)) if (I915_SELFTEST_ONLY(engine->breadcrumbs.mock))
return true; return true;
/* Interrupt/tasklet pending? */
if (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted))
return false;
/* Waiting to drain ELSP? */ /* Waiting to drain ELSP? */
if (READ_ONCE(engine->execlists.active)) if (READ_ONCE(engine->execlists.active))
return false; 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, static void intel_engine_print_registers(const struct intel_engine_cs *engine,
struct drm_printer *m, 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_private *dev_priv = engine->i915; struct drm_i915_private *dev_priv = engine->i915;
struct drm_i915_gem_request *rq; const struct intel_engine_execlists * const execlists =
struct rb_node *rb; &engine->execlists;
char hdr[80];
u64 addr; u64 addr;
if (header) { drm_printf(m, "\tRING_START: 0x%08x\n",
va_list ap; I915_READ(RING_START(engine->mmio_base)));
drm_printf(m, "\tRING_HEAD: 0x%08x\n",
va_start(ap, header); I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR);
drm_vprintf(m, header, &ap); drm_printf(m, "\tRING_TAIL: 0x%08x\n",
va_end(ap); I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR);
}
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_CTL: 0x%08x%s\n", drm_printf(m, "\tRING_CTL: 0x%08x%s\n",
I915_READ(RING_CTL(engine->mmio_base)), I915_READ(RING_CTL(engine->mmio_base)),
I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? " [waiting]" : ""); 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)),
I915_READ(RING_MI_MODE(engine->mmio_base)) & (MODE_IDLE) ? " [idle]" : ""); 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)) { if (HAS_LEGACY_SEMAPHORES(dev_priv)) {
drm_printf(m, "\tSYNC_0: 0x%08x\n", drm_printf(m, "\tSYNC_0: 0x%08x\n",
I915_READ(RING_SYNC_0(engine->mmio_base))); 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))); I915_READ(RING_SYNC_2(engine->mmio_base)));
} }
rcu_read_unlock();
addr = intel_engine_get_active_head(engine); addr = intel_engine_get_active_head(engine);
drm_printf(m, "\tACTHD: 0x%08x_%08x\n", drm_printf(m, "\tACTHD: 0x%08x_%08x\n",
upper_32_bits(addr), lower_32_bits(addr)); upper_32_bits(addr), lower_32_bits(addr));
@ -1855,10 +1803,13 @@ void intel_engine_dump(struct intel_engine_cs *engine,
rcu_read_lock(); rcu_read_lock();
for (idx = 0; idx < execlists_num_ports(execlists); idx++) { for (idx = 0; idx < execlists_num_ports(execlists); idx++) {
struct drm_i915_gem_request *rq;
unsigned int count; unsigned int count;
rq = port_unpack(&execlists->port[idx], &count); rq = port_unpack(&execlists->port[idx], &count);
if (rq) { if (rq) {
char hdr[80];
snprintf(hdr, sizeof(hdr), snprintf(hdr, sizeof(hdr),
"\t\tELSP[%d] count=%d, rq: ", "\t\tELSP[%d] count=%d, rq: ",
idx, count); idx, count);
@ -1877,6 +1828,77 @@ void intel_engine_dump(struct intel_engine_cs *engine,
drm_printf(m, "\tPP_DIR_DCLV: 0x%08x\n", drm_printf(m, "\tPP_DIR_DCLV: 0x%08x\n",
I915_READ(RING_PP_DIR_DCLV(engine))); 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); spin_lock_irq(&engine->timeline->lock);
list_for_each_entry(rq, &engine->timeline->requests, link) 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); 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", drm_printf(m, "IRQ? 0x%lx (breadcrumbs? %s) (execlists? %s)\n",
engine->irq_posted, engine->irq_posted,
yesno(test_bit(ENGINE_IRQ_BREADCRUMB, yesno(test_bit(ENGINE_IRQ_BREADCRUMB,

View file

@ -183,7 +183,7 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv)
else else
dpfc_ctl |= DPFC_CTL_LIMIT_1X; 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; dpfc_ctl |= DPFC_CTL_FENCE_EN | params->vma->fence->id;
I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset); I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
} else { } else {
@ -241,7 +241,7 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
break; break;
} }
if (params->vma->fence) { if (params->flags & PLANE_HAS_FENCE) {
dpfc_ctl |= DPFC_CTL_FENCE_EN; dpfc_ctl |= DPFC_CTL_FENCE_EN;
if (IS_GEN5(dev_priv)) if (IS_GEN5(dev_priv))
dpfc_ctl |= params->vma->fence->id; dpfc_ctl |= params->vma->fence->id;
@ -324,7 +324,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
break; break;
} }
if (params->vma->fence) { if (params->flags & PLANE_HAS_FENCE) {
dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN; dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
I915_WRITE(SNB_DPFC_CTL_SA, I915_WRITE(SNB_DPFC_CTL_SA,
SNB_CPU_FENCE_ENABLE | 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; struct drm_framebuffer *fb = plane_state->base.fb;
cache->vma = NULL; cache->vma = NULL;
cache->flags = 0;
cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags; cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags;
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) 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->fb.stride = fb->pitches[0];
cache->vma = plane_state->vma; 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) 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 * so have no fence associated with it) due to aperture constaints
* at the time of pinning. * at the time of pinning.
*/ */
if (!cache->vma->fence) { if (!(cache->flags & PLANE_HAS_FENCE)) {
fbc->no_fbc_reason = "framebuffer not tiled or fenced"; fbc->no_fbc_reason = "framebuffer not tiled or fenced";
return false; return false;
} }
@ -897,6 +901,7 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
memset(params, 0, sizeof(*params)); memset(params, 0, sizeof(*params));
params->vma = cache->vma; params->vma = cache->vma;
params->flags = cache->flags;
params->crtc.pipe = crtc->pipe; params->crtc.pipe = crtc->pipe;
params->crtc.i9xx_plane = to_intel_plane(crtc->base.primary)->i9xx_plane; params->crtc.i9xx_plane = to_intel_plane(crtc->base.primary)->i9xx_plane;

View file

@ -48,7 +48,8 @@
static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev) static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev)
{ {
struct drm_i915_gem_object *obj = ifbdev->fb->obj; 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); intel_fb_obj_invalidate(obj, origin);
} }
@ -177,6 +178,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
struct fb_info *info; struct fb_info *info;
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct i915_vma *vma; struct i915_vma *vma;
unsigned long flags = 0;
bool prealloc = false; bool prealloc = false;
void __iomem *vaddr; void __iomem *vaddr;
int ret; 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 * This also validates that any existing fb inherited from the
* BIOS is suitable for own access. * 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)) { if (IS_ERR(vma)) {
ret = PTR_ERR(vma); ret = PTR_ERR(vma);
goto out_unlock; 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", DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x\n",
fb->width, fb->height, i915_ggtt_offset(vma)); fb->width, fb->height, i915_ggtt_offset(vma));
ifbdev->vma = vma; ifbdev->vma = vma;
ifbdev->vma_flags = flags;
intel_runtime_pm_put(dev_priv); intel_runtime_pm_put(dev_priv);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
@ -275,7 +280,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
return 0; return 0;
out_unpin: out_unpin:
intel_unpin_fb_vma(vma); intel_unpin_fb_vma(vma, flags);
out_unlock: out_unlock:
intel_runtime_pm_put(dev_priv); intel_runtime_pm_put(dev_priv);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
@ -513,7 +518,7 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
if (ifbdev->vma) { if (ifbdev->vma) {
mutex_lock(&ifbdev->helper.dev->struct_mutex); 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); mutex_unlock(&ifbdev->helper.dev->struct_mutex);
} }

View file

@ -688,7 +688,7 @@ static void guc_dequeue(struct intel_engine_cs *engine)
goto unlock; goto unlock;
if (port_isset(port)) { if (port_isset(port)) {
if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) { if (engine->i915->preempt_context) {
struct guc_preempt_work *preempt_work = struct guc_preempt_work *preempt_work =
&engine->i915->guc.preempt_work[engine->id]; &engine->i915->guc.preempt_work[engine->id];
@ -747,6 +747,12 @@ done:
execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); execlists_set_active(execlists, EXECLISTS_ACTIVE_USER);
guc_submit(engine); 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: unlock:
spin_unlock_irq(&engine->timeline->lock); spin_unlock_irq(&engine->timeline->lock);
} }
@ -832,10 +838,12 @@ static int guc_clients_doorbell_init(struct intel_guc *guc)
if (ret) if (ret)
return ret; return ret;
ret = create_doorbell(guc->preempt_client); if (guc->preempt_client) {
if (ret) { ret = create_doorbell(guc->preempt_client);
destroy_doorbell(guc->execbuf_client); if (ret) {
return ret; destroy_doorbell(guc->execbuf_client);
return ret;
}
} }
return 0; 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 * Instead of trying (in vain) to communicate with it, let's just
* cleanup the doorbell HW and our internal state. * cleanup the doorbell HW and our internal state.
*/ */
__destroy_doorbell(guc->preempt_client); if (guc->preempt_client) {
__update_doorbell_desc(guc->preempt_client, GUC_DOORBELL_INVALID); __destroy_doorbell(guc->preempt_client);
__update_doorbell_desc(guc->preempt_client,
GUC_DOORBELL_INVALID);
}
__destroy_doorbell(guc->execbuf_client); __destroy_doorbell(guc->execbuf_client);
__update_doorbell_desc(guc->execbuf_client, GUC_DOORBELL_INVALID); __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; guc->execbuf_client = client;
client = guc_client_alloc(dev_priv, if (dev_priv->preempt_context) {
INTEL_INFO(dev_priv)->ring_mask, client = guc_client_alloc(dev_priv,
GUC_CLIENT_PRIORITY_KMD_HIGH, INTEL_INFO(dev_priv)->ring_mask,
dev_priv->preempt_context); GUC_CLIENT_PRIORITY_KMD_HIGH,
if (IS_ERR(client)) { dev_priv->preempt_context);
DRM_ERROR("Failed to create GuC client for preemption!\n"); if (IS_ERR(client)) {
guc_client_free(guc->execbuf_client); DRM_ERROR("Failed to create GuC client for preemption!\n");
guc->execbuf_client = NULL; guc_client_free(guc->execbuf_client);
return PTR_ERR(client); guc->execbuf_client = NULL;
return PTR_ERR(client);
}
guc->preempt_client = client;
} }
guc->preempt_client = client;
return 0; return 0;
} }
@ -998,10 +1011,11 @@ static void guc_clients_destroy(struct intel_guc *guc)
{ {
struct intel_guc_client *client; struct intel_guc_client *client;
client = fetch_and_zero(&guc->execbuf_client);
guc_client_free(client);
client = fetch_and_zero(&guc->preempt_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); guc_client_free(client);
} }
@ -1160,7 +1174,8 @@ int intel_guc_submission_enable(struct intel_guc *guc)
GEM_BUG_ON(!guc->execbuf_client); GEM_BUG_ON(!guc->execbuf_client);
guc_reset_wq(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); err = intel_guc_sample_forcewake(guc);
if (err) if (err)

View file

@ -118,7 +118,8 @@ void intel_huc_init_early(struct intel_huc *huc)
/** /**
* huc_ucode_xfer() - DMA's the firmware * 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. * Transfer the firmware image to RAM for execution by the microcontroller.
* *

View file

@ -74,7 +74,6 @@
static struct platform_device * static struct platform_device *
lpe_audio_platdev_create(struct drm_i915_private *dev_priv) lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
{ {
int ret;
struct drm_device *dev = &dev_priv->drm; struct drm_device *dev = &dev_priv->drm;
struct platform_device_info pinfo = {}; struct platform_device_info pinfo = {};
struct resource *rsc; struct resource *rsc;
@ -119,24 +118,19 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
spin_lock_init(&pdata->lpe_audio_slock); spin_lock_init(&pdata->lpe_audio_slock);
platdev = platform_device_register_full(&pinfo); platdev = platform_device_register_full(&pinfo);
if (IS_ERR(platdev)) {
ret = PTR_ERR(platdev);
DRM_ERROR("Failed to allocate LPE audio platform device\n");
goto err;
}
kfree(rsc); kfree(rsc);
kfree(pdata);
if (IS_ERR(platdev)) {
DRM_ERROR("Failed to allocate LPE audio platform device\n");
return platdev;
}
pm_runtime_forbid(&platdev->dev); pm_runtime_forbid(&platdev->dev);
pm_runtime_set_active(&platdev->dev); pm_runtime_set_active(&platdev->dev);
pm_runtime_enable(&platdev->dev); pm_runtime_enable(&platdev->dev);
return platdev; return platdev;
err:
kfree(rsc);
kfree(pdata);
return ERR_PTR(ret);
} }
static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv) static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv)

View file

@ -161,7 +161,6 @@
#define EXECLISTS_REQUEST_SIZE 64 /* bytes */ #define EXECLISTS_REQUEST_SIZE 64 /* bytes */
#define WA_TAIL_DWORDS 2 #define WA_TAIL_DWORDS 2
#define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS) #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS)
#define PREEMPT_ID 0x1
static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
struct intel_engine_cs *engine); 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]; &engine->i915->preempt_context->engine[engine->id];
unsigned int n; 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)); GEM_BUG_ON(!IS_ALIGNED(ce->ring->size, WA_TAIL_BYTES));
memset(ce->ring->vaddr + ce->ring->tail, 0, 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)) if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_HWACK))
goto unlock; goto unlock;
if (HAS_LOGICAL_RING_PREEMPTION(engine->i915) && if (engine->i915->preempt_context &&
rb_entry(rb, struct i915_priolist, node)->priority > rb_entry(rb, struct i915_priolist, node)->priority >
max(last->priotree.priority, 0)) { max(last->priotree.priority, 0)) {
/* /*
@ -642,6 +642,10 @@ done:
execlists->first = rb; execlists->first = rb;
if (submit) if (submit)
port_assign(port, last); 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: unlock:
spin_unlock_irq(&engine->timeline->lock); spin_unlock_irq(&engine->timeline->lock);
@ -649,6 +653,9 @@ unlock:
execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); execlists_set_active(execlists, EXECLISTS_ACTIVE_USER);
execlists_submit_ports(engine); execlists_submit_ports(engine);
} }
GEM_BUG_ON(port_isset(execlists->port) &&
!execlists_is_active(execlists, EXECLISTS_ACTIVE_USER));
} }
void void
@ -844,7 +851,7 @@ static void execlists_submission_tasklet(unsigned long data)
GEM_BUG_ON(status & GEN8_CTX_STATUS_IDLE_ACTIVE); GEM_BUG_ON(status & GEN8_CTX_STATUS_IDLE_ACTIVE);
if (status & GEN8_CTX_STATUS_COMPLETE && 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); GEM_TRACE("%s preempt-idle\n", engine->name);
execlists_cancel_port_requests(execlists); execlists_cancel_port_requests(execlists);
@ -1963,6 +1970,12 @@ static void execlists_set_default_submission(struct intel_engine_cs *engine)
engine->unpark = NULL; engine->unpark = NULL;
engine->flags |= I915_ENGINE_SUPPORTS_STATS; 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 static void
@ -2039,6 +2052,11 @@ static int logical_ring_init(struct intel_engine_cs *engine)
engine->execlists.elsp = engine->execlists.elsp =
engine->i915->regs + i915_mmio_reg_offset(RING_ELSP(engine)); 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; return 0;
error: error:
@ -2301,7 +2319,7 @@ populate_lr_context(struct i915_gem_context *ctx,
if (!engine->default_state) if (!engine->default_state)
regs[CTX_CONTEXT_CONTROL + 1] |= regs[CTX_CONTEXT_CONTROL + 1] |=
_MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); _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] |= regs[CTX_CONTEXT_CONTROL + 1] |=
_MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT |
CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT); CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT);

View file

@ -189,7 +189,7 @@ static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
/* Convert from 100ms to 100us units */ /* Convert from 100ms to 100us units */
pps->t4 = val * 1000; 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) { pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
DRM_DEBUG_KMS("Panel power timings uninitialized, " DRM_DEBUG_KMS("Panel power timings uninitialized, "
"setting defaults\n"); "setting defaults\n");
@ -268,7 +268,9 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder,
/* set the corresponsding LVDS_BORDER bit */ /* set the corresponsding LVDS_BORDER bit */
temp &= ~LVDS_BORDER_ENABLE; temp &= ~LVDS_BORDER_ENABLE;
temp |= pipe_config->gmch_pfit.lvds_border_bits; 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. * set the DPLLs for dual-channel mode or not.
*/ */
if (lvds_encoder->is_dual_link) if (lvds_encoder->is_dual_link)
@ -276,7 +278,8 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder,
else else
temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); 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 * appropriately here, but we need to look more thoroughly into how
* panels behave in the two modes. For now, let's just maintain the * panels behave in the two modes. For now, let's just maintain the
* value we got from the BIOS. * 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_A3_POWER_MASK;
temp |= lvds_encoder->a3_power; 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 * 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)) { 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) if (pipe_config->dither && pipe_config->pipe_bpp == 18)
temp |= LVDS_ENABLE_DITHER; temp |= LVDS_ENABLE_DITHER;
else else
@ -304,7 +311,7 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder,
I915_WRITE(lvds_encoder->reg, temp); I915_WRITE(lvds_encoder->reg, temp);
} }
/** /*
* Sets the power state for the panel. * Sets the power state for the panel.
*/ */
static void intel_enable_lvds(struct intel_encoder *encoder, 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; return true;
} }
/** /*
* Detect the LVDS connection. * Detect the LVDS connection.
* *
* Since LVDS doesn't have hotlug, we use the lid as a proxy. Open means * 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 connector_status_connected;
} }
/** /*
* Return the list of DDC modes if available, or the BIOS fixed mode otherwise. * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
*/ */
static int intel_lvds_get_modes(struct drm_connector *connector) 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)) if (dmi_check_system(intel_dual_link_lvds))
return true; 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; * 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 * we need to check "the value to be set" in VBT when LVDS
* register is uninitialized. * 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) 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)) if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
return true; 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 && if (INTEL_GEN(dev_priv) <= 4 &&
IS_MOBILE(dev_priv) && !IS_I830(dev_priv)) IS_MOBILE(dev_priv) && !IS_I830(dev_priv))
return true; 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 * 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 * Create the connector, register the LVDS DDC bus, and try to figure out what
* modes we can display on the LVDS panel (if present). * modes we can display on the LVDS panel (if present).

View file

@ -187,7 +187,7 @@ static bool get_mocs_settings(struct drm_i915_private *dev_priv,
table->table = broxton_mocs_table; table->table = broxton_mocs_table;
result = true; result = true;
} else { } 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"); "Platform that should have a MOCS table does not.\n");
} }

View file

@ -801,7 +801,8 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
atomic_inc(&dev_priv->gpu_error.pending_fb_pin); 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)) { if (IS_ERR(vma)) {
ret = PTR_ERR(vma); ret = PTR_ERR(vma);
goto out_pin_section; goto out_pin_section;

View file

@ -397,8 +397,11 @@ intel_panel_detect(struct drm_i915_private *dev_priv)
/** /**
* scale - scale values from one range to another * scale - scale values from one range to another
*
* @source_val: value in range [@source_min..@source_max] * @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 * Return @source_val in range [@source_min..@source_max] scaled to range
* [@target_min..@target_max]. * [@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); source_val = clamp(source_val, source_min, source_max);
/* avoid overflows */ /* avoid overflows */
target_val = DIV_ROUND_CLOSEST_ULL((uint64_t)(source_val - source_min) * target_val = mul_u32_u32(source_val - source_min,
(target_max - target_min), source_max - source_min); target_max - target_min);
target_val = DIV_ROUND_CLOSEST_ULL(target_val, source_max - source_min);
target_val += target_min; target_val += target_min;
return target_val; return target_val;
@ -497,7 +501,7 @@ static u32 i9xx_get_backlight(struct intel_connector *connector)
u32 val; u32 val;
val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; 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; val >>= 1;
if (panel->backlight.combination_mode) { if (panel->backlight.combination_mode) {

View file

@ -729,6 +729,7 @@ static unsigned int intel_wm_method2(unsigned int pixel_rate,
* intel_calculate_wm - calculate watermark level * intel_calculate_wm - calculate watermark level
* @pixel_rate: pixel clock * @pixel_rate: pixel clock
* @wm: chip FIFO params * @wm: chip FIFO params
* @fifo_size: size of the FIFO buffer
* @cpp: bytes per pixel * @cpp: bytes per pixel
* @latency_ns: memory latency for the platform * @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 */ /* ILK cursor LP0 latency is 1300 ns */
if (IS_GEN5(dev_priv)) if (IS_GEN5(dev_priv))
wm[0] = 13; 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) 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; 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) { min_disp_buf_needed >= ddb_allocation) {
*enabled = false; *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_blocks = res_blocks;
*out_lines = res_lines;
*enabled = true; *enabled = true;
return 0; return 0;
@ -4710,6 +4709,7 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate,
if (!dev_priv->ipc_enabled) if (!dev_priv->ipc_enabled)
goto exit; goto exit;
trans_min = 0;
if (INTEL_GEN(dev_priv) >= 10) if (INTEL_GEN(dev_priv) >= 10)
trans_min = 4; 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 * 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 * Calculate watermark values for the various WM regs based on current mode
* and plane configuration. * and plane configuration.
@ -6372,12 +6373,15 @@ void gen6_rps_boost(struct drm_i915_gem_request *rq,
if (!rps->enabled) if (!rps->enabled)
return; return;
if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags))
return;
/* Serializes with i915_gem_request_retire() */
boost = false; boost = false;
spin_lock_irqsave(&rq->lock, flags); spin_lock_irqsave(&rq->lock, flags);
if (!rq->waitboost && !i915_gem_request_completed(rq)) { if (!rq->waitboost && !dma_fence_is_signaled_locked(&rq->fence)) {
atomic_inc(&rps->num_waiters); boost = !atomic_fetch_inc(&rps->num_waiters);
rq->waitboost = true; rq->waitboost = true;
boost = true;
} }
spin_unlock_irqrestore(&rq->lock, flags); spin_unlock_irqrestore(&rq->lock, flags);
if (!boost) 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. * No floor required for ring frequency on SKL.
*/ */
ring_freq = gpu_freq; 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 */ /* max(2 * GT, DDR). NB: GT is 50MHz units */
ring_freq = max(min_ring_freq, gpu_freq); ring_freq = max(min_ring_freq, gpu_freq);
} else if (IS_HASWELL(dev_priv)) { } else if (IS_HASWELL(dev_priv)) {
@ -7549,7 +7553,7 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
{ {
unsigned long val; unsigned long val;
if (INTEL_INFO(dev_priv)->gen != 5) if (!IS_GEN5(dev_priv))
return 0; return 0;
spin_lock_irq(&mchdev_lock); 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) void i915_update_gfx_val(struct drm_i915_private *dev_priv)
{ {
if (INTEL_INFO(dev_priv)->gen != 5) if (!IS_GEN5(dev_priv))
return; return;
spin_lock_irq(&mchdev_lock); spin_lock_irq(&mchdev_lock);
@ -7684,7 +7688,7 @@ unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
{ {
unsigned long val; unsigned long val;
if (INTEL_INFO(dev_priv)->gen != 5) if (!IS_GEN5(dev_priv))
return 0; return 0;
spin_lock_irq(&mchdev_lock); 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) const i915_reg_t reg)
{ {
u32 lower, upper, tmp; u32 lower, upper, tmp;
unsigned long flags;
int loop = 2; 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. * 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 * With a control bit, we can choose between upper or lower
* 32bit window into this counter. * 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); upper = I915_READ_FW(reg);
} while (upper != tmp && --loop); } 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 * VLV_COUNT_RANGE_HIGH bit set - so it is safe to leave it set
* now. * now.
*/ */
spin_unlock_irqrestore(&dev_priv->uncore.lock, flags);
return lower | (u64)upper << 8; return lower | (u64)upper << 8;
} }
u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv, u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv,
const i915_reg_t reg) 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; u32 mul, div;
if (!HAS_RC6(dev_priv)) if (!HAS_RC6(dev_priv))
return 0; 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 */ /* On VLV and CHV, residency time is in CZ units rather than 1.28us */
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
mul = 1000000; mul = 1000000;
div = dev_priv->czclk_freq; div = dev_priv->czclk_freq;
overflow_hw = BIT_ULL(40);
time_hw = vlv_residency_raw(dev_priv, reg); time_hw = vlv_residency_raw(dev_priv, reg);
} else { } else {
/* 833.33ns units on Gen9LP, 1.28us elsewhere. */ /* 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; 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) u32 intel_get_cagf(struct drm_i915_private *dev_priv, u32 rpstat)

View file

@ -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, static i915_reg_t psr_aux_ctl_reg(struct drm_i915_private *dev_priv,
enum port port) enum port port)
{ {
if (INTEL_INFO(dev_priv)->gen >= 9) if (INTEL_GEN(dev_priv) >= 9)
return DP_AUX_CH_CTL(port); return DP_AUX_CH_CTL(port);
else else
return EDP_PSR_AUX_CTL; 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, static i915_reg_t psr_aux_data_reg(struct drm_i915_private *dev_priv,
enum port port, int index) 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); return DP_AUX_CH_DATA(port, index);
else else
return EDP_PSR_AUX_DATA(index); return EDP_PSR_AUX_DATA(index);

View file

@ -137,7 +137,7 @@ gen4_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
return 0; return 0;
} }
/** /*
* Emits a PIPE_CONTROL with a non-zero post-sync operation, for * Emits a PIPE_CONTROL with a non-zero post-sync operation, for
* implementing two workarounds on gen6. From section 1.4.7.1 * implementing two workarounds on gen6. From section 1.4.7.1
* "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 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)) { if (!stop_ring(engine)) {
/* G45 ring initialization often fails to reset head to zero */ /* G45 ring initialization often fails to reset head to zero */
DRM_DEBUG_KMS("%s head not reset to zero " DRM_DEBUG_DRIVER("%s head not reset to zero "
"ctl %08x head %08x tail %08x start %08x\n", "ctl %08x head %08x tail %08x start %08x\n",
engine->name, engine->name,
I915_READ_CTL(engine), I915_READ_CTL(engine),
I915_READ_HEAD(engine), I915_READ_HEAD(engine),
I915_READ_TAIL(engine), I915_READ_TAIL(engine),
I915_READ_START(engine)); I915_READ_START(engine));
if (!stop_ring(engine)) { if (!stop_ring(engine)) {
DRM_ERROR("failed to set %s head to zero " 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 */ /* WaClearRingBufHeadRegAtInit:ctg,elk */
if (I915_READ_HEAD(engine)) if (I915_READ_HEAD(engine))
DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", DRM_DEBUG_DRIVER("%s initialization failed [head=%08x], fudging\n",
engine->name, I915_READ_HEAD(engine)); engine->name, I915_READ_HEAD(engine));
intel_ring_update_space(ring); intel_ring_update_space(ring);
I915_WRITE_HEAD(engine, ring->head); 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)) if (IS_GEN(dev_priv, 6, 7))
I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); 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); I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
return init_workarounds_ring(engine); 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; 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) static void gen6_sema_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs)
{ {
return i9xx_emit_breadcrumb(req, return i9xx_emit_breadcrumb(req,

View file

@ -279,6 +279,11 @@ struct intel_engine_execlists {
* @csb_use_mmio: access csb through mmio, instead of hwsp * @csb_use_mmio: access csb through mmio, instead of hwsp
*/ */
bool csb_use_mmio; bool csb_use_mmio;
/**
* @preempt_complete_status: expected CSB upon completing preemption
*/
u32 preempt_complete_status;
}; };
#define INTEL_ENGINE_CS_MAX_NAME 8 #define INTEL_ENGINE_CS_MAX_NAME 8
@ -654,7 +659,7 @@ intel_engine_flag(const struct intel_engine_cs *engine)
} }
static inline u32 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. */ /* Ensure that the compiler doesn't optimize away the load. */
return READ_ONCE(engine->status_page.page_addr[reg]); 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_blt_ring_buffer(struct intel_engine_cs *engine);
int intel_init_vebox_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_active_head(const struct intel_engine_cs *engine);
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);
static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine) static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine)
{ {

View file

@ -2646,6 +2646,48 @@ static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
DRM_ERROR("DBuf power disable timeout!\n"); 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, static void skl_display_core_init(struct drm_i915_private *dev_priv,
bool resume) bool resume)
{ {
@ -2794,12 +2836,19 @@ static const struct cnl_procmon {
{ .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, }, { .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; const struct cnl_procmon *procmon;
u32 val; 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)) { switch (val & (PROCESS_INFO_MASK | VOLTAGE_INFO_MASK)) {
default: default:
MISSING_CASE(val); MISSING_CASE(val);
@ -2820,13 +2869,13 @@ static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv)
break; break;
} }
val = I915_READ(CNL_PORT_COMP_DW1); val = I915_READ(ICL_PORT_COMP_DW1(port));
val &= ~((0xff << 16) | 0xff); val &= ~((0xff << 16) | 0xff);
val |= procmon->dw1; 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(ICL_PORT_COMP_DW9(port), procmon->dw9);
I915_WRITE(CNL_PORT_COMP_DW10, procmon->dw10); I915_WRITE(ICL_PORT_COMP_DW10(port), procmon->dw10);
} }
static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume) 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; val &= ~CNL_COMP_PWR_DOWN;
I915_WRITE(CHICKEN_MISC_2, val); 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 = I915_READ(CNL_PORT_COMP_DW0);
val |= COMP_INIT; 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); 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) static void chv_phy_control_init(struct drm_i915_private *dev_priv)
{ {
struct i915_power_well *cmn_bc = 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; 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); cnl_display_core_init(dev_priv, resume);
} else if (IS_GEN9_BC(dev_priv)) { } else if (IS_GEN9_BC(dev_priv)) {
skl_display_core_init(dev_priv, resume); 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) if (!i915_modparams.disable_power_well)
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); 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); cnl_display_core_uninit(dev_priv);
else if (IS_GEN9_BC(dev_priv)) else if (IS_GEN9_BC(dev_priv))
skl_display_core_uninit(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 * @dev_priv: i915 device instance
* *
* This function grabs a device-level runtime pm reference if the device is * 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 * Any runtime pm reference obtained by this function must have a symmetric
* call to intel_runtime_pm_put() to release the reference again. * 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) 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)) { 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 * 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 * function, since the power state is undefined. This applies
* atm to the late/early system suspend/resume handlers. * atm to the late/early system suspend/resume handlers.
*/ */
WARN_ONCE(ret < 0, if (pm_runtime_get_if_in_use(kdev) <= 0)
"pm_runtime_get_if_in_use() failed: %d\n", ret);
if (ret <= 0)
return false; return false;
} }

View file

@ -214,7 +214,7 @@ static bool
intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo,
struct intel_sdvo_connector *intel_sdvo_connector); struct intel_sdvo_connector *intel_sdvo_connector);
/** /*
* Writes the SDVOB or SDVOC with the given value, but always writes both * Writes the SDVOB or SDVOC with the given value, but always writes both
* SDVOB and SDVOC to work around apparent hardware issues (according to * SDVOB and SDVOC to work around apparent hardware issues (according to
* comments in the BIOS). * 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'. * writing them only once doesn't appear to 'stick'.
* The BIOS does this too. Yay, magic * The BIOS does this too. Yay, magic
*/ */
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++) {
{
I915_WRITE(GEN3_SDVOB, bval); I915_WRITE(GEN3_SDVOB, bval);
POSTING_READ(GEN3_SDVOB); POSTING_READ(GEN3_SDVOB);
I915_WRITE(GEN3_SDVOC, cval); I915_WRITE(GEN3_SDVOC, cval);
POSTING_READ(GEN3_SDVOC); POSTING_READ(GEN3_SDVOC);
} }
@ -643,7 +643,7 @@ static bool intel_sdvo_set_target_input(struct intel_sdvo *intel_sdvo)
&targets, sizeof(targets)); &targets, sizeof(targets));
} }
/** /*
* Return whether each input is trained. * Return whether each input is trained.
* *
* This function is making an assumption about the layout of the response, * 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; 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 static bool
intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
const struct drm_display_mode *mode, 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; unsigned dotclock = pipe_config->port_clock;
struct dpll *clock = &pipe_config->dpll; 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) { if (dotclock >= 100000 && dotclock < 140500) {
clock->p1 = 2; clock->p1 = 2;
clock->p2 = 10; 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))) if (HAS_PCH_SPLIT(to_i915(encoder->base.dev)))
pipe_config->has_pch_encoder = true; 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 * output timings. To do that, we have to set the output
* timings, even though this isn't really the right place in * timings, even though this isn't really the right place in
* the sequence to do it. Oh well. * the sequence to do it. Oh well.
@ -1155,7 +1160,8 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
adjusted_mode); 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. * SDVO device will factor out the multiplier during mode_set.
*/ */
pipe_config->pixel_multiplier = pipe_config->pixel_multiplier =
@ -1169,9 +1175,12 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
pipe_config->has_audio = true; pipe_config->has_audio = true;
if (intel_sdvo_state->base.broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) { 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 * See CEA-861-E - 5.1 Default Encoding Parameters
* bit per color mode. */ *
* FIXME: This bit is only valid when using TMDS encoding and 8
* bit per color mode.
*/
if (pipe_config->has_hdmi_sink && if (pipe_config->has_hdmi_sink &&
drm_match_cea_mode(adjusted_mode) > 1) drm_match_cea_mode(adjusted_mode) > 1)
pipe_config->limited_color_range = true; 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); 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 * 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 * which case the first input is the output from the appropriate SDVO
* channel on the motherboard. In a two-input device, the first input * 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); ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd);
if (!ret) { 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"); DRM_DEBUG_DRIVER("failed to retrieve SDVO DTD\n");
pipe_config->quirks |= PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS; pipe_config->quirks |= PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS;
} else { } else {
@ -1585,7 +1597,9 @@ static void intel_enable_sdvo(struct intel_encoder *encoder,
intel_wait_for_vblank(dev_priv, intel_crtc->pipe); intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
success = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2); 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 lot of SDVO devices fail to notify of sync, but it's
* a given it the status is a success, we succeeded. * 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)) if (!I915_HAS_HOTPLUG(dev_priv))
return 0; 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)) if (IS_I945G(dev_priv) || IS_I945GM(dev_priv))
return 0; return 0;
@ -1957,7 +1973,8 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name); 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.
*/ */
format_map = 1 << conn_state->tv.mode; format_map = 1 << conn_state->tv.mode;
@ -2268,7 +2285,8 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
uint16_t mask = 0; uint16_t mask = 0;
unsigned int num_bits; 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. * list.
*/ */
switch (sdvo->controlled_output) { switch (sdvo->controlled_output) {
@ -2298,7 +2316,7 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
sdvo->ddc_bus = 1 << num_bits; sdvo->ddc_bus = 1 << num_bits;
} }
/** /*
* Choose the appropriate DDC bus for control bus switch command for this * Choose the appropriate DDC bus for control bus switch command for this
* SDVO output based on the controlled output. * 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); 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 * 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); 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) if (my_mapping->slave_addr)
return 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. * address that it isn't using.
*/ */
if (other_mapping->slave_addr) { if (other_mapping->slave_addr) {
@ -2389,7 +2410,8 @@ intel_sdvo_get_slave_addr(struct drm_i915_private *dev_priv,
return 0x70; 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. * so use mapping assumption we had before BIOS parsing.
*/ */
if (sdvo->port == PORT_B) 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) & if (intel_sdvo_get_hotplug_support(intel_sdvo) &
intel_sdvo_connector->output_flag) { intel_sdvo_connector->output_flag) {
intel_sdvo->hotplug_active |= 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. * Ensure that they get re-enabled when an interrupt happens.
*/ */
intel_encoder->hot_plug = intel_sdvo_enable_hotplug; 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); to_intel_sdvo_connector_state(conn_state);
uint16_t response, data_value[2]; 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 (enhancements.overscan_h) {
if (!intel_sdvo_get_value(intel_sdvo, if (!intel_sdvo_get_value(intel_sdvo,
SDVO_CMD_GET_MAX_OVERSCAN_H, SDVO_CMD_GET_MAX_OVERSCAN_H,
@ -3074,7 +3097,8 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
goto err_output; 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. * hotplug lines.
*/ */
if (intel_sdvo->hotplug_active) { if (intel_sdvo->hotplug_active) {

View file

@ -1063,8 +1063,8 @@ intel_check_sprite_plane(struct intel_plane *plane,
return 0; return 0;
} }
int intel_sprite_set_colorkey(struct drm_device *dev, void *data, int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_intel_sprite_colorkey *set = data; 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 */ /* ignore the pointless "none" flag */
set->flags &= ~I915_SET_COLORKEY_NONE; 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 */ /* 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)) if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
return -EINVAL; return -EINVAL;

View file

@ -43,7 +43,6 @@ enum tv_margin {
TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM
}; };
/** Private structure for the integrated TV support */
struct intel_tv { struct intel_tv {
struct intel_encoder base; struct intel_encoder base;
@ -370,12 +369,11 @@ struct tv_mode {
* The constants below were all computed using a 107.520MHz clock * The constants below were all computed using a 107.520MHz clock
*/ */
/** /*
* Register programming values for TV modes. * Register programming values for TV modes.
* *
* These values account for -1s required. * These values account for -1s required.
*/ */
static const struct tv_mode tv_modes[] = { static const struct tv_mode tv_modes[] = {
{ {
.name = "NTSC-M", .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 static int
intel_tv_detect_type(struct intel_tv *intel_tv, intel_tv_detect_type(struct intel_tv *intel_tv,
struct drm_connector *connector) struct drm_connector *connector)
@ -1259,12 +1249,6 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
connector->state->tv.mode = i; 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 static int
intel_tv_detect(struct drm_connector *connector, intel_tv_detect(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx, 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 static int
intel_tv_get_modes(struct drm_connector *connector) 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; connector = &intel_connector->base;
state = connector->state; 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. * using a polling method rather than hotplug detection for TVs.
* This is because in order to perform the hotplug detection, the PLLs * This is because in order to perform the hotplug detection, the PLLs
* for the TV must be kept alive increasing power drain and starving * for the TV must be kept alive increasing power drain and starving

View file

@ -197,11 +197,12 @@ fail:
/** /**
* intel_uc_fw_upload - load uC firmware using custom loader * intel_uc_fw_upload - load uC firmware using custom loader
*
* @uc_fw: uC firmware * @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. * 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 intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
int (*xfer)(struct intel_uc_fw *uc_fw, int (*xfer)(struct intel_uc_fw *uc_fw,

View file

@ -1522,9 +1522,11 @@ static void gen3_stop_engine(struct intel_engine_cs *engine)
engine->name); engine->name);
I915_WRITE_FW(RING_HEAD(base), I915_READ_FW(RING_TAIL(base))); 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_HEAD(base), 0);
I915_WRITE_FW(RING_TAIL(base), 0); I915_WRITE_FW(RING_TAIL(base), 0);
POSTING_READ_FW(RING_TAIL(base));
/* The ring must be empty before it is disabled */ /* The ring must be empty before it is disabled */
I915_WRITE_FW(RING_CTL(base), 0); 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); gen3_stop_engine(engine);
} }
static bool i915_reset_complete(struct pci_dev *pdev) static bool i915_in_reset(struct pci_dev *pdev)
{ {
u8 gdrst; u8 gdrst;
pci_read_config_byte(pdev, I915_GDRST, &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) static int i915_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask)
{ {
struct pci_dev *pdev = dev_priv->drm.pdev; 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); pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE);
usleep_range(50, 200); usleep_range(50, 200);
pci_write_config_byte(pdev, I915_GDRST, 0); err = wait_for(i915_in_reset(pdev), 500);
return wait_for(i915_reset_complete(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 err;
} }
static bool g4x_reset_complete(struct pci_dev *pdev) 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) if (!i915_modparams.reset)
return NULL; return NULL;
if (INTEL_INFO(dev_priv)->gen >= 8) if (INTEL_GEN(dev_priv) >= 8)
return gen8_reset_engines; return gen8_reset_engines;
else if (INTEL_INFO(dev_priv)->gen >= 6) else if (INTEL_GEN(dev_priv) >= 6)
return gen6_reset_engines; return gen6_reset_engines;
else if (IS_GEN5(dev_priv)) else if (IS_GEN5(dev_priv))
return ironlake_do_reset; 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; return g4x_do_reset;
else if (IS_G33(dev_priv) || IS_PINEVIEW(dev_priv)) else if (IS_G33(dev_priv) || IS_PINEVIEW(dev_priv))
return g33_do_reset; return g33_do_reset;
else if (INTEL_INFO(dev_priv)->gen >= 3) else if (INTEL_GEN(dev_priv) >= 3)
return i915_do_reset; return i915_do_reset;
else else
return NULL; return NULL;

View file

@ -198,4 +198,9 @@ int intel_wait_for_register_fw(struct drm_i915_private *dev_priv,
2, timeout_ms, NULL); 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__ */ #endif /* !__INTEL_UNCORE_H__ */

View file

@ -129,8 +129,8 @@ huge_gem_object(struct drm_i915_private *i915,
drm_gem_private_object_init(&i915->drm, &obj->base, dma_size); drm_gem_private_object_init(&i915->drm, &obj->base, dma_size);
i915_gem_object_init(obj, &huge_ops); i915_gem_object_init(obj, &huge_ops);
obj->base.read_domains = I915_GEM_DOMAIN_CPU; obj->read_domains = I915_GEM_DOMAIN_CPU;
obj->base.write_domain = I915_GEM_DOMAIN_CPU; obj->write_domain = I915_GEM_DOMAIN_CPU;
cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE; cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE;
i915_gem_object_set_cache_coherency(obj, cache_level); i915_gem_object_set_cache_coherency(obj, cache_level);
obj->scratch = phys_size; obj->scratch = phys_size;

View file

@ -178,8 +178,8 @@ huge_pages_object(struct drm_i915_private *i915,
drm_gem_private_object_init(&i915->drm, &obj->base, size); drm_gem_private_object_init(&i915->drm, &obj->base, size);
i915_gem_object_init(obj, &huge_page_ops); i915_gem_object_init(obj, &huge_page_ops);
obj->base.write_domain = I915_GEM_DOMAIN_CPU; obj->write_domain = I915_GEM_DOMAIN_CPU;
obj->base.read_domains = I915_GEM_DOMAIN_CPU; obj->read_domains = I915_GEM_DOMAIN_CPU;
obj->cache_level = I915_CACHE_NONE; obj->cache_level = I915_CACHE_NONE;
obj->mm.page_mask = page_mask; obj->mm.page_mask = page_mask;
@ -329,8 +329,8 @@ fake_huge_pages_object(struct drm_i915_private *i915, u64 size, bool single)
else else
i915_gem_object_init(obj, &fake_ops); i915_gem_object_init(obj, &fake_ops);
obj->base.write_domain = I915_GEM_DOMAIN_CPU; obj->write_domain = I915_GEM_DOMAIN_CPU;
obj->base.read_domains = I915_GEM_DOMAIN_CPU; obj->read_domains = I915_GEM_DOMAIN_CPU;
obj->cache_level = I915_CACHE_NONE; obj->cache_level = I915_CACHE_NONE;
return obj; return obj;

View file

@ -215,8 +215,8 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
} }
i915_gem_obj_finish_shmem_access(obj); i915_gem_obj_finish_shmem_access(obj);
obj->base.read_domains = I915_GEM_DOMAIN_GTT | I915_GEM_DOMAIN_CPU; obj->read_domains = I915_GEM_DOMAIN_GTT | I915_GEM_DOMAIN_CPU;
obj->base.write_domain = 0; obj->write_domain = 0;
return 0; return 0;
} }

View file

@ -113,8 +113,8 @@ fake_dma_object(struct drm_i915_private *i915, u64 size)
drm_gem_private_object_init(&i915->drm, &obj->base, size); drm_gem_private_object_init(&i915->drm, &obj->base, size);
i915_gem_object_init(obj, &fake_ops); i915_gem_object_init(obj, &fake_ops);
obj->base.write_domain = I915_GEM_DOMAIN_CPU; obj->write_domain = I915_GEM_DOMAIN_CPU;
obj->base.read_domains = I915_GEM_DOMAIN_CPU; obj->read_domains = I915_GEM_DOMAIN_CPU;
obj->cache_level = I915_CACHE_NONE; obj->cache_level = I915_CACHE_NONE;
/* Preallocate the "backing storage" */ /* Preallocate the "backing storage" */
@ -927,7 +927,7 @@ static int shrink_boom(struct drm_i915_private *i915,
explode = fake_dma_object(i915, size); explode = fake_dma_object(i915, size);
if (IS_ERR(explode)) { if (IS_ERR(explode)) {
err = PTR_ERR(purge); err = PTR_ERR(explode);
goto err_purge; goto err_purge;
} }

View file

@ -212,8 +212,11 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
return -EINTR; return -EINTR;
err = i915_gem_object_set_tiling(obj, tile->tiling, tile->stride); 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; return err;
}
GEM_BUG_ON(i915_gem_object_get_tiling(obj) != tile->tiling); GEM_BUG_ON(i915_gem_object_get_tiling(obj) != tile->tiling);
GEM_BUG_ON(i915_gem_object_get_stride(obj) != tile->stride); 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); GEM_BUG_ON(view.partial.size > nreal);
err = i915_gem_object_set_to_gtt_domain(obj, true); 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; return err;
}
vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE); vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE);
if (IS_ERR(vma)) { if (IS_ERR(vma)) {
pr_err("Failed to pin partial view: offset=%lu\n", pr_err("Failed to pin partial view: offset=%lu; err=%d\n",
page); page, (int)PTR_ERR(vma));
return 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); io = i915_vma_pin_iomap(vma);
i915_vma_unpin(vma); i915_vma_unpin(vma);
if (IS_ERR(io)) { if (IS_ERR(io)) {
pr_err("Failed to iomap partial view: offset=%lu\n", pr_err("Failed to iomap partial view: offset=%lu; err=%d\n",
page); page, (int)PTR_ERR(io));
return PTR_ERR(io); return PTR_ERR(io);
} }

View file

@ -87,7 +87,7 @@ static int validate_client(struct intel_guc_client *client,
static bool client_doorbell_in_sync(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; goto unlock;
} }
GEM_BUG_ON(!guc->execbuf_client); GEM_BUG_ON(!guc->execbuf_client);
GEM_BUG_ON(!guc->preempt_client);
err = validate_client(guc->execbuf_client, err = validate_client(guc->execbuf_client,
GUC_CLIENT_PRIORITY_KMD_NORMAL, false); GUC_CLIENT_PRIORITY_KMD_NORMAL, false);
@ -146,16 +145,18 @@ static int igt_guc_clients(void *args)
goto out; goto out;
} }
err = validate_client(guc->preempt_client, if (guc->preempt_client) {
GUC_CLIENT_PRIORITY_KMD_HIGH, true); err = validate_client(guc->preempt_client,
if (err) { GUC_CLIENT_PRIORITY_KMD_HIGH, true);
pr_err("preempt client validation failed\n"); if (err) {
goto out; pr_err("preempt client validation failed\n");
goto out;
}
} }
/* each client should now have reserved a doorbell */ /* each client should now have reserved a doorbell */
if (!has_doorbell(guc->execbuf_client) || 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"); pr_err("guc_clients_create didn't reserve doorbells\n");
err = -EINVAL; err = -EINVAL;
goto out; goto out;
@ -224,7 +225,8 @@ out:
* clients during unload. * clients during unload.
*/ */
destroy_doorbell(guc->execbuf_client); 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_destroy(guc);
guc_clients_create(guc); guc_clients_create(guc);
guc_clients_doorbell_init(guc); guc_clients_doorbell_init(guc);

View file

@ -243,16 +243,10 @@ struct drm_i915_private *mock_gem_device(void)
if (!i915->kernel_context) if (!i915->kernel_context)
goto err_engine; goto err_engine;
i915->preempt_context = mock_context(i915, NULL);
if (!i915->preempt_context)
goto err_kernel_context;
WARN_ON(i915_gemfs_init(i915)); WARN_ON(i915_gemfs_init(i915));
return i915; return i915;
err_kernel_context:
i915_gem_context_put(i915->kernel_context);
err_engine: err_engine:
for_each_engine(engine, i915, id) for_each_engine(engine, i915, id)
mock_engine_free(engine); mock_engine_free(engine);

View file

@ -570,7 +570,7 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc,
base &= ~7; base &= ~7;
} }
work->base = base; 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); dev->driver->get_vblank_counter(dev, work->crtc_id);
/* We borrow the event spin lock for protecting flip_work */ /* We borrow the event spin lock for protecting flip_work */

View file

@ -1359,7 +1359,7 @@ static u32 tegra_dc_get_vblank_counter(struct drm_crtc *crtc)
return host1x_syncpt_read(dc->syncpt); return host1x_syncpt_read(dc->syncpt);
/* fallback to software emulated VBLANK counter */ /* 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) static int tegra_dc_enable_vblank(struct drm_crtc *crtc)

View file

@ -154,7 +154,7 @@ struct __drm_crtcs_state {
struct drm_crtc *ptr; struct drm_crtc *ptr;
struct drm_crtc_state *state, *old_state, *new_state; struct drm_crtc_state *state, *old_state, *new_state;
s32 __user *out_fence_ptr; s32 __user *out_fence_ptr;
unsigned last_vblank_count; u64 last_vblank_count;
}; };
struct __drm_connnectors_state { struct __drm_connnectors_state {

View file

@ -115,21 +115,6 @@ struct drm_gem_object {
*/ */
int name; int name;
/**
* @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.
*/
uint32_t read_domains;
/**
* @write_domain: Corresponding unique write memory domain.
*/
uint32_t write_domain;
/** /**
* @dma_buf: * @dma_buf:
* *

View file

@ -195,7 +195,9 @@ void drm_crtc_wait_one_vblank(struct drm_crtc *crtc);
void drm_crtc_vblank_off(struct drm_crtc *crtc); void drm_crtc_vblank_off(struct drm_crtc *crtc);
void drm_crtc_vblank_reset(struct drm_crtc *crtc); void drm_crtc_vblank_reset(struct drm_crtc *crtc);
void drm_crtc_vblank_on(struct drm_crtc *crtc); void drm_crtc_vblank_on(struct drm_crtc *crtc);
u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc);
void drm_vblank_restore(struct drm_device *dev, unsigned int pipe);
void drm_crtc_vblank_restore(struct drm_crtc *crtc);
bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
unsigned int pipe, int *max_error, unsigned int pipe, int *max_error,

View file

@ -416,18 +416,19 @@
/* CNL */ /* CNL */
#define INTEL_CNL_IDS(info) \ #define INTEL_CNL_IDS(info) \
INTEL_VGA_DEVICE(0x5A52, info), \
INTEL_VGA_DEVICE(0x5A5A, info), \
INTEL_VGA_DEVICE(0x5A42, info), \
INTEL_VGA_DEVICE(0x5A4A, info), \
INTEL_VGA_DEVICE(0x5A51, info), \ INTEL_VGA_DEVICE(0x5A51, info), \
INTEL_VGA_DEVICE(0x5A59, info), \ INTEL_VGA_DEVICE(0x5A59, info), \
INTEL_VGA_DEVICE(0x5A41, info), \ INTEL_VGA_DEVICE(0x5A41, info), \
INTEL_VGA_DEVICE(0x5A49, info), \ INTEL_VGA_DEVICE(0x5A49, info), \
INTEL_VGA_DEVICE(0x5A71, info), \ INTEL_VGA_DEVICE(0x5A52, info), \
INTEL_VGA_DEVICE(0x5A79, info), \ INTEL_VGA_DEVICE(0x5A5A, info), \
INTEL_VGA_DEVICE(0x5A42, info), \
INTEL_VGA_DEVICE(0x5A4A, info), \
INTEL_VGA_DEVICE(0x5A50, info), \
INTEL_VGA_DEVICE(0x5A40, info), \
INTEL_VGA_DEVICE(0x5A54, info), \ INTEL_VGA_DEVICE(0x5A54, info), \
INTEL_VGA_DEVICE(0x5A5C, info), \ INTEL_VGA_DEVICE(0x5A5C, info), \
INTEL_VGA_DEVICE(0x5A44, info) INTEL_VGA_DEVICE(0x5A44, info), \
INTEL_VGA_DEVICE(0x5A4C, info)
#endif /* _I915_PCIIDS_H */ #endif /* _I915_PCIIDS_H */