Merge branch 'writeback-for-next' of git://git.kernel.org/pub/scm/linux/kernel/git...
[profile/ivi/kernel-adaptation-intel-automotive.git] / drivers / staging / ramster / tmem.h
1 /*
2  * tmem.h
3  *
4  * Transcendent memory
5  *
6  * Copyright (c) 2009-2012, Dan Magenheimer, Oracle Corp.
7  */
8
9 #ifndef _TMEM_H_
10 #define _TMEM_H_
11
12 #include <linux/types.h>
13 #include <linux/highmem.h>
14 #include <linux/hash.h>
15 #include <linux/atomic.h>
16
17 /*
18  * These are defined by the Xen<->Linux ABI so should remain consistent
19  */
20 #define TMEM_POOL_PERSIST               1
21 #define TMEM_POOL_SHARED                2
22 #define TMEM_POOL_PRECOMPRESSED         4
23 #define TMEM_POOL_PAGESIZE_SHIFT        4
24 #define TMEM_POOL_PAGESIZE_MASK         0xf
25 #define TMEM_POOL_RESERVED_BITS         0x00ffff00
26
27 /*
28  * sentinels have proven very useful for debugging but can be removed
29  * or disabled before final merge.
30  */
31 #undef SENTINELS
32 #ifdef SENTINELS
33 #define DECL_SENTINEL uint32_t sentinel;
34 #define SET_SENTINEL(_x, _y) (_x->sentinel = _y##_SENTINEL)
35 #define INVERT_SENTINEL(_x, _y) (_x->sentinel = ~_y##_SENTINEL)
36 #define ASSERT_SENTINEL(_x, _y) WARN_ON(_x->sentinel != _y##_SENTINEL)
37 #define ASSERT_INVERTED_SENTINEL(_x, _y) WARN_ON(_x->sentinel != ~_y##_SENTINEL)
38 #else
39 #define DECL_SENTINEL
40 #define SET_SENTINEL(_x, _y) do { } while (0)
41 #define INVERT_SENTINEL(_x, _y) do { } while (0)
42 #define ASSERT_SENTINEL(_x, _y) do { } while (0)
43 #define ASSERT_INVERTED_SENTINEL(_x, _y) do { } while (0)
44 #endif
45
46 #define ASSERT_SPINLOCK(_l)     lockdep_assert_held(_l)
47
48 /*
49  * A pool is the highest-level data structure managed by tmem and
50  * usually corresponds to a large independent set of pages such as
51  * a filesystem.  Each pool has an id, and certain attributes and counters.
52  * It also contains a set of hash buckets, each of which contains an rbtree
53  * of objects and a lock to manage concurrency within the pool.
54  */
55
56 #define TMEM_HASH_BUCKET_BITS   8
57 #define TMEM_HASH_BUCKETS       (1<<TMEM_HASH_BUCKET_BITS)
58
59 struct tmem_hashbucket {
60         struct rb_root obj_rb_root;
61         spinlock_t lock;
62 };
63
64 struct tmem_pool {
65         void *client; /* "up" for some clients, avoids table lookup */
66         struct list_head pool_list;
67         uint32_t pool_id;
68         bool persistent;
69         bool shared;
70         atomic_t obj_count;
71         atomic_t refcount;
72         struct tmem_hashbucket hashbucket[TMEM_HASH_BUCKETS];
73         DECL_SENTINEL
74 };
75
76 #define is_persistent(_p)  (_p->persistent)
77 #define is_ephemeral(_p)   (!(_p->persistent))
78
79 /*
80  * An object id ("oid") is large: 192-bits (to ensure, for example, files
81  * in a modern filesystem can be uniquely identified).
82  */
83
84 struct tmem_oid {
85         uint64_t oid[3];
86 };
87
88 static inline void tmem_oid_set_invalid(struct tmem_oid *oidp)
89 {
90         oidp->oid[0] = oidp->oid[1] = oidp->oid[2] = -1UL;
91 }
92
93 static inline bool tmem_oid_valid(struct tmem_oid *oidp)
94 {
95         return oidp->oid[0] != -1UL || oidp->oid[1] != -1UL ||
96                 oidp->oid[2] != -1UL;
97 }
98
99 static inline int tmem_oid_compare(struct tmem_oid *left,
100                                         struct tmem_oid *right)
101 {
102         int ret;
103
104         if (left->oid[2] == right->oid[2]) {
105                 if (left->oid[1] == right->oid[1]) {
106                         if (left->oid[0] == right->oid[0])
107                                 ret = 0;
108                         else if (left->oid[0] < right->oid[0])
109                                 ret = -1;
110                         else
111                                 return 1;
112                 } else if (left->oid[1] < right->oid[1])
113                         ret = -1;
114                 else
115                         ret = 1;
116         } else if (left->oid[2] < right->oid[2])
117                 ret = -1;
118         else
119                 ret = 1;
120         return ret;
121 }
122
123 static inline unsigned tmem_oid_hash(struct tmem_oid *oidp)
124 {
125         return hash_long(oidp->oid[0] ^ oidp->oid[1] ^ oidp->oid[2],
126                                 TMEM_HASH_BUCKET_BITS);
127 }
128
129 #ifdef CONFIG_RAMSTER
130 struct tmem_xhandle {
131         uint8_t client_id;
132         uint8_t xh_data_cksum;
133         uint16_t xh_data_size;
134         uint16_t pool_id;
135         struct tmem_oid oid;
136         uint32_t index;
137         void *extra;
138 };
139
140 static inline struct tmem_xhandle tmem_xhandle_fill(uint16_t client_id,
141                                         struct tmem_pool *pool,
142                                         struct tmem_oid *oidp,
143                                         uint32_t index)
144 {
145         struct tmem_xhandle xh;
146         xh.client_id = client_id;
147         xh.xh_data_cksum = (uint8_t)-1;
148         xh.xh_data_size = (uint16_t)-1;
149         xh.pool_id = pool->pool_id;
150         xh.oid = *oidp;
151         xh.index = index;
152         return xh;
153 }
154 #endif
155
156
157 /*
158  * A tmem_obj contains an identifier (oid), pointers to the parent
159  * pool and the rb_tree to which it belongs, counters, and an ordered
160  * set of pampds, structured in a radix-tree-like tree.  The intermediate
161  * nodes of the tree are called tmem_objnodes.
162  */
163
164 struct tmem_objnode;
165
166 struct tmem_obj {
167         struct tmem_oid oid;
168         struct tmem_pool *pool;
169         struct rb_node rb_tree_node;
170         struct tmem_objnode *objnode_tree_root;
171         unsigned int objnode_tree_height;
172         unsigned long objnode_count;
173         long pampd_count;
174 #ifdef CONFIG_RAMSTER
175         /*
176          * for current design of ramster, all pages belonging to
177          * an object reside on the same remotenode and extra is
178          * used to record the number of the remotenode so a
179          * flush-object operation can specify it
180          */
181         void *extra; /* for private use by pampd implementation */
182 #endif
183         DECL_SENTINEL
184 };
185
186 #define OBJNODE_TREE_MAP_SHIFT 6
187 #define OBJNODE_TREE_MAP_SIZE (1UL << OBJNODE_TREE_MAP_SHIFT)
188 #define OBJNODE_TREE_MAP_MASK (OBJNODE_TREE_MAP_SIZE-1)
189 #define OBJNODE_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long))
190 #define OBJNODE_TREE_MAX_PATH \
191                 (OBJNODE_TREE_INDEX_BITS/OBJNODE_TREE_MAP_SHIFT + 2)
192
193 struct tmem_objnode {
194         struct tmem_obj *obj;
195         DECL_SENTINEL
196         void *slots[OBJNODE_TREE_MAP_SIZE];
197         unsigned int slots_in_use;
198 };
199
200 struct tmem_handle {
201         struct tmem_oid oid; /* 24 bytes */
202         uint32_t index;
203         uint16_t pool_id;
204         uint16_t client_id;
205 };
206
207
208 /* pampd abstract datatype methods provided by the PAM implementation */
209 struct tmem_pamops {
210         void (*create_finish)(void *, bool);
211         int (*get_data)(char *, size_t *, bool, void *, struct tmem_pool *,
212                                 struct tmem_oid *, uint32_t);
213         int (*get_data_and_free)(char *, size_t *, bool, void *,
214                                 struct tmem_pool *, struct tmem_oid *,
215                                 uint32_t);
216         void (*free)(void *, struct tmem_pool *,
217                                 struct tmem_oid *, uint32_t, bool);
218 #ifdef CONFIG_RAMSTER
219         void (*new_obj)(struct tmem_obj *);
220         void (*free_obj)(struct tmem_pool *, struct tmem_obj *, bool);
221         void *(*repatriate_preload)(void *, struct tmem_pool *,
222                                         struct tmem_oid *, uint32_t, bool *);
223         int (*repatriate)(void *, void *, struct tmem_pool *,
224                                 struct tmem_oid *, uint32_t, bool, void *);
225         bool (*is_remote)(void *);
226         int (*replace_in_obj)(void *, struct tmem_obj *);
227 #endif
228 };
229 extern void tmem_register_pamops(struct tmem_pamops *m);
230
231 /* memory allocation methods provided by the host implementation */
232 struct tmem_hostops {
233         struct tmem_obj *(*obj_alloc)(struct tmem_pool *);
234         void (*obj_free)(struct tmem_obj *, struct tmem_pool *);
235         struct tmem_objnode *(*objnode_alloc)(struct tmem_pool *);
236         void (*objnode_free)(struct tmem_objnode *, struct tmem_pool *);
237 };
238 extern void tmem_register_hostops(struct tmem_hostops *m);
239
240 /* core tmem accessor functions */
241 extern int tmem_put(struct tmem_pool *, struct tmem_oid *, uint32_t index,
242                         bool, void *);
243 extern int tmem_get(struct tmem_pool *, struct tmem_oid *, uint32_t index,
244                         char *, size_t *, bool, int);
245 extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *,
246                         uint32_t index);
247 extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *);
248 extern int tmem_destroy_pool(struct tmem_pool *);
249 extern void tmem_new_pool(struct tmem_pool *, uint32_t);
250 #ifdef CONFIG_RAMSTER
251 extern int tmem_replace(struct tmem_pool *, struct tmem_oid *, uint32_t index,
252                         void *);
253 extern void *tmem_localify_get_pampd(struct tmem_pool *, struct tmem_oid *,
254                                    uint32_t index, struct tmem_obj **,
255                                    void **);
256 extern void tmem_localify_finish(struct tmem_obj *, uint32_t index,
257                                  void *, void *, bool);
258 #endif
259 #endif /* _TMEM_H */