drivers/gpu/drm/drm_vblank_work.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/drm_vblank_work.c
Extension
.c
Size
8905 bytes
Lines
293
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (rescheduling) {
			list_del_init(&work->node);
			wake = true;
		}
	} else {
		if (!rescheduling)
			list_add_tail(&work->node, &vblank->pending_work);
		ret = true;
	}

out:
	spin_unlock_irqrestore(&dev->event_lock, irqflags);
	if (wake)
		wake_up_all(&vblank->work_wait_queue);
	return ret;
}
EXPORT_SYMBOL(drm_vblank_work_schedule);

/**
 * drm_vblank_work_cancel_sync - cancel a vblank work and wait for it to
 * finish executing
 * @work: vblank work to cancel
 *
 * Cancel an already scheduled vblank work and wait for its
 * execution to finish.
 *
 * On return, @work is guaranteed to no longer be scheduled or running, even
 * if it's self-arming.
 *
 * Returns:
 * %True if the work was cancelled before it started to execute, %false
 * otherwise.
 */
bool drm_vblank_work_cancel_sync(struct drm_vblank_work *work)
{
	struct drm_vblank_crtc *vblank = work->vblank;
	struct drm_device *dev = vblank->dev;
	bool ret = false;

	spin_lock_irq(&dev->event_lock);
	if (!list_empty(&work->node)) {
		list_del_init(&work->node);
		drm_vblank_put(vblank->dev, vblank->pipe);
		ret = true;
	}

	work->cancelling++;
	spin_unlock_irq(&dev->event_lock);

	wake_up_all(&vblank->work_wait_queue);

	if (kthread_cancel_work_sync(&work->base))
		ret = true;

	spin_lock_irq(&dev->event_lock);
	work->cancelling--;
	spin_unlock_irq(&dev->event_lock);

	return ret;
}
EXPORT_SYMBOL(drm_vblank_work_cancel_sync);

/**
 * drm_vblank_work_flush - wait for a scheduled vblank work to finish
 * executing
 * @work: vblank work to flush
 *
 * Wait until @work has finished executing once.
 */
void drm_vblank_work_flush(struct drm_vblank_work *work)
{
	struct drm_vblank_crtc *vblank = work->vblank;
	struct drm_device *dev = vblank->dev;

	spin_lock_irq(&dev->event_lock);
	wait_event_lock_irq(vblank->work_wait_queue, list_empty(&work->node),
			    dev->event_lock);
	spin_unlock_irq(&dev->event_lock);

	kthread_flush_work(&work->base);
}
EXPORT_SYMBOL(drm_vblank_work_flush);

/**
 * drm_vblank_work_flush_all - flush all currently pending vblank work on crtc.
 * @crtc: crtc for which vblank work to flush
 *
 * Wait until all currently queued vblank work on @crtc
 * has finished executing once.
 */

Annotation

Implementation Notes