Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f0308d76 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-next-2018-02-07' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

UAPI Changes:

- Userspace whitelist register GEN9_SLICE_COMMON_ECO_CHICKEN1 for GLK (Kenneth)
- Non-existent PMU counters are not placed to sysfs (Tvrtko)
- Add a note to deprecate I915_SET_COLORKEY_NONE and ignore it (Ville)
	* Intel DDX never ended using it, and implementation was wonky

Core Changes:

- Moved away from struct timeval into ktime_t in prep for 2038 (Arnd)
	* Merged the i915 portion through drm-tip, no core dependencies

Driver Changes:

- Base support for Icelake and Icelake PCH (Anusha, Rodrigo, Mahesh, Paulo, James, Kelvin)
- Add AUX-F port support for Cannonlake (Rodrigo)
- New DMC firmware for 1.07 Cannonlake (Anusha)
	* Go to linux-firmware.git to get it
- Reject non-cursor planes nearly (3 px) out of screen on GLK/CNL (Imre)
- Y/Yf modifiers restored for SKL+ sprites (Ville)
- Compressed framebuffer support for sprites (Ville)
- Tune down overly aggressive shrinking (Chris)
- Shrink kmem caches when GPU is idle (Chris)
- EDID bit-banging fallback for HDMI EDID (Stefan)
- Don't boost the GPU when the waited request is already running (Chris)
- Avoid GLK/BXT CDCLK frequency locking timeouts (Imre)
- Limit DP link rate according to VBT on CNL+ (Jani)
- Skip post-reset request emission if the engine is not idle (Chris)
- Report any link training error on a fixed eDP panel as errors (Manasi)
- DSI panel fixes for Bay Trail (Hans)
- Selftest additions and improvements (Chris, Matt)
- DMA fence test additions and accompanying fixes (Chris)
- Power domain vs. register access fix (Maarten)
- Squelch warnings for people with teensy framebuffers (stride < 512) (Maarten)
- Increase Render/Media power gating hysteresis for Gen9+ (Chris)
- HDMI vswing display workaround for Gen9+ (Ville)
- GuC code cleanup and lockdep fixes (Sagar, Michal Wa.)
- Continuously run hangcheck for simplicity (Chris)
- Execlist debugging improvements (Chris)
- GuC debugging improvements (Sujaritha, Michal Wa., Sagar)
- Command parser boundary checks (Michal Srb)
- Add a workaround for 3DSTATE_SAMPLE_PATTERN on CNL (Rafael)
- Fix PMU enabling race condition (Tvrtko)
- Usual smaller testing and debugging improvements

* tag 'drm-intel-next-2018-02-07' of git://anongit.freedesktop.org/drm/drm-intel: (158 commits)
  drm/i915: Update DRIVER_DATE to 20180207
  drm/i915/pmu: Fix PMU enable vs execlists tasklet race
  drm/i915/cnl: WaPipeControlBefore3DStateSamplePattern
  drm/i915/cmdparser: Do not check past the cmd length.
  drm/i915/cmdparser: Check reg_table_count before derefencing.
  drm/i915: Deprecate I915_SET_COLORKEY_NONE
  drm/i915: Skip post-reset request emission if the engine is not idle
  drm/i915/execlists: Move the reset bits to a more natural home
  drm/i915/selftests: Use a sacrificial context for hang testing
  drm/i915/selftests: Flush old resets between engines
  drm/i915/breadcrumbs: Drop request reference for the signaler thread
  drm/i915: Remove unbannable context spam from reset
  drm/i915/execlists: Remove the startup spam
  drm/i915: Show the GPU state when declaring wedged
  drm/i915: Always update the no_fbc_reason when disabling
  drm/i915: Add some newlines to intel_engine_dump() headers
  drm/i915: Report if an unbannable context is involved in a GPU hang
  drm/i915: Remove spurious DRM_ERROR for cancelled interrupts
  drm/i915/execlists: Flush GTIIR on clearing CS interrupts during reset
  drm/i915: reduce indent in pch detection
  ...
