drivers/gpu/drm/vmwgfx/vmwgfx_irq.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
Extension
.c
Size
9948 bytes
Lines
371
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (dev_priv->cman) {
			ret = vmw_cmdbuf_idle(dev_priv->cman, interruptible,
					      10*HZ);
			if (ret)
				goto out_err;
		} else if (fifo_state) {
			down_read(&fifo_state->rwsem);
			fifo_down = true;
		}
	}

	signal_seq = atomic_read(&dev_priv->marker_seq);
	ret = 0;

	for (;;) {
		prepare_to_wait(&dev_priv->fence_queue, &__wait,
				(interruptible) ?
				TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
		if (wait_condition(dev_priv, seqno))
			break;
		if (time_after_eq(jiffies, end_jiffies)) {
			DRM_ERROR("SVGA device lockup.\n");
			break;
		}
		if (lazy)
			schedule_timeout(1);
		else if ((++count & 0x0F) == 0) {
			/**
			 * FIXME: Use schedule_hr_timeout here for
			 * newer kernels and lower CPU utilization.
			 */

			__set_current_state(TASK_RUNNING);
			schedule();
			__set_current_state((interruptible) ?
					    TASK_INTERRUPTIBLE :
					    TASK_UNINTERRUPTIBLE);
		}
		if (interruptible && signal_pending(current)) {
			ret = -ERESTARTSYS;
			break;
		}
	}
	finish_wait(&dev_priv->fence_queue, &__wait);
	if (ret == 0 && fifo_idle && fifo_state)
		vmw_fence_write(dev_priv, signal_seq);

	wake_up_all(&dev_priv->fence_queue);
out_err:
	if (fifo_down)
		up_read(&fifo_state->rwsem);

	return ret;
}

bool vmw_generic_waiter_add(struct vmw_private *dev_priv,
			    u32 flag, int *waiter_count)
{
	bool hw_programmed = false;

	spin_lock(&dev_priv->waiter_lock);
	if ((*waiter_count)++ == 0) {
		vmw_irq_status_write(dev_priv, flag);
		dev_priv->irq_mask |= flag;
		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
		hw_programmed = true;
	}
	spin_unlock(&dev_priv->waiter_lock);
	return hw_programmed;
}

bool vmw_generic_waiter_remove(struct vmw_private *dev_priv,
			       u32 flag, int *waiter_count)
{
	bool hw_programmed = false;

	spin_lock(&dev_priv->waiter_lock);
	if (--(*waiter_count) == 0) {
		dev_priv->irq_mask &= ~flag;
		vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
		hw_programmed = true;
	}
	spin_unlock(&dev_priv->waiter_lock);
	return hw_programmed;
}

bool vmw_seqno_waiter_add(struct vmw_private *dev_priv)
{
	return vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_ANY_FENCE,
					&dev_priv->fence_queue_waiters);

Annotation

Implementation Notes