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

Commit 218c872b authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-next-2012-05-06-merged' of...

Merge tag 'drm-intel-next-2012-05-06-merged' of git://people.freedesktop.org/~danvet/drm-intel into drm-core-next

Daniel says

Highlights:
- sparse fixes from Ben.
- tons of little cleanups from Chris all over: tiling_changed
 clarification, deferred_free list removal, ...
- fix up irq handler on gen2 & gen3 + related cleanups from Chris
- prep work for wait_rendering_timeout from Ben with some nice
 refactorings
- first set of infoframe fixes from Paulo for doubleclocked CEA modes
- improve pch pll handling from Jesse and Chris
- gpu hangman, this also contains the reset fix for gen4
- rps sanity check from Chris - this papers over issues when the gpu fails
 to clock up on snb/ivb, and it is shockingly easy to hit. The code
 prints a big WARN backtrace and restores the hw to a sane state. The
 real fix is still in the works.

Atm I'm aware of 2 regressions in -next:
- One of the gmbus patches (not gmbus itself) regressed lvds detection on
 a MacbookPro. I've analyzed the bug already and I think I know what's
 going on, patch is awaiting test feedback.
- Just today QA reported that DP on ilk regressed. That bug is fresh of
 the press and still awaiting detailed logfiles and the bisect result.
 The only thing that's clear atm is that -fixes works and -next doesn't.
parents b06d66be 5e13a0c5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
	  i915_gem_evict.o \
	  i915_gem_execbuffer.o \
	  i915_gem_gtt.o \
	  i915_gem_stolen.o \
	  i915_gem_tiling.o \
	  i915_sysfs.o \
	  i915_trace_points.o \
+161 −109
Original line number Diff line number Diff line
@@ -47,7 +47,6 @@ enum {
	FLUSHING_LIST,
	INACTIVE_LIST,
	PINNED_LIST,
	DEFERRED_FREE_LIST,
};

static const char *yesno(int v)
@@ -178,18 +177,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
		seq_printf(m, "Inactive:\n");
		head = &dev_priv->mm.inactive_list;
		break;
	case PINNED_LIST:
		seq_printf(m, "Pinned:\n");
		head = &dev_priv->mm.pinned_list;
		break;
	case FLUSHING_LIST:
		seq_printf(m, "Flushing:\n");
		head = &dev_priv->mm.flushing_list;
		break;
	case DEFERRED_FREE_LIST:
		seq_printf(m, "Deferred free:\n");
		head = &dev_priv->mm.deferred_free_list;
		break;
	default:
		mutex_unlock(&dev->struct_mutex);
		return -EINVAL;
