summaryrefslogtreecommitdiff
path: root/drivers/e24/e24_alloc.h
blob: 4abad6266c6ca4423817b8e9d381d85d22cc65d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef E24_ALLOC_H
#define E24_ALLOC_H

struct e24_allocation_pool;
struct e24_allocation;

struct e24_allocation_ops {
	long (*alloc)(struct e24_allocation_pool *allocation_pool,
		      u32 size, u32 align, struct e24_allocation **alloc);
	void (*free)(struct e24_allocation *allocation);
	void (*free_pool)(struct e24_allocation_pool *allocation_pool);
	phys_addr_t (*offset)(const struct e24_allocation *allocation);
};

struct e24_allocation_pool {
	const struct e24_allocation_ops *ops;
};

struct e24_allocation {
	struct e24_allocation_pool *pool;
	struct e24_allocation *next;
	phys_addr_t start;
	u32 size;
	atomic_t ref;
};

static inline void e24_free_pool(struct e24_allocation_pool *allocation_pool)
{
	allocation_pool->ops->free_pool(allocation_pool);
}

static inline void e24_free(struct e24_allocation *allocation)
{
	return allocation->pool->ops->free(allocation);
}

static inline long e24_allocate(struct e24_allocation_pool *allocation_pool,
				u32 size, u32 align,
				struct e24_allocation **alloc)
{
	return allocation_pool->ops->alloc(allocation_pool,
					   size, align, alloc);
}

static inline void e24_allocation_put(struct e24_allocation *e24_allocation)
{
	if (atomic_dec_and_test(&e24_allocation->ref))
		e24_allocation->pool->ops->free(e24_allocation);
}

static inline phys_addr_t e24_allocation_offset(const struct e24_allocation *allocation)
{
	return allocation->pool->ops->offset(allocation);
}

long e24_init_private_pool(struct e24_allocation_pool **ppool, phys_addr_t start, u32 size);

#endif