drivers/dma-buf/dma-fence-array.c

Source file repositories/reference/linux-study-clean/drivers/dma-buf/dma-fence-array.c

File Facts

System
Linux kernel
Corpus path
drivers/dma-buf/dma-fence-array.c
Extension
.c
Size
9669 bytes
Lines
333
Domain
Driver Families
Bucket
drivers/dma-buf
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 (atomic_dec_and_test(&array->num_pending)) {
				dma_fence_array_clear_pending_error(array);
				return false;
			}
		}
	}

	return true;
}

static bool dma_fence_array_signaled(struct dma_fence *fence)
{
	struct dma_fence_array *array = to_dma_fence_array(fence);
	int num_pending;
	unsigned int i;

	/*
	 * We need to read num_pending before checking the enable_signal bit
	 * to avoid racing with the enable_signaling() implementation, which
	 * might decrement the counter, and cause a partial check.
	 * atomic_read_acquire() pairs with atomic_dec_and_test() in
	 * dma_fence_array_enable_signaling()
	 *
	 * The !--num_pending check is here to account for the any_signaled case
	 * if we race with enable_signaling(), that means the !num_pending check
	 * in the is_signalling_enabled branch might be outdated (num_pending
	 * might have been decremented), but that's fine. The user will get the
	 * right value when testing again later.
	 */
	num_pending = atomic_read_acquire(&array->num_pending);
	if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &array->base.flags)) {
		if (num_pending <= 0)
			goto signal;
		return false;
	}

	for (i = 0; i < array->num_fences; ++i) {
		if (dma_fence_is_signaled(array->fences[i]) && !--num_pending)
			goto signal;
	}
	return false;

signal:
	dma_fence_array_clear_pending_error(array);
	return true;
}

static void dma_fence_array_release(struct dma_fence *fence)
{
	struct dma_fence_array *array = to_dma_fence_array(fence);
	unsigned i;

	for (i = 0; i < array->num_fences; ++i)
		dma_fence_put(array->fences[i]);

	kfree(array->fences);
	dma_fence_free(fence);
}

static void dma_fence_array_set_deadline(struct dma_fence *fence,
					 ktime_t deadline)
{
	struct dma_fence_array *array = to_dma_fence_array(fence);
	unsigned i;

	for (i = 0; i < array->num_fences; ++i)
		dma_fence_set_deadline(array->fences[i], deadline);
}

const struct dma_fence_ops dma_fence_array_ops = {
	.get_driver_name = dma_fence_array_get_driver_name,
	.get_timeline_name = dma_fence_array_get_timeline_name,
	.enable_signaling = dma_fence_array_enable_signaling,
	.signaled = dma_fence_array_signaled,
	.release = dma_fence_array_release,
	.set_deadline = dma_fence_array_set_deadline,
};
EXPORT_SYMBOL(dma_fence_array_ops);

/**
 * dma_fence_array_alloc - Allocate a custom fence array
 * @num_fences:		[in]	number of fences to add in the array
 *
 * Return dma fence array on success, NULL on failure
 */
struct dma_fence_array *dma_fence_array_alloc(int num_fences)
{
	struct dma_fence_array *array;

	return kzalloc_flex(*array, callbacks, num_fences);

Annotation

Implementation Notes