@@ -251,21 +242,11 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
	seq_printf(m, "  %u [%u] active objects, %zu [%zu] bytes\n",
		   count, mappable_count, size, mappable_size);

	size = count = mappable_size = mappable_count = 0;
	count_objects(&dev_priv->mm.pinned_list, mm_list);
	seq_printf(m, "  %u [%u] pinned objects, %zu [%zu] bytes\n",
		   count, mappable_count, size, mappable_size);

	size = count = mappable_size = mappable_count = 0;
	count_objects(&dev_priv->mm.inactive_list, mm_list);
	seq_printf(m, "  %u [%u] inactive objects, %zu [%zu] bytes\n",
		   count, mappable_count, size, mappable_size);

	size = count = mappable_size = mappable_count = 0;
	count_objects(&dev_priv->mm.deferred_free_list, mm_list);
	seq_printf(m, "  %u [%u] freed objects, %zu [%zu] bytes\n",
		   count, mappable_count, size, mappable_size);

	size = count = mappable_size = mappable_count = 0;
	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
		if (obj->fault_mappable) {
@@ -294,6 +275,7 @@ static int i915_gem_gtt_info(struct seq_file *m, void* data)
{
	struct drm_info_node *node = (struct drm_info_node *) m->private;
	struct drm_device *dev = node->minor->dev;
	uintptr_t list = (uintptr_t) node->info_ent->data;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_i915_gem_object *obj;
	size_t total_obj_size, total_gtt_size;
@@ -305,6 +287,9 @@ static int i915_gem_gtt_info(struct seq_file *m, void* data)

	total_obj_size = total_gtt_size = count = 0;
	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
		if (list == PINNED_LIST && obj->pin_count == 0)
			continue;

		seq_printf(m, "   ");
		describe_obj(m, obj);
		seq_printf(m, "\n");
@@ -321,7 +306,6 @@ static int i915_gem_gtt_info(struct seq_file *m, void* data)
	return 0;
}


static int i915_gem_pageflip_info(struct seq_file *m, void *data)
{
	struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -430,10 +414,6 @@ static void i915_ring_seqno_info(struct seq_file *m,
	if (ring->get_seqno) {
		seq_printf(m, "Current sequence (%s): %d\n",
			   ring->name, ring->get_seqno(ring));
		seq_printf(m, "Waiter sequence (%s):  %d\n",
			   ring->name, ring->waiting_seqno);
		seq_printf(m, "IRQ sequence (%s):     %d\n",
			   ring->name, ring->irq_seqno);
	}
}

@@ -602,69 +582,6 @@ static int i915_hws_info(struct seq_file *m, void *data)
	return 0;
}

static int i915_ringbuffer_data(struct seq_file *m, void *data)
{
	struct drm_info_node *node = (struct drm_info_node *) m->private;
	struct drm_device *dev = node->minor->dev;
	drm_i915_private_t *dev_priv = dev->dev_private;
	struct intel_ring_buffer *ring;
	int ret;

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

	ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
	if (!ring->obj) {
		seq_printf(m, "No ringbuffer setup\n");
	} else {
		const u8 __iomem *virt = ring->virtual_start;
		uint32_t off;

		for (off = 0; off < ring->size; off += 4) {
			uint32_t *ptr = (uint32_t *)(virt + off);
			seq_printf(m, "%08x :  %08x\n", off, *ptr);
		}
	}
	mutex_unlock(&dev->struct_mutex);

	return 0;
}

static int i915_ringbuffer_info(struct seq_file *m, void *data)
{
	struct drm_info_node *node = (struct drm_info_node *) m->private;
	struct drm_device *dev = node->minor->dev;
	drm_i915_private_t *dev_priv = dev->dev_private;
	struct intel_ring_buffer *ring;
	int ret;

	ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
	if (ring->size == 0)
		return 0;

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

	seq_printf(m, "Ring %s:\n", ring->name);
	seq_printf(m, "  Head :    %08x\n", I915_READ_HEAD(ring) & HEAD_ADDR);
	seq_printf(m, "  Tail :    %08x\n", I915_READ_TAIL(ring) & TAIL_ADDR);
	seq_printf(m, "  Size :    %08x\n", ring->size);
	seq_printf(m, "  Active :  %08x\n", intel_ring_get_active_head(ring));
	seq_printf(m, "  NOPID :   %08x\n", I915_READ_NOPID(ring));
	if (IS_GEN6(dev) || IS_GEN7(dev)) {
		seq_printf(m, "  Sync 0 :   %08x\n", I915_READ_SYNC_0(ring));
		seq_printf(m, "  Sync 1 :   %08x\n", I915_READ_SYNC_1(ring));
	}
	seq_printf(m, "  Control : %08x\n", I915_READ_CTL(ring));
	seq_printf(m, "  Start :   %08x\n", I915_READ_START(ring));

	mutex_unlock(&dev->struct_mutex);

	return 0;
}

static const char *ring_str(int ring)
{
	switch (ring) {
@@ -766,31 +683,35 @@ static void i915_ring_error_state(struct seq_file *m,
			   error->semaphore_mboxes[ring][1]);
	}
	seq_printf(m, "  seqno: 0x%08x\n", error->seqno[ring]);
	seq_printf(m, "  waiting: %s\n", yesno(error->waiting[ring]));
	seq_printf(m, "  ring->head: 0x%08x\n", error->cpu_ring_head[ring]);
	seq_printf(m, "  ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]);
}

struct i915_error_state_file_priv {
	struct drm_device *dev;
	struct drm_i915_error_state *error;
};

static int i915_error_state(struct seq_file *m, void *unused)
{
	struct drm_info_node *node = (struct drm_info_node *) m->private;
	struct drm_device *dev = node->minor->dev;
	struct i915_error_state_file_priv *error_priv = m->private;
	struct drm_device *dev = error_priv->dev;
	drm_i915_private_t *dev_priv = dev->dev_private;
	struct drm_i915_error_state *error;
	unsigned long flags;
	struct drm_i915_error_state *error = error_priv->error;
	int i, j, page, offset, elt;

	spin_lock_irqsave(&dev_priv->error_lock, flags);
	if (!dev_priv->first_error) {
	if (!error) {
		seq_printf(m, "no error state collected\n");
		goto out;
		return 0;
	}

	error = dev_priv->first_error;

	seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
		   error->time.tv_usec);
	seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
	seq_printf(m, "EIR: 0x%08x\n", error->eir);
	seq_printf(m, "IER: 0x%08x\n", error->ier);
	seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);

	for (i = 0; i < dev_priv->num_fence_regs; i++)
@@ -867,12 +788,71 @@ static int i915_error_state(struct seq_file *m, void *unused)
	if (error->display)
		intel_display_print_error_state(m, dev, error->display);

out:
	return 0;
}

static ssize_t
i915_error_state_write(struct file *filp,
		       const char __user *ubuf,
		       size_t cnt,
		       loff_t *ppos)
{
	struct seq_file *m = filp->private_data;
	struct i915_error_state_file_priv *error_priv = m->private;
	struct drm_device *dev = error_priv->dev;

	DRM_DEBUG_DRIVER("Resetting error state\n");

	mutex_lock(&dev->struct_mutex);
	i915_destroy_error_state(dev);
	mutex_unlock(&dev->struct_mutex);

	return cnt;
}

static int i915_error_state_open(struct inode *inode, struct file *file)
{
	struct drm_device *dev = inode->i_private;
	drm_i915_private_t *dev_priv = dev->dev_private;
	struct i915_error_state_file_priv *error_priv;
	unsigned long flags;

	error_priv = kzalloc(sizeof(*error_priv), GFP_KERNEL);
	if (!error_priv)
		return -ENOMEM;

	error_priv->dev = dev;

	spin_lock_irqsave(&dev_priv->error_lock, flags);
	error_priv->error = dev_priv->first_error;
	if (error_priv->error)
		kref_get(&error_priv->error->ref);
	spin_unlock_irqrestore(&dev_priv->error_lock, flags);

	return 0;
	return single_open(file, i915_error_state, error_priv);
}

static int i915_error_state_release(struct inode *inode, struct file *file)
{
	struct seq_file *m = file->private_data;
	struct i915_error_state_file_priv *error_priv = m->private;

	if (error_priv->error)
		kref_put(&error_priv->error->ref, i915_error_state_free);
	kfree(error_priv);

	return single_release(inode, file);
}

static const struct file_operations i915_error_state_fops = {
	.owner = THIS_MODULE,
	.open = i915_error_state_open,
	.read = seq_read,
	.write = i915_error_state_write,
	.llseek = default_llseek,
	.release = i915_error_state_release,
};

static int i915_rstdby_delays(struct seq_file *m, void *unused)
{
	struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -1356,17 +1336,25 @@ static int i915_opregion(struct seq_file *m, void *unused)
	struct drm_device *dev = node->minor->dev;
	drm_i915_private_t *dev_priv = dev->dev_private;
	struct intel_opregion *opregion = &dev_priv->opregion;
	void *data = kmalloc(OPREGION_SIZE, GFP_KERNEL);
	int ret;

	if (data == NULL)
		return -ENOMEM;

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

	if (opregion->header)
		seq_write(m, opregion->header, OPREGION_SIZE);
	if (opregion->header) {
		memcpy_fromio(data, opregion->header, OPREGION_SIZE);
		seq_write(m, data, OPREGION_SIZE);
	}

	mutex_unlock(&dev->struct_mutex);

out:
	kfree(data);
	return 0;
}

@@ -1658,6 +1646,65 @@ static const struct file_operations i915_wedged_fops = {
	.llseek = default_llseek,
};

static ssize_t
i915_ring_stop_read(struct file *filp,
		    char __user *ubuf,
		    size_t max,
		    loff_t *ppos)
{
	struct drm_device *dev = filp->private_data;
	drm_i915_private_t *dev_priv = dev->dev_private;
	char buf[20];
	int len;

	len = snprintf(buf, sizeof(buf),
		       "0x%08x\n", dev_priv->stop_rings);

	if (len > sizeof(buf))
		len = sizeof(buf);

	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
}

static ssize_t
i915_ring_stop_write(struct file *filp,
		     const char __user *ubuf,
		     size_t cnt,
		     loff_t *ppos)
{
	struct drm_device *dev = filp->private_data;
	struct drm_i915_private *dev_priv = dev->dev_private;
	char buf[20];
	int val = 0;

	if (cnt > 0) {
		if (cnt > sizeof(buf) - 1)
			return -EINVAL;

		if (copy_from_user(buf, ubuf, cnt))
			return -EFAULT;
		buf[cnt] = 0;

		val = simple_strtoul(buf, NULL, 0);
	}

	DRM_DEBUG_DRIVER("Stopping rings 0x%08x\n", val);

	mutex_lock(&dev->struct_mutex);
	dev_priv->stop_rings = val;
	mutex_unlock(&dev->struct_mutex);

	return cnt;
}

static const struct file_operations i915_ring_stop_fops = {
	.owner = THIS_MODULE,
	.open = simple_open,
	.read = i915_ring_stop_read,
	.write = i915_ring_stop_write,
	.llseek = default_llseek,
};

static ssize_t
i915_max_freq_read(struct file *filp,
		   char __user *ubuf,
@@ -1900,11 +1947,10 @@ static 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_pinned", i915_gem_gtt_info, 0, (void *) PINNED_LIST},
	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
	{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
	{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
	{"i915_gem_pinned", i915_gem_object_list_info, 0, (void *) PINNED_LIST},
	{"i915_gem_deferred_free", i915_gem_object_list_info, 0, (void *) DEFERRED_FREE_LIST},
	{"i915_gem_pageflip", i915_gem_pageflip_info, 0},
	{"i915_gem_request", i915_gem_request_info, 0},
	{"i915_gem_seqno", i915_gem_seqno_info, 0},
@@ -1913,13 +1959,6 @@ static struct drm_info_list i915_debugfs_list[] = {
	{"i915_gem_hws", i915_hws_info, 0, (void *)RCS},
	{"i915_gem_hws_blt", i915_hws_info, 0, (void *)BCS},
	{"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS},
	{"i915_ringbuffer_data", i915_ringbuffer_data, 0, (void *)RCS},
	{"i915_ringbuffer_info", i915_ringbuffer_info, 0, (void *)RCS},
	{"i915_bsd_ringbuffer_data", i915_ringbuffer_data, 0, (void *)VCS},
	{"i915_bsd_ringbuffer_info", i915_ringbuffer_info, 0, (void *)VCS},
	{"i915_blt_ringbuffer_data", i915_ringbuffer_data, 0, (void *)BCS},
	{"i915_blt_ringbuffer_info", i915_ringbuffer_info, 0, (void *)BCS},
	{"i915_error_state", i915_error_state, 0},
	{"i915_rstdby_delays", i915_rstdby_delays, 0},
	{"i915_cur_delayinfo", i915_cur_delayinfo, 0},
	{"i915_delayfreq_table", i915_delayfreq_table, 0},
@@ -1965,6 +2004,17 @@ int i915_debugfs_init(struct drm_minor *minor)
				  &i915_cache_sharing_fops);
	if (ret)
		return ret;
	ret = i915_debugfs_create(minor->debugfs_root, minor,
				  "i915_ring_stop",
				  &i915_ring_stop_fops);
	if (ret)
		return ret;

	ret = i915_debugfs_create(minor->debugfs_root, minor,
				  "i915_error_state",
				  &i915_error_state_fops);
	if (ret)
		return ret;

	return drm_debugfs_create_files(i915_debugfs_list,
					I915_DEBUGFS_ENTRIES,
@@ -1983,6 +2033,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor)
				 1, minor);
	drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops,
				 1, minor);
	drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops,
				 1, minor);
}

#endif /* CONFIG_DEBUG_FS */
+248 −828

File changed.

Preview size limit exceeded, changes collapsed.

+83 −49
Original line number Diff line number Diff line
@@ -377,18 +377,23 @@ void intel_detect_pch(struct drm_device *dev)

			if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
				dev_priv->pch_type = PCH_IBX;
				dev_priv->num_pch_pll = 2;
				DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
			} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
				dev_priv->pch_type = PCH_CPT;
				dev_priv->num_pch_pll = 2;
				DRM_DEBUG_KMS("Found CougarPoint PCH\n");
			} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
				/* PantherPoint is CPT compatible */
				dev_priv->pch_type = PCH_CPT;
				dev_priv->num_pch_pll = 2;
				DRM_DEBUG_KMS("Found PatherPoint PCH\n");
			} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
				dev_priv->pch_type = PCH_LPT;
				dev_priv->num_pch_pll = 0;
				DRM_DEBUG_KMS("Found LynxPoint PCH\n");
			}
			BUG_ON(dev_priv->num_pch_pll > I915_NUM_PLLS);
		}
		pci_dev_put(pch);
	}
