Example #1
0
static int i915_wait_irq(drm_device_t * dev, int irq_nr)
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
	int ret = 0;

	DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr,
		  READ_BREADCRUMB(dev_priv));

	if (READ_BREADCRUMB(dev_priv) >= irq_nr)
		return 0;

	dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;

	DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
		    READ_BREADCRUMB(dev_priv) >= irq_nr);

	if (ret == DRM_ERR(EBUSY)) {
		DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n",
			  __FUNCTION__,
			  READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
	}

	dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
	return ret;
}
Example #2
0
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
	drm_device_t *dev = (drm_device_t *) arg;
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
	u16 temp;

	temp = I915_READ16(I915REG_INT_IDENTITY_R);

	temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);

	DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);

	if (temp == 0)
		return IRQ_NONE;

	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);

	dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);

	if (temp & USER_INT_FLAG)
		DRM_WAKEUP(&dev_priv->irq_queue);

	if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
		atomic_inc(&dev->vbl_received);
		DRM_WAKEUP(&dev->vbl_queue);
		drm_vbl_send_signals(dev);
	}

	return IRQ_HANDLED;
}
Example #3
0
static void i915_initiate_rwflush(struct drm_i915_private *dev_priv, 
				  struct drm_fence_class_manager *fc)
{
	if ((fc->pending_flush & DRM_I915_FENCE_TYPE_RW) && 
	    !dev_priv->flush_pending) {
		dev_priv->flush_sequence = (uint32_t) READ_BREADCRUMB(dev_priv);
		dev_priv->flush_flags = fc->pending_flush;
		dev_priv->saved_flush_status = READ_HWSP(dev_priv, 0);
		I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21));
		dev_priv->flush_pending = 1;
		fc->pending_flush &= ~DRM_I915_FENCE_TYPE_RW;
	}
}
Example #4
0
static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class,
			    uint32_t waiting_types)
{
	struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
	struct drm_fence_manager *fm = &dev->fm;
	struct drm_fence_class_manager *fc = &fm->fence_class[0];
	uint32_t flush_flags = 0;
	uint32_t flush_sequence = 0;
	uint32_t i_status;
	uint32_t sequence;

	if (unlikely(!dev_priv))
		return;

	/*
	 * First, report any executed sync flush:
	 */

	if (dev_priv->flush_pending) {
		i_status = READ_HWSP(dev_priv, 0);
		if ((i_status & (1 << 12)) !=
		    (dev_priv->saved_flush_status & (1 << 12))) {
			flush_flags = dev_priv->flush_flags;
			flush_sequence = dev_priv->flush_sequence;
			dev_priv->flush_pending = 0;
			drm_fence_handler(dev, 0, flush_sequence, flush_flags, 0);
		}
	}		

	/*
	 * Report A new breadcrumb, and adjust IRQs.
	 */

	if (waiting_types & DRM_FENCE_TYPE_EXE) {
		sequence = READ_BREADCRUMB(dev_priv);

		if (sequence != dev_priv->reported_sequence ||
		    !dev_priv->reported_sequence_valid) {
			drm_fence_handler(dev, 0, sequence, 
					  DRM_FENCE_TYPE_EXE, 0);
			dev_priv->reported_sequence = sequence;
			dev_priv->reported_sequence_valid = 1;
		}

		if (dev_priv->fence_irq_on && !(waiting_types & DRM_FENCE_TYPE_EXE)) {
			i915_user_irq_off(dev_priv);
			dev_priv->fence_irq_on = 0;
		} else if (!dev_priv->fence_irq_on && (waiting_types & DRM_FENCE_TYPE_EXE)) {
			i915_user_irq_on(dev_priv);
			dev_priv->fence_irq_on = 1;
		}
	}

	/*
	 * There may be new RW flushes pending. Start them.
	 */
	
	i915_initiate_rwflush(dev_priv, fc); 

	/*
	 * And possibly, but unlikely, they finish immediately. 
	 */

	if (dev_priv->flush_pending) {
		i_status = READ_HWSP(dev_priv, 0);
		if (unlikely((i_status & (1 << 12)) !=
		    (dev_priv->saved_flush_status & (1 << 12)))) {
			flush_flags = dev_priv->flush_flags;
			flush_sequence = dev_priv->flush_sequence;
			dev_priv->flush_pending = 0;
			drm_fence_handler(dev, 0, flush_sequence, flush_flags, 0);
		}
	}
}