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

Commit fc6826d1 authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter
Browse files

drm/i915: Refactor the deferred PM_IIR handling into a single function



This function, along with the registers and deferred work hander, are
all shared with SandyBridge, IvyBridge and their variants. So remove the
duplicate code into a single function.

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarBen Widawsky <ben@bwidawsk.net>
Signed-Off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent c07496fa
Loading
Loading
Loading
Loading
+31 −39
Original line number Diff line number Diff line
@@ -451,6 +451,31 @@ static void snb_gt_irq_handler(struct drm_device *dev,
	}
}

static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
				u32 pm_iir)
{
	unsigned long flags;

	/*
	 * IIR bits should never already be set because IMR should
	 * prevent an interrupt from being shown in IIR. The warning
	 * displays a case where we've unsafely cleared
	 * dev_priv->pm_iir. Although missing an interrupt of the same
	 * type is not a problem, it displays a problem in the logic.
	 *
	 * The mask bit in IMR is cleared by rps_work.
	 */

	spin_lock_irqsave(&dev_priv->rps_lock, flags);
	WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
	dev_priv->pm_iir |= pm_iir;
	I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
	POSTING_READ(GEN6_PMIMR);
	spin_unlock_irqrestore(&dev_priv->rps_lock, flags);

	queue_work(dev_priv->wq, &dev_priv->rps_work);
}

static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
{
	struct drm_device *dev = (struct drm_device *) arg;
@@ -532,16 +557,8 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
		if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
			blc_event = true;

		if (pm_iir & GEN6_PM_DEFERRED_EVENTS) {
			unsigned long flags;
			spin_lock_irqsave(&dev_priv->rps_lock, flags);
			WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
			dev_priv->pm_iir |= pm_iir;
			I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
			POSTING_READ(GEN6_PMIMR);
			spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
			queue_work(dev_priv->wq, &dev_priv->rps_work);
		}
		if (pm_iir & GEN6_PM_DEFERRED_EVENTS)
			gen6_queue_rps_work(dev_priv, pm_iir);

		I915_WRITE(GTIIR, gt_iir);
		I915_WRITE(GEN6_PMIIR, pm_iir);
@@ -655,16 +672,8 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
		pch_irq_handler(dev);
	}

	if (pm_iir & GEN6_PM_DEFERRED_EVENTS) {
		unsigned long flags;
		spin_lock_irqsave(&dev_priv->rps_lock, flags);
		WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
		dev_priv->pm_iir |= pm_iir;
		I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
		POSTING_READ(GEN6_PMIMR);
		spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
		queue_work(dev_priv->wq, &dev_priv->rps_work);
	}
	if (pm_iir & GEN6_PM_DEFERRED_EVENTS)
		gen6_queue_rps_work(dev_priv, pm_iir);

	/* should clear PCH hotplug event before clear CPU irq */
	I915_WRITE(SDEIIR, pch_iir);
@@ -764,25 +773,8 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
		i915_handle_rps_change(dev);
	}

	if (IS_GEN6(dev) && pm_iir & GEN6_PM_DEFERRED_EVENTS) {
		/*
		 * IIR bits should never already be set because IMR should
		 * prevent an interrupt from being shown in IIR. The warning
		 * displays a case where we've unsafely cleared
		 * dev_priv->pm_iir. Although missing an interrupt of the same
		 * type is not a problem, it displays a problem in the logic.
		 *
		 * The mask bit in IMR is cleared by rps_work.
		 */
		unsigned long flags;
		spin_lock_irqsave(&dev_priv->rps_lock, flags);
		WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
		dev_priv->pm_iir |= pm_iir;
		I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
		POSTING_READ(GEN6_PMIMR);
		spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
		queue_work(dev_priv->wq, &dev_priv->rps_work);
	}
	if (IS_GEN6(dev) && pm_iir & GEN6_PM_DEFERRED_EVENTS)
		gen6_queue_rps_work(dev_priv, pm_iir);

	/* should clear PCH hotplug event before clear CPU irq */
	I915_WRITE(SDEIIR, pch_iir);