@@ -433,7 +438,7 @@ void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1))
		udelay(10);

	I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 1);
	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1));
	POSTING_READ(FORCEWAKE_MT);

	count = 0;
@@ -475,7 +480,7 @@ void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)

void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
{
	I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0);
	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1));
	/* The below doubles as a POSTING_READ */
	gen6_gt_check_fifodbg(dev_priv);
}
@@ -668,7 +673,7 @@ int i915_resume(struct drm_device *dev)
	return 0;
}

static int i8xx_do_reset(struct drm_device *dev, u8 flags)
static int i8xx_do_reset(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

@@ -702,11 +707,12 @@ static int i965_reset_complete(struct drm_device *dev)
{
	u8 gdrst;
	pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
	return gdrst & 0x1;
	return (gdrst & GRDOM_RESET_ENABLE) == 0;
}

static int i965_do_reset(struct drm_device *dev, u8 flags)
static int i965_do_reset(struct drm_device *dev)
{
	int ret;
	u8 gdrst;

	/*
@@ -715,20 +721,43 @@ static int i965_do_reset(struct drm_device *dev, u8 flags)
	 * triggers the reset; when done, the hardware will clear it.
	 */
	pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
	pci_write_config_byte(dev->pdev, I965_GDRST, gdrst | flags | 0x1);
	pci_write_config_byte(dev->pdev, I965_GDRST,
			      gdrst | GRDOM_RENDER |
			      GRDOM_RESET_ENABLE);
	ret =  wait_for(i965_reset_complete(dev), 500);
	if (ret)
		return ret;

	/* We can't reset render&media without also resetting display ... */
	pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
	pci_write_config_byte(dev->pdev, I965_GDRST,
			      gdrst | GRDOM_MEDIA |
			      GRDOM_RESET_ENABLE);

	return wait_for(i965_reset_complete(dev), 500);
}

static int ironlake_do_reset(struct drm_device *dev, u8 flags)
static int ironlake_do_reset(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	u32 gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR, gdrst | flags | 0x1);
	u32 gdrst;
	int ret;

	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
		   gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE);
	ret = wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
	if (ret)
		return ret;

	/* We can't reset render&media without also resetting display ... */
	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
		   gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE);
	return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
}

