This source file includes following definitions.
- brcmf_commonring_register_cb
- brcmf_commonring_config
- brcmf_commonring_lock
- brcmf_commonring_unlock
- brcmf_commonring_write_available
- brcmf_commonring_reserve_for_write
- brcmf_commonring_reserve_for_write_multiple
- brcmf_commonring_write_complete
- brcmf_commonring_write_cancel
- brcmf_commonring_get_read_ptr
- brcmf_commonring_read_complete
1
2
3
4
5
6 #include <linux/types.h>
7 #include <linux/netdevice.h>
8
9 #include <brcmu_utils.h>
10 #include <brcmu_wifi.h>
11
12 #include "core.h"
13 #include "commonring.h"
14
15 void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
16 int (*cr_ring_bell)(void *ctx),
17 int (*cr_update_rptr)(void *ctx),
18 int (*cr_update_wptr)(void *ctx),
19 int (*cr_write_rptr)(void *ctx),
20 int (*cr_write_wptr)(void *ctx), void *ctx)
21 {
22 commonring->cr_ring_bell = cr_ring_bell;
23 commonring->cr_update_rptr = cr_update_rptr;
24 commonring->cr_update_wptr = cr_update_wptr;
25 commonring->cr_write_rptr = cr_write_rptr;
26 commonring->cr_write_wptr = cr_write_wptr;
27 commonring->cr_ctx = ctx;
28 }
29
30
31 void brcmf_commonring_config(struct brcmf_commonring *commonring, u16 depth,
32 u16 item_len, void *buf_addr)
33 {
34 commonring->depth = depth;
35 commonring->item_len = item_len;
36 commonring->buf_addr = buf_addr;
37 if (!commonring->inited) {
38 spin_lock_init(&commonring->lock);
39 commonring->inited = true;
40 }
41 commonring->r_ptr = 0;
42 if (commonring->cr_write_rptr)
43 commonring->cr_write_rptr(commonring->cr_ctx);
44 commonring->w_ptr = 0;
45 if (commonring->cr_write_wptr)
46 commonring->cr_write_wptr(commonring->cr_ctx);
47 commonring->f_ptr = 0;
48 }
49
50
51 void brcmf_commonring_lock(struct brcmf_commonring *commonring)
52 __acquires(&commonring->lock)
53 {
54 unsigned long flags;
55
56 spin_lock_irqsave(&commonring->lock, flags);
57 commonring->flags = flags;
58 }
59
60
61 void brcmf_commonring_unlock(struct brcmf_commonring *commonring)
62 __releases(&commonring->lock)
63 {
64 spin_unlock_irqrestore(&commonring->lock, commonring->flags);
65 }
66
67
68 bool brcmf_commonring_write_available(struct brcmf_commonring *commonring)
69 {
70 u16 available;
71 bool retry = true;
72
73 again:
74 if (commonring->r_ptr <= commonring->w_ptr)
75 available = commonring->depth - commonring->w_ptr +
76 commonring->r_ptr;
77 else
78 available = commonring->r_ptr - commonring->w_ptr;
79
80 if (available > 1) {
81 if (!commonring->was_full)
82 return true;
83 if (available > commonring->depth / 8) {
84 commonring->was_full = false;
85 return true;
86 }
87 if (retry) {
88 if (commonring->cr_update_rptr)
89 commonring->cr_update_rptr(commonring->cr_ctx);
90 retry = false;
91 goto again;
92 }
93 return false;
94 }
95
96 if (retry) {
97 if (commonring->cr_update_rptr)
98 commonring->cr_update_rptr(commonring->cr_ctx);
99 retry = false;
100 goto again;
101 }
102
103 commonring->was_full = true;
104 return false;
105 }
106
107
108 void *brcmf_commonring_reserve_for_write(struct brcmf_commonring *commonring)
109 {
110 void *ret_ptr;
111 u16 available;
112 bool retry = true;
113
114 again:
115 if (commonring->r_ptr <= commonring->w_ptr)
116 available = commonring->depth - commonring->w_ptr +
117 commonring->r_ptr;
118 else
119 available = commonring->r_ptr - commonring->w_ptr;
120
121 if (available > 1) {
122 ret_ptr = commonring->buf_addr +
123 (commonring->w_ptr * commonring->item_len);
124 commonring->w_ptr++;
125 if (commonring->w_ptr == commonring->depth)
126 commonring->w_ptr = 0;
127 return ret_ptr;
128 }
129
130 if (retry) {
131 if (commonring->cr_update_rptr)
132 commonring->cr_update_rptr(commonring->cr_ctx);
133 retry = false;
134 goto again;
135 }
136
137 commonring->was_full = true;
138 return NULL;
139 }
140
141
142 void *
143 brcmf_commonring_reserve_for_write_multiple(struct brcmf_commonring *commonring,
144 u16 n_items, u16 *alloced)
145 {
146 void *ret_ptr;
147 u16 available;
148 bool retry = true;
149
150 again:
151 if (commonring->r_ptr <= commonring->w_ptr)
152 available = commonring->depth - commonring->w_ptr +
153 commonring->r_ptr;
154 else
155 available = commonring->r_ptr - commonring->w_ptr;
156
157 if (available > 1) {
158 ret_ptr = commonring->buf_addr +
159 (commonring->w_ptr * commonring->item_len);
160 *alloced = min_t(u16, n_items, available - 1);
161 if (*alloced + commonring->w_ptr > commonring->depth)
162 *alloced = commonring->depth - commonring->w_ptr;
163 commonring->w_ptr += *alloced;
164 if (commonring->w_ptr == commonring->depth)
165 commonring->w_ptr = 0;
166 return ret_ptr;
167 }
168
169 if (retry) {
170 if (commonring->cr_update_rptr)
171 commonring->cr_update_rptr(commonring->cr_ctx);
172 retry = false;
173 goto again;
174 }
175
176 commonring->was_full = true;
177 return NULL;
178 }
179
180
181 int brcmf_commonring_write_complete(struct brcmf_commonring *commonring)
182 {
183 void *address;
184
185 address = commonring->buf_addr;
186 address += (commonring->f_ptr * commonring->item_len);
187 if (commonring->f_ptr > commonring->w_ptr) {
188 address = commonring->buf_addr;
189 commonring->f_ptr = 0;
190 }
191
192 commonring->f_ptr = commonring->w_ptr;
193
194 if (commonring->cr_write_wptr)
195 commonring->cr_write_wptr(commonring->cr_ctx);
196 if (commonring->cr_ring_bell)
197 return commonring->cr_ring_bell(commonring->cr_ctx);
198
199 return -EIO;
200 }
201
202
203 void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
204 u16 n_items)
205 {
206 if (commonring->w_ptr == 0)
207 commonring->w_ptr = commonring->depth - n_items;
208 else
209 commonring->w_ptr -= n_items;
210 }
211
212
213 void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
214 u16 *n_items)
215 {
216 if (commonring->cr_update_wptr)
217 commonring->cr_update_wptr(commonring->cr_ctx);
218
219 *n_items = (commonring->w_ptr >= commonring->r_ptr) ?
220 (commonring->w_ptr - commonring->r_ptr) :
221 (commonring->depth - commonring->r_ptr);
222
223 if (*n_items == 0)
224 return NULL;
225
226 return commonring->buf_addr +
227 (commonring->r_ptr * commonring->item_len);
228 }
229
230
231 int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
232 u16 n_items)
233 {
234 commonring->r_ptr += n_items;
235 if (commonring->r_ptr == commonring->depth)
236 commonring->r_ptr = 0;
237
238 if (commonring->cr_write_rptr)
239 return commonring->cr_write_rptr(commonring->cr_ctx);
240
241 return -EIO;
242 }