parents 7928b2cb 2f2f2db8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ i915-y += i915_cmd_parser.o \
i915-y += intel_uc.o \
	  intel_uc_fw.o \
	  intel_guc.o \
	  intel_guc_ads.o \
	  intel_guc_ct.o \
	  intel_guc_fw.o \
	  intel_guc_log.o \
+62 −23
Original line number Diff line number Diff line
@@ -988,7 +988,10 @@ i915_next_seqno_set(void *data, u64 val)
	if (ret)
		return ret;

	intel_runtime_pm_get(dev_priv);
	ret = i915_gem_set_global_seqno(dev, val);
	intel_runtime_pm_put(dev_priv);

	mutex_unlock(&dev->struct_mutex);

	return ret;
@@ -2464,24 +2467,11 @@ static int i915_guc_log_control_get(void *data, u64 *val)
static int i915_guc_log_control_set(void *data, u64 val)
{
	struct drm_i915_private *dev_priv = data;
	int ret;

	if (!HAS_GUC(dev_priv))
		return -ENODEV;

	if (!dev_priv->guc.log.vma)
		return -EINVAL;

	ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex);
	if (ret)
		return ret;

	intel_runtime_pm_get(dev_priv);
	ret = i915_guc_log_control(dev_priv, val);
	intel_runtime_pm_put(dev_priv);

	mutex_unlock(&dev_priv->drm.struct_mutex);
	return ret;
	return intel_guc_log_control(&dev_priv->guc, val);
}

DEFINE_SIMPLE_ATTRIBUTE(i915_guc_log_control_fops,
@@ -2518,15 +2508,19 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
	u32 stat[3];
	enum pipe pipe;
	bool enabled = false;
	bool sink_support;

	if (!HAS_PSR(dev_priv))
		return -ENODEV;

	sink_support = dev_priv->psr.sink_support;
	seq_printf(m, "Sink_Support: %s\n", yesno(sink_support));
	if (!sink_support)
		return 0;

	intel_runtime_pm_get(dev_priv);

	mutex_lock(&dev_priv->psr.lock);
	seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
	seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv->psr.enabled));
	seq_printf(m, "Active: %s\n", yesno(dev_priv->psr.active));
	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
