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

Commit 36a5fdf7 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-next-2017-10-23' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

This time really the last i915 batch for v4.15:

- PSR state tracking in crtc state (Ville)
- Fix eviction when the GGTT is idle but full (Chris)
- BDW DP aux channel timeout fix (James)
- LSPCON detection fixes (Shashank)
- Use for_each_pipe to iterate over pipes (Mika Kahola)
- Replace *_reference/unreference() or *_ref/unref with _get/put() (Harsha)
- Refactoring and preparation for DDI encoder type cleanup (Ville)
- Broadwell DDI FDI buf translation fix (Chris)
- Read CSB and CSB write pointer from HWSP in GVT-g VM if available (Weinan)
- GuC/HuC firmware loader refactoring (Michal)
- Make shrinking more effective and not stall so much (Chris)
- Cannonlake PLL fixes (Rodrigo)
- DP MST connector error propagation fixes (James)
- Convert timers to use timer_setup (Kees Cook)
- Skylake plane enable/disable unification (Juha-Pekka)
- Fix to actually free driver internal objects when requested (Chris)
- DDI buf trans refactoring (Ville)
- Skip waking the device to service pwrite (Chris)
- Improve DSI VBT backlight parsing abstraction (Madhav)
- Cannonlake VBT DDC pin mapping fix (Rodrigo)

* tag 'drm-intel-next-2017-10-23' of git://anongit.freedesktop.org/drm/drm-intel: (87 commits)
  drm/i915: Update DRIVER_DATE to 20171023
  drm/i915/cnl: Map VBT DDC Pin to BSpec DDC Pin.
  drm/i915: Let's use more enum intel_dpll_id pll_id.
  drm/i915: Use existing DSI backlight ports info
  drm/i915: Parse DSI backlight/cabc ports.
  drm/i915: Skip waking the device to service pwrite
  drm/i915/crt: split compute_config hook by platforms
  drm/i915: remove g4x lowfreq_avail and has_pipe_cxsr
  drm/i915: Drop the redundant hdmi prefix/suffix from a lot of variables
  drm/i915: Unify error handling for missing DDI buf trans tables
  drm/i915: Centralize the SKL DDI A/E vs. B/C/D buf trans handling
  drm/i915: Kill off the BXT buf_trans default_index
  drm/i915: Pass encoder type to cnl_ddi_vswing_sequence() explicitly
  drm/i915: Integrate BXT into intel_ddi_dp_voltage_max()
  drm/i915: Pass the level to intel_prepare_hdmi_ddi_buffers()
  drm/i915: Pass the encoder type explicitly to skl_set_iboost()
  drm/i915: Extract intel_ddi_get_buf_trans_hdmi()
  drm/i915: Relocate intel_ddi_get_buf_trans_*() functions
  drm/i915: Flush the idle-worker for debugfs/i915_drop_caches
  drm/i915: adjust get_crtc_fence_y_offset() to use base.y instead of crtc.y
  ...
parents bf6eb600 cdc1cdca
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -410,6 +410,7 @@ int drm_lspcon_get_mode(struct i2c_adapter *adapter,
{
	u8 data;
	int ret = 0;
	int retry;

	if (!mode) {
		DRM_ERROR("NULL input\n");
@@ -417,10 +418,19 @@ int drm_lspcon_get_mode(struct i2c_adapter *adapter,
	}

	/* Read Status: i2c over aux */
	ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_LSPCON_CURRENT_MODE,
	for (retry = 0; retry < 6; retry++) {
		if (retry)
			usleep_range(500, 1000);

		ret = drm_dp_dual_mode_read(adapter,
					    DP_DUAL_MODE_LSPCON_CURRENT_MODE,
					    &data, sizeof(data));
		if (!ret)
			break;
	}

	if (ret < 0) {
		DRM_ERROR("LSPCON read(0x80, 0x41) failed\n");
		DRM_DEBUG_KMS("LSPCON read(0x80, 0x41) failed\n");
		return -EFAULT;
	}

+1 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ i915-y += intel_uc.o \
	  intel_guc.o \
	  intel_guc_ct.o \
	  intel_guc_log.o \
	  intel_guc_loader.o \
	  intel_guc_fw.o \
	  intel_huc.o \
	  i915_guc_submission.o

+67 −108
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@ static char get_active_flag(struct drm_i915_gem_object *obj)

static char get_pin_flag(struct drm_i915_gem_object *obj)
{
	return obj->pin_display ? 'p' : ' ';
	return obj->pin_global ? 'p' : ' ';
}

static char get_tiling_flag(struct drm_i915_gem_object *obj)
@@ -180,8 +180,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
			pin_count++;
	}
	seq_printf(m, " (pinned x %d)", pin_count);
	if (obj->pin_display)
		seq_printf(m, " (display)");
	if (obj->pin_global)
		seq_printf(m, " (global)");
	list_for_each_entry(vma, &obj->vma_list, obj_link) {
		if (!drm_mm_node_allocated(&vma->node))
			continue;
@@ -271,7 +271,9 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
		goto out;

	total_obj_size = total_gtt_size = count = 0;
	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {

	spin_lock(&dev_priv->mm.obj_lock);
	list_for_each_entry(obj, &dev_priv->mm.bound_list, mm.link) {
		if (count == total)
			break;

@@ -283,7 +285,7 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
		total_gtt_size += i915_gem_obj_total_ggtt_size(obj);

	}
	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) {
	list_for_each_entry(obj, &dev_priv->mm.unbound_list, mm.link) {
		if (count == total)
			break;

@@ -293,6 +295,7 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
		objects[count++] = obj;
		total_obj_size += obj->base.size;
	}
	spin_unlock(&dev_priv->mm.obj_lock);

	sort(objects, count, sizeof(*objects), obj_rank_by_stolen, NULL);

@@ -454,7 +457,9 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
	mapped_size = mapped_count = 0;
	purgeable_size = purgeable_count = 0;
	huge_size = huge_count = 0;
	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) {

	spin_lock(&dev_priv->mm.obj_lock);
	list_for_each_entry(obj, &dev_priv->mm.unbound_list, mm.link) {
		size += obj->base.size;
		++count;

@@ -477,11 +482,11 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
	seq_printf(m, "%u unbound objects, %llu bytes\n", count, size);

	size = count = dpy_size = dpy_count = 0;
	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {
	list_for_each_entry(obj, &dev_priv->mm.bound_list, mm.link) {
		size += obj->base.size;
		++count;

		if (obj->pin_display) {
		if (obj->pin_global) {
			dpy_size += obj->base.size;
			++dpy_count;
		}
@@ -502,6 +507,8 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
			page_sizes |= obj->mm.page_sizes.sg;
		}
	}
	spin_unlock(&dev_priv->mm.obj_lock);

	seq_printf(m, "%u bound objects, %llu bytes\n",
		   count, size);
	seq_printf(m, "%u purgeable objects, %llu bytes\n",
@@ -512,7 +519,7 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
		   huge_count,
		   stringify_page_sizes(page_sizes, buf, sizeof(buf)),
		   huge_size);
	seq_printf(m, "%u display objects (pinned), %llu bytes\n",
	seq_printf(m, "%u display objects (globally pinned), %llu bytes\n",
		   dpy_count, dpy_size);

	seq_printf(m, "%llu [%llu] gtt total\n",
@@ -568,32 +575,46 @@ static int i915_gem_gtt_info(struct seq_file *m, void *data)
	struct drm_info_node *node = m->private;
	struct drm_i915_private *dev_priv = node_to_i915(node);
	struct drm_device *dev = &dev_priv->drm;
	bool show_pin_display_only = !!node->info_ent->data;
	struct drm_i915_gem_object **objects;
	struct drm_i915_gem_object *obj;
	u64 total_obj_size, total_gtt_size;
	unsigned long nobject, n;
	int count, ret;

	nobject = READ_ONCE(dev_priv->mm.object_count);
	objects = kvmalloc_array(nobject, sizeof(*objects), GFP_KERNEL);
	if (!objects)
		return -ENOMEM;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	total_obj_size = total_gtt_size = count = 0;
	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {
		if (show_pin_display_only && !obj->pin_display)
			continue;
	count = 0;
	spin_lock(&dev_priv->mm.obj_lock);
	list_for_each_entry(obj, &dev_priv->mm.bound_list, mm.link) {
		objects[count++] = obj;
		if (count == nobject)
			break;
	}
	spin_unlock(&dev_priv->mm.obj_lock);

	total_obj_size = total_gtt_size = 0;
	for (n = 0;  n < count; n++) {
		obj = objects[n];

		seq_puts(m, "   ");
		describe_obj(m, obj);
		seq_putc(m, '\n');
		total_obj_size += obj->base.size;
		total_gtt_size += i915_gem_obj_total_ggtt_size(obj);
		count++;
	}

	mutex_unlock(&dev->struct_mutex);

	seq_printf(m, "Total %d objects, %llu bytes, %llu GTT size\n",
		   count, total_obj_size, total_gtt_size);
	kvfree(objects);

	return 0;
}
@@ -643,54 +664,6 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data)
	return 0;
}

static void print_request(struct seq_file *m,
			  struct drm_i915_gem_request *rq,
			  const char *prefix)
{
	seq_printf(m, "%s%x [%x:%x] prio=%d @ %dms: %s\n", prefix,
		   rq->global_seqno, rq->ctx->hw_id, rq->fence.seqno,
		   rq->priotree.priority,
		   jiffies_to_msecs(jiffies - rq->emitted_jiffies),
		   rq->timeline->common->name);
}

static int i915_gem_request_info(struct seq_file *m, void *data)
{
	struct drm_i915_private *dev_priv = node_to_i915(m->private);
	struct drm_device *dev = &dev_priv->drm;
	struct drm_i915_gem_request *req;
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	int ret, any;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	any = 0;
	for_each_engine(engine, dev_priv, id) {
		int count;

		count = 0;
		list_for_each_entry(req, &engine->timeline->requests, link)
			count++;
		if (count == 0)
			continue;

		seq_printf(m, "%s requests: %d\n", engine->name, count);
		list_for_each_entry(req, &engine->timeline->requests, link)
			print_request(m, req, "    ");

		any++;
	}
	mutex_unlock(&dev->struct_mutex);

	if (any == 0)
		seq_puts(m, "No requests\n");

	return 0;
}

static void i915_ring_seqno_info(struct seq_file *m,
				 struct intel_engine_cs *engine)
{
@@ -2386,27 +2359,13 @@ static int i915_llc(struct seq_file *m, void *data)
static int i915_huc_load_status_info(struct seq_file *m, void *data)
{
	struct drm_i915_private *dev_priv = node_to_i915(m->private);
	struct intel_uc_fw *huc_fw = &dev_priv->huc.fw;
	struct drm_printer p;

	if (!HAS_HUC_UCODE(dev_priv))
		return 0;

	seq_puts(m, "HuC firmware status:\n");
	seq_printf(m, "\tpath: %s\n", huc_fw->path);
	seq_printf(m, "\tfetch: %s\n",
		intel_uc_fw_status_repr(huc_fw->fetch_status));
	seq_printf(m, "\tload: %s\n",
		intel_uc_fw_status_repr(huc_fw->load_status));
	seq_printf(m, "\tversion wanted: %d.%d\n",
		huc_fw->major_ver_wanted, huc_fw->minor_ver_wanted);
	seq_printf(m, "\tversion found: %d.%d\n",
		huc_fw->major_ver_found, huc_fw->minor_ver_found);
	seq_printf(m, "\theader: offset is %d; size = %d\n",
		huc_fw->header_offset, huc_fw->header_size);
	seq_printf(m, "\tuCode: offset is %d; size = %d\n",
		huc_fw->ucode_offset, huc_fw->ucode_size);
	seq_printf(m, "\tRSA: offset is %d; size = %d\n",
		huc_fw->rsa_offset, huc_fw->rsa_size);
	p = drm_seq_file_printer(m);
	intel_uc_fw_dump(&dev_priv->huc.fw, &p);

	intel_runtime_pm_get(dev_priv);
	seq_printf(m, "\nHuC status 0x%08x:\n", I915_READ(HUC_STATUS2));
@@ -2418,29 +2377,14 @@ static int i915_huc_load_status_info(struct seq_file *m, void *data)
static int i915_guc_load_status_info(struct seq_file *m, void *data)
{
	struct drm_i915_private *dev_priv = node_to_i915(m->private);
	struct intel_uc_fw *guc_fw = &dev_priv->guc.fw;
	struct drm_printer p;
	u32 tmp, i;

	if (!HAS_GUC_UCODE(dev_priv))
		return 0;

	seq_printf(m, "GuC firmware status:\n");
	seq_printf(m, "\tpath: %s\n",
		guc_fw->path);
	seq_printf(m, "\tfetch: %s\n",
		intel_uc_fw_status_repr(guc_fw->fetch_status));
	seq_printf(m, "\tload: %s\n",
		intel_uc_fw_status_repr(guc_fw->load_status));
	seq_printf(m, "\tversion wanted: %d.%d\n",
		guc_fw->major_ver_wanted, guc_fw->minor_ver_wanted);
	seq_printf(m, "\tversion found: %d.%d\n",
		guc_fw->major_ver_found, guc_fw->minor_ver_found);
	seq_printf(m, "\theader: offset is %d; size = %d\n",
		guc_fw->header_offset, guc_fw->header_size);
	seq_printf(m, "\tuCode: offset is %d; size = %d\n",
		guc_fw->ucode_offset, guc_fw->ucode_size);
	seq_printf(m, "\tRSA: offset is %d; size = %d\n",
		guc_fw->rsa_offset, guc_fw->rsa_size);
	p = drm_seq_file_printer(m);
	intel_uc_fw_dump(&dev_priv->guc.fw, &p);

	intel_runtime_pm_get(dev_priv);

@@ -3310,6 +3254,16 @@ static int i915_engine_info(struct seq_file *m, void *unused)
	return 0;
}

static int i915_shrinker_info(struct seq_file *m, void *unused)
{
	struct drm_i915_private *i915 = node_to_i915(m->private);

	seq_printf(m, "seeks = %d\n", i915->mm.shrinker.seeks);
	seq_printf(m, "batch = %lu\n", i915->mm.shrinker.batch);

	return 0;
}

static int i915_semaphore_status(struct seq_file *m, void *unused)
{
	struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -4225,18 +4179,20 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_ring_test_irq_fops,
			i915_ring_test_irq_get, i915_ring_test_irq_set,
			"0x%08llx\n");

#define DROP_UNBOUND 0x1
#define DROP_BOUND 0x2
#define DROP_RETIRE 0x4
#define DROP_ACTIVE 0x8
#define DROP_FREED 0x10
#define DROP_SHRINK_ALL 0x20
#define DROP_UNBOUND	BIT(0)
#define DROP_BOUND	BIT(1)
#define DROP_RETIRE	BIT(2)
#define DROP_ACTIVE	BIT(3)
#define DROP_FREED	BIT(4)
#define DROP_SHRINK_ALL	BIT(5)
#define DROP_IDLE	BIT(6)
#define DROP_ALL (DROP_UNBOUND	| \
		  DROP_BOUND	| \
		  DROP_RETIRE	| \
		  DROP_ACTIVE	| \
		  DROP_FREED	| \
		  DROP_SHRINK_ALL)
		  DROP_SHRINK_ALL |\
		  DROP_IDLE)
static int
i915_drop_caches_get(void *data, u64 *val)
{
@@ -4252,7 +4208,8 @@ i915_drop_caches_set(void *data, u64 val)
	struct drm_device *dev = &dev_priv->drm;
	int ret = 0;

	DRM_DEBUG("Dropping caches: 0x%08llx\n", val);
	DRM_DEBUG("Dropping caches: 0x%08llx [0x%08llx]\n",
		  val, val & DROP_ALL);

	/* No need to check and wait for gpu resets, only libdrm auto-restarts
	 * on ioctls on -EAGAIN. */
@@ -4283,6 +4240,9 @@ i915_drop_caches_set(void *data, u64 val)
		i915_gem_shrink_all(dev_priv);
	fs_reclaim_release(GFP_KERNEL);

	if (val & DROP_IDLE)
		drain_delayed_work(&dev_priv->gt.idle_work);

	if (val & DROP_FREED) {
		synchronize_rcu();
		i915_gem_drain_freed_objects(dev_priv);
@@ -4751,9 +4711,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
	{"i915_capabilities", i915_capabilities, 0},
	{"i915_gem_objects", i915_gem_object_info, 0},
	{"i915_gem_gtt", i915_gem_gtt_info, 0},
	{"i915_gem_pin_display", i915_gem_gtt_info, 0, (void *)1},
	{"i915_gem_stolen", i915_gem_stolen_list_info },
	{"i915_gem_request", i915_gem_request_info, 0},
	{"i915_gem_seqno", i915_gem_seqno_info, 0},
	{"i915_gem_fence_regs", i915_gem_fence_regs_info, 0},
	{"i915_gem_interrupt", i915_interrupt_info, 0},
@@ -4791,6 +4749,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
	{"i915_dmc_info", i915_dmc_info, 0},
	{"i915_display_info", i915_display_info, 0},
	{"i915_engine_info", i915_engine_info, 0},
	{"i915_shrinker_info", i915_shrinker_info, 0},
	{"i915_semaphore_status", i915_semaphore_status, 0},
	{"i915_shared_dplls_info", i915_shared_dplls_info, 0},
	{"i915_dp_mst_info", i915_dp_mst_info, 0},
+28 −13
Original line number Diff line number Diff line
@@ -80,8 +80,8 @@

#define DRIVER_NAME		"i915"
#define DRIVER_DESC		"Intel Graphics"
#define DRIVER_DATE		"20171012"
#define DRIVER_TIMESTAMP	1507831511
#define DRIVER_DATE		"20171023"
#define DRIVER_TIMESTAMP	1508748913

/* 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
@@ -785,7 +785,6 @@ struct intel_csr {
	func(has_logical_ring_contexts); \
	func(has_logical_ring_preemption); \
	func(has_overlay); \
	func(has_pipe_cxsr); \
	func(has_pooled_eu); \
	func(has_psr); \
	func(has_rc6); \
@@ -1108,6 +1107,16 @@ struct intel_fbc {
			int src_w;
			int src_h;
			bool visible;
			/*
			 * Display surface base address adjustement for
			 * pageflips. Note that on gen4+ this only adjusts up
			 * to a tile, offsets within a tile are handled in
			 * the hw itself (with the TILEOFF register).
			 */
			int adjusted_x;
			int adjusted_y;

			int y;
		} plane;

		struct {
@@ -1490,6 +1499,9 @@ struct i915_gem_mm {
	 * always the inner lock when overlapping with struct_mutex. */
	struct mutex stolen_lock;

	/* Protects bound_list/unbound_list and #drm_i915_gem_object.mm.link */
	spinlock_t obj_lock;

	/** List of all objects in gtt_space. Used to restore gtt
	 * mappings on resume */
	struct list_head bound_list;
@@ -1510,6 +1522,7 @@ struct i915_gem_mm {
	 */
	struct llist_head free_list;
	struct work_struct free_work;
	spinlock_t free_lock;

	/**
	 * Small stash of WC pages
@@ -1765,6 +1778,8 @@ struct intel_vbt_data {
		u16 panel_id;
		struct mipi_config *config;
		struct mipi_pps_data *pps;
		u16 bl_ports;
		u16 cabc_ports;
		u8 seq_version;
		u32 size;
		u8 *data;
@@ -1960,13 +1975,7 @@ struct i915_wa_reg {
	u32 mask;
};

/*
 * RING_MAX_NONPRIV_SLOTS is per-engine but at this point we are only
 * allowing it for RCS as we don't foresee any requirement of having
 * a whitelist for other engines. When it is really required for
 * other engines then the limit need to be increased.
 */
#define I915_MAX_WA_REGS (16 + RING_MAX_NONPRIV_SLOTS)
#define I915_MAX_WA_REGS 16

struct i915_workarounds {
	struct i915_wa_reg reg[I915_MAX_WA_REGS];
@@ -3077,6 +3086,7 @@ intel_info(const struct drm_i915_private *dev_priv)

#define CNL_REVID_A0		0x0
#define CNL_REVID_B0		0x1
#define CNL_REVID_C0		0x2

#define IS_CNL_REVID(p, since, until) \
	(IS_CANNONLAKE(p) && IS_REVID(p, since, until))
@@ -3168,7 +3178,6 @@ intel_info(const struct drm_i915_private *dev_priv)
#define I915_HAS_HOTPLUG(dev_priv)	((dev_priv)->info.has_hotplug)

#define HAS_FW_BLC(dev_priv) 	(INTEL_GEN(dev_priv) > 2)
#define HAS_PIPE_CXSR(dev_priv) ((dev_priv)->info.has_pipe_cxsr)
#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)

@@ -3565,10 +3574,16 @@ i915_gem_object_pin_pages(struct drm_i915_gem_object *obj)
	return __i915_gem_object_get_pages(obj);
}

static inline bool
i915_gem_object_has_pages(struct drm_i915_gem_object *obj)
{
	return !IS_ERR_OR_NULL(READ_ONCE(obj->mm.pages));
}

static inline void
__i915_gem_object_pin_pages(struct drm_i915_gem_object *obj)
{
	GEM_BUG_ON(!obj->mm.pages);
	GEM_BUG_ON(!i915_gem_object_has_pages(obj));

	atomic_inc(&obj->mm.pages_pin_count);
}
@@ -3582,8 +3597,8 @@ i915_gem_object_has_pinned_pages(struct drm_i915_gem_object *obj)
static inline void
__i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
{
	GEM_BUG_ON(!i915_gem_object_has_pages(obj));
	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
	GEM_BUG_ON(!obj->mm.pages);

	atomic_dec(&obj->mm.pages_pin_count);
}
+111 −44
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ static bool cpu_write_needs_clflush(struct drm_i915_gem_object *obj)
	if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE))
		return true;

	return obj->pin_display;
	return obj->pin_global; /* currently in use by HW, keep flushed */
}

static int
@@ -1240,7 +1240,23 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
	if (ret)
		return ret;

	if (i915_gem_object_has_struct_page(obj)) {
		/*
		 * Avoid waking the device up if we can fallback, as
		 * waking/resuming is very slow (worst-case 10-100 ms
		 * depending on PCI sleeps and our own resume time).
		 * This easily dwarfs any performance advantage from
		 * using the cache bypass of indirect GGTT access.
		 */
		if (!intel_runtime_pm_get_if_in_use(i915)) {
			ret = -EFAULT;
			goto out_unlock;
		}
	} else {
		/* No backing pages, no fallback, we must force GGTT access */
		intel_runtime_pm_get(i915);
	}

	vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
				       PIN_MAPPABLE |
				       PIN_NONFAULT |
@@ -1257,7 +1273,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
	if (IS_ERR(vma)) {
		ret = insert_mappable_node(ggtt, &node, PAGE_SIZE);
		if (ret)
			goto out_unlock;
			goto out_rpm;
		GEM_BUG_ON(!node.allocated);
	}

@@ -1320,8 +1336,9 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
	} else {
		i915_vma_unpin(vma);
	}
out_unlock:
out_rpm:
	intel_runtime_pm_put(i915);
out_unlock:
	mutex_unlock(&i915->drm.struct_mutex);
	return ret;
}
@@ -1537,6 +1554,8 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
	struct list_head *list;
	struct i915_vma *vma;

	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));

	list_for_each_entry(vma, &obj->vma_list, obj_link) {
		if (!i915_vma_is_ggtt(vma))
			break;
@@ -1551,8 +1570,10 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
	}

	i915 = to_i915(obj->base.dev);
	spin_lock(&i915->mm.obj_lock);
	list = obj->bind_count ? &i915->mm.bound_list : &i915->mm.unbound_list;
	list_move_tail(&obj->global_link, list);
	list_move_tail(&obj->mm.link, list);
	spin_unlock(&i915->mm.obj_lock);
}

/**
@@ -2196,7 +2217,7 @@ void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj)
	struct address_space *mapping;

	lockdep_assert_held(&obj->mm.lock);
	GEM_BUG_ON(obj->mm.pages);
	GEM_BUG_ON(i915_gem_object_has_pages(obj));

	switch (obj->mm.madv) {
	case I915_MADV_DONTNEED:
@@ -2253,13 +2274,14 @@ static void __i915_gem_object_reset_page_iter(struct drm_i915_gem_object *obj)
void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
				 enum i915_mm_subclass subclass)
{
	struct drm_i915_private *i915 = to_i915(obj->base.dev);
	struct sg_table *pages;

	if (i915_gem_object_has_pinned_pages(obj))
		return;

	GEM_BUG_ON(obj->bind_count);
	if (!READ_ONCE(obj->mm.pages))
	if (!i915_gem_object_has_pages(obj))
		return;

	/* May be called by shrinker from within get_pages() (on another bo) */
@@ -2273,6 +2295,10 @@ void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
	pages = fetch_and_zero(&obj->mm.pages);
	GEM_BUG_ON(!pages);

	spin_lock(&i915->mm.obj_lock);
	list_del(&obj->mm.link);
	spin_unlock(&i915->mm.obj_lock);

	if (obj->mm.mapping) {
		void *ptr;

@@ -2507,7 +2533,7 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
	obj->mm.pages = pages;

	if (i915_gem_object_is_tiled(obj) &&
	    to_i915(obj->base.dev)->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
	    i915->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
		GEM_BUG_ON(obj->mm.quirked);
		__i915_gem_object_pin_pages(obj);
		obj->mm.quirked = true;
@@ -2529,8 +2555,11 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
		if (obj->mm.page_sizes.phys & ~0u << i)
			obj->mm.page_sizes.sg |= BIT(i);
	}

	GEM_BUG_ON(!HAS_PAGE_SIZES(i915, obj->mm.page_sizes.sg));

	spin_lock(&i915->mm.obj_lock);
	list_add(&obj->mm.link, &i915->mm.unbound_list);
	spin_unlock(&i915->mm.obj_lock);
}

static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
@@ -2563,7 +2592,7 @@ int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
	if (err)
		return err;

	if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) {
	if (unlikely(!i915_gem_object_has_pages(obj))) {
		GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj));

		err = ____i915_gem_object_get_pages(obj);
@@ -2648,7 +2677,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
	type &= ~I915_MAP_OVERRIDE;

	if (!atomic_inc_not_zero(&obj->mm.pages_pin_count)) {
		if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) {
		if (unlikely(!i915_gem_object_has_pages(obj))) {
			GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj));

			ret = ____i915_gem_object_get_pages(obj);
@@ -2660,7 +2689,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
		atomic_inc(&obj->mm.pages_pin_count);
		pinned = false;
	}
	GEM_BUG_ON(!obj->mm.pages);
	GEM_BUG_ON(!i915_gem_object_has_pages(obj));

	ptr = page_unpack_bits(obj->mm.mapping, &has_type);
	if (ptr && has_type != type) {
@@ -2715,7 +2744,7 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj,
	 * allows it to avoid the cost of retrieving a page (either swapin
	 * or clearing-before-use) before it is overwritten.
	 */
	if (READ_ONCE(obj->mm.pages))
	if (i915_gem_object_has_pages(obj))
		return -ENODEV;

	if (obj->mm.madv != I915_MADV_WILLNEED)
@@ -3090,7 +3119,6 @@ void i915_gem_reset_finish(struct drm_i915_private *dev_priv)

static void nop_submit_request(struct drm_i915_gem_request *request)
{
	GEM_BUG_ON(!i915_terminally_wedged(&request->i915->gpu_error));
	dma_fence_set_error(&request->fence, -EIO);

	i915_gem_request_submit(request);
@@ -3100,7 +3128,6 @@ static void nop_complete_submit_request(struct drm_i915_gem_request *request)
{
	unsigned long flags;

	GEM_BUG_ON(!i915_terminally_wedged(&request->i915->gpu_error));
	dma_fence_set_error(&request->fence, -EIO);

	spin_lock_irqsave(&request->engine->timeline->lock, flags);
@@ -3498,7 +3525,7 @@ static void __i915_gem_object_flush_for_display(struct drm_i915_gem_object *obj)

void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj)
{
	if (!READ_ONCE(obj->pin_display))
	if (!READ_ONCE(obj->pin_global))
		return;

	mutex_lock(&obj->base.dev->struct_mutex);
@@ -3865,10 +3892,10 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,

	lockdep_assert_held(&obj->base.dev->struct_mutex);

	/* Mark the pin_display early so that we account for the
	/* Mark the global pin early so that we account for the
	 * display coherency whilst setting up the cache domains.
	 */
	obj->pin_display++;
	obj->pin_global++;

	/* The display engine is not coherent with the LLC cache on gen6.  As
	 * a result, we make sure that the pinning that is about to occur is
@@ -3884,7 +3911,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
					      I915_CACHE_WT : I915_CACHE_NONE);
	if (ret) {
		vma = ERR_PTR(ret);
		goto err_unpin_display;
		goto err_unpin_global;
	}

	/* As the user may map the buffer once pinned in the display plane
@@ -3915,7 +3942,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
		vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, flags);
	}
	if (IS_ERR(vma))
		goto err_unpin_display;
		goto err_unpin_global;

	vma->display_alignment = max_t(u64, vma->display_alignment, alignment);

@@ -3930,8 +3957,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,

	return vma;

err_unpin_display:
	obj->pin_display--;
err_unpin_global:
	obj->pin_global--;
	return vma;
}

@@ -3940,10 +3967,10 @@ i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
{
	lockdep_assert_held(&vma->vm->i915->drm.struct_mutex);

	if (WARN_ON(vma->obj->pin_display == 0))
	if (WARN_ON(vma->obj->pin_global == 0))
		return;

	if (--vma->obj->pin_display == 0)
	if (--vma->obj->pin_global == 0)
		vma->display_alignment = I915_GTT_MIN_ALIGNMENT;

	/* Bump the LRU to try and avoid premature eviction whilst flipping  */
@@ -4283,7 +4310,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
	if (err)
		goto out;

	if (obj->mm.pages &&
	if (i915_gem_object_has_pages(obj) &&
	    i915_gem_object_is_tiled(obj) &&
	    dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
		if (obj->mm.madv == I915_MADV_WILLNEED) {
@@ -4302,7 +4329,8 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
		obj->mm.madv = args->madv;

	/* if the object is no longer attached, discard its backing storage */
	if (obj->mm.madv == I915_MADV_DONTNEED && !obj->mm.pages)
	if (obj->mm.madv == I915_MADV_DONTNEED &&
	    !i915_gem_object_has_pages(obj))
		i915_gem_object_truncate(obj);

	args->retained = obj->mm.madv != __I915_MADV_PURGED;
@@ -4328,7 +4356,6 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
{
	mutex_init(&obj->mm.lock);

	INIT_LIST_HEAD(&obj->global_link);
	INIT_LIST_HEAD(&obj->vma_list);
	INIT_LIST_HEAD(&obj->lut_list);
	INIT_LIST_HEAD(&obj->batch_pool_link);
@@ -4483,13 +4510,14 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
{
	struct drm_i915_gem_object *obj, *on;

	mutex_lock(&i915->drm.struct_mutex);
	intel_runtime_pm_get(i915);
	llist_for_each_entry(obj, freed, freed) {
	llist_for_each_entry_safe(obj, on, freed, freed) {
		struct i915_vma *vma, *vn;

		trace_i915_gem_object_destroy(obj);

		mutex_lock(&i915->drm.struct_mutex);

		GEM_BUG_ON(i915_gem_object_is_active(obj));
		list_for_each_entry_safe(vma, vn,
					 &obj->vma_list, obj_link) {
@@ -4500,14 +4528,20 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
		GEM_BUG_ON(!list_empty(&obj->vma_list));
		GEM_BUG_ON(!RB_EMPTY_ROOT(&obj->vma_tree));

		list_del(&obj->global_link);
		/* This serializes freeing with the shrinker. Since the free
		 * is delayed, first by RCU then by the workqueue, we want the
		 * shrinker to be able to free pages of unreferenced objects,
		 * or else we may oom whilst there are plenty of deferred
		 * freed objects.
		 */
		if (i915_gem_object_has_pages(obj)) {
			spin_lock(&i915->mm.obj_lock);
			list_del_init(&obj->mm.link);
			spin_unlock(&i915->mm.obj_lock);
		}
	intel_runtime_pm_put(i915);
	mutex_unlock(&i915->drm.struct_mutex);

	cond_resched();
		mutex_unlock(&i915->drm.struct_mutex);

	llist_for_each_entry_safe(obj, on, freed, freed) {
		GEM_BUG_ON(obj->bind_count);
		GEM_BUG_ON(obj->userfault_count);
		GEM_BUG_ON(atomic_read(&obj->frontbuffer_bits));
@@ -4519,7 +4553,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
		if (WARN_ON(i915_gem_object_has_pinned_pages(obj)))
			atomic_set(&obj->mm.pages_pin_count, 0);
		__i915_gem_object_put_pages(obj, I915_MM_NORMAL);
		GEM_BUG_ON(obj->mm.pages);
		GEM_BUG_ON(i915_gem_object_has_pages(obj));

		if (obj->base.import_attach)
			drm_prime_gem_destroy(&obj->base, NULL);
@@ -4530,17 +4564,30 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,

		kfree(obj->bit_17);
		i915_gem_object_free(obj);

		if (on)
			cond_resched();
	}
	intel_runtime_pm_put(i915);
}

static void i915_gem_flush_free_objects(struct drm_i915_private *i915)
{
	struct llist_node *freed;

	freed = llist_del_all(&i915->mm.free_list);
	if (unlikely(freed))
	/* Free the oldest, most stale object to keep the free_list short */
	freed = NULL;
	if (!llist_empty(&i915->mm.free_list)) { /* quick test for hotpath */
		/* Only one consumer of llist_del_first() allowed */
		spin_lock(&i915->mm.free_lock);
		freed = llist_del_first(&i915->mm.free_list);
		spin_unlock(&i915->mm.free_lock);
	}
	if (unlikely(freed)) {
		freed->next = NULL;
		__i915_gem_free_objects(i915, freed);
	}
}

static void __i915_gem_free_work(struct work_struct *work)
{
@@ -4840,6 +4887,10 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
	init_unused_rings(dev_priv);

	BUG_ON(!dev_priv->kernel_context);
	if (i915_terminally_wedged(&dev_priv->gpu_error)) {
		ret = -EIO;
		goto out;
	}

	ret = i915_ppgtt_init_hw(dev_priv);
	if (ret) {
@@ -4938,8 +4989,10 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
		 * wedged. But we only want to do this where the GPU is angry,
		 * for all other failure, such as an allocation failure, bail.
		 */
		if (!i915_terminally_wedged(&dev_priv->gpu_error)) {
			DRM_ERROR("Failed to initialize GPU, declaring it wedged\n");
			i915_gem_set_wedged(dev_priv);
		}
		ret = 0;
	}

@@ -5039,11 +5092,15 @@ i915_gem_load_init(struct drm_i915_private *dev_priv)
		goto err_priorities;

	INIT_WORK(&dev_priv->mm.free_work, __i915_gem_free_work);

	spin_lock_init(&dev_priv->mm.obj_lock);
	spin_lock_init(&dev_priv->mm.free_lock);
	init_llist_head(&dev_priv->mm.free_list);
	INIT_LIST_HEAD(&dev_priv->mm.unbound_list);
	INIT_LIST_HEAD(&dev_priv->mm.bound_list);
	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
	INIT_LIST_HEAD(&dev_priv->mm.userfault_list);

	INIT_DELAYED_WORK(&dev_priv->gt.retire_work,
			  i915_gem_retire_work_handler);
	INIT_DELAYED_WORK(&dev_priv->gt.idle_work,
@@ -5137,12 +5194,12 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv)
	i915_gem_shrink(dev_priv, -1UL, NULL, I915_SHRINK_UNBOUND);
	i915_gem_drain_freed_objects(dev_priv);

	mutex_lock(&dev_priv->drm.struct_mutex);
	spin_lock(&dev_priv->mm.obj_lock);
	for (p = phases; *p; p++) {
		list_for_each_entry(obj, *p, global_link)
		list_for_each_entry(obj, *p, mm.link)
			__start_cpu_write(obj);
	}
	mutex_unlock(&dev_priv->drm.struct_mutex);
	spin_unlock(&dev_priv->mm.obj_lock);

	return 0;
}
@@ -5461,7 +5518,17 @@ int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align)
		goto err_unlock;
	}

	pages = obj->mm.pages;
	pages = fetch_and_zero(&obj->mm.pages);
	if (pages) {
		struct drm_i915_private *i915 = to_i915(obj->base.dev);

		__i915_gem_object_reset_page_iter(obj);

		spin_lock(&i915->mm.obj_lock);
		list_del(&obj->mm.link);
		spin_unlock(&i915->mm.obj_lock);
	}

	obj->ops = &i915_gem_phys_ops;

	err = ____i915_gem_object_get_pages(obj);
Loading