static int gen6_do_reset(struct drm_device *dev, u8 flags)
static int gen6_do_reset(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	int	ret;
@@ -763,10 +792,44 @@ static int gen6_do_reset(struct drm_device *dev, u8 flags)
	return ret;
}

static int intel_gpu_reset(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	int ret = -ENODEV;

	switch (INTEL_INFO(dev)->gen) {
	case 7:
	case 6:
		ret = gen6_do_reset(dev);
		break;
	case 5:
		ret = ironlake_do_reset(dev);
		break;
	case 4:
		ret = i965_do_reset(dev);
		break;
	case 2:
		ret = i8xx_do_reset(dev);
		break;
	}

	/* Also reset the gpu hangman. */
	if (dev_priv->stop_rings) {
		DRM_DEBUG("Simulated gpu hang, resetting stop_rings\n");
		dev_priv->stop_rings = 0;
		if (ret == -ENODEV) {
			DRM_ERROR("Reset not implemented, but ignoring "
				  "error for simulated gpu hangs\n");
			ret = 0;
		}
	}

	return ret;
}

/**
 * i915_reset - reset chip after a hang
 * @dev: drm device to reset
 * @flags: reset domains
 *
 * Reset the chip.  Useful if a hang is detected. Returns zero on successful
 * reset or otherwise an error code.
@@ -779,14 +842,9 @@ static int gen6_do_reset(struct drm_device *dev, u8 flags)
 *   - re-init interrupt state
 *   - re-init display
 */
int i915_reset(struct drm_device *dev, u8 flags)
int i915_reset(struct drm_device *dev)
{
	drm_i915_private_t *dev_priv = dev->dev_private;
	/*
	 * We really should only reset the display subsystem if we actually
	 * need to
	 */
	bool need_display = true;
	int ret;

	if (!i915_try_reset)
@@ -795,26 +853,16 @@ int i915_reset(struct drm_device *dev, u8 flags)
	if (!mutex_trylock(&dev->struct_mutex))
		return -EBUSY;

	dev_priv->stop_rings = 0;

	i915_gem_reset(dev);

	ret = -ENODEV;
	if (get_seconds() - dev_priv->last_gpu_reset < 5) {
	if (get_seconds() - dev_priv->last_gpu_reset < 5)
		DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
	} else switch (INTEL_INFO(dev)->gen) {
	case 7:
	case 6:
		ret = gen6_do_reset(dev, flags);
		break;
	case 5:
		ret = ironlake_do_reset(dev, flags);
		break;
	case 4:
		ret = i965_do_reset(dev, flags);
		break;
	case 2:
		ret = i8xx_do_reset(dev, flags);
		break;
	}
	else
		ret = intel_gpu_reset(dev);

	dev_priv->last_gpu_reset = get_seconds();
	if (ret) {
		DRM_ERROR("Failed to reset chip.\n");
@@ -856,23 +904,9 @@ int i915_reset(struct drm_device *dev, u8 flags)
			intel_modeset_init_hw(dev);

		drm_irq_uninstall(dev);
		drm_mode_config_reset(dev);
		drm_irq_install(dev);

		mutex_lock(&dev->struct_mutex);
	}

	} else {
		mutex_unlock(&dev->struct_mutex);

	/*
	 * Perform a full modeset as on later generations, e.g. Ironlake, we may
	 * need to retrain the display link and cannot just restore the register
	 * values.
	 */
	if (need_display) {
		mutex_lock(&dev->mode_config.mutex);
		drm_helper_resume_force_mode(dev);
		mutex_unlock(&dev->mode_config.mutex);
	}

	return 0;
+56 −66
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include <drm/intel-gtt.h>
#include <linux/backlight.h>
#include <linux/intel-iommu.h>
#include <linux/kref.h>

/* General customization:
 */
@@ -78,6 +79,16 @@ enum port {

#define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++)

struct intel_pch_pll {
	int refcount; /* count of number of CRTCs sharing this PLL */
	int active; /* count of number of active CRTCs (i.e. DPMS on) */
	bool on; /* is the PLL actually active? Disabled during modeset */
	int pll_reg;
	int fp0_reg;
	int fp1_reg;
};
#define I915_NUM_PLLS 2

/* Interface history:
 *
 * 1.1: Original.
@@ -122,11 +133,11 @@ struct opregion_asle;
struct drm_i915_private;

struct intel_opregion {
	struct opregion_header *header;
	struct opregion_acpi *acpi;
	struct opregion_swsci *swsci;
	struct opregion_asle *asle;
	void *vbt;
	struct opregion_header __iomem *header;
	struct opregion_acpi __iomem *acpi;
	struct opregion_swsci __iomem *swsci;
	struct opregion_asle __iomem *asle;
	void __iomem *vbt;
	u32 __iomem *lid_state;
};
#define OPREGION_SIZE            (8*1024)
@@ -161,8 +172,11 @@ struct sdvo_device_mapping {
struct intel_display_error_state;

struct drm_i915_error_state {
	struct kref ref;
	u32 eir;
	u32 pgtbl_er;
	u32 ier;
	bool waiting[I915_NUM_RINGS];
	u32 pipestat[I915_MAX_PIPES];
	u32 tail[I915_NUM_RINGS];
	u32 head[I915_NUM_RINGS];
@@ -228,11 +242,13 @@ struct drm_i915_display_funcs {
	void (*update_wm)(struct drm_device *dev);
	void (*update_sprite_wm)(struct drm_device *dev, int pipe,
				 uint32_t sprite_width, int pixel_size);
	void (*sanitize_pm)(struct drm_device *dev);
	int (*crtc_mode_set)(struct drm_crtc *crtc,
			     struct drm_display_mode *mode,
			     struct drm_display_mode *adjusted_mode,
			     int x, int y,
			     struct drm_framebuffer *old_fb);
	void (*off)(struct drm_crtc *crtc);
	void (*write_eld)(struct drm_connector *connector,
			  struct drm_crtc *crtc);
	void (*fdi_link_train)(struct drm_crtc *crtc);
@@ -328,7 +344,6 @@ typedef struct drm_i915_private {

	const struct intel_device_info *info;

	int has_gem;
	int relative_constants_mode;

	void __iomem *regs;
@@ -357,7 +372,6 @@ typedef struct drm_i915_private {

	drm_dma_handle_t *status_page_dmah;
	uint32_t counter;
	drm_local_map_t hws_map;
	struct drm_i915_gem_object *pwrctx;
	struct drm_i915_gem_object *renderctx;

@@ -386,11 +400,9 @@ typedef struct drm_i915_private {
	u32 hotplug_supported_mask;
	struct work_struct hotplug_work;

	int tex_lru_log_granularity;
	int allow_batchbuffer;
	unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
	int vblank_pipe;
	int num_pipe;
	int num_pch_pll;

	/* For hangcheck timer */
#define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
@@ -402,6 +414,8 @@ typedef struct drm_i915_private {
	uint32_t last_instdone;
	uint32_t last_instdone1;

	unsigned int stop_rings;

	unsigned long cfb_size;
	unsigned int cfb_fb;
	enum plane cfb_plane;
@@ -453,6 +467,7 @@ typedef struct drm_i915_private {
	unsigned int fsb_freq, mem_freq, is_ddr3;

	spinlock_t error_lock;
	/* Protected by dev->error_lock. */
	struct drm_i915_error_state *first_error;
	struct work_struct error_work;
	struct completion error_completion;
@@ -677,23 +692,9 @@ typedef struct drm_i915_private {
		 */
		struct list_head inactive_list;

		/**
		 * LRU list of objects which are not in the ringbuffer but
		 * are still pinned in the GTT.
		 */
		struct list_head pinned_list;

		/** LRU list of objects with fence regs on them. */
		struct list_head fence_list;

		/**
		 * List of objects currently pending being freed.
		 *
		 * These objects are no longer in use, but due to a signal
		 * we were prevented from freeing them at the appointed time.
		 */
		struct list_head deferred_free_list;

		/**
		 * We leave the user IRQ off as much as possible,
		 * but this means that requests will finish and never
@@ -742,6 +743,16 @@ typedef struct drm_i915_private {
		size_t object_memory;
		u32 object_count;
	} mm;

	/* Old dri1 support infrastructure, beware the dragons ya fools entering
	 * here! */
	struct {
		unsigned allow_batchbuffer : 1;
		u32 __iomem *gfx_hws_cpu_addr;
	} dri1;

	/* Kernel Modesetting */

	struct sdvo_device_mapping sdvo_mappings[2];
	/* indicate whether the LVDS_BORDER should be enabled or not */
	unsigned int lvds_border_bits;
@@ -751,7 +762,8 @@ typedef struct drm_i915_private {
	struct drm_crtc *plane_to_crtc_mapping[3];
	struct drm_crtc *pipe_to_crtc_mapping[3];
	wait_queue_head_t pending_flip_queue;
	bool flip_pending_is_done;

	struct intel_pch_pll pch_plls[I915_NUM_PLLS];

	/* Reclocking support */
	bool render_reclock_avail;
@@ -869,7 +881,14 @@ struct drm_i915_gem_object {
	 * Current tiling mode for the object.
	 */
	unsigned int tiling_mode:2;
	unsigned int tiling_changed:1;
	/**
	 * Whether the tiling parameters for the currently associated fence
	 * register have changed. Note that for the purposes of tracking
	 * tiling changes we also treat the unfenced register, the register
	 * slot that the object occupies whilst it executes a fenced
	 * command (such as BLT on gen2/3), as a "fence".
	 */
	unsigned int fence_dirty:1;

	/** How many users have pinned this object in GTT space. The following
	 * users can each hold at most one reference: pwrite/pread, pin_ioctl
@@ -1116,6 +1135,7 @@ extern int i915_master_create(struct drm_device *dev, struct drm_master *master)
extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);

				/* i915_dma.c */
void i915_update_dri1_breadcrumb(struct drm_device *dev);
extern void i915_kernel_lost_context(struct drm_device * dev);
extern int i915_driver_load(struct drm_device *, unsigned long flags);
extern int i915_driver_unload(struct drm_device *);
@@ -1133,7 +1153,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
extern int i915_emit_box(struct drm_device *dev,
			 struct drm_clip_rect *box,
			 int DR1, int DR4);
extern int i915_reset(struct drm_device *dev, u8 flags);
extern int i915_reset(struct drm_device *dev);
extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
@@ -1143,19 +1163,10 @@ extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
/* i915_irq.c */
void i915_hangcheck_elapsed(unsigned long data);
void i915_handle_error(struct drm_device *dev, bool wedged);
extern int i915_irq_emit(struct drm_device *dev, void *data,
			 struct drm_file *file_priv);
extern int i915_irq_wait(struct drm_device *dev, void *data,
			 struct drm_file *file_priv);

extern void intel_irq_init(struct drm_device *dev);

extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
				struct drm_file *file_priv);
extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
				struct drm_file *file_priv);
extern int i915_vblank_swap(struct drm_device *dev, void *data,
			    struct drm_file *file_priv);
void i915_error_state_free(struct kref *error_ref);

void
i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
@@ -1287,18 +1298,18 @@ int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj,
					    uint32_t read_domains,
					    uint32_t write_domain);
int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj);
int __must_check i915_gem_init(struct drm_device *dev);
int __must_check i915_gem_init_hw(struct drm_device *dev);
void i915_gem_init_swizzling(struct drm_device *dev);
void i915_gem_init_ppgtt(struct drm_device *dev);
void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
int __must_check i915_gpu_idle(struct drm_device *dev, bool do_retire);
int __must_check i915_gpu_idle(struct drm_device *dev);
int __must_check i915_gem_idle(struct drm_device *dev);
int __must_check i915_add_request(struct intel_ring_buffer *ring,
				  struct drm_file *file,
				  struct drm_i915_gem_request *request);
int __must_check i915_wait_request(struct intel_ring_buffer *ring,
				   uint32_t seqno,
				   bool do_retire);
				   uint32_t seqno);
int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
int __must_check
i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
@@ -1349,10 +1360,11 @@ void i915_gem_init_global_gtt(struct drm_device *dev,
/* i915_gem_evict.c */
int __must_check i915_gem_evict_something(struct drm_device *dev, int min_size,
					  unsigned alignment, bool mappable);
int __must_check i915_gem_evict_everything(struct drm_device *dev,
					   bool purgeable_only);
int __must_check i915_gem_evict_inactive(struct drm_device *dev,
					 bool purgeable_only);
int i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only);

/* i915_gem_stolen.c */
int i915_gem_init_stolen(struct drm_device *dev);
void i915_gem_cleanup_stolen(struct drm_device *dev);

/* i915_gem_tiling.c */
void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
@@ -1467,28 +1479,6 @@ extern void intel_display_print_error_state(struct seq_file *m,
					    struct intel_display_error_state *error);
#endif

#define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])

#define BEGIN_LP_RING(n) \
	intel_ring_begin(LP_RING(dev_priv), (n))

#define OUT_RING(x) \
	intel_ring_emit(LP_RING(dev_priv), x)

#define ADVANCE_LP_RING() \
	intel_ring_advance(LP_RING(dev_priv))

/**
 * Lock test for when it's just for synchronization of ring access.
 *
 * In that case, we don't need to do it when GEM is initialized as nobody else
 * has access to the ring.
 */
#define RING_LOCK_TEST_WITH_RETURN(dev, file) do {			\
	if (LP_RING(dev->dev_private)->obj == NULL)			\
		LOCK_TEST_WITH_RETURN(dev, file);			\
} while (0)

/* On SNB platform, before reading ring registers forcewake bit
 * must be set to prevent GT core from power down and stale values being
 * returned.
Loading