@@ -2584,9 +2578,9 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
		seq_printf(m, "Performance_Counter: %u\n", psrperf);
	}
	if (dev_priv->psr.psr2_support) {
		u32 psr2 = I915_READ(EDP_PSR2_STATUS_CTL);
		u32 psr2 = I915_READ(EDP_PSR2_STATUS);

		seq_printf(m, "EDP_PSR2_STATUS_CTL: %x [%s]\n",
		seq_printf(m, "EDP_PSR2_STATUS: %x [%s]\n",
			   psr2, psr2_live_status(psr2));
	}
	mutex_unlock(&dev_priv->psr.lock);
@@ -2710,7 +2704,8 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
	if (!HAS_RUNTIME_PM(dev_priv))
		seq_puts(m, "Runtime power management not supported\n");

	seq_printf(m, "GPU idle: %s\n", yesno(!dev_priv->gt.awake));
	seq_printf(m, "GPU idle: %s (epoch %u)\n",
		   yesno(!dev_priv->gt.awake), dev_priv->gt.epoch);
	seq_printf(m, "IRQs disabled: %s\n",
		   yesno(!intel_irqs_enabled(dev_priv)));
#ifdef CONFIG_PM
@@ -3143,8 +3138,8 @@ static int i915_engine_info(struct seq_file *m, void *unused)

	intel_runtime_pm_get(dev_priv);

	seq_printf(m, "GT awake? %s\n",
		   yesno(dev_priv->gt.awake));
	seq_printf(m, "GT awake? %s (epoch %u)\n",
		   yesno(dev_priv->gt.awake), dev_priv->gt.epoch);
	seq_printf(m, "Global active requests: %d\n",
		   dev_priv->gt.active_requests);
	seq_printf(m, "CS timestamp frequency: %u kHz\n",
@@ -3363,7 +3358,10 @@ static void drrs_status_per_crtc(struct seq_file *m,

		/* disable_drrs() will make drrs->dp NULL */
		if (!drrs->dp) {
			seq_puts(m, "Idleness DRRS: Disabled");
			seq_puts(m, "Idleness DRRS: Disabled\n");
			if (dev_priv->psr.enabled)
				seq_puts(m,
				"\tAs PSR is enabled, DRRS is not enabled\n");
			mutex_unlock(&drrs->mutex);
			return;
		}
@@ -4606,6 +4604,46 @@ static const struct file_operations i915_hpd_storm_ctl_fops = {
	.write = i915_hpd_storm_ctl_write
};

static int i915_drrs_ctl_set(void *data, u64 val)
{
	struct drm_i915_private *dev_priv = data;
	struct drm_device *dev = &dev_priv->drm;
	struct intel_crtc *intel_crtc;
	struct intel_encoder *encoder;
	struct intel_dp *intel_dp;

	if (INTEL_GEN(dev_priv) < 7)
		return -ENODEV;

	drm_modeset_lock_all(dev);
	for_each_intel_crtc(dev, intel_crtc) {
		if (!intel_crtc->base.state->active ||
					!intel_crtc->config->has_drrs)
			continue;

		for_each_encoder_on_crtc(dev, &intel_crtc->base, encoder) {
			if (encoder->type != INTEL_OUTPUT_EDP)
				continue;

			DRM_DEBUG_DRIVER("Manually %sabling DRRS. %llu\n",
						val ? "en" : "dis", val);

			intel_dp = enc_to_intel_dp(&encoder->base);
			if (val)
				intel_edp_drrs_enable(intel_dp,
							intel_crtc->config);
			else
				intel_edp_drrs_disable(intel_dp,
							intel_crtc->config);
		}
	}
	drm_modeset_unlock_all(dev);

	return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(i915_drrs_ctl_fops, NULL, i915_drrs_ctl_set, "%llu\n");

static const struct drm_info_list i915_debugfs_list[] = {
	{"i915_capabilities", i915_capabilities, 0},
	{"i915_gem_objects", i915_gem_object_info, 0},
@@ -4683,7 +4721,8 @@ static const struct i915_debugfs_files {
	{"i915_dp_test_active", &i915_displayport_test_active_fops},
	{"i915_guc_log_control", &i915_guc_log_control_fops},
	{"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops},
	{"i915_ipc_status", &i915_ipc_status_fops}
	{"i915_ipc_status", &i915_ipc_status_fops},
	{"i915_drrs_ctl", &i915_drrs_ctl_fops}
};

int i915_debugfs_register(struct drm_i915_private *dev_priv)
+112 −94
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@

static struct drm_driver driver;

#if IS_ENABLED(CONFIG_DRM_I915_DEBUG)
static unsigned int i915_load_fail_count;

bool __i915_inject_load_failure(const char *func, int line)
@@ -70,6 +71,7 @@ bool __i915_inject_load_failure(const char *func, int line)

	return false;
}
#endif

#define FDO_BUG_URL "https://bugs.freedesktop.org/enter_bug.cgi?product=DRI"
#define FDO_BUG_MSG "Please file a bug at " FDO_BUG_URL " against DRM/Intel " \
@@ -107,8 +109,12 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level,

static bool i915_error_injected(struct drm_i915_private *dev_priv)
{
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG)
	return i915_modparams.inject_load_failure &&
	       i915_load_fail_count == i915_modparams.inject_load_failure;
#else
	return false;
#endif
}

#define i915_load_error(dev_priv, fmt, ...)				     \
@@ -176,8 +182,12 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv)
	 * of only checking the first one.
	 */
	while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) {
		if (pch->vendor == PCI_VENDOR_ID_INTEL) {
			unsigned short id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
		unsigned short id;

		if (pch->vendor != PCI_VENDOR_ID_INTEL)
			continue;

		id = pch->device & INTEL_PCH_DEVICE_ID_MASK;

		dev_priv->pch_id = id;

@@ -252,6 +262,10 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv)
			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 &&
@@ -259,14 +273,13 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv)
			    PCI_SUBVENDOR_ID_REDHAT_QUMRANET &&
			    pch->subsystem_device ==
			    PCI_SUBDEVICE_ID_QEMU)) {
				dev_priv->pch_type =
					intel_virt_detect_pch(dev_priv);
			} else
			dev_priv->pch_type = intel_virt_detect_pch(dev_priv);
		} else {
			continue;
		}

		break;
	}
	}
	if (!pch)
		DRM_DEBUG_KMS("No PCH found.\n");

