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

Commit 7608867d authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-next-fixes-2014-12-04' of...

Merge tag 'drm-intel-next-fixes-2014-12-04' of git://anongit.freedesktop.org/drm-intel into drm-next

Fixes for 3.20. I did stick the gen3/4 reset work from Ville in because we
have an awful lot of gen4 mesa hangs, and with this reset should also work
on vintage i965g/gm (we already have reset for g4x/gen4.5). So should help
to appease users suffering from these hangs. Otherwise all over.

This is the last 3.20 pull from me, from here on Jani will take over. By Ville Syrjälä (8) and others
* tag 'drm-intel-next-fixes-2014-12-04' of git://anongit.freedesktop.org/drm-intel:
  drm/i915: Reject modeset when the same digital port is used more than once
  drm/i915: mask RPS IRQs properly when disabling RPS
  drm/i915: Tune down spurious CRC interrupt warning
  drm/i915: Fix context object leak for legacy contexts
  drm/i915/skl: Update in Gen9 multi-engine forcewake range
  drm/i915/eDP: When enabling panel VDD cancel pending disable worker
  drm/i915: Handle runtime pm in the CRC setup code
  drm/i915: Disable crtcs gracefully before GPU reset on gen3/4
  drm/i915: Grab modeset locks for GPU rest on pre-ctg
  drm/i915: Implement GPU reset for g33
  drm/i915: Implement GPU reset for 915/945
  drm/i915: Restore the display config after a GPU reset on gen4
  drm/i915: Fix gen4 GPU reset
  drm/i915: Stop gathering error states for CS error interrupts
  drm/i915: Disallow pin ioctl completely for kms drivers
  drm/i915: Only warn the first time we attempt to mmio whilst suspended
  drm/i915/chv: Enable AVI, SPD and HDMI infoframes for CHV.
  drm/i915: Don't clobber crtc->new_config when nothing changes
parents 047b35f2 00f0b378
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -3338,6 +3338,11 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
	if (pipe_crc->source && source)
		return -EINVAL;

	if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) {
		DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n");
		return -EIO;
	}

	if (IS_GEN2(dev))
		ret = i8xx_pipe_crc_ctl_reg(&source, &val);
	else if (INTEL_INFO(dev)->gen < 5)
+10 −5
Original line number Diff line number Diff line
@@ -2574,11 +2574,13 @@ static void i915_gem_free_request(struct drm_i915_gem_request *request)
	list_del(&request->list);
	i915_gem_request_remove_from_client(request);

	if (i915.enable_execlists && ctx) {
	if (ctx) {
		if (i915.enable_execlists) {
			struct intel_engine_cs *ring = request->ring;

			if (ctx != ring->default_context)
				intel_lr_context_unpin(ring, ctx);
		}
		i915_gem_context_unreference(ctx);
	}
	kfree(request);
@@ -4263,7 +4265,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
	struct drm_i915_gem_object *obj;
	int ret;

	if (INTEL_INFO(dev)->gen >= 6)
	if (drm_core_check_feature(dev, DRIVER_MODESET))
		return -ENODEV;

	ret = i915_mutex_lock_interruptible(dev);
@@ -4319,6 +4321,9 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
	struct drm_i915_gem_object *obj;
	int ret;

	if (drm_core_check_feature(dev, DRIVER_MODESET))
		return -ENODEV;

	ret = i915_mutex_lock_interruptible(dev);
	if (ret)
		return ret;
+32 −27
Original line number Diff line number Diff line
@@ -231,9 +231,6 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,

	assert_spin_locked(&dev_priv->irq_lock);

	if (WARN_ON(!intel_irqs_enabled(dev_priv)))
		return;

	new_val = dev_priv->pm_irq_mask;
	new_val &= ~interrupt_mask;
	new_val |= (~enabled_irq_mask & interrupt_mask);
@@ -247,14 +244,26 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,

void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
{
	if (WARN_ON(!intel_irqs_enabled(dev_priv)))
		return;

	snb_update_pm_irq(dev_priv, mask, mask);
}

void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
static void __gen6_disable_pm_irq(struct drm_i915_private *dev_priv,
				  uint32_t mask)
{
	snb_update_pm_irq(dev_priv, mask, 0);
}

void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
{
	if (WARN_ON(!intel_irqs_enabled(dev_priv)))
		return;

	__gen6_disable_pm_irq(dev_priv, mask);
}

void gen6_reset_rps_interrupts(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -289,16 +298,20 @@ void gen6_disable_rps_interrupts(struct drm_device *dev)

	cancel_work_sync(&dev_priv->rps.work);

	spin_lock_irq(&dev_priv->irq_lock);

	I915_WRITE(GEN6_PMINTRMSK, INTEL_INFO(dev_priv)->gen >= 8 ?
		   ~GEN8_PMINTR_REDIRECT_TO_NON_DISP : ~0);

	__gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events);
	I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) &
				~dev_priv->pm_rps_events);
	I915_WRITE(gen6_pm_iir(dev_priv), dev_priv->pm_rps_events);
	I915_WRITE(gen6_pm_iir(dev_priv), dev_priv->pm_rps_events);

	spin_lock_irq(&dev_priv->irq_lock);
	dev_priv->rps.pm_iir = 0;
	spin_unlock_irq(&dev_priv->irq_lock);

	I915_WRITE(gen6_pm_iir(dev_priv), dev_priv->pm_rps_events);
	spin_unlock_irq(&dev_priv->irq_lock);
}

