hwspinlock.h (16013B)
1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Hardware spinlock public header 4 * 5 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com 6 * 7 * Contact: Ohad Ben-Cohen <ohad@wizery.com> 8 */ 9 10#ifndef __LINUX_HWSPINLOCK_H 11#define __LINUX_HWSPINLOCK_H 12 13#include <linux/err.h> 14#include <linux/sched.h> 15 16/* hwspinlock mode argument */ 17#define HWLOCK_IRQSTATE 0x01 /* Disable interrupts, save state */ 18#define HWLOCK_IRQ 0x02 /* Disable interrupts, don't save state */ 19#define HWLOCK_RAW 0x03 20#define HWLOCK_IN_ATOMIC 0x04 /* Called while in atomic context */ 21 22struct device; 23struct device_node; 24struct hwspinlock; 25struct hwspinlock_device; 26struct hwspinlock_ops; 27 28/** 29 * struct hwspinlock_pdata - platform data for hwspinlock drivers 30 * @base_id: base id for this hwspinlock device 31 * 32 * hwspinlock devices provide system-wide hardware locks that are used 33 * by remote processors that have no other way to achieve synchronization. 34 * 35 * To achieve that, each physical lock must have a system-wide id number 36 * that is agreed upon, otherwise remote processors can't possibly assume 37 * they're using the same hardware lock. 38 * 39 * Usually boards have a single hwspinlock device, which provides several 40 * hwspinlocks, and in this case, they can be trivially numbered 0 to 41 * (num-of-locks - 1). 42 * 43 * In case boards have several hwspinlocks devices, a different base id 44 * should be used for each hwspinlock device (they can't all use 0 as 45 * a starting id!). 46 * 47 * This platform data structure should be used to provide the base id 48 * for each device (which is trivially 0 when only a single hwspinlock 49 * device exists). It can be shared between different platforms, hence 50 * its location. 51 */ 52struct hwspinlock_pdata { 53 int base_id; 54}; 55 56#ifdef CONFIG_HWSPINLOCK 57 58int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev, 59 const struct hwspinlock_ops *ops, int base_id, int num_locks); 60int hwspin_lock_unregister(struct hwspinlock_device *bank); 61struct hwspinlock *hwspin_lock_request(void); 62struct hwspinlock *hwspin_lock_request_specific(unsigned int id); 63int hwspin_lock_free(struct hwspinlock *hwlock); 64int of_hwspin_lock_get_id(struct device_node *np, int index); 65int hwspin_lock_get_id(struct hwspinlock *hwlock); 66int __hwspin_lock_timeout(struct hwspinlock *, unsigned int, int, 67 unsigned long *); 68int __hwspin_trylock(struct hwspinlock *, int, unsigned long *); 69void __hwspin_unlock(struct hwspinlock *, int, unsigned long *); 70int of_hwspin_lock_get_id_byname(struct device_node *np, const char *name); 71int devm_hwspin_lock_free(struct device *dev, struct hwspinlock *hwlock); 72struct hwspinlock *devm_hwspin_lock_request(struct device *dev); 73struct hwspinlock *devm_hwspin_lock_request_specific(struct device *dev, 74 unsigned int id); 75int devm_hwspin_lock_unregister(struct device *dev, 76 struct hwspinlock_device *bank); 77int devm_hwspin_lock_register(struct device *dev, 78 struct hwspinlock_device *bank, 79 const struct hwspinlock_ops *ops, 80 int base_id, int num_locks); 81 82#else /* !CONFIG_HWSPINLOCK */ 83 84/* 85 * We don't want these functions to fail if CONFIG_HWSPINLOCK is not 86 * enabled. We prefer to silently succeed in this case, and let the 87 * code path get compiled away. This way, if CONFIG_HWSPINLOCK is not 88 * required on a given setup, users will still work. 89 * 90 * The only exception is hwspin_lock_register/hwspin_lock_unregister, with which 91 * we _do_ want users to fail (no point in registering hwspinlock instances if 92 * the framework is not available). 93 * 94 * Note: ERR_PTR(-ENODEV) will still be considered a success for NULL-checking 95 * users. Others, which care, can still check this with IS_ERR. 96 */ 97static inline struct hwspinlock *hwspin_lock_request(void) 98{ 99 return ERR_PTR(-ENODEV); 100} 101 102static inline struct hwspinlock *hwspin_lock_request_specific(unsigned int id) 103{ 104 return ERR_PTR(-ENODEV); 105} 106 107static inline int hwspin_lock_free(struct hwspinlock *hwlock) 108{ 109 return 0; 110} 111 112static inline 113int __hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to, 114 int mode, unsigned long *flags) 115{ 116 return 0; 117} 118 119static inline 120int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags) 121{ 122 return 0; 123} 124 125static inline 126void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags) 127{ 128} 129 130static inline int of_hwspin_lock_get_id(struct device_node *np, int index) 131{ 132 return 0; 133} 134 135static inline int hwspin_lock_get_id(struct hwspinlock *hwlock) 136{ 137 return 0; 138} 139 140static inline 141int of_hwspin_lock_get_id_byname(struct device_node *np, const char *name) 142{ 143 return 0; 144} 145 146static inline 147int devm_hwspin_lock_free(struct device *dev, struct hwspinlock *hwlock) 148{ 149 return 0; 150} 151 152static inline struct hwspinlock *devm_hwspin_lock_request(struct device *dev) 153{ 154 return ERR_PTR(-ENODEV); 155} 156 157static inline 158struct hwspinlock *devm_hwspin_lock_request_specific(struct device *dev, 159 unsigned int id) 160{ 161 return ERR_PTR(-ENODEV); 162} 163 164#endif /* !CONFIG_HWSPINLOCK */ 165 166/** 167 * hwspin_trylock_irqsave() - try to lock an hwspinlock, disable interrupts 168 * @hwlock: an hwspinlock which we want to trylock 169 * @flags: a pointer to where the caller's interrupt state will be saved at 170 * 171 * This function attempts to lock the underlying hwspinlock, and will 172 * immediately fail if the hwspinlock is already locked. 173 * 174 * Upon a successful return from this function, preemption and local 175 * interrupts are disabled (previous interrupts state is saved at @flags), 176 * so the caller must not sleep, and is advised to release the hwspinlock 177 * as soon as possible. 178 * 179 * Returns 0 if we successfully locked the hwspinlock, -EBUSY if 180 * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid. 181 */ 182static inline 183int hwspin_trylock_irqsave(struct hwspinlock *hwlock, unsigned long *flags) 184{ 185 return __hwspin_trylock(hwlock, HWLOCK_IRQSTATE, flags); 186} 187 188/** 189 * hwspin_trylock_irq() - try to lock an hwspinlock, disable interrupts 190 * @hwlock: an hwspinlock which we want to trylock 191 * 192 * This function attempts to lock the underlying hwspinlock, and will 193 * immediately fail if the hwspinlock is already locked. 194 * 195 * Upon a successful return from this function, preemption and local 196 * interrupts are disabled, so the caller must not sleep, and is advised 197 * to release the hwspinlock as soon as possible. 198 * 199 * Returns 0 if we successfully locked the hwspinlock, -EBUSY if 200 * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid. 201 */ 202static inline int hwspin_trylock_irq(struct hwspinlock *hwlock) 203{ 204 return __hwspin_trylock(hwlock, HWLOCK_IRQ, NULL); 205} 206 207/** 208 * hwspin_trylock_raw() - attempt to lock a specific hwspinlock 209 * @hwlock: an hwspinlock which we want to trylock 210 * 211 * This function attempts to lock an hwspinlock, and will immediately fail 212 * if the hwspinlock is already taken. 213 * 214 * Caution: User must protect the routine of getting hardware lock with mutex 215 * or spinlock to avoid dead-lock, that will let user can do some time-consuming 216 * or sleepable operations under the hardware lock. 217 * 218 * Returns 0 if we successfully locked the hwspinlock, -EBUSY if 219 * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid. 220 */ 221static inline int hwspin_trylock_raw(struct hwspinlock *hwlock) 222{ 223 return __hwspin_trylock(hwlock, HWLOCK_RAW, NULL); 224} 225 226/** 227 * hwspin_trylock_in_atomic() - attempt to lock a specific hwspinlock 228 * @hwlock: an hwspinlock which we want to trylock 229 * 230 * This function attempts to lock an hwspinlock, and will immediately fail 231 * if the hwspinlock is already taken. 232 * 233 * This function shall be called only from an atomic context. 234 * 235 * Returns 0 if we successfully locked the hwspinlock, -EBUSY if 236 * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid. 237 */ 238static inline int hwspin_trylock_in_atomic(struct hwspinlock *hwlock) 239{ 240 return __hwspin_trylock(hwlock, HWLOCK_IN_ATOMIC, NULL); 241} 242 243/** 244 * hwspin_trylock() - attempt to lock a specific hwspinlock 245 * @hwlock: an hwspinlock which we want to trylock 246 * 247 * This function attempts to lock an hwspinlock, and will immediately fail 248 * if the hwspinlock is already taken. 249 * 250 * Upon a successful return from this function, preemption is disabled, 251 * so the caller must not sleep, and is advised to release the hwspinlock 252 * as soon as possible. This is required in order to minimize remote cores 253 * polling on the hardware interconnect. 254 * 255 * Returns 0 if we successfully locked the hwspinlock, -EBUSY if 256 * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid. 257 */ 258static inline int hwspin_trylock(struct hwspinlock *hwlock) 259{ 260 return __hwspin_trylock(hwlock, 0, NULL); 261} 262 263/** 264 * hwspin_lock_timeout_irqsave() - lock hwspinlock, with timeout, disable irqs 265 * @hwlock: the hwspinlock to be locked 266 * @to: timeout value in msecs 267 * @flags: a pointer to where the caller's interrupt state will be saved at 268 * 269 * This function locks the underlying @hwlock. If the @hwlock 270 * is already taken, the function will busy loop waiting for it to 271 * be released, but give up when @timeout msecs have elapsed. 272 * 273 * Upon a successful return from this function, preemption and local interrupts 274 * are disabled (plus previous interrupt state is saved), so the caller must 275 * not sleep, and is advised to release the hwspinlock as soon as possible. 276 * 277 * Returns 0 when the @hwlock was successfully taken, and an appropriate 278 * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still 279 * busy after @timeout msecs). The function will never sleep. 280 */ 281static inline int hwspin_lock_timeout_irqsave(struct hwspinlock *hwlock, 282 unsigned int to, unsigned long *flags) 283{ 284 return __hwspin_lock_timeout(hwlock, to, HWLOCK_IRQSTATE, flags); 285} 286 287/** 288 * hwspin_lock_timeout_irq() - lock hwspinlock, with timeout, disable irqs 289 * @hwlock: the hwspinlock to be locked 290 * @to: timeout value in msecs 291 * 292 * This function locks the underlying @hwlock. If the @hwlock 293 * is already taken, the function will busy loop waiting for it to 294 * be released, but give up when @timeout msecs have elapsed. 295 * 296 * Upon a successful return from this function, preemption and local interrupts 297 * are disabled so the caller must not sleep, and is advised to release the 298 * hwspinlock as soon as possible. 299 * 300 * Returns 0 when the @hwlock was successfully taken, and an appropriate 301 * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still 302 * busy after @timeout msecs). The function will never sleep. 303 */ 304static inline 305int hwspin_lock_timeout_irq(struct hwspinlock *hwlock, unsigned int to) 306{ 307 return __hwspin_lock_timeout(hwlock, to, HWLOCK_IRQ, NULL); 308} 309 310/** 311 * hwspin_lock_timeout_raw() - lock an hwspinlock with timeout limit 312 * @hwlock: the hwspinlock to be locked 313 * @to: timeout value in msecs 314 * 315 * This function locks the underlying @hwlock. If the @hwlock 316 * is already taken, the function will busy loop waiting for it to 317 * be released, but give up when @timeout msecs have elapsed. 318 * 319 * Caution: User must protect the routine of getting hardware lock with mutex 320 * or spinlock to avoid dead-lock, that will let user can do some time-consuming 321 * or sleepable operations under the hardware lock. 322 * 323 * Returns 0 when the @hwlock was successfully taken, and an appropriate 324 * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still 325 * busy after @timeout msecs). The function will never sleep. 326 */ 327static inline 328int hwspin_lock_timeout_raw(struct hwspinlock *hwlock, unsigned int to) 329{ 330 return __hwspin_lock_timeout(hwlock, to, HWLOCK_RAW, NULL); 331} 332 333/** 334 * hwspin_lock_timeout_in_atomic() - lock an hwspinlock with timeout limit 335 * @hwlock: the hwspinlock to be locked 336 * @to: timeout value in msecs 337 * 338 * This function locks the underlying @hwlock. If the @hwlock 339 * is already taken, the function will busy loop waiting for it to 340 * be released, but give up when @timeout msecs have elapsed. 341 * 342 * This function shall be called only from an atomic context and the timeout 343 * value shall not exceed a few msecs. 344 * 345 * Returns 0 when the @hwlock was successfully taken, and an appropriate 346 * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still 347 * busy after @timeout msecs). The function will never sleep. 348 */ 349static inline 350int hwspin_lock_timeout_in_atomic(struct hwspinlock *hwlock, unsigned int to) 351{ 352 return __hwspin_lock_timeout(hwlock, to, HWLOCK_IN_ATOMIC, NULL); 353} 354 355/** 356 * hwspin_lock_timeout() - lock an hwspinlock with timeout limit 357 * @hwlock: the hwspinlock to be locked 358 * @to: timeout value in msecs 359 * 360 * This function locks the underlying @hwlock. If the @hwlock 361 * is already taken, the function will busy loop waiting for it to 362 * be released, but give up when @timeout msecs have elapsed. 363 * 364 * Upon a successful return from this function, preemption is disabled 365 * so the caller must not sleep, and is advised to release the hwspinlock 366 * as soon as possible. 367 * This is required in order to minimize remote cores polling on the 368 * hardware interconnect. 369 * 370 * Returns 0 when the @hwlock was successfully taken, and an appropriate 371 * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still 372 * busy after @timeout msecs). The function will never sleep. 373 */ 374static inline 375int hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to) 376{ 377 return __hwspin_lock_timeout(hwlock, to, 0, NULL); 378} 379 380/** 381 * hwspin_unlock_irqrestore() - unlock hwspinlock, restore irq state 382 * @hwlock: a previously-acquired hwspinlock which we want to unlock 383 * @flags: previous caller's interrupt state to restore 384 * 385 * This function will unlock a specific hwspinlock, enable preemption and 386 * restore the previous state of the local interrupts. It should be used 387 * to undo, e.g., hwspin_trylock_irqsave(). 388 * 389 * @hwlock must be already locked before calling this function: it is a bug 390 * to call unlock on a @hwlock that is already unlocked. 391 */ 392static inline void hwspin_unlock_irqrestore(struct hwspinlock *hwlock, 393 unsigned long *flags) 394{ 395 __hwspin_unlock(hwlock, HWLOCK_IRQSTATE, flags); 396} 397 398/** 399 * hwspin_unlock_irq() - unlock hwspinlock, enable interrupts 400 * @hwlock: a previously-acquired hwspinlock which we want to unlock 401 * 402 * This function will unlock a specific hwspinlock, enable preemption and 403 * enable local interrupts. Should be used to undo hwspin_lock_irq(). 404 * 405 * @hwlock must be already locked (e.g. by hwspin_trylock_irq()) before 406 * calling this function: it is a bug to call unlock on a @hwlock that is 407 * already unlocked. 408 */ 409static inline void hwspin_unlock_irq(struct hwspinlock *hwlock) 410{ 411 __hwspin_unlock(hwlock, HWLOCK_IRQ, NULL); 412} 413 414/** 415 * hwspin_unlock_raw() - unlock hwspinlock 416 * @hwlock: a previously-acquired hwspinlock which we want to unlock 417 * 418 * This function will unlock a specific hwspinlock. 419 * 420 * @hwlock must be already locked (e.g. by hwspin_trylock()) before calling 421 * this function: it is a bug to call unlock on a @hwlock that is already 422 * unlocked. 423 */ 424static inline void hwspin_unlock_raw(struct hwspinlock *hwlock) 425{ 426 __hwspin_unlock(hwlock, HWLOCK_RAW, NULL); 427} 428 429/** 430 * hwspin_unlock_in_atomic() - unlock hwspinlock 431 * @hwlock: a previously-acquired hwspinlock which we want to unlock 432 * 433 * This function will unlock a specific hwspinlock. 434 * 435 * @hwlock must be already locked (e.g. by hwspin_trylock()) before calling 436 * this function: it is a bug to call unlock on a @hwlock that is already 437 * unlocked. 438 */ 439static inline void hwspin_unlock_in_atomic(struct hwspinlock *hwlock) 440{ 441 __hwspin_unlock(hwlock, HWLOCK_IN_ATOMIC, NULL); 442} 443 444/** 445 * hwspin_unlock() - unlock hwspinlock 446 * @hwlock: a previously-acquired hwspinlock which we want to unlock 447 * 448 * This function will unlock a specific hwspinlock and enable preemption 449 * back. 450 * 451 * @hwlock must be already locked (e.g. by hwspin_trylock()) before calling 452 * this function: it is a bug to call unlock on a @hwlock that is already 453 * unlocked. 454 */ 455static inline void hwspin_unlock(struct hwspinlock *hwlock) 456{ 457 __hwspin_unlock(hwlock, 0, NULL); 458} 459 460#endif /* __LINUX_HWSPINLOCK_H */