@@ -622,7 +635,7 @@ static void i915_gem_fini(struct drm_i915_private *dev_priv)
	i915_gem_contexts_fini(dev_priv);
	mutex_unlock(&dev_priv->drm.struct_mutex);

	intel_uc_fini_wq(dev_priv);
	intel_uc_fini_misc(dev_priv);
	i915_gem_cleanup_userptr(dev_priv);

	i915_gem_drain_freed_objects(dev_priv);
@@ -2596,6 +2609,11 @@ static int intel_runtime_suspend(struct device *kdev)

		intel_runtime_pm_enable_interrupts(dev_priv);

		intel_guc_resume(dev_priv);

		i915_gem_init_swizzling(dev_priv);
		i915_gem_restore_fences(dev_priv);

		enable_rpm_wakeref_asserts(dev_priv);

		return ret;
@@ -2661,8 +2679,6 @@ static int intel_runtime_resume(struct device *kdev)
	if (intel_uncore_unclaimed_mmio(dev_priv))
		DRM_DEBUG_DRIVER("Unclaimed access during suspend, bios?\n");

	intel_guc_resume(dev_priv);

	if (IS_GEN9_LP(dev_priv)) {
		bxt_disable_dc9(dev_priv);
		bxt_display_core_init(dev_priv, true);
@@ -2677,6 +2693,10 @@ static int intel_runtime_resume(struct device *kdev)

	intel_uncore_runtime_resume(dev_priv);

	intel_runtime_pm_enable_interrupts(dev_priv);

	intel_guc_resume(dev_priv);

	/*
	 * No point of rolling back things in case of an error, as the best
	 * we can do is to hope that things will still work (and disable RPM).
@@ -2684,8 +2704,6 @@ static int intel_runtime_resume(struct device *kdev)
	i915_gem_init_swizzling(dev_priv);
	i915_gem_restore_fences(dev_priv);

	intel_runtime_pm_enable_interrupts(dev_priv);

	/*
	 * On VLV/CHV display interrupts are part of the display
	 * power well, so hpd is reinitialized from there. For
+37 −19
Original line number Diff line number Diff line
@@ -83,8 +83,8 @@

#define DRIVER_NAME		"i915"
#define DRIVER_DESC		"Intel Graphics"
#define DRIVER_DATE		"20171222"
#define DRIVER_TIMESTAMP	1513971710
#define DRIVER_DATE		"20180207"
#define DRIVER_TIMESTAMP	1517988364

/* 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
@@ -104,9 +104,13 @@
#define I915_STATE_WARN_ON(x)						\
	I915_STATE_WARN((x), "%s", "WARN_ON(" __stringify(x) ")")

#if IS_ENABLED(CONFIG_DRM_I915_DEBUG)
bool __i915_inject_load_failure(const char *func, int line);
#define i915_inject_load_failure() \
	__i915_inject_load_failure(__func__, __LINE__)
#else
#define i915_inject_load_failure() false
#endif

typedef struct {
	uint32_t val;
@@ -453,9 +457,9 @@ struct intel_display_error_state;

struct i915_gpu_state {
	struct kref ref;
	struct timeval time;
	struct timeval boottime;
	struct timeval uptime;
	ktime_t time;
	ktime_t boottime;
	ktime_t uptime;

	struct drm_i915_private *i915;

@@ -551,6 +555,7 @@ struct i915_gpu_state {
			int ban_score;
			int active;
			int guilty;
			bool bannable;
		} context;

		struct drm_i915_error_object {
@@ -754,7 +759,6 @@ struct i915_drrs {
struct i915_psr {
	struct mutex lock;
	bool sink_support;
	bool source_ok;
	struct intel_dp *enabled;
	bool active;
	struct delayed_work work;
@@ -783,6 +787,7 @@ enum intel_pch {
	PCH_SPT,        /* Sunrisepoint PCH */
	PCH_KBP,        /* Kaby Lake PCH */
	PCH_CNP,        /* Cannon Lake PCH */
	PCH_ICP,	/* Ice Lake PCH */
	PCH_NOP,
};

