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#include <linux/kernel.h>
34
35#include "rds.h"
36#include "ib.h"
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64DECLARE_WAIT_QUEUE_HEAD(rds_ib_ring_empty_wait);
65
66void rds_ib_ring_init(struct rds_ib_work_ring *ring, u32 nr)
67{
68 memset(ring, 0, sizeof(*ring));
69 ring->w_nr = nr;
70 rdsdebug("ring %p nr %u\n", ring, ring->w_nr);
71}
72
73static inline u32 __rds_ib_ring_used(struct rds_ib_work_ring *ring)
74{
75 u32 diff;
76
77
78 diff = ring->w_alloc_ctr - (u32) atomic_read(&ring->w_free_ctr);
79 BUG_ON(diff > ring->w_nr);
80
81 return diff;
82}
83
84void rds_ib_ring_resize(struct rds_ib_work_ring *ring, u32 nr)
85{
86
87
88 BUG_ON(__rds_ib_ring_used(ring));
89 ring->w_nr = nr;
90}
91
92static int __rds_ib_ring_empty(struct rds_ib_work_ring *ring)
93{
94 return __rds_ib_ring_used(ring) == 0;
95}
96
97u32 rds_ib_ring_alloc(struct rds_ib_work_ring *ring, u32 val, u32 *pos)
98{
99 u32 ret = 0, avail;
100
101 avail = ring->w_nr - __rds_ib_ring_used(ring);
102
103 rdsdebug("ring %p val %u next %u free %u\n", ring, val,
104 ring->w_alloc_ptr, avail);
105
106 if (val && avail) {
107 ret = min(val, avail);
108 *pos = ring->w_alloc_ptr;
109
110 ring->w_alloc_ptr = (ring->w_alloc_ptr + ret) % ring->w_nr;
111 ring->w_alloc_ctr += ret;
112 }
113
114 return ret;
115}
116
117void rds_ib_ring_free(struct rds_ib_work_ring *ring, u32 val)
118{
119 ring->w_free_ptr = (ring->w_free_ptr + val) % ring->w_nr;
120 atomic_add(val, &ring->w_free_ctr);
121
122 if (__rds_ib_ring_empty(ring) &&
123 waitqueue_active(&rds_ib_ring_empty_wait))
124 wake_up(&rds_ib_ring_empty_wait);
125}
126
127void rds_ib_ring_unalloc(struct rds_ib_work_ring *ring, u32 val)
128{
129 ring->w_alloc_ptr = (ring->w_alloc_ptr - val) % ring->w_nr;
130 ring->w_alloc_ctr -= val;
131}
132
133int rds_ib_ring_empty(struct rds_ib_work_ring *ring)
134{
135 return __rds_ib_ring_empty(ring);
136}
137
138int rds_ib_ring_low(struct rds_ib_work_ring *ring)
139{
140 return __rds_ib_ring_used(ring) <= (ring->w_nr >> 1);
141}
142
143
144
145
146
147u32 rds_ib_ring_oldest(struct rds_ib_work_ring *ring)
148{
149 return ring->w_free_ptr;
150}
151
152
153
154
155
156u32 rds_ib_ring_completed(struct rds_ib_work_ring *ring, u32 wr_id, u32 oldest)
157{
158 u32 ret;
159
160 if (oldest <= (unsigned long long)wr_id)
161 ret = (unsigned long long)wr_id - oldest + 1;
162 else
163 ret = ring->w_nr - oldest + (unsigned long long)wr_id + 1;
164
165 rdsdebug("ring %p ret %u wr_id %u oldest %u\n", ring, ret,
166 wr_id, oldest);
167 return ret;
168}
169