xref: /linux/drivers/gpu/drm/xe/xe_guard.h (revision 24f171c7e145f43b9f187578e89b0982ce87e54c)
1*387aba39SMichal Wajdeczko /* SPDX-License-Identifier: MIT */
2*387aba39SMichal Wajdeczko /*
3*387aba39SMichal Wajdeczko  * Copyright © 2025 Intel Corporation
4*387aba39SMichal Wajdeczko  */
5*387aba39SMichal Wajdeczko 
6*387aba39SMichal Wajdeczko #ifndef _XE_GUARD_H_
7*387aba39SMichal Wajdeczko #define _XE_GUARD_H_
8*387aba39SMichal Wajdeczko 
9*387aba39SMichal Wajdeczko #include <linux/spinlock.h>
10*387aba39SMichal Wajdeczko 
11*387aba39SMichal Wajdeczko /**
12*387aba39SMichal Wajdeczko  * struct xe_guard - Simple logic to protect a feature.
13*387aba39SMichal Wajdeczko  *
14*387aba39SMichal Wajdeczko  * Implements simple semaphore-like logic that can be used to lockdown the
15*387aba39SMichal Wajdeczko  * feature unless it is already in use.  Allows enabling of the otherwise
16*387aba39SMichal Wajdeczko  * incompatible features, where we can't follow the strict owner semantics
17*387aba39SMichal Wajdeczko  * required by the &rw_semaphore.
18*387aba39SMichal Wajdeczko  *
19*387aba39SMichal Wajdeczko  * NOTE! It shouldn't be used to protect a data, use &rw_semaphore instead.
20*387aba39SMichal Wajdeczko  */
21*387aba39SMichal Wajdeczko struct xe_guard {
22*387aba39SMichal Wajdeczko 	/**
23*387aba39SMichal Wajdeczko 	 * @counter: implements simple exclusive/lockdown logic:
24*387aba39SMichal Wajdeczko 	 *           if == 0 then guard/feature is idle/not in use,
25*387aba39SMichal Wajdeczko 	 *           if < 0 then feature is active and can't be locked-down,
26*387aba39SMichal Wajdeczko 	 *           if > 0 then feature is lockded-down and can't be activated.
27*387aba39SMichal Wajdeczko 	 */
28*387aba39SMichal Wajdeczko 	int counter;
29*387aba39SMichal Wajdeczko 
30*387aba39SMichal Wajdeczko 	/** @name: the name of the guard (useful for debug) */
31*387aba39SMichal Wajdeczko 	const char *name;
32*387aba39SMichal Wajdeczko 
33*387aba39SMichal Wajdeczko 	/** @owner: the info about the last owner of the guard (for debug) */
34*387aba39SMichal Wajdeczko 	void *owner;
35*387aba39SMichal Wajdeczko 
36*387aba39SMichal Wajdeczko 	/** @lock: protects guard's data */
37*387aba39SMichal Wajdeczko 	spinlock_t lock;
38*387aba39SMichal Wajdeczko };
39*387aba39SMichal Wajdeczko 
40*387aba39SMichal Wajdeczko /**
41*387aba39SMichal Wajdeczko  * xe_guard_init() - Initialize the guard.
42*387aba39SMichal Wajdeczko  * @guard: the &xe_guard to init
43*387aba39SMichal Wajdeczko  * @name: name of the guard
44*387aba39SMichal Wajdeczko  */
45*387aba39SMichal Wajdeczko static inline void xe_guard_init(struct xe_guard *guard, const char *name)
46*387aba39SMichal Wajdeczko {
47*387aba39SMichal Wajdeczko 	spin_lock_init(&guard->lock);
48*387aba39SMichal Wajdeczko 	guard->counter = 0;
49*387aba39SMichal Wajdeczko 	guard->name = name;
50*387aba39SMichal Wajdeczko }
51*387aba39SMichal Wajdeczko 
52*387aba39SMichal Wajdeczko /**
53*387aba39SMichal Wajdeczko  * xe_guard_arm() - Arm the guard for the exclusive/lockdown mode.
54*387aba39SMichal Wajdeczko  * @guard: the &xe_guard to arm
55*387aba39SMichal Wajdeczko  * @lockdown: arm for lockdown(true) or exclusive(false) mode
56*387aba39SMichal Wajdeczko  * @who: optional owner info (for debug only)
57*387aba39SMichal Wajdeczko  *
58*387aba39SMichal Wajdeczko  * Multiple lockdown requests are allowed.
59*387aba39SMichal Wajdeczko  * Only single exclusive access can be granted.
60*387aba39SMichal Wajdeczko  * Will fail if the guard is already in exclusive mode.
61*387aba39SMichal Wajdeczko  * On success, must call the xe_guard_disarm() to release.
62*387aba39SMichal Wajdeczko  *
63*387aba39SMichal Wajdeczko  * Return: 0 on success or a negative error code on failure.
64*387aba39SMichal Wajdeczko  */
65*387aba39SMichal Wajdeczko static inline int xe_guard_arm(struct xe_guard *guard, bool lockdown, void *who)
66*387aba39SMichal Wajdeczko {
67*387aba39SMichal Wajdeczko 	guard(spinlock)(&guard->lock);
68*387aba39SMichal Wajdeczko 
69*387aba39SMichal Wajdeczko 	if (lockdown) {
70*387aba39SMichal Wajdeczko 		if (guard->counter < 0)
71*387aba39SMichal Wajdeczko 			return -EBUSY;
72*387aba39SMichal Wajdeczko 		guard->counter++;
73*387aba39SMichal Wajdeczko 	} else {
74*387aba39SMichal Wajdeczko 		if (guard->counter > 0)
75*387aba39SMichal Wajdeczko 			return -EPERM;
76*387aba39SMichal Wajdeczko 		if (guard->counter < 0)
77*387aba39SMichal Wajdeczko 			return -EUSERS;
78*387aba39SMichal Wajdeczko 		guard->counter--;
79*387aba39SMichal Wajdeczko 	}
80*387aba39SMichal Wajdeczko 
81*387aba39SMichal Wajdeczko 	guard->owner = who;
82*387aba39SMichal Wajdeczko 	return 0;
83*387aba39SMichal Wajdeczko }
84*387aba39SMichal Wajdeczko 
85*387aba39SMichal Wajdeczko /**
86*387aba39SMichal Wajdeczko  * xe_guard_disarm() - Disarm the guard from exclusive/lockdown mode.
87*387aba39SMichal Wajdeczko  * @guard: the &xe_guard to disarm
88*387aba39SMichal Wajdeczko  * @lockdown: disarm from lockdown(true) or exclusive(false) mode
89*387aba39SMichal Wajdeczko  *
90*387aba39SMichal Wajdeczko  * Return: true if successfully disarmed or false in case of mismatch.
91*387aba39SMichal Wajdeczko  */
92*387aba39SMichal Wajdeczko static inline bool xe_guard_disarm(struct xe_guard *guard, bool lockdown)
93*387aba39SMichal Wajdeczko {
94*387aba39SMichal Wajdeczko 	guard(spinlock)(&guard->lock);
95*387aba39SMichal Wajdeczko 
96*387aba39SMichal Wajdeczko 	if (lockdown) {
97*387aba39SMichal Wajdeczko 		if (guard->counter <= 0)
98*387aba39SMichal Wajdeczko 			return false;
99*387aba39SMichal Wajdeczko 		guard->counter--;
100*387aba39SMichal Wajdeczko 	} else {
101*387aba39SMichal Wajdeczko 		if (guard->counter != -1)
102*387aba39SMichal Wajdeczko 			return false;
103*387aba39SMichal Wajdeczko 		guard->counter++;
104*387aba39SMichal Wajdeczko 	}
105*387aba39SMichal Wajdeczko 	return true;
106*387aba39SMichal Wajdeczko }
107*387aba39SMichal Wajdeczko 
108*387aba39SMichal Wajdeczko /**
109*387aba39SMichal Wajdeczko  * xe_guard_mode_str() - Convert guard mode into a string.
110*387aba39SMichal Wajdeczko  * @lockdown: flag used to select lockdown or exclusive mode
111*387aba39SMichal Wajdeczko  *
112*387aba39SMichal Wajdeczko  * Return: "lockdown" or "exclusive" string.
113*387aba39SMichal Wajdeczko  */
114*387aba39SMichal Wajdeczko static inline const char *xe_guard_mode_str(bool lockdown)
115*387aba39SMichal Wajdeczko {
116*387aba39SMichal Wajdeczko 	return lockdown ? "lockdown" : "exclusive";
117*387aba39SMichal Wajdeczko }
118*387aba39SMichal Wajdeczko 
119*387aba39SMichal Wajdeczko #endif
120