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