1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 #ifndef _ASM_POWERPC_QSPINLOCK_TYPES_H
3 #define _ASM_POWERPC_QSPINLOCK_TYPES_H
4 
5 #include <linux/types.h>
6 #include <asm/byteorder.h>
7 
8 typedef struct qspinlock {
9 	union {
10 		u32 val;
11 
12 #ifdef __LITTLE_ENDIAN
13 		struct {
14 			u16	locked;
15 			u8	reserved[2];
16 		};
17 #else
18 		struct {
19 			u8	reserved[2];
20 			u16	locked;
21 		};
22 #endif
23 	};
24 } arch_spinlock_t;
25 
26 #define	__ARCH_SPIN_LOCK_UNLOCKED	{ { .val = 0 } }
27 
28 /*
29  * Bitfields in the lock word:
30  *
31  *     0: locked bit
32  *  1-14: lock holder cpu
33  *    15: lock owner or queuer vcpus observed to be preempted bit
34  *    16: must queue bit
35  * 17-31: tail cpu (+1)
36  */
37 #define	_Q_SET_MASK(type)	(((1U << _Q_ ## type ## _BITS) - 1)\
38 				      << _Q_ ## type ## _OFFSET)
39 /* 0x00000001 */
40 #define _Q_LOCKED_OFFSET	0
41 #define _Q_LOCKED_BITS		1
42 #define _Q_LOCKED_VAL		(1U << _Q_LOCKED_OFFSET)
43 
44 /* 0x00007ffe */
45 #define _Q_OWNER_CPU_OFFSET	1
46 #define _Q_OWNER_CPU_BITS	14
47 #define _Q_OWNER_CPU_MASK	_Q_SET_MASK(OWNER_CPU)
48 
49 #if CONFIG_NR_CPUS > (1U << _Q_OWNER_CPU_BITS)
50 #error "qspinlock does not support such large CONFIG_NR_CPUS"
51 #endif
52 
53 /* 0x00008000 */
54 #define _Q_SLEEPY_OFFSET	15
55 #define _Q_SLEEPY_BITS		1
56 #define _Q_SLEEPY_VAL		(1U << _Q_SLEEPY_OFFSET)
57 
58 /* 0x00010000 */
59 #define _Q_MUST_Q_OFFSET	16
60 #define _Q_MUST_Q_BITS		1
61 #define _Q_MUST_Q_VAL		(1U << _Q_MUST_Q_OFFSET)
62 
63 /* 0xfffe0000 */
64 #define _Q_TAIL_CPU_OFFSET	17
65 #define _Q_TAIL_CPU_BITS	15
66 #define _Q_TAIL_CPU_MASK	_Q_SET_MASK(TAIL_CPU)
67 
68 #if CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS)
69 #error "qspinlock does not support such large CONFIG_NR_CPUS"
70 #endif
71 
72 #endif /* _ASM_POWERPC_QSPINLOCK_TYPES_H */
73