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#ifndef __PVRDMA_RING_H__
47#define __PVRDMA_RING_H__
48
49#include <linux/types.h>
50
51#define PVRDMA_INVALID_IDX -1
52
53struct pvrdma_ring {
54 atomic_t prod_tail;
55 atomic_t cons_head;
56};
57
58struct pvrdma_ring_state {
59 struct pvrdma_ring tx;
60 struct pvrdma_ring rx;
61};
62
63static inline int pvrdma_idx_valid(__u32 idx, __u32 max_elems)
64{
65
66 return (idx & ~((max_elems << 1) - 1)) == 0;
67}
68
69static inline __s32 pvrdma_idx(atomic_t *var, __u32 max_elems)
70{
71 const unsigned int idx = atomic_read(var);
72
73 if (pvrdma_idx_valid(idx, max_elems))
74 return idx & (max_elems - 1);
75 return PVRDMA_INVALID_IDX;
76}
77
78static inline void pvrdma_idx_ring_inc(atomic_t *var, __u32 max_elems)
79{
80 __u32 idx = atomic_read(var) + 1;
81
82 idx &= (max_elems << 1) - 1;
83 atomic_set(var, idx);
84}
85
86static inline __s32 pvrdma_idx_ring_has_space(const struct pvrdma_ring *r,
87 __u32 max_elems, __u32 *out_tail)
88{
89 const __u32 tail = atomic_read(&r->prod_tail);
90 const __u32 head = atomic_read(&r->cons_head);
91
92 if (pvrdma_idx_valid(tail, max_elems) &&
93 pvrdma_idx_valid(head, max_elems)) {
94 *out_tail = tail & (max_elems - 1);
95 return tail != (head ^ max_elems);
96 }
97 return PVRDMA_INVALID_IDX;
98}
99
100static inline __s32 pvrdma_idx_ring_has_data(const struct pvrdma_ring *r,
101 __u32 max_elems, __u32 *out_head)
102{
103 const __u32 tail = atomic_read(&r->prod_tail);
104 const __u32 head = atomic_read(&r->cons_head);
105
106 if (pvrdma_idx_valid(tail, max_elems) &&
107 pvrdma_idx_valid(head, max_elems)) {
108 *out_head = head & (max_elems - 1);
109 return tail != head;
110 }
111 return PVRDMA_INVALID_IDX;
112}
113
114static inline bool pvrdma_idx_ring_is_valid_idx(const struct pvrdma_ring *r,
115 __u32 max_elems, __u32 *idx)
116{
117 const __u32 tail = atomic_read(&r->prod_tail);
118 const __u32 head = atomic_read(&r->cons_head);
119
120 if (pvrdma_idx_valid(tail, max_elems) &&
121 pvrdma_idx_valid(head, max_elems) &&
122 pvrdma_idx_valid(*idx, max_elems)) {
123 if (tail > head && (*idx < tail && *idx >= head))
124 return true;
125 else if (head > tail && (*idx >= head || *idx < tail))
126 return true;
127 }
128 return false;
129}
130
131#endif
132