1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * drivers/block/zram/zram_group/zlist.h
4 *
5 * Copyright (c) 2020-2022 Huawei Technologies Co., Ltd.
6 */
7
8 #ifndef _ZLIST_H_
9 #define _ZLIST_H_
10
11 #define ZLIST_IDX_SHIFT 30
12 #define ZLIST_LOCK_BIT ZLIST_IDX_SHIFT
13 #define ZLIST_PRIV_BIT ((ZLIST_IDX_SHIFT << 1) + 1)
14
15 #define ZLIST_IDX_MAX (1 << ZLIST_IDX_SHIFT)
16
17 struct zlist_node {
18 u64 prev : ZLIST_IDX_SHIFT;
19 u64 lock : 1;
20 u64 next : ZLIST_IDX_SHIFT;
21 u64 priv : 1;
22 };
23
24 struct zlist_table {
25 struct zlist_node *(*idx2node)(u32 idx, void *priv);
26 void *private;
27 };
28
idx2node(u32 idx,struct zlist_table * tab)29 static inline struct zlist_node *idx2node(u32 idx, struct zlist_table *tab)
30 {
31 return tab->idx2node(idx, tab->private);
32 }
33
next_idx(u32 idx,struct zlist_table * tab)34 static inline u32 next_idx(u32 idx, struct zlist_table *tab)
35 {
36 return idx2node(idx, tab)->next;
37 }
38
prev_idx(u32 idx,struct zlist_table * tab)39 static inline u32 prev_idx(u32 idx, struct zlist_table *tab)
40 {
41 return idx2node(idx, tab)->prev;
42 }
43
zlist_table_free(struct zlist_table * tab)44 static inline void zlist_table_free(struct zlist_table *tab)
45 {
46 kfree(tab);
47 }
48
49 struct zlist_table *zlist_table_alloc(struct zlist_node *(*i2n)(u32, void*),
50 void *private, gfp_t gfp);
51
52 void zlist_lock(u32 idx, struct zlist_table *tab);
53 void zlist_unlock(u32 idx, struct zlist_table *tab);
54
55 void zlist_add_nolock(u32 hid, u32 idx, struct zlist_table *tab);
56 void zlist_add_tail_nolock(u32 hid, u32 idx, struct zlist_table *tab);
57 bool zlist_del_nolock(u32 hid, u32 idx, struct zlist_table *tab);
58 bool zlist_is_isolated_nolock(u32 idx, struct zlist_table *tab);
59
zlist_add(u32 hid,u32 idx,struct zlist_table * tab)60 static inline void zlist_add(u32 hid, u32 idx, struct zlist_table *tab)
61 {
62 zlist_lock(hid, tab);
63 zlist_add_nolock(hid, idx, tab);
64 zlist_unlock(hid, tab);
65 }
66
zlist_add_tail(u32 hid,u32 idx,struct zlist_table * tab)67 static inline void zlist_add_tail(u32 hid, u32 idx, struct zlist_table *tab)
68 {
69 zlist_lock(hid, tab);
70 zlist_add_tail_nolock(hid, idx, tab);
71 zlist_unlock(hid, tab);
72 }
73
zlist_del(u32 hid,u32 idx,struct zlist_table * tab)74 static inline bool zlist_del(u32 hid, u32 idx, struct zlist_table *tab)
75 {
76 bool ret = false;
77
78 zlist_lock(hid, tab);
79 ret = zlist_del_nolock(hid, idx, tab);
80 zlist_unlock(hid, tab);
81
82 return ret;
83 }
84
85 bool zlist_set_priv(u32 idx, struct zlist_table *tab);
86 bool zlist_clr_priv_nolock(u32 idx, struct zlist_table *tab);
87 bool zlist_test_priv_nolock(u32 idx, struct zlist_table *tab);
88
89 void zlist_node_init(u32 idx, struct zlist_table *tab);
90
91 #define zlist_for_each_entry(idx, hid, tab) \
92 for ((idx) = next_idx(hid, tab); (idx) != (hid); \
93 (idx) = next_idx(idx, tab))
94 #define zlist_for_each_entry_reverse(idx, hid, tab) \
95 for ((idx) = prev_idx(hid, tab); (idx) != (hid); \
96 (idx) = prev_idx(idx, tab))
97 #endif
98