/**
@@ -1339,10 +1352,8 @@ static void snb_gt_irq_handler(struct drm_device *dev,

	if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT |
		      GT_BSD_CS_ERROR_INTERRUPT |
		      GT_RENDER_CS_MASTER_ERROR_INTERRUPT)) {
		i915_handle_error(dev, false, "GT error interrupt 0x%08x",
				  gt_iir);
	}
		      GT_RENDER_CS_MASTER_ERROR_INTERRUPT))
		DRM_DEBUG("Command parser error, gt_iir 0x%08x\n", gt_iir);

	if (gt_iir & GT_PARITY_ERROR(dev))
		ivybridge_parity_error_irq_handler(dev, gt_iir);
@@ -1623,7 +1634,7 @@ static void display_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe,

	if (!pipe_crc->entries) {
		spin_unlock(&pipe_crc->lock);
		DRM_ERROR("spurious interrupt\n");
		DRM_DEBUG_KMS("spurious interrupt\n");
		return;
	}

@@ -1731,11 +1742,8 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
		if (pm_iir & PM_VEBOX_USER_INTERRUPT)
			notify_ring(dev_priv->dev, &dev_priv->ring[VECS]);

		if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) {
			i915_handle_error(dev_priv->dev, false,
					  "VEBOX CS error interrupt 0x%08x",
					  pm_iir);
		}
		if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT)
			DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir);
	}
}

@@ -2428,6 +2436,9 @@ static void i915_error_work_func(struct work_struct *work)
		 * simulated reset via debugs, so get an RPM reference.
		 */
		intel_runtime_pm_get(dev_priv);

		intel_prepare_reset(dev);

		/*
		 * All state reset _must_ be completed before we update the
		 * reset counter, for otherwise waiters might miss the reset
@@ -2436,7 +2447,7 @@ static void i915_error_work_func(struct work_struct *work)
		 */
		ret = i915_reset(dev);

		intel_display_handle_reset(dev);
		intel_finish_reset(dev);

		intel_runtime_pm_put(dev_priv);

