drivers/gpu/drm/imagination/pvr_ccb.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/imagination/pvr_ccb.c
Extension
.c
Size
17627 bytes
Lines
668
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

struct pvr_kccb_fence {
	/** @base: Base dma_fence object. */
	struct dma_fence base;

	/** @node: Node used to insert the fence in the pvr_device::kccb::waiters list. */
	struct list_head node;
};

/**
 * pvr_kccb_wake_up_waiters() - Check the KCCB waiters
 * @pvr_dev: Target PowerVR device
 *
 * Signal as many KCCB fences as we have slots available.
 */
void pvr_kccb_wake_up_waiters(struct pvr_device *pvr_dev)
{
	struct pvr_kccb_fence *fence, *tmp_fence;
	u32 used_count, available_count;

	/* Wake up those waiting for KCCB slot execution. */
	wake_up_all(&pvr_dev->kccb.rtn_q);

	/* Then iterate over all KCCB fences and signal as many as we can. */
	mutex_lock(&pvr_dev->kccb.ccb.lock);
	used_count = pvr_kccb_used_slot_count_locked(pvr_dev);

	if (WARN_ON(used_count + pvr_dev->kccb.reserved_count > pvr_kccb_capacity(pvr_dev)))
		goto out_unlock;

	available_count = pvr_kccb_capacity(pvr_dev) - used_count - pvr_dev->kccb.reserved_count;
	list_for_each_entry_safe(fence, tmp_fence, &pvr_dev->kccb.waiters, node) {
		if (!available_count)
			break;

		list_del(&fence->node);
		pvr_dev->kccb.reserved_count++;
		available_count--;
		dma_fence_signal(&fence->base);
		dma_fence_put(&fence->base);
	}

out_unlock:
	mutex_unlock(&pvr_dev->kccb.ccb.lock);
}

/**
 * pvr_kccb_fini() - Cleanup device KCCB
 * @pvr_dev: Target PowerVR device
 */
void pvr_kccb_fini(struct pvr_device *pvr_dev)
{
	pvr_ccb_fini(&pvr_dev->kccb.ccb);
	WARN_ON(!list_empty(&pvr_dev->kccb.waiters));
	WARN_ON(pvr_dev->kccb.reserved_count);
}

/**
 * pvr_kccb_init() - Initialise device KCCB
 * @pvr_dev: Target PowerVR device
 *
 * Returns:
 *  * 0 on success, or
 *  * Any error returned by pvr_ccb_init().
 */
int
pvr_kccb_init(struct pvr_device *pvr_dev)
{
	pvr_dev->kccb.slot_count = 1 << ROGUE_FWIF_KCCB_NUMCMDS_LOG2_DEFAULT;
	INIT_LIST_HEAD(&pvr_dev->kccb.waiters);
	pvr_dev->kccb.fence_ctx.id = dma_fence_context_alloc(1);
	spin_lock_init(&pvr_dev->kccb.fence_ctx.lock);

	return pvr_ccb_init(pvr_dev, &pvr_dev->kccb.ccb,
			    ROGUE_FWIF_KCCB_NUMCMDS_LOG2_DEFAULT,
			    sizeof(struct rogue_fwif_kccb_cmd));
}

/**
 * pvr_kccb_fence_alloc() - Allocate a pvr_kccb_fence object
 *
 * Return:
 *  * NULL if the allocation fails, or
 *  * A valid dma_fence pointer otherwise.
 */
struct dma_fence *pvr_kccb_fence_alloc(void)
{
	struct pvr_kccb_fence *kccb_fence;

	kccb_fence = kzalloc_obj(*kccb_fence);
	if (!kccb_fence)

Annotation

Implementation Notes