@@ -1255,6 +1260,7 @@ enum modeset_restore {
#define DP_AUX_B 0x10
#define DP_AUX_C 0x20
#define DP_AUX_D 0x30
#define DP_AUX_F 0x60

#define DDC_PIN_B  0x05
#define DDC_PIN_C  0x04
@@ -1281,6 +1287,7 @@ struct ddi_vbt_port_info {

	uint8_t dp_boost_level;
	uint8_t hdmi_boost_level;
	int dp_max_link_rate;		/* 0 for not limited by VBT */
};

enum psr_lines_to_wait {
@@ -1460,6 +1467,7 @@ struct skl_wm_params {
	uint_fixed_16_16_t plane_blocks_per_line;
	uint_fixed_16_16_t y_tile_minimum;
	uint32_t linetime_us;
	uint32_t dbuf_block_size;
};

/*
@@ -1792,7 +1800,7 @@ struct i915_oa_ops {
};

struct intel_cdclk_state {
	unsigned int cdclk, vco, ref;
	unsigned int cdclk, vco, ref, bypass;
	u8 voltage_level;
};

@@ -2312,6 +2320,12 @@ struct drm_i915_private {
		 */
		bool awake;

		/**
		 * The number of times we have woken up.
		 */
		unsigned int epoch;
#define I915_EPOCH_INVALID 0

		/**
		 * We leave the user IRQ off as much as possible,
		 * but this means that requests will finish and never
@@ -2404,16 +2418,11 @@ enum hdmi_force_audio {
 *
 * We have one bit per pipe and per scanout plane type.
 */
#define INTEL_MAX_SPRITE_BITS_PER_PIPE 5
#define INTEL_FRONTBUFFER_BITS_PER_PIPE 8
#define INTEL_FRONTBUFFER_PRIMARY(pipe) \
	(1 << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))
#define INTEL_FRONTBUFFER_CURSOR(pipe) \
	(1 << (1 + (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
#define INTEL_FRONTBUFFER_SPRITE(pipe, plane) \
	(1 << (2 + plane + (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
#define INTEL_FRONTBUFFER(pipe, plane_id) \
	(1 << ((plane_id) + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))
#define INTEL_FRONTBUFFER_OVERLAY(pipe) \
	(1 << (2 + INTEL_MAX_SPRITE_BITS_PER_PIPE + (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
	(1 << (INTEL_FRONTBUFFER_BITS_PER_PIPE - 1 + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))
#define INTEL_FRONTBUFFER_ALL_MASK(pipe) \
	(0xff << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))

@@ -2595,6 +2604,7 @@ intel_info(const struct drm_i915_private *dev_priv)
#define IS_GEMINILAKE(dev_priv)	IS_PLATFORM(dev_priv, INTEL_GEMINILAKE)
#define IS_COFFEELAKE(dev_priv)	IS_PLATFORM(dev_priv, INTEL_COFFEELAKE)
#define IS_CANNONLAKE(dev_priv)	IS_PLATFORM(dev_priv, INTEL_CANNONLAKE)
#define IS_ICELAKE(dev_priv)	IS_PLATFORM(dev_priv, INTEL_ICELAKE)
#define IS_MOBILE(dev_priv)	((dev_priv)->info.is_mobile)
#define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \
				    (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0C00)
@@ -2646,6 +2656,8 @@ intel_info(const struct drm_i915_private *dev_priv)
				 (dev_priv)->info.gt == 2)
#define IS_CFL_GT3(dev_priv)	(IS_COFFEELAKE(dev_priv) && \
				 (dev_priv)->info.gt == 3)
#define IS_CNL_WITH_PORT_F(dev_priv)   (IS_CANNONLAKE(dev_priv) && \
					(INTEL_DEVID(dev_priv) & 0x0004) == 0x0004)

#define IS_ALPHA_SUPPORT(intel_info) ((intel_info)->is_alpha_support)

@@ -2706,6 +2718,7 @@ intel_info(const struct drm_i915_private *dev_priv)
#define IS_GEN8(dev_priv)	(!!((dev_priv)->info.gen_mask & BIT(7)))
#define IS_GEN9(dev_priv)	(!!((dev_priv)->info.gen_mask & BIT(8)))
#define IS_GEN10(dev_priv)	(!!((dev_priv)->info.gen_mask & BIT(9)))
#define IS_GEN11(dev_priv)	(!!((dev_priv)->info.gen_mask & BIT(10)))

#define IS_LP(dev_priv)	(INTEL_INFO(dev_priv)->is_lp)
#define IS_GEN9_LP(dev_priv)	(IS_GEN9(dev_priv) && IS_LP(dev_priv))
@@ -2843,11 +2856,13 @@ intel_info(const struct drm_i915_private *dev_priv)
#define INTEL_PCH_KBP_DEVICE_ID_TYPE		0xA280
#define INTEL_PCH_CNP_DEVICE_ID_TYPE		0xA300
#define INTEL_PCH_CNP_LP_DEVICE_ID_TYPE		0x9D80
#define INTEL_PCH_ICP_DEVICE_ID_TYPE		0x3480
#define INTEL_PCH_P2X_DEVICE_ID_TYPE		0x7100
#define INTEL_PCH_P3X_DEVICE_ID_TYPE		0x7000
#define INTEL_PCH_QEMU_DEVICE_ID_TYPE		0x2900 /* qemu q35 has 2918 */

#define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type)
#define HAS_PCH_ICP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ICP)
#define HAS_PCH_CNP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CNP)
#define HAS_PCH_CNP_LP(dev_priv) \
	((dev_priv)->pch_id == INTEL_PCH_CNP_LP_DEVICE_ID_TYPE)
@@ -2950,8 +2965,10 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
void intel_hpd_init(struct drm_i915_private *dev_priv);
void intel_hpd_init_work(struct drm_i915_private *dev_priv);
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
enum port intel_hpd_pin_to_port(enum hpd_pin pin);
enum hpd_pin intel_hpd_pin(enum port port);
enum port intel_hpd_pin_to_port(struct drm_i915_private *dev_priv,
				enum hpd_pin pin);
enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv,
				   enum port port);
bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin);
void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin);

@@ -3718,9 +3735,10 @@ extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e,

int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val);
int sandybridge_pcode_write_timeout(struct drm_i915_private *dev_priv, u32 mbox,
				    u32 val, int timeout_us);
				    u32 val, int fast_timeout_us,
				    int slow_timeout_ms);
#define sandybridge_pcode_write(dev_priv, mbox, val)	\
	sandybridge_pcode_write_timeout(dev_priv, mbox, val, 500)
	sandybridge_pcode_write_timeout(dev_priv, mbox, val, 500, 0)

int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request,
		      u32 reply_mask, u32 reply, int timeout_base_ms);
+118 −27
Original line number Diff line number Diff line
@@ -369,7 +369,8 @@ i915_gem_object_wait_fence(struct dma_fence *fence,
	if (i915_gem_request_completed(rq))
		goto out;

	/* This client is about to stall waiting for the GPU. In many cases
	/*
	 * This client is about to stall waiting for the GPU. In many cases
	 * this is undesirable and limits the throughput of the system, as
	 * many clients cannot continue processing user input/output whilst
	 * blocked. RPS autotuning may take tens of milliseconds to respond
@@ -384,11 +385,9 @@ i915_gem_object_wait_fence(struct dma_fence *fence,
	 * forcing the clocks too high for the whole system, we only allow
	 * each client to waitboost once in a busy period.
	 */
	if (rps_client) {
	if (rps_client && !i915_gem_request_started(rq)) {
		if (INTEL_GEN(rq->i915) >= 6)
			gen6_rps_boost(rq, rps_client);
		else
			rps_client = NULL;
	}

	timeout = i915_wait_request(rq, flags, timeout);
@@ -2824,24 +2823,23 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj,
	return 0;
}

static bool ban_context(const struct i915_gem_context *ctx,
			unsigned int score)
{
	return (i915_gem_context_is_bannable(ctx) &&
		score >= CONTEXT_SCORE_BAN_THRESHOLD);
}

static void i915_gem_context_mark_guilty(struct i915_gem_context *ctx)
{
	unsigned int score;
	bool banned;

	atomic_inc(&ctx->guilty_count);

	score = atomic_add_return(CONTEXT_SCORE_GUILTY, &ctx->ban_score);
	banned = ban_context(ctx, score);
	banned = false;
	if (i915_gem_context_is_bannable(ctx)) {
		unsigned int score;

		score = atomic_add_return(CONTEXT_SCORE_GUILTY,
					  &ctx->ban_score);
		banned = score >= CONTEXT_SCORE_BAN_THRESHOLD;

		DRM_DEBUG_DRIVER("context %s marked guilty (score %d) banned? %s\n",
				 ctx->name, score, yesno(banned));
	}
	if (!banned)
		return;

@@ -3135,7 +3133,7 @@ void i915_gem_reset(struct drm_i915_private *dev_priv)
		 * an incoherent read by the CS (presumably stale TLB). An
		 * empty request appears sufficient to paper over the glitch.
		 */
		if (list_empty(&engine->timeline->requests)) {
		if (intel_engine_is_idle(engine)) {
			struct drm_i915_gem_request *rq;

			rq = i915_gem_request_alloc(engine,
@@ -3200,6 +3198,13 @@ void i915_gem_set_wedged(struct drm_i915_private *i915)
	struct intel_engine_cs *engine;
	enum intel_engine_id id;

	if (drm_debug & DRM_UT_DRIVER) {
		struct drm_printer p = drm_debug_printer(__func__);

		for_each_engine(engine, i915, id)
			intel_engine_dump(engine, &p, "%s\n", engine->name);
	}

	/*
	 * First, stop submission to hw, but do not yet complete requests by
	 * rolling the global seqno forward (since this would complete requests
@@ -3334,6 +3339,65 @@ i915_gem_retire_work_handler(struct work_struct *work)
				   round_jiffies_up_relative(HZ));
}

static void shrink_caches(struct drm_i915_private *i915)
{
	/*
	 * kmem_cache_shrink() discards empty slabs and reorders partially
	 * filled slabs to prioritise allocating from the mostly full slabs,
	 * with the aim of reducing fragmentation.
	 */
	kmem_cache_shrink(i915->priorities);
	kmem_cache_shrink(i915->dependencies);
	kmem_cache_shrink(i915->requests);
	kmem_cache_shrink(i915->luts);
	kmem_cache_shrink(i915->vmas);
	kmem_cache_shrink(i915->objects);
}

struct sleep_rcu_work {
	union {
		struct rcu_head rcu;
		struct work_struct work;
	};
	struct drm_i915_private *i915;
	unsigned int epoch;
};

static inline bool
same_epoch(struct drm_i915_private *i915, unsigned int epoch)
{
	/*
	 * There is a small chance that the epoch wrapped since we started
	 * sleeping. If we assume that epoch is at least a u32, then it will
	 * take at least 2^32 * 100ms for it to wrap, or about 326 years.
	 */
	return epoch == READ_ONCE(i915->gt.epoch);
}

static void __sleep_work(struct work_struct *work)
{
	struct sleep_rcu_work *s = container_of(work, typeof(*s), work);
	struct drm_i915_private *i915 = s->i915;
	unsigned int epoch = s->epoch;

	kfree(s);
	if (same_epoch(i915, epoch))
		shrink_caches(i915);
}

static void __sleep_rcu(struct rcu_head *rcu)
{
	struct sleep_rcu_work *s = container_of(rcu, typeof(*s), rcu);
	struct drm_i915_private *i915 = s->i915;

	if (same_epoch(i915, s->epoch)) {
		INIT_WORK(&s->work, __sleep_work);
		queue_work(i915->wq, &s->work);
	} else {
		kfree(s);
	}
}

static inline bool
new_requests_since_last_retire(const struct drm_i915_private *i915)
{
@@ -3346,6 +3410,7 @@ i915_gem_idle_work_handler(struct work_struct *work)
{
	struct drm_i915_private *dev_priv =
		container_of(work, typeof(*dev_priv), gt.idle_work.work);
	unsigned int epoch = I915_EPOCH_INVALID;
	bool rearm_hangcheck;
	ktime_t end;

@@ -3405,6 +3470,8 @@ i915_gem_idle_work_handler(struct work_struct *work)

	GEM_BUG_ON(!dev_priv->gt.awake);
	dev_priv->gt.awake = false;
	epoch = dev_priv->gt.epoch;
	GEM_BUG_ON(epoch == I915_EPOCH_INVALID);
	rearm_hangcheck = false;

	if (INTEL_GEN(dev_priv) >= 6)
@@ -3421,6 +3488,23 @@ i915_gem_idle_work_handler(struct work_struct *work)
		GEM_BUG_ON(!dev_priv->gt.awake);
		i915_queue_hangcheck(dev_priv);
	}

	/*
	 * When we are idle, it is an opportune time to reap our caches.
	 * However, we have many objects that utilise RCU and the ordered
	 * i915->wq that this work is executing on. To try and flush any
	 * pending frees now we are idle, we first wait for an RCU grace
	 * period, and then queue a task (that will run last on the wq) to
	 * shrink and re-optimize the caches.
	 */
	if (same_epoch(dev_priv, epoch)) {
		struct sleep_rcu_work *s = kmalloc(sizeof(*s), GFP_KERNEL);
		if (s) {
			s->i915 = dev_priv;
			s->epoch = epoch;
			call_rcu(&s->rcu, __sleep_rcu);
		}
	}
}

void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file)
@@ -3566,7 +3650,7 @@ static int wait_for_engines(struct drm_i915_private *i915)

			for_each_engine(engine, i915, id)
				intel_engine_dump(engine, &p,
						  "%s", engine->name);
						  "%s\n", engine->name);
		}

		i915_gem_set_wedged(i915);
@@ -4698,7 +4782,8 @@ static void __i915_gem_free_work(struct work_struct *work)
		container_of(work, struct drm_i915_private, mm.free_work);
	struct llist_node *freed;

	/* All file-owned VMA should have been released by this point through
	/*
	 * All file-owned VMA should have been released by this point through
	 * i915_gem_close_object(), or earlier by i915_gem_context_close().
	 * However, the object may also be bound into the global GTT (e.g.
	 * older GPUs without per-process support, or for direct access through
@@ -4725,13 +4810,18 @@ static void __i915_gem_free_object_rcu(struct rcu_head *head)
		container_of(head, typeof(*obj), rcu);
	struct drm_i915_private *i915 = to_i915(obj->base.dev);

	/* We can't simply use call_rcu() from i915_gem_free_object()
	 * as we need to block whilst unbinding, and the call_rcu
	 * task may be called from softirq context. So we take a
	 * detour through a worker.
	/*
	 * Since we require blocking on struct_mutex to unbind the freed
	 * object from the GPU before releasing resources back to the
	 * system, we can not do that directly from the RCU callback (which may
	 * be a softirq context), but must instead then defer that work onto a
	 * kthread. We use the RCU callback rather than move the freed object
	 * directly onto the work queue so that we can mix between using the
	 * worker and performing frees directly from subsequent allocations for
	 * crude but effective memory throttling.
	 */
	if (llist_add(&obj->freed, &i915->mm.free_list))
		schedule_work(&i915->mm.free_work);
		queue_work(i915->wq, &i915->mm.free_work);
}

void i915_gem_free_object(struct drm_gem_object *gem_obj)
@@ -4744,7 +4834,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
	if (discard_backing_storage(obj))
		obj->mm.madv = I915_MADV_DONTNEED;

	/* Before we free the object, make sure any pure RCU-only
	/*
	 * Before we free the object, make sure any pure RCU-only
	 * read-side critical sections are complete, e.g.
	 * i915_gem_busy_ioctl(). For the corresponding synchronized
	 * lookup see i915_gem_object_lookup_rcu().
@@ -5186,7 +5277,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
	if (ret)
		return ret;

	ret = intel_uc_init_wq(dev_priv);
	ret = intel_uc_init_misc(dev_priv);
	if (ret)
		return ret;

@@ -5282,7 +5373,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
	mutex_unlock(&dev_priv->drm.struct_mutex);

	intel_uc_fini_wq(dev_priv);
	intel_uc_fini_misc(dev_priv);

	if (ret != -EIO)
		i915_gem_cleanup_userptr(dev_priv);
Loading