This source file includes following definitions.
- scif_rb_init
- memcpy_torb
- memcpy_fromrb
- scif_rb_space
- scif_rb_write
- scif_rb_commit
- scif_rb_get
- scif_rb_get_next
- scif_rb_update_read_ptr
- scif_rb_count
1
2
3
4
5
6
7
8
9 #include <linux/circ_buf.h>
10 #include <linux/types.h>
11 #include <linux/io.h>
12 #include <linux/errno.h>
13
14 #include "scif_rb.h"
15
16 #define scif_rb_ring_cnt(head, tail, size) CIRC_CNT(head, tail, size)
17 #define scif_rb_ring_space(head, tail, size) CIRC_SPACE(head, tail, size)
18
19
20
21
22
23
24
25
26
27 void scif_rb_init(struct scif_rb *rb, u32 *read_ptr, u32 *write_ptr,
28 void *rb_base, u8 size)
29 {
30 rb->rb_base = rb_base;
31 rb->size = (1 << size);
32 rb->read_ptr = read_ptr;
33 rb->write_ptr = write_ptr;
34 rb->current_read_offset = *read_ptr;
35 rb->current_write_offset = *write_ptr;
36 }
37
38
39 static void memcpy_torb(struct scif_rb *rb, void *header,
40 void *msg, u32 size)
41 {
42 u32 size1, size2;
43
44 if (header + size >= rb->rb_base + rb->size) {
45
46 size1 = (u32)(rb->rb_base + rb->size - header);
47 size2 = size - size1;
48 memcpy_toio((void __iomem __force *)header, msg, size1);
49 memcpy_toio((void __iomem __force *)rb->rb_base,
50 msg + size1, size2);
51 } else {
52 memcpy_toio((void __iomem __force *)header, msg, size);
53 }
54 }
55
56
57 static void memcpy_fromrb(struct scif_rb *rb, void *header,
58 void *msg, u32 size)
59 {
60 u32 size1, size2;
61
62 if (header + size >= rb->rb_base + rb->size) {
63
64 size1 = (u32)(rb->rb_base + rb->size - header);
65 size2 = size - size1;
66 memcpy_fromio(msg, (void __iomem __force *)header, size1);
67 memcpy_fromio(msg + size1,
68 (void __iomem __force *)rb->rb_base, size2);
69 } else {
70 memcpy_fromio(msg, (void __iomem __force *)header, size);
71 }
72 }
73
74
75
76
77
78
79
80 u32 scif_rb_space(struct scif_rb *rb)
81 {
82 rb->current_read_offset = *rb->read_ptr;
83
84
85
86
87
88 mb();
89 return scif_rb_ring_space(rb->current_write_offset,
90 rb->current_read_offset, rb->size);
91 }
92
93
94
95
96
97
98
99
100
101
102 int scif_rb_write(struct scif_rb *rb, void *msg, u32 size)
103 {
104 void *header;
105
106 if (scif_rb_space(rb) < size)
107 return -ENOMEM;
108 header = rb->rb_base + rb->current_write_offset;
109 memcpy_torb(rb, header, msg, size);
110
111
112
113
114 rb->current_write_offset =
115 (rb->current_write_offset + size) & (rb->size - 1);
116 return 0;
117 }
118
119
120
121
122
123 void scif_rb_commit(struct scif_rb *rb)
124 {
125
126
127
128
129
130
131 wmb();
132 WRITE_ONCE(*rb->write_ptr, rb->current_write_offset);
133 #ifdef CONFIG_INTEL_MIC_CARD
134
135
136
137
138
139
140
141 WRITE_ONCE(*rb->write_ptr, rb->current_write_offset);
142 #endif
143 }
144
145
146
147
148
149
150
151
152
153 static void *scif_rb_get(struct scif_rb *rb, u32 size)
154 {
155 void *header = NULL;
156
157 if (scif_rb_count(rb, size) >= size)
158 header = rb->rb_base + rb->current_read_offset;
159 return header;
160 }
161
162
163
164
165
166
167
168
169
170
171 u32 scif_rb_get_next(struct scif_rb *rb, void *msg, u32 size)
172 {
173 void *header = NULL;
174 int read_size = 0;
175
176 header = scif_rb_get(rb, size);
177 if (header) {
178 u32 next_cmd_offset =
179 (rb->current_read_offset + size) & (rb->size - 1);
180
181 read_size = size;
182 rb->current_read_offset = next_cmd_offset;
183 memcpy_fromrb(rb, header, msg, size);
184 }
185 return read_size;
186 }
187
188
189
190
191
192 void scif_rb_update_read_ptr(struct scif_rb *rb)
193 {
194 u32 new_offset;
195
196 new_offset = rb->current_read_offset;
197
198
199
200
201
202
203 mb();
204 WRITE_ONCE(*rb->read_ptr, new_offset);
205 #ifdef CONFIG_INTEL_MIC_CARD
206
207
208
209
210
211
212
213 WRITE_ONCE(*rb->read_ptr, new_offset);
214 #endif
215 }
216
217
218
219
220
221
222
223
224 u32 scif_rb_count(struct scif_rb *rb, u32 size)
225 {
226 if (scif_rb_ring_cnt(rb->current_write_offset,
227 rb->current_read_offset,
228 rb->size) < size) {
229 rb->current_write_offset = *rb->write_ptr;
230
231
232
233
234
235 smp_rmb();
236 }
237 return scif_rb_ring_cnt(rb->current_write_offset,
238 rb->current_read_offset,
239 rb->size);
240 }