@@ -3746,9 +3757,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
		 */
		spin_lock(&dev_priv->irq_lock);
		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
			i915_handle_error(dev, false,
					  "Command parser error, iir 0x%08x",
					  iir);
			DRM_DEBUG("Command parser error, iir 0x%08x\n", iir);

		for_each_pipe(dev_priv, pipe) {
			int reg = PIPESTAT(pipe);
@@ -3929,9 +3938,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
		 */
		spin_lock(&dev_priv->irq_lock);
		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
			i915_handle_error(dev, false,
					  "Command parser error, iir 0x%08x",
					  iir);
			DRM_DEBUG("Command parser error, iir 0x%08x\n", iir);

		for_each_pipe(dev_priv, pipe) {
			int reg = PIPESTAT(pipe);
@@ -4154,9 +4161,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
		 */
		spin_lock(&dev_priv->irq_lock);
		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
			i915_handle_error(dev, false,
					  "Command parser error, iir 0x%08x",
					  iir);
			DRM_DEBUG("Command parser error, iir 0x%08x\n", iir);

		for_each_pipe(dev_priv, pipe) {
			int reg = PIPESTAT(pipe);
+2 −1
Original line number Diff line number Diff line
@@ -78,11 +78,12 @@


/* Graphics reset regs */
#define I965_GDRST 0xc0 /* PCI config register */
#define I915_GDRST 0xc0 /* PCI config register */
#define  GRDOM_FULL	(0<<2)
#define  GRDOM_RENDER	(1<<2)
#define  GRDOM_MEDIA	(3<<2)
#define  GRDOM_MASK	(3<<2)
#define  GRDOM_RESET_STATUS (1<<1)
#define  GRDOM_RESET_ENABLE (1<<0)

#define ILK_GDSR 0x2ca4 /* MCHBAR offset */
+132 −19
Original line number Diff line number Diff line
@@ -2765,25 +2765,10 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
	return 0;
}

void intel_display_handle_reset(struct drm_device *dev)
static void intel_complete_page_flips(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_crtc *crtc;

	/*
	 * Flips in the rings have been nuked by the reset,
	 * so complete all pending flips so that user space
	 * will get its events and not get stuck.
	 *
	 * Also update the base address of all primary
	 * planes to the the last fb to make sure we're
	 * showing the correct fb after a reset.
	 *
	 * Need to make two loops over the crtcs so that we
	 * don't try to grab a crtc mutex before the
	 * pending_flip_queue really got woken up.
	 */

	for_each_crtc(dev, crtc) {
		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
		enum plane plane = intel_crtc->plane;
@@ -2791,6 +2776,12 @@ void intel_display_handle_reset(struct drm_device *dev)
		intel_prepare_page_flip(dev, plane);
		intel_finish_page_flip_plane(dev, plane);
	}
}

static void intel_update_primary_planes(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_crtc *crtc;

	for_each_crtc(dev, crtc) {
		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -2810,6 +2801,79 @@ void intel_display_handle_reset(struct drm_device *dev)
	}
}

void intel_prepare_reset(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct intel_crtc *crtc;

	/* no reset support for gen2 */
	if (IS_GEN2(dev))
		return;

	/* reset doesn't touch the display */
	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
		return;

	drm_modeset_lock_all(dev);

	/*
	 * Disabling the crtcs gracefully seems nicer. Also the
	 * g33 docs say we should at least disable all the planes.
	 */
	for_each_intel_crtc(dev, crtc) {
		if (crtc->active)
			dev_priv->display.crtc_disable(&crtc->base);
	}
}

void intel_finish_reset(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = to_i915(dev);

	/*
	 * Flips in the rings will be nuked by the reset,
	 * so complete all pending flips so that user space
	 * will get its events and not get stuck.
	 */
	intel_complete_page_flips(dev);

	/* no reset support for gen2 */
	if (IS_GEN2(dev))
		return;

	/* reset doesn't touch the display */
	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) {
		/*
		 * Flips in the rings have been nuked by the reset,
		 * so update the base address of all primary
		 * planes to the the last fb to make sure we're
		 * showing the correct fb after a reset.
		 */
		intel_update_primary_planes(dev);
		return;
	}

	/*
	 * The display has been reset as well,
	 * so need a full re-initialization.
	 */
	intel_runtime_pm_disable_interrupts(dev_priv);
	intel_runtime_pm_enable_interrupts(dev_priv);

	intel_modeset_init_hw(dev);

	spin_lock_irq(&dev_priv->irq_lock);
	if (dev_priv->display.hpd_irq_setup)
		dev_priv->display.hpd_irq_setup(dev);
	spin_unlock_irq(&dev_priv->irq_lock);

	intel_modeset_setup_hw_state(dev, true);

	intel_hpd_init(dev_priv);

	drm_modeset_unlock_all(dev);
}

static int
intel_finish_fb(struct drm_framebuffer *old_fb)
{
@@ -10089,6 +10153,48 @@ static bool check_encoder_cloning(struct intel_crtc *crtc)
	return true;
}

static bool check_digital_port_conflicts(struct drm_device *dev)
{
	struct intel_connector *connector;
	unsigned int used_ports = 0;

	/*
	 * Walk the connector list instead of the encoder
	 * list to detect the problem on ddi platforms
	 * where there's just one encoder per digital port.
	 */
	list_for_each_entry(connector,
			    &dev->mode_config.connector_list, base.head) {
		struct intel_encoder *encoder = connector->new_encoder;

		if (!encoder)
			continue;

		WARN_ON(!encoder->new_crtc);

		switch (encoder->type) {
			unsigned int port_mask;
		case INTEL_OUTPUT_UNKNOWN:
			if (WARN_ON(!HAS_DDI(dev)))
				break;
		case INTEL_OUTPUT_DISPLAYPORT:
		case INTEL_OUTPUT_HDMI:
		case INTEL_OUTPUT_EDP:
			port_mask = 1 << enc_to_dig_port(&encoder->base)->port;

			/* the same port mustn't appear more than once */
			if (used_ports & port_mask)
				return false;

			used_ports |= port_mask;
		default:
			break;
		}
	}

	return true;
}

static struct intel_crtc_config *
intel_modeset_pipe_config(struct drm_crtc *crtc,
			  struct drm_framebuffer *fb,
@@ -10105,6 +10211,11 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
		return ERR_PTR(-EINVAL);
	}

	if (!check_digital_port_conflicts(dev)) {
		DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n");
		return ERR_PTR(-EINVAL);
	}

	pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
	if (!pipe_config)
		return ERR_PTR(-ENOMEM);
@@ -10907,7 +11018,6 @@ intel_modeset_compute_config(struct drm_crtc *crtc,
	}
	intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,
			       "[modeset]");
	to_intel_crtc(crtc)->new_config = pipe_config;

out:
	return pipe_config;
@@ -10933,6 +11043,9 @@ static int __intel_set_mode(struct drm_crtc *crtc,

	*saved_mode = crtc->mode;

	if (modeset_pipes)
		to_intel_crtc(crtc)->new_config = pipe_config;

	/*
	 * See if the config requires any additional preparation, e.g.
	 * to adjust global state with pipes off.  We need to do this
@@ -11466,12 +11579,12 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
		ret = PTR_ERR(pipe_config);
		goto fail;
	} else if (pipe_config) {
		if (to_intel_crtc(set->crtc)->new_config->has_audio !=
		if (pipe_config->has_audio !=
		    to_intel_crtc(set->crtc)->config.has_audio)
			config->mode_changed = true;

		/* Force mode sets for any infoframe stuff */
		if (to_intel_crtc(set->crtc)->new_config->has_infoframe ||
		if (pipe_config->has_infoframe ||
		    to_intel_crtc(set->crtc)->config.has_infoframe)
			config->mode_changed = true;
	}
Loading