drivers/gpu/drm/drm_modeset_lock.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/drm_modeset_lock.c
Extension
.c
Size
14229 bytes
Lines
484
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

*     foreach (lock in random_ordered_set_of_locks) {
 *         ret = drm_modeset_lock(lock, ctx)
 *         if (ret == -EDEADLK) {
 *             ret = drm_modeset_backoff(ctx);
 *             if (!ret)
 *                 goto retry;
 *         }
 *         if (ret)
 *             goto out;
 *     }
 *     ... do stuff ...
 *     out:
 *     drm_modeset_drop_locks(ctx);
 *     drm_modeset_acquire_fini(ctx);
 *
 * For convenience this control flow is implemented in
 * DRM_MODESET_LOCK_ALL_BEGIN() and DRM_MODESET_LOCK_ALL_END() for the case
 * where all modeset locks need to be taken through drm_modeset_lock_all_ctx().
 *
 * If all that is needed is a single modeset lock, then the &struct
 * drm_modeset_acquire_ctx is not needed and the locking can be simplified
 * by passing a NULL instead of ctx in the drm_modeset_lock() call or
 * calling  drm_modeset_lock_single_interruptible(). To unlock afterwards
 * call drm_modeset_unlock().
 *
 * On top of these per-object locks using &ww_mutex there's also an overall
 * &drm_mode_config.mutex, for protecting everything else. Mostly this means
 * probe state of connectors, and preventing hotplug add/removal of connectors.
 *
 * Finally there's a bunch of dedicated locks to protect drm core internal
 * lists and lookup data structures.
 */

static DEFINE_WW_CLASS(crtc_ww_class);

#if IS_ENABLED(CONFIG_DRM_DEBUG_MODESET_LOCK)
static noinline depot_stack_handle_t __drm_stack_depot_save(void)
{
	unsigned long entries[8];
	unsigned int n;

	n = stack_trace_save(entries, ARRAY_SIZE(entries), 1);

	return stack_depot_save(entries, n, GFP_NOWAIT | __GFP_NOWARN);
}

static void __drm_stack_depot_print(depot_stack_handle_t stack_depot)
{
	struct drm_printer p = drm_dbg_printer(NULL, DRM_UT_KMS, "drm_modeset_lock");
	unsigned long *entries;
	unsigned int nr_entries;
	char *buf;

	buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN);
	if (!buf)
		return;

	nr_entries = stack_depot_fetch(stack_depot, &entries);
	stack_trace_snprint(buf, PAGE_SIZE, entries, nr_entries, 2);

	drm_printf(&p, "attempting to lock a contended lock without backoff:\n%s", buf);

	kfree(buf);
}

static void __drm_stack_depot_init(void)
{
	stack_depot_init();
}
#else /* CONFIG_DRM_DEBUG_MODESET_LOCK */
static depot_stack_handle_t __drm_stack_depot_save(void)
{
	return 0;
}
static void __drm_stack_depot_print(depot_stack_handle_t stack_depot)
{
}
static void __drm_stack_depot_init(void)
{
}
#endif /* CONFIG_DRM_DEBUG_MODESET_LOCK */

/**
 * drm_modeset_lock_all - take all modeset locks
 * @dev: DRM device
 *
 * This function takes all modeset locks, suitable where a more fine-grained
 * scheme isn't (yet) implemented. Locks must be dropped by calling the
 * drm_modeset_unlock_all() function.
 *

Annotation

Implementation Notes