Branch data Line data Source code
1 : : // SPDX-License-Identifier: ISC
2 : : /*
3 : : * Copyright (c) 2005-2011 Atheros Communications Inc.
4 : : * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
5 : : * Copyright (c) 2018 The Linux Foundation. All rights reserved.
6 : : */
7 : :
8 : : #include "hif.h"
9 : : #include "ce.h"
10 : : #include "debug.h"
11 : :
12 : : /*
13 : : * Support for Copy Engine hardware, which is mainly used for
14 : : * communication between Host and Target over a PCIe interconnect.
15 : : */
16 : :
17 : : /*
18 : : * A single CopyEngine (CE) comprises two "rings":
19 : : * a source ring
20 : : * a destination ring
21 : : *
22 : : * Each ring consists of a number of descriptors which specify
23 : : * an address, length, and meta-data.
24 : : *
25 : : * Typically, one side of the PCIe/AHB/SNOC interconnect (Host or Target)
26 : : * controls one ring and the other side controls the other ring.
27 : : * The source side chooses when to initiate a transfer and it
28 : : * chooses what to send (buffer address, length). The destination
29 : : * side keeps a supply of "anonymous receive buffers" available and
30 : : * it handles incoming data as it arrives (when the destination
31 : : * receives an interrupt).
32 : : *
33 : : * The sender may send a simple buffer (address/length) or it may
34 : : * send a small list of buffers. When a small list is sent, hardware
35 : : * "gathers" these and they end up in a single destination buffer
36 : : * with a single interrupt.
37 : : *
38 : : * There are several "contexts" managed by this layer -- more, it
39 : : * may seem -- than should be needed. These are provided mainly for
40 : : * maximum flexibility and especially to facilitate a simpler HIF
41 : : * implementation. There are per-CopyEngine recv, send, and watermark
42 : : * contexts. These are supplied by the caller when a recv, send,
43 : : * or watermark handler is established and they are echoed back to
44 : : * the caller when the respective callbacks are invoked. There is
45 : : * also a per-transfer context supplied by the caller when a buffer
46 : : * (or sendlist) is sent and when a buffer is enqueued for recv.
47 : : * These per-transfer contexts are echoed back to the caller when
48 : : * the buffer is sent/received.
49 : : */
50 : :
51 : : static inline u32 shadow_sr_wr_ind_addr(struct ath10k *ar,
52 : : struct ath10k_ce_pipe *ce_state)
53 : : {
54 : : u32 ce_id = ce_state->id;
55 : : u32 addr = 0;
56 : :
57 : : switch (ce_id) {
58 : : case 0:
59 : : addr = 0x00032000;
60 : : break;
61 : : case 3:
62 : : addr = 0x0003200C;
63 : : break;
64 : : case 4:
65 : : addr = 0x00032010;
66 : : break;
67 : : case 5:
68 : : addr = 0x00032014;
69 : : break;
70 : : case 7:
71 : : addr = 0x0003201C;
72 : : break;
73 : : default:
74 : : ath10k_warn(ar, "invalid CE id: %d", ce_id);
75 : : break;
76 : : }
77 : : return addr;
78 : : }
79 : :
80 : : static inline u32 shadow_dst_wr_ind_addr(struct ath10k *ar,
81 : : struct ath10k_ce_pipe *ce_state)
82 : : {
83 : : u32 ce_id = ce_state->id;
84 : : u32 addr = 0;
85 : :
86 : : switch (ce_id) {
87 : : case 1:
88 : : addr = 0x00032034;
89 : : break;
90 : : case 2:
91 : : addr = 0x00032038;
92 : : break;
93 : : case 5:
94 : : addr = 0x00032044;
95 : : break;
96 : : case 7:
97 : : addr = 0x0003204C;
98 : : break;
99 : : case 8:
100 : : addr = 0x00032050;
101 : : break;
102 : : case 9:
103 : : addr = 0x00032054;
104 : : break;
105 : : case 10:
106 : : addr = 0x00032058;
107 : : break;
108 : : case 11:
109 : : addr = 0x0003205C;
110 : : break;
111 : : default:
112 : : ath10k_warn(ar, "invalid CE id: %d", ce_id);
113 : : break;
114 : : }
115 : :
116 : : return addr;
117 : : }
118 : :
119 : : static inline unsigned int
120 : 3985 : ath10k_set_ring_byte(unsigned int offset,
121 : : struct ath10k_hw_ce_regs_addr_map *addr_map)
122 : : {
123 : 3985 : return ((offset << addr_map->lsb) & addr_map->mask);
124 : : }
125 : :
126 : : static inline unsigned int
127 : : ath10k_get_ring_byte(unsigned int offset,
128 : : struct ath10k_hw_ce_regs_addr_map *addr_map)
129 : : {
130 : : return ((offset & addr_map->mask) >> (addr_map->lsb));
131 : : }
132 : :
133 : 7004 : static inline u32 ath10k_ce_read32(struct ath10k *ar, u32 offset)
134 : : {
135 : 7004 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
136 : :
137 : 7004 : return ce->bus_ops->read32(ar, offset);
138 : : }
139 : :
140 : 8036 : static inline void ath10k_ce_write32(struct ath10k *ar, u32 offset, u32 value)
141 : : {
142 : 0 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
143 : :
144 : 1487 : ce->bus_ops->write32(ar, offset, value);
145 : : }
146 : :
147 : 133 : static inline void ath10k_ce_dest_ring_write_index_set(struct ath10k *ar,
148 : : u32 ce_ctrl_addr,
149 : : unsigned int n)
150 : : {
151 : 133 : ath10k_ce_write32(ar, ce_ctrl_addr +
152 : 133 : ar->hw_ce_regs->dst_wr_index_addr, n);
153 : : }
154 : :
155 : 32 : static inline u32 ath10k_ce_dest_ring_write_index_get(struct ath10k *ar,
156 : : u32 ce_ctrl_addr)
157 : : {
158 : 32 : return ath10k_ce_read32(ar, ce_ctrl_addr +
159 : 32 : ar->hw_ce_regs->dst_wr_index_addr);
160 : : }
161 : :
162 : 132 : static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar,
163 : : u32 ce_ctrl_addr,
164 : : unsigned int n)
165 : : {
166 : 132 : ath10k_ce_write32(ar, ce_ctrl_addr +
167 : 132 : ar->hw_ce_regs->sr_wr_index_addr, n);
168 : 132 : }
169 : :
170 : 32 : static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar,
171 : : u32 ce_ctrl_addr)
172 : : {
173 : 32 : return ath10k_ce_read32(ar, ce_ctrl_addr +
174 : 32 : ar->hw_ce_regs->sr_wr_index_addr);
175 : : }
176 : :
177 : 0 : static inline u32 ath10k_ce_src_ring_read_index_from_ddr(struct ath10k *ar,
178 : : u32 ce_id)
179 : : {
180 : 0 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
181 : :
182 : 0 : return ce->vaddr_rri[ce_id] & CE_DDR_RRI_MASK;
183 : : }
184 : :
185 : 901 : static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar,
186 : : u32 ce_ctrl_addr)
187 : : {
188 [ - + ]: 901 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
189 : 901 : u32 ce_id = COPY_ENGINE_ID(ce_ctrl_addr);
190 : 901 : struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
191 : 901 : u32 index;
192 : :
193 [ - + ]: 901 : if (ar->hw_params.rri_on_ddr &&
194 [ # # ]: 0 : (ce_state->attr_flags & CE_ATTR_DIS_INTR))
195 : 0 : index = ath10k_ce_src_ring_read_index_from_ddr(ar, ce_id);
196 : : else
197 : 901 : index = ath10k_ce_read32(ar, ce_ctrl_addr +
198 : 901 : ar->hw_ce_regs->current_srri_addr);
199 : :
200 : 901 : return index;
201 : : }
202 : :
203 : : static inline void
204 : 0 : ath10k_ce_shadow_src_ring_write_index_set(struct ath10k *ar,
205 : : struct ath10k_ce_pipe *ce_state,
206 : : unsigned int value)
207 : : {
208 : 0 : ath10k_ce_write32(ar, shadow_sr_wr_ind_addr(ar, ce_state), value);
209 : 0 : }
210 : :
211 : : static inline void
212 : : ath10k_ce_shadow_dest_ring_write_index_set(struct ath10k *ar,
213 : : struct ath10k_ce_pipe *ce_state,
214 : : unsigned int value)
215 : : {
216 : : ath10k_ce_write32(ar, shadow_dst_wr_ind_addr(ar, ce_state), value);
217 : : }
218 : :
219 : 804 : static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar,
220 : : u32 ce_id,
221 : : u64 addr)
222 : : {
223 : 804 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
224 : 804 : struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
225 : 804 : u32 ce_ctrl_addr = ath10k_ce_base_address(ar, ce_id);
226 : 804 : u32 addr_lo = lower_32_bits(addr);
227 : :
228 : 804 : ath10k_ce_write32(ar, ce_ctrl_addr +
229 : 804 : ar->hw_ce_regs->sr_base_addr_lo, addr_lo);
230 : :
231 [ - + ]: 804 : if (ce_state->ops->ce_set_src_ring_base_addr_hi) {
232 : 0 : ce_state->ops->ce_set_src_ring_base_addr_hi(ar, ce_ctrl_addr,
233 : : addr);
234 : : }
235 : 804 : }
236 : :
237 : 0 : static void ath10k_ce_set_src_ring_base_addr_hi(struct ath10k *ar,
238 : : u32 ce_ctrl_addr,
239 : : u64 addr)
240 : : {
241 : 0 : u32 addr_hi = upper_32_bits(addr) & CE_DESC_ADDR_HI_MASK;
242 : :
243 : 0 : ath10k_ce_write32(ar, ce_ctrl_addr +
244 : 0 : ar->hw_ce_regs->sr_base_addr_hi, addr_hi);
245 : 0 : }
246 : :
247 : 320 : static inline void ath10k_ce_src_ring_size_set(struct ath10k *ar,
248 : : u32 ce_ctrl_addr,
249 : : unsigned int n)
250 : : {
251 : 320 : ath10k_ce_write32(ar, ce_ctrl_addr +
252 : 320 : ar->hw_ce_regs->sr_size_addr, n);
253 : : }
254 : :
255 : 804 : static inline void ath10k_ce_src_ring_dmax_set(struct ath10k *ar,
256 : : u32 ce_ctrl_addr,
257 : : unsigned int n)
258 : : {
259 : 804 : struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
260 : :
261 : 804 : u32 ctrl1_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
262 : 804 : ctrl_regs->addr);
263 : :
264 : 804 : ath10k_ce_write32(ar, ce_ctrl_addr + ctrl_regs->addr,
265 : 804 : (ctrl1_addr & ~(ctrl_regs->dmax->mask)) |
266 : 804 : ath10k_set_ring_byte(n, ctrl_regs->dmax));
267 : 804 : }
268 : :
269 : 484 : static inline void ath10k_ce_src_ring_byte_swap_set(struct ath10k *ar,
270 : : u32 ce_ctrl_addr,
271 : : unsigned int n)
272 : : {
273 : 484 : struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
274 : :
275 : 484 : u32 ctrl1_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
276 : 484 : ctrl_regs->addr);
277 : :
278 : 484 : ath10k_ce_write32(ar, ce_ctrl_addr + ctrl_regs->addr,
279 : 484 : (ctrl1_addr & ~(ctrl_regs->src_ring->mask)) |
280 : 484 : ath10k_set_ring_byte(n, ctrl_regs->src_ring));
281 : 484 : }
282 : :
283 : 363 : static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar,
284 : : u32 ce_ctrl_addr,
285 : : unsigned int n)
286 : : {
287 : 363 : struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
288 : :
289 : 363 : u32 ctrl1_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
290 : 363 : ctrl_regs->addr);
291 : :
292 : 363 : ath10k_ce_write32(ar, ce_ctrl_addr + ctrl_regs->addr,
293 : 363 : (ctrl1_addr & ~(ctrl_regs->dst_ring->mask)) |
294 : 363 : ath10k_set_ring_byte(n, ctrl_regs->dst_ring));
295 : 363 : }
296 : :
297 : : static inline
298 : 0 : u32 ath10k_ce_dest_ring_read_index_from_ddr(struct ath10k *ar, u32 ce_id)
299 : : {
300 : 0 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
301 : :
302 : 0 : return (ce->vaddr_rri[ce_id] >> CE_DDR_DRRI_SHIFT) &
303 : : CE_DDR_RRI_MASK;
304 : : }
305 : :
306 : 395 : static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar,
307 : : u32 ce_ctrl_addr)
308 : : {
309 [ - + ]: 395 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
310 : 395 : u32 ce_id = COPY_ENGINE_ID(ce_ctrl_addr);
311 : 395 : struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
312 : 395 : u32 index;
313 : :
314 [ - + ]: 395 : if (ar->hw_params.rri_on_ddr &&
315 [ # # ]: 0 : (ce_state->attr_flags & CE_ATTR_DIS_INTR))
316 : 0 : index = ath10k_ce_dest_ring_read_index_from_ddr(ar, ce_id);
317 : : else
318 : 395 : index = ath10k_ce_read32(ar, ce_ctrl_addr +
319 : 395 : ar->hw_ce_regs->current_drri_addr);
320 : :
321 : 395 : return index;
322 : : }
323 : :
324 : 683 : static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar,
325 : : u32 ce_id,
326 : : u64 addr)
327 : : {
328 : 683 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
329 : 683 : struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
330 : 683 : u32 ce_ctrl_addr = ath10k_ce_base_address(ar, ce_id);
331 : 683 : u32 addr_lo = lower_32_bits(addr);
332 : :
333 : 683 : ath10k_ce_write32(ar, ce_ctrl_addr +
334 : 683 : ar->hw_ce_regs->dr_base_addr_lo, addr_lo);
335 : :
336 [ - + ]: 683 : if (ce_state->ops->ce_set_dest_ring_base_addr_hi) {
337 : 0 : ce_state->ops->ce_set_dest_ring_base_addr_hi(ar, ce_ctrl_addr,
338 : : addr);
339 : : }
340 : 683 : }
341 : :
342 : 0 : static void ath10k_ce_set_dest_ring_base_addr_hi(struct ath10k *ar,
343 : : u32 ce_ctrl_addr,
344 : : u64 addr)
345 : : {
346 : 0 : u32 addr_hi = upper_32_bits(addr) & CE_DESC_ADDR_HI_MASK;
347 : 0 : u32 reg_value;
348 : :
349 : 0 : reg_value = ath10k_ce_read32(ar, ce_ctrl_addr +
350 : 0 : ar->hw_ce_regs->dr_base_addr_hi);
351 : 0 : reg_value &= ~CE_DESC_ADDR_HI_MASK;
352 : 0 : reg_value |= addr_hi;
353 : 0 : ath10k_ce_write32(ar, ce_ctrl_addr +
354 : 0 : ar->hw_ce_regs->dr_base_addr_hi, reg_value);
355 : 0 : }
356 : :
357 : 320 : static inline void ath10k_ce_dest_ring_size_set(struct ath10k *ar,
358 : : u32 ce_ctrl_addr,
359 : : unsigned int n)
360 : : {
361 : 320 : ath10k_ce_write32(ar, ce_ctrl_addr +
362 : 320 : ar->hw_ce_regs->dr_size_addr, n);
363 : : }
364 : :
365 : 804 : static inline void ath10k_ce_src_ring_highmark_set(struct ath10k *ar,
366 : : u32 ce_ctrl_addr,
367 : : unsigned int n)
368 : : {
369 : 804 : struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr;
370 : 804 : u32 addr = ath10k_ce_read32(ar, ce_ctrl_addr + srcr_wm->addr);
371 : :
372 : 804 : ath10k_ce_write32(ar, ce_ctrl_addr + srcr_wm->addr,
373 : 804 : (addr & ~(srcr_wm->wm_high->mask)) |
374 : 804 : (ath10k_set_ring_byte(n, srcr_wm->wm_high)));
375 : 804 : }
376 : :
377 : 484 : static inline void ath10k_ce_src_ring_lowmark_set(struct ath10k *ar,
378 : : u32 ce_ctrl_addr,
379 : : unsigned int n)
380 : : {
381 : 484 : struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr;
382 : 484 : u32 addr = ath10k_ce_read32(ar, ce_ctrl_addr + srcr_wm->addr);
383 : :
384 : 484 : ath10k_ce_write32(ar, ce_ctrl_addr + srcr_wm->addr,
385 : 484 : (addr & ~(srcr_wm->wm_low->mask)) |
386 : 484 : (ath10k_set_ring_byte(n, srcr_wm->wm_low)));
387 : 484 : }
388 : :
389 : 683 : static inline void ath10k_ce_dest_ring_highmark_set(struct ath10k *ar,
390 : : u32 ce_ctrl_addr,
391 : : unsigned int n)
392 : : {
393 : 683 : struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr;
394 : 683 : u32 addr = ath10k_ce_read32(ar, ce_ctrl_addr + dstr_wm->addr);
395 : :
396 : 683 : ath10k_ce_write32(ar, ce_ctrl_addr + dstr_wm->addr,
397 : 683 : (addr & ~(dstr_wm->wm_high->mask)) |
398 : 683 : (ath10k_set_ring_byte(n, dstr_wm->wm_high)));
399 : 683 : }
400 : :
401 : 363 : static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar,
402 : : u32 ce_ctrl_addr,
403 : : unsigned int n)
404 : : {
405 : 363 : struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr;
406 : 363 : u32 addr = ath10k_ce_read32(ar, ce_ctrl_addr + dstr_wm->addr);
407 : :
408 : 363 : ath10k_ce_write32(ar, ce_ctrl_addr + dstr_wm->addr,
409 : 363 : (addr & ~(dstr_wm->wm_low->mask)) |
410 : 363 : (ath10k_set_ring_byte(n, dstr_wm->wm_low)));
411 : 363 : }
412 : :
413 : 0 : static inline void ath10k_ce_copy_complete_inter_enable(struct ath10k *ar,
414 : : u32 ce_ctrl_addr)
415 : : {
416 : 0 : struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie;
417 : :
418 : 0 : u32 host_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
419 : 0 : ar->hw_ce_regs->host_ie_addr);
420 : :
421 : 0 : ath10k_ce_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr,
422 : 0 : host_ie_addr | host_ie->copy_complete->mask);
423 : 0 : }
424 : :
425 : 553 : static inline void ath10k_ce_copy_complete_intr_disable(struct ath10k *ar,
426 : : u32 ce_ctrl_addr)
427 : : {
428 : 553 : struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie;
429 : :
430 : 553 : u32 host_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
431 : 553 : ar->hw_ce_regs->host_ie_addr);
432 : :
433 : 553 : ath10k_ce_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr,
434 : 553 : host_ie_addr & ~(host_ie->copy_complete->mask));
435 : 553 : }
436 : :
437 : 553 : static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar,
438 : : u32 ce_ctrl_addr)
439 : : {
440 : 553 : struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
441 : :
442 : 553 : u32 host_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
443 : 553 : ar->hw_ce_regs->host_ie_addr);
444 : :
445 : 553 : ath10k_ce_write32(ar, ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr,
446 : 553 : host_ie_addr & ~(wm_regs->wm_mask));
447 : 553 : }
448 : :
449 : : static inline void ath10k_ce_error_intr_enable(struct ath10k *ar,
450 : : u32 ce_ctrl_addr)
451 : : {
452 : : struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs;
453 : :
454 : : u32 misc_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
455 : : ar->hw_ce_regs->misc_ie_addr);
456 : :
457 : : ath10k_ce_write32(ar,
458 : : ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr,
459 : : misc_ie_addr | misc_regs->err_mask);
460 : : }
461 : :
462 : 553 : static inline void ath10k_ce_error_intr_disable(struct ath10k *ar,
463 : : u32 ce_ctrl_addr)
464 : : {
465 : 553 : struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs;
466 : :
467 : 553 : u32 misc_ie_addr = ath10k_ce_read32(ar,
468 : 553 : ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr);
469 : :
470 : 553 : ath10k_ce_write32(ar,
471 : 553 : ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr,
472 : 553 : misc_ie_addr & ~(misc_regs->err_mask));
473 : 553 : }
474 : :
475 : 0 : static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
476 : : u32 ce_ctrl_addr,
477 : : unsigned int mask)
478 : : {
479 : 0 : struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
480 : :
481 : 0 : ath10k_ce_write32(ar, ce_ctrl_addr + wm_regs->addr, mask);
482 : : }
483 : :
484 : : /*
485 : : * Guts of ath10k_ce_send.
486 : : * The caller takes responsibility for any needed locking.
487 : : */
488 : 133 : static int _ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
489 : : void *per_transfer_context,
490 : : dma_addr_t buffer,
491 : : unsigned int nbytes,
492 : : unsigned int transfer_id,
493 : : unsigned int flags)
494 : : {
495 : 133 : struct ath10k *ar = ce_state->ar;
496 : 133 : struct ath10k_ce_ring *src_ring = ce_state->src_ring;
497 : 133 : struct ce_desc *desc, sdesc;
498 : 133 : unsigned int nentries_mask = src_ring->nentries_mask;
499 : 133 : unsigned int sw_index = src_ring->sw_index;
500 : 133 : unsigned int write_index = src_ring->write_index;
501 : 133 : u32 ctrl_addr = ce_state->ctrl_addr;
502 : 133 : u32 desc_flags = 0;
503 : 133 : int ret = 0;
504 : :
505 [ - + ]: 133 : if (nbytes > ce_state->src_sz_max)
506 : 0 : ath10k_warn(ar, "%s: send more we can (nbytes: %d, max: %d)\n",
507 : : __func__, nbytes, ce_state->src_sz_max);
508 : :
509 [ + + ]: 133 : if (unlikely(CE_RING_DELTA(nentries_mask,
510 : : write_index, sw_index - 1) <= 0)) {
511 : 1 : printk(KERN_INFO "nentries_mask %x, write_index %x, sw_index %x\n",
512 : : nentries_mask, write_index, sw_index);
513 : 1 : WARN_ON(1);
514 : 1 : ret = -ENOSR;
515 : 1 : goto exit;
516 : : }
517 : : else {
518 : 132 : printk(KERN_INFO "CE_RING_DELTA okay write_index %x, sw_index %x\n",
519 : : write_index, sw_index);
520 : : }
521 : :
522 : 132 : desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space,
523 : : write_index);
524 : :
525 : 132 : desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA);
526 : :
527 [ - + ]: 132 : if (flags & CE_SEND_FLAG_GATHER)
528 : 0 : desc_flags |= CE_DESC_FLAGS_GATHER;
529 [ - + ]: 132 : if (flags & CE_SEND_FLAG_BYTE_SWAP)
530 : 0 : desc_flags |= CE_DESC_FLAGS_BYTE_SWAP;
531 : :
532 : 132 : sdesc.addr = __cpu_to_le32(buffer);
533 : 132 : sdesc.nbytes = __cpu_to_le16(nbytes);
534 : 132 : sdesc.flags = __cpu_to_le16(desc_flags);
535 : :
536 : 132 : *desc = sdesc;
537 : :
538 : 132 : src_ring->per_transfer_context[write_index] = per_transfer_context;
539 : :
540 : : /* Update Source Ring Write Index */
541 : 132 : write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
542 : :
543 : : /* WORKAROUND */
544 [ + - ]: 132 : if (!(flags & CE_SEND_FLAG_GATHER))
545 : 132 : ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, write_index);
546 : :
547 : 132 : src_ring->write_index = write_index;
548 : 133 : exit:
549 : 133 : return ret;
550 : : }
551 : :
552 : 0 : static int _ath10k_ce_send_nolock_64(struct ath10k_ce_pipe *ce_state,
553 : : void *per_transfer_context,
554 : : dma_addr_t buffer,
555 : : unsigned int nbytes,
556 : : unsigned int transfer_id,
557 : : unsigned int flags)
558 : : {
559 : 0 : struct ath10k *ar = ce_state->ar;
560 : 0 : struct ath10k_ce_ring *src_ring = ce_state->src_ring;
561 : 0 : struct ce_desc_64 *desc, sdesc;
562 : 0 : unsigned int nentries_mask = src_ring->nentries_mask;
563 : 0 : unsigned int sw_index;
564 : 0 : unsigned int write_index = src_ring->write_index;
565 : 0 : u32 ctrl_addr = ce_state->ctrl_addr;
566 : 0 : __le32 *addr;
567 : 0 : u32 desc_flags = 0;
568 : 0 : int ret = 0;
569 : :
570 [ # # ]: 0 : if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
571 : : return -ESHUTDOWN;
572 : :
573 [ # # ]: 0 : if (nbytes > ce_state->src_sz_max)
574 : 0 : ath10k_warn(ar, "%s: send more we can (nbytes: %d, max: %d)\n",
575 : : __func__, nbytes, ce_state->src_sz_max);
576 : :
577 [ # # ]: 0 : if (ar->hw_params.rri_on_ddr)
578 : 0 : sw_index = ath10k_ce_src_ring_read_index_from_ddr(ar, ce_state->id);
579 : : else
580 : 0 : sw_index = src_ring->sw_index;
581 : :
582 [ # # ]: 0 : if (unlikely(CE_RING_DELTA(nentries_mask,
583 : : write_index, sw_index - 1) <= 0)) {
584 : 0 : printk(KERN_INFO "nentries_mask %x, write_index %x, sw_index %x\n",
585 : : nentries_mask, write_index, sw_index);
586 : 0 : ret = -ENOSR;
587 : 0 : goto exit;
588 : : }
589 : :
590 : 0 : desc = CE_SRC_RING_TO_DESC_64(src_ring->base_addr_owner_space,
591 : : write_index);
592 : :
593 : 0 : desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA);
594 : :
595 [ # # ]: 0 : if (flags & CE_SEND_FLAG_GATHER)
596 : 0 : desc_flags |= CE_DESC_FLAGS_GATHER;
597 : :
598 [ # # ]: 0 : if (flags & CE_SEND_FLAG_BYTE_SWAP)
599 : 0 : desc_flags |= CE_DESC_FLAGS_BYTE_SWAP;
600 : :
601 : 0 : addr = (__le32 *)&sdesc.addr;
602 : :
603 : 0 : flags |= upper_32_bits(buffer) & CE_DESC_ADDR_HI_MASK;
604 : 0 : addr[0] = __cpu_to_le32(buffer);
605 : 0 : addr[1] = __cpu_to_le32(flags);
606 [ # # ]: 0 : if (flags & CE_SEND_FLAG_GATHER)
607 : 0 : addr[1] |= __cpu_to_le32(CE_WCN3990_DESC_FLAGS_GATHER);
608 : : else
609 : 0 : addr[1] &= ~(__cpu_to_le32(CE_WCN3990_DESC_FLAGS_GATHER));
610 : :
611 : 0 : sdesc.nbytes = __cpu_to_le16(nbytes);
612 : 0 : sdesc.flags = __cpu_to_le16(desc_flags);
613 : :
614 : 0 : *desc = sdesc;
615 : :
616 : 0 : src_ring->per_transfer_context[write_index] = per_transfer_context;
617 : :
618 : : /* Update Source Ring Write Index */
619 : 0 : write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
620 : :
621 [ # # ]: 0 : if (!(flags & CE_SEND_FLAG_GATHER)) {
622 [ # # ]: 0 : if (ar->hw_params.shadow_reg_support)
623 : 0 : ath10k_ce_shadow_src_ring_write_index_set(ar, ce_state,
624 : : write_index);
625 : : else
626 : 0 : ath10k_ce_src_ring_write_index_set(ar, ctrl_addr,
627 : : write_index);
628 : : }
629 : :
630 : 0 : src_ring->write_index = write_index;
631 : : exit:
632 : : return ret;
633 : : }
634 : :
635 : 133 : int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
636 : : void *per_transfer_context,
637 : : dma_addr_t buffer,
638 : : unsigned int nbytes,
639 : : unsigned int transfer_id,
640 : : unsigned int flags)
641 : : {
642 : 0 : return ce_state->ops->ce_send_nolock(ce_state, per_transfer_context,
643 : : buffer, nbytes, transfer_id, flags);
644 : : }
645 : : EXPORT_SYMBOL(ath10k_ce_send_nolock);
646 : :
647 : 0 : void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe)
648 : : {
649 : 0 : struct ath10k *ar = pipe->ar;
650 [ # # ]: 0 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
651 : 0 : struct ath10k_ce_ring *src_ring = pipe->src_ring;
652 : 0 : u32 ctrl_addr = pipe->ctrl_addr;
653 : :
654 : 0 : lockdep_assert_held(&ce->ce_lock);
655 : :
656 : : /*
657 : : * This function must be called only if there is an incomplete
658 : : * scatter-gather transfer (before index register is updated)
659 : : * that needs to be cleaned up.
660 : : */
661 [ # # # # ]: 0 : if (WARN_ON_ONCE(src_ring->write_index == src_ring->sw_index))
662 : : return;
663 : :
664 [ # # # # ]: 0 : if (WARN_ON_ONCE(src_ring->write_index ==
665 : : ath10k_ce_src_ring_write_index_get(ar, ctrl_addr)))
666 : : return;
667 : :
668 : 0 : src_ring->write_index--;
669 : 0 : src_ring->write_index &= src_ring->nentries_mask;
670 : :
671 : 0 : src_ring->per_transfer_context[src_ring->write_index] = NULL;
672 : : }
673 : : EXPORT_SYMBOL(__ath10k_ce_send_revert);
674 : :
675 : 133 : int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
676 : : void *per_transfer_context,
677 : : dma_addr_t buffer,
678 : : unsigned int nbytes,
679 : : unsigned int transfer_id,
680 : : unsigned int flags)
681 : : {
682 : 133 : struct ath10k *ar = ce_state->ar;
683 : 133 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
684 : 133 : int ret;
685 : :
686 : 133 : spin_lock_bh(&ce->ce_lock);
687 : 133 : ret = ath10k_ce_send_nolock(ce_state, per_transfer_context,
688 : : buffer, nbytes, transfer_id, flags);
689 : 133 : spin_unlock_bh(&ce->ce_lock);
690 : :
691 : 133 : return ret;
692 : : }
693 : : EXPORT_SYMBOL(ath10k_ce_send);
694 : :
695 : 0 : int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe)
696 : : {
697 : 0 : struct ath10k *ar = pipe->ar;
698 : 0 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
699 : 0 : int delta;
700 : :
701 : 0 : spin_lock_bh(&ce->ce_lock);
702 : 0 : delta = CE_RING_DELTA(pipe->src_ring->nentries_mask,
703 : : pipe->src_ring->write_index,
704 : : pipe->src_ring->sw_index - 1);
705 : 0 : spin_unlock_bh(&ce->ce_lock);
706 : :
707 : 0 : return delta;
708 : : }
709 : : EXPORT_SYMBOL(ath10k_ce_num_free_src_entries);
710 : :
711 : 0 : int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe)
712 : : {
713 : 0 : struct ath10k *ar = pipe->ar;
714 : 0 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
715 : 0 : struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
716 : 0 : unsigned int nentries_mask = dest_ring->nentries_mask;
717 : 0 : unsigned int write_index = dest_ring->write_index;
718 : 0 : unsigned int sw_index = dest_ring->sw_index;
719 : :
720 : 0 : lockdep_assert_held(&ce->ce_lock);
721 : :
722 : 0 : return CE_RING_DELTA(nentries_mask, write_index, sw_index - 1);
723 : : }
724 : : EXPORT_SYMBOL(__ath10k_ce_rx_num_free_bufs);
725 : :
726 : 135 : static int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx,
727 : : dma_addr_t paddr)
728 : : {
729 : 135 : printk(KERN_INFO "ath10k_ce_rx_post_buf\n");
730 : 135 : struct ath10k *ar = pipe->ar;
731 [ + - ]: 135 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
732 : 135 : struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
733 : 135 : unsigned int nentries_mask = dest_ring->nentries_mask;
734 : 135 : unsigned int write_index = dest_ring->write_index;
735 : 135 : unsigned int sw_index = dest_ring->sw_index;
736 : 135 : struct ce_desc *base = dest_ring->base_addr_owner_space;
737 : 135 : struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, write_index);
738 : 135 : u32 ctrl_addr = pipe->ctrl_addr;
739 : :
740 : 135 : lockdep_assert_held(&ce->ce_lock);
741 : :
742 [ + - ]: 135 : if ((pipe->id != 5) &&
743 [ + + ]: 135 : CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0) {
744 : 2 : printk(KERN_INFO "pipe id: %x\n", pipe->id);
745 : 2 : printk(KERN_INFO "nentries_mask %x, write_index %x, sw_index %x\n",
746 : : nentries_mask, write_index, sw_index);
747 : :
748 : 2 : return -ENOSPC;
749 : : }
750 : :
751 : 133 : printk(KERN_INFO "ath10k_ce_rx_post_buf okay write_index %x, sw_index %x\n",
752 : : write_index, sw_index);
753 : :
754 : 133 : desc->addr = __cpu_to_le32(paddr);
755 : 133 : desc->nbytes = 0;
756 : :
757 : 133 : dest_ring->per_transfer_context[write_index] = ctx;
758 : 133 : write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
759 : 133 : ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index);
760 : 133 : dest_ring->write_index = write_index;
761 : :
762 : 133 : return 0;
763 : : }
764 : :
765 : 0 : static int __ath10k_ce_rx_post_buf_64(struct ath10k_ce_pipe *pipe,
766 : : void *ctx,
767 : : dma_addr_t paddr)
768 : : {
769 : 0 : struct ath10k *ar = pipe->ar;
770 [ # # ]: 0 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
771 : 0 : struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
772 : 0 : unsigned int nentries_mask = dest_ring->nentries_mask;
773 : 0 : unsigned int write_index = dest_ring->write_index;
774 : 0 : unsigned int sw_index = dest_ring->sw_index;
775 : 0 : struct ce_desc_64 *base = dest_ring->base_addr_owner_space;
776 : 0 : struct ce_desc_64 *desc =
777 : 0 : CE_DEST_RING_TO_DESC_64(base, write_index);
778 : 0 : u32 ctrl_addr = pipe->ctrl_addr;
779 : :
780 : 0 : lockdep_assert_held(&ce->ce_lock);
781 : :
782 [ # # ]: 0 : if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0)
783 : : return -ENOSPC;
784 : :
785 : 0 : desc->addr = __cpu_to_le64(paddr);
786 : 0 : desc->addr &= __cpu_to_le64(CE_DESC_ADDR_MASK);
787 : :
788 : 0 : desc->nbytes = 0;
789 : :
790 : 0 : dest_ring->per_transfer_context[write_index] = ctx;
791 : 0 : write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
792 : 0 : ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index);
793 : 0 : dest_ring->write_index = write_index;
794 : :
795 : 0 : return 0;
796 : : }
797 : :
798 : 0 : void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries)
799 : : {
800 : 0 : struct ath10k *ar = pipe->ar;
801 : 0 : struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
802 : 0 : unsigned int nentries_mask = dest_ring->nentries_mask;
803 : 0 : unsigned int write_index = dest_ring->write_index;
804 : 0 : u32 ctrl_addr = pipe->ctrl_addr;
805 : 0 : u32 cur_write_idx = ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr);
806 : :
807 : : /* Prevent CE ring stuck issue that will occur when ring is full.
808 : : * Make sure that write index is 1 less than read index.
809 : : */
810 [ # # ]: 0 : if (((cur_write_idx + nentries) & nentries_mask) == dest_ring->sw_index)
811 : 0 : nentries -= 1;
812 : :
813 : 0 : write_index = CE_RING_IDX_ADD(nentries_mask, write_index, nentries);
814 : 0 : ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index);
815 : 0 : dest_ring->write_index = write_index;
816 : 0 : }
817 : : EXPORT_SYMBOL(ath10k_ce_rx_update_write_idx);
818 : :
819 : 135 : int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx,
820 : : dma_addr_t paddr)
821 : : {
822 : 135 : struct ath10k *ar = pipe->ar;
823 : 135 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
824 : 135 : int ret;
825 : :
826 : 135 : spin_lock_bh(&ce->ce_lock);
827 : 135 : ret = pipe->ops->ce_rx_post_buf(pipe, ctx, paddr);
828 : 135 : spin_unlock_bh(&ce->ce_lock);
829 : :
830 : 135 : return ret;
831 : : }
832 : : EXPORT_SYMBOL(ath10k_ce_rx_post_buf);
833 : :
834 : : /*
835 : : * Guts of ath10k_ce_completed_recv_next.
836 : : * The caller takes responsibility for any necessary locking.
837 : : */
838 : : static int
839 : 1485 : _ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
840 : : void **per_transfer_contextp,
841 : : unsigned int *nbytesp)
842 : : {
843 : 1485 : struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
844 : 1485 : unsigned int nentries_mask = dest_ring->nentries_mask;
845 : 1485 : unsigned int sw_index = dest_ring->sw_index;
846 : :
847 : 1485 : struct ce_desc *base = dest_ring->base_addr_owner_space;
848 : 1485 : struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, sw_index);
849 : 1485 : struct ce_desc sdesc;
850 : 1485 : u16 nbytes;
851 : :
852 : : /* Copy in one go for performance reasons */
853 : 1485 : sdesc = *desc;
854 : :
855 : 1485 : nbytes = __le16_to_cpu(sdesc.nbytes);
856 [ + + ]: 1485 : if (nbytes == 0) {
857 : : /*
858 : : * This closes a relatively unusual race where the Host
859 : : * sees the updated DRRI before the update to the
860 : : * corresponding descriptor has completed. We treat this
861 : : * as a descriptor that is not yet done.
862 : : */
863 : : return -EIO;
864 : : }
865 : :
866 : 1483 : desc->nbytes = 0;
867 : :
868 : : /* Return data from completed destination descriptor */
869 : 1483 : *nbytesp = nbytes;
870 : :
871 [ + - ]: 1483 : if (per_transfer_contextp)
872 : 1483 : *per_transfer_contextp =
873 : 1483 : dest_ring->per_transfer_context[sw_index];
874 : :
875 : : /* Copy engine 5 (HTT Rx) will reuse the same transfer context.
876 : : * So update transfer context all CEs except CE5.
877 : : */
878 [ + - ]: 1483 : if (ce_state->id != 5)
879 : 1483 : dest_ring->per_transfer_context[sw_index] = NULL;
880 : :
881 : : /* Update sw_index */
882 : 1483 : sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
883 : 1483 : dest_ring->sw_index = sw_index;
884 : :
885 : 1483 : return 0;
886 : : }
887 : :
888 : : static int
889 : 0 : _ath10k_ce_completed_recv_next_nolock_64(struct ath10k_ce_pipe *ce_state,
890 : : void **per_transfer_contextp,
891 : : unsigned int *nbytesp)
892 : : {
893 : 0 : struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
894 : 0 : unsigned int nentries_mask = dest_ring->nentries_mask;
895 : 0 : unsigned int sw_index = dest_ring->sw_index;
896 : 0 : struct ce_desc_64 *base = dest_ring->base_addr_owner_space;
897 : 0 : struct ce_desc_64 *desc =
898 : 0 : CE_DEST_RING_TO_DESC_64(base, sw_index);
899 : 0 : struct ce_desc_64 sdesc;
900 : 0 : u16 nbytes;
901 : :
902 : : /* Copy in one go for performance reasons */
903 : 0 : sdesc = *desc;
904 : :
905 : 0 : nbytes = __le16_to_cpu(sdesc.nbytes);
906 [ # # ]: 0 : if (nbytes == 0) {
907 : : /* This closes a relatively unusual race where the Host
908 : : * sees the updated DRRI before the update to the
909 : : * corresponding descriptor has completed. We treat this
910 : : * as a descriptor that is not yet done.
911 : : */
912 : : return -EIO;
913 : : }
914 : :
915 : 0 : desc->nbytes = 0;
916 : :
917 : : /* Return data from completed destination descriptor */
918 : 0 : *nbytesp = nbytes;
919 : :
920 [ # # ]: 0 : if (per_transfer_contextp)
921 : 0 : *per_transfer_contextp =
922 : 0 : dest_ring->per_transfer_context[sw_index];
923 : :
924 : : /* Copy engine 5 (HTT Rx) will reuse the same transfer context.
925 : : * So update transfer context all CEs except CE5.
926 : : */
927 [ # # ]: 0 : if (ce_state->id != 5)
928 : 0 : dest_ring->per_transfer_context[sw_index] = NULL;
929 : :
930 : : /* Update sw_index */
931 : 0 : sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
932 : 0 : dest_ring->sw_index = sw_index;
933 : :
934 : 0 : return 0;
935 : : }
936 : :
937 : 0 : int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
938 : : void **per_transfer_ctx,
939 : : unsigned int *nbytesp)
940 : : {
941 : 0 : return ce_state->ops->ce_completed_recv_next_nolock(ce_state,
942 : : per_transfer_ctx,
943 : : nbytesp);
944 : : }
945 : : EXPORT_SYMBOL(ath10k_ce_completed_recv_next_nolock);
946 : :
947 : 1485 : int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
948 : : void **per_transfer_contextp,
949 : : unsigned int *nbytesp)
950 : : {
951 : 1485 : struct ath10k *ar = ce_state->ar;
952 : 1485 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
953 : 1485 : int ret;
954 : :
955 : 1485 : spin_lock_bh(&ce->ce_lock);
956 : 1485 : ret = ce_state->ops->ce_completed_recv_next_nolock(ce_state,
957 : : per_transfer_contextp,
958 : : nbytesp);
959 : :
960 : 1485 : spin_unlock_bh(&ce->ce_lock);
961 : :
962 : 1485 : return ret;
963 : : }
964 : : EXPORT_SYMBOL(ath10k_ce_completed_recv_next);
965 : :
966 : 7 : static int _ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
967 : : void **per_transfer_contextp,
968 : : dma_addr_t *bufferp)
969 : : {
970 : 7 : struct ath10k_ce_ring *dest_ring;
971 : 7 : unsigned int nentries_mask;
972 : 7 : unsigned int sw_index;
973 : 7 : unsigned int write_index;
974 : 7 : int ret;
975 : 7 : struct ath10k *ar;
976 : 7 : struct ath10k_ce *ce;
977 : :
978 : 7 : dest_ring = ce_state->dest_ring;
979 : :
980 [ + - ]: 7 : if (!dest_ring)
981 : : return -EIO;
982 : :
983 : 7 : ar = ce_state->ar;
984 : 7 : ce = ath10k_ce_priv(ar);
985 : :
986 : 7 : spin_lock_bh(&ce->ce_lock);
987 : :
988 : 7 : nentries_mask = dest_ring->nentries_mask;
989 : 7 : sw_index = dest_ring->sw_index;
990 : 7 : write_index = dest_ring->write_index;
991 [ - + ]: 7 : if (write_index != sw_index) {
992 : 0 : struct ce_desc *base = dest_ring->base_addr_owner_space;
993 : 0 : struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, sw_index);
994 : :
995 : : /* Return data from completed destination descriptor */
996 : 0 : *bufferp = __le32_to_cpu(desc->addr);
997 : :
998 [ # # ]: 0 : if (per_transfer_contextp)
999 : 0 : *per_transfer_contextp =
1000 : 0 : dest_ring->per_transfer_context[sw_index];
1001 : :
1002 : : /* sanity */
1003 : 0 : dest_ring->per_transfer_context[sw_index] = NULL;
1004 : 0 : desc->nbytes = 0;
1005 : :
1006 : : /* Update sw_index */
1007 : 0 : sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
1008 : 0 : dest_ring->sw_index = sw_index;
1009 : 0 : ret = 0;
1010 : : } else {
1011 : : ret = -EIO;
1012 : : }
1013 : :
1014 : 7 : spin_unlock_bh(&ce->ce_lock);
1015 : :
1016 : 7 : return ret;
1017 : : }
1018 : :
1019 : 0 : static int _ath10k_ce_revoke_recv_next_64(struct ath10k_ce_pipe *ce_state,
1020 : : void **per_transfer_contextp,
1021 : : dma_addr_t *bufferp)
1022 : : {
1023 : 0 : struct ath10k_ce_ring *dest_ring;
1024 : 0 : unsigned int nentries_mask;
1025 : 0 : unsigned int sw_index;
1026 : 0 : unsigned int write_index;
1027 : 0 : int ret;
1028 : 0 : struct ath10k *ar;
1029 : 0 : struct ath10k_ce *ce;
1030 : :
1031 : 0 : dest_ring = ce_state->dest_ring;
1032 : :
1033 [ # # ]: 0 : if (!dest_ring)
1034 : : return -EIO;
1035 : :
1036 : 0 : ar = ce_state->ar;
1037 : 0 : ce = ath10k_ce_priv(ar);
1038 : :
1039 : 0 : spin_lock_bh(&ce->ce_lock);
1040 : :
1041 : 0 : nentries_mask = dest_ring->nentries_mask;
1042 : 0 : sw_index = dest_ring->sw_index;
1043 : 0 : write_index = dest_ring->write_index;
1044 [ # # ]: 0 : if (write_index != sw_index) {
1045 : 0 : struct ce_desc_64 *base = dest_ring->base_addr_owner_space;
1046 : 0 : struct ce_desc_64 *desc =
1047 : 0 : CE_DEST_RING_TO_DESC_64(base, sw_index);
1048 : :
1049 : : /* Return data from completed destination descriptor */
1050 : 0 : *bufferp = __le64_to_cpu(desc->addr);
1051 : :
1052 [ # # ]: 0 : if (per_transfer_contextp)
1053 : 0 : *per_transfer_contextp =
1054 : 0 : dest_ring->per_transfer_context[sw_index];
1055 : :
1056 : : /* sanity */
1057 : 0 : dest_ring->per_transfer_context[sw_index] = NULL;
1058 : 0 : desc->nbytes = 0;
1059 : :
1060 : : /* Update sw_index */
1061 : 0 : sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
1062 : 0 : dest_ring->sw_index = sw_index;
1063 : 0 : ret = 0;
1064 : : } else {
1065 : : ret = -EIO;
1066 : : }
1067 : :
1068 : 0 : spin_unlock_bh(&ce->ce_lock);
1069 : :
1070 : 0 : return ret;
1071 : : }
1072 : :
1073 : 7 : int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
1074 : : void **per_transfer_contextp,
1075 : : dma_addr_t *bufferp)
1076 : : {
1077 : 7 : return ce_state->ops->ce_revoke_recv_next(ce_state,
1078 : : per_transfer_contextp,
1079 : : bufferp);
1080 : : }
1081 : : EXPORT_SYMBOL(ath10k_ce_revoke_recv_next);
1082 : :
1083 : : /*
1084 : : * Guts of ath10k_ce_completed_send_next.
1085 : : * The caller takes responsibility for any necessary locking.
1086 : : */
1087 : 1554 : static int _ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
1088 : : void **per_transfer_contextp)
1089 : : {
1090 : 1554 : struct ath10k_ce_ring *src_ring = ce_state->src_ring;
1091 : 1554 : u32 ctrl_addr = ce_state->ctrl_addr;
1092 : 1554 : struct ath10k *ar = ce_state->ar;
1093 : 1554 : unsigned int nentries_mask = src_ring->nentries_mask;
1094 : 1554 : unsigned int sw_index = src_ring->sw_index;
1095 : 1554 : unsigned int read_index;
1096 : 1554 : struct ce_desc *desc;
1097 : 1554 : printk(KERN_INFO "[_ath10k_ce_completed_send_next_nolock]\n");
1098 : :
1099 [ + + ]: 1554 : if (src_ring->hw_index == sw_index) {
1100 : : /*
1101 : : * The SW completion index has caught up with the cached
1102 : : * version of the HW completion index.
1103 : : * Update the cached HW completion index to see whether
1104 : : * the SW has really caught up to the HW, or if the cached
1105 : : * value of the HW index has become stale.
1106 : : */
1107 : :
1108 : 385 : read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
1109 [ + - ]: 385 : if (read_index == 0xffffffff)
1110 : : return -ENODEV;
1111 : :
1112 : 385 : read_index &= nentries_mask;
1113 : 385 : src_ring->hw_index = read_index;
1114 : : }
1115 : :
1116 [ - + ]: 1554 : if (ar->hw_params.rri_on_ddr)
1117 : 0 : read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
1118 : : else
1119 : 1554 : read_index = src_ring->hw_index;
1120 : :
1121 [ + + ]: 1554 : if (read_index == sw_index)
1122 : : return -EIO;
1123 : :
1124 [ + + ]: 1469 : if (per_transfer_contextp) {
1125 : 1344 : *per_transfer_contextp =
1126 : 1344 : src_ring->per_transfer_context[sw_index];
1127 : 1344 : printk(KERN_INFO "Setting per_transfer_contextp\n");
1128 : :
1129 : : }
1130 : : else {
1131 : 125 : printk(KERN_INFO "NOT Setting per_transfer_contextp\n");
1132 : : }
1133 : :
1134 : : /* sanity */
1135 : 1469 : src_ring->per_transfer_context[sw_index] = NULL;
1136 : 1469 : desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space,
1137 : : sw_index);
1138 : 1469 : desc->nbytes = 0;
1139 : :
1140 : : /* Update sw_index */
1141 : 1469 : sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
1142 : 1469 : src_ring->sw_index = sw_index;
1143 : : // printk(KERN_INFO "UPDATE 1 write_index %x, sw_index %x\n",
1144 : : // src_ring->write_index, sw_index);
1145 : : // if (unlikely(CE_RING_DELTA(nentries_mask,
1146 : : // src_ring->write_index, sw_index - 1) <= 0)) {
1147 : : // WARN_ON(1);
1148 : : // }
1149 : 1469 : return 0;
1150 : : }
1151 : :
1152 : 0 : static int _ath10k_ce_completed_send_next_nolock_64(struct ath10k_ce_pipe *ce_state,
1153 : : void **per_transfer_contextp)
1154 : : {
1155 : 0 : struct ath10k_ce_ring *src_ring = ce_state->src_ring;
1156 : 0 : u32 ctrl_addr = ce_state->ctrl_addr;
1157 : 0 : struct ath10k *ar = ce_state->ar;
1158 : 0 : unsigned int nentries_mask = src_ring->nentries_mask;
1159 : 0 : unsigned int sw_index = src_ring->sw_index;
1160 : 0 : unsigned int read_index;
1161 : 0 : struct ce_desc_64 *desc;
1162 : :
1163 [ # # ]: 0 : if (src_ring->hw_index == sw_index) {
1164 : : /*
1165 : : * The SW completion index has caught up with the cached
1166 : : * version of the HW completion index.
1167 : : * Update the cached HW completion index to see whether
1168 : : * the SW has really caught up to the HW, or if the cached
1169 : : * value of the HW index has become stale.
1170 : : */
1171 : :
1172 : 0 : read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
1173 [ # # ]: 0 : if (read_index == 0xffffffff)
1174 : : return -ENODEV;
1175 : :
1176 : 0 : read_index &= nentries_mask;
1177 : 0 : src_ring->hw_index = read_index;
1178 : : }
1179 : :
1180 [ # # ]: 0 : if (ar->hw_params.rri_on_ddr)
1181 : 0 : read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
1182 : : else
1183 : 0 : read_index = src_ring->hw_index;
1184 : :
1185 [ # # ]: 0 : if (read_index == sw_index)
1186 : : return -EIO;
1187 : :
1188 [ # # ]: 0 : if (per_transfer_contextp)
1189 : 0 : *per_transfer_contextp =
1190 : 0 : src_ring->per_transfer_context[sw_index];
1191 : :
1192 : : /* sanity */
1193 : 0 : src_ring->per_transfer_context[sw_index] = NULL;
1194 : 0 : desc = CE_SRC_RING_TO_DESC_64(src_ring->base_addr_owner_space,
1195 : : sw_index);
1196 : 0 : desc->nbytes = 0;
1197 : :
1198 : : /* Update sw_index */
1199 : 0 : sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
1200 : 0 : src_ring->sw_index = sw_index;
1201 : 0 : printk(KERN_INFO "UPDATE 2 write_index %x, sw_index %x\n",
1202 : : src_ring->write_index, sw_index);
1203 : :
1204 : 0 : return 0;
1205 : : }
1206 : :
1207 : 1554 : int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
1208 : : void **per_transfer_contextp)
1209 : : {
1210 : 0 : return ce_state->ops->ce_completed_send_next_nolock(ce_state,
1211 : : per_transfer_contextp);
1212 : : }
1213 : : EXPORT_SYMBOL(ath10k_ce_completed_send_next_nolock);
1214 : :
1215 : 0 : static void ath10k_ce_extract_desc_data(struct ath10k *ar,
1216 : : struct ath10k_ce_ring *src_ring,
1217 : : u32 sw_index,
1218 : : dma_addr_t *bufferp,
1219 : : u32 *nbytesp,
1220 : : u32 *transfer_idp)
1221 : : {
1222 : 0 : struct ce_desc *base = src_ring->base_addr_owner_space;
1223 : 0 : struct ce_desc *desc = CE_SRC_RING_TO_DESC(base, sw_index);
1224 : :
1225 : : /* Return data from completed source descriptor */
1226 : 0 : *bufferp = __le32_to_cpu(desc->addr);
1227 : 0 : *nbytesp = __le16_to_cpu(desc->nbytes);
1228 : 0 : *transfer_idp = MS(__le16_to_cpu(desc->flags),
1229 : : CE_DESC_FLAGS_META_DATA);
1230 : 0 : }
1231 : :
1232 : 0 : static void ath10k_ce_extract_desc_data_64(struct ath10k *ar,
1233 : : struct ath10k_ce_ring *src_ring,
1234 : : u32 sw_index,
1235 : : dma_addr_t *bufferp,
1236 : : u32 *nbytesp,
1237 : : u32 *transfer_idp)
1238 : : {
1239 : 0 : struct ce_desc_64 *base = src_ring->base_addr_owner_space;
1240 : 0 : struct ce_desc_64 *desc =
1241 : 0 : CE_SRC_RING_TO_DESC_64(base, sw_index);
1242 : :
1243 : : /* Return data from completed source descriptor */
1244 : 0 : *bufferp = __le64_to_cpu(desc->addr);
1245 : 0 : *nbytesp = __le16_to_cpu(desc->nbytes);
1246 : 0 : *transfer_idp = MS(__le16_to_cpu(desc->flags),
1247 : : CE_DESC_FLAGS_META_DATA);
1248 : 0 : }
1249 : :
1250 : : /* NB: Modeled after ath10k_ce_completed_send_next */
1251 : 0 : int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state,
1252 : : void **per_transfer_contextp,
1253 : : dma_addr_t *bufferp,
1254 : : unsigned int *nbytesp,
1255 : : unsigned int *transfer_idp)
1256 : : {
1257 : 0 : struct ath10k_ce_ring *src_ring;
1258 : 0 : unsigned int nentries_mask;
1259 : 0 : unsigned int sw_index;
1260 : 0 : unsigned int write_index;
1261 : 0 : int ret;
1262 : 0 : struct ath10k *ar;
1263 : 0 : struct ath10k_ce *ce;
1264 : :
1265 : 0 : src_ring = ce_state->src_ring;
1266 : :
1267 [ # # ]: 0 : if (!src_ring)
1268 : : return -EIO;
1269 : :
1270 : 0 : ar = ce_state->ar;
1271 : 0 : ce = ath10k_ce_priv(ar);
1272 : :
1273 : 0 : spin_lock_bh(&ce->ce_lock);
1274 : :
1275 : 0 : nentries_mask = src_ring->nentries_mask;
1276 : 0 : sw_index = src_ring->sw_index;
1277 : 0 : write_index = src_ring->write_index;
1278 : :
1279 [ # # ]: 0 : if (write_index != sw_index) {
1280 : 0 : ce_state->ops->ce_extract_desc_data(ar, src_ring, sw_index,
1281 : : bufferp, nbytesp,
1282 : : transfer_idp);
1283 : :
1284 [ # # ]: 0 : if (per_transfer_contextp)
1285 : 0 : *per_transfer_contextp =
1286 : 0 : src_ring->per_transfer_context[sw_index];
1287 : :
1288 : : /* sanity */
1289 : 0 : src_ring->per_transfer_context[sw_index] = NULL;
1290 : :
1291 : : /* Update sw_index */
1292 : 0 : sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
1293 : 0 : src_ring->sw_index = sw_index;
1294 : 0 : printk(KERN_INFO "UPDATE 3 write_index %x, sw_index %x\n",
1295 : : src_ring->write_index, sw_index);
1296 : 0 : ret = 0;
1297 : : } else {
1298 : : ret = -EIO;
1299 : : }
1300 : :
1301 : 0 : spin_unlock_bh(&ce->ce_lock);
1302 : :
1303 : 0 : return ret;
1304 : : }
1305 : : EXPORT_SYMBOL(ath10k_ce_cancel_send_next);
1306 : :
1307 : 1554 : int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
1308 : : void **per_transfer_contextp)
1309 : : {
1310 : 1554 : struct ath10k *ar = ce_state->ar;
1311 : 1554 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
1312 : 1554 : int ret;
1313 : :
1314 : 1554 : spin_lock_bh(&ce->ce_lock);
1315 : 1554 : ret = ath10k_ce_completed_send_next_nolock(ce_state,
1316 : : per_transfer_contextp);
1317 : 1554 : spin_unlock_bh(&ce->ce_lock);
1318 : :
1319 : 1554 : return ret;
1320 : : }
1321 : : EXPORT_SYMBOL(ath10k_ce_completed_send_next);
1322 : :
1323 : : /*
1324 : : * Guts of interrupt handler for per-engine interrupts on a particular CE.
1325 : : *
1326 : : * Invokes registered callbacks for recv_complete,
1327 : : * send_complete, and watermarks.
1328 : : */
1329 : 0 : void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
1330 : : {
1331 : 0 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
1332 : 0 : struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
1333 : 0 : struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
1334 : 0 : u32 ctrl_addr = ce_state->ctrl_addr;
1335 : :
1336 : 0 : spin_lock_bh(&ce->ce_lock);
1337 : :
1338 : : /* Clear the copy-complete interrupts that will be handled here. */
1339 : 0 : ath10k_ce_engine_int_status_clear(ar, ctrl_addr,
1340 : : wm_regs->cc_mask);
1341 : :
1342 : 0 : spin_unlock_bh(&ce->ce_lock);
1343 : :
1344 [ # # ]: 0 : if (ce_state->recv_cb)
1345 : 0 : ce_state->recv_cb(ce_state);
1346 : :
1347 [ # # ]: 0 : if (ce_state->send_cb)
1348 : 0 : ce_state->send_cb(ce_state);
1349 : :
1350 : 0 : spin_lock_bh(&ce->ce_lock);
1351 : :
1352 : : /*
1353 : : * Misc CE interrupts are not being handled, but still need
1354 : : * to be cleared.
1355 : : */
1356 : 0 : ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->wm_mask);
1357 : :
1358 : 0 : spin_unlock_bh(&ce->ce_lock);
1359 : 0 : }
1360 : : EXPORT_SYMBOL(ath10k_ce_per_engine_service);
1361 : :
1362 : : /*
1363 : : * Handler for per-engine interrupts on ALL active CEs.
1364 : : * This is used in cases where the system is sharing a
1365 : : * single interrput for all CEs
1366 : : */
1367 : :
1368 : 0 : void ath10k_ce_per_engine_service_any(struct ath10k *ar)
1369 : : {
1370 : 0 : int ce_id;
1371 : 0 : u32 intr_summary;
1372 : :
1373 [ # # ]: 0 : intr_summary = ath10k_ce_interrupt_summary(ar);
1374 : :
1375 [ # # # # ]: 0 : for (ce_id = 0; intr_summary && (ce_id < CE_COUNT); ce_id++) {
1376 [ # # ]: 0 : if (intr_summary & (1 << ce_id))
1377 : 0 : intr_summary &= ~(1 << ce_id);
1378 : : else
1379 : : /* no intr pending on this CE */
1380 : 0 : continue;
1381 : :
1382 : 0 : ath10k_ce_per_engine_service(ar, ce_id);
1383 : : }
1384 : 0 : }
1385 : : EXPORT_SYMBOL(ath10k_ce_per_engine_service_any);
1386 : :
1387 : : /*
1388 : : * Adjust interrupts for the copy complete handler.
1389 : : * If it's needed for either send or recv, then unmask
1390 : : * this interrupt; otherwise, mask it.
1391 : : *
1392 : : * Called with ce_lock held.
1393 : : */
1394 : 0 : static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state)
1395 : : {
1396 : 0 : u32 ctrl_addr = ce_state->ctrl_addr;
1397 : 0 : struct ath10k *ar = ce_state->ar;
1398 : 0 : bool disable_copy_compl_intr = ce_state->attr_flags & CE_ATTR_DIS_INTR;
1399 : :
1400 [ # # ]: 0 : if ((!disable_copy_compl_intr) &&
1401 [ # # # # ]: 0 : (ce_state->send_cb || ce_state->recv_cb))
1402 : 0 : ath10k_ce_copy_complete_inter_enable(ar, ctrl_addr);
1403 : : else
1404 : 0 : ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
1405 : :
1406 : 0 : ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
1407 : 0 : }
1408 : :
1409 : 79 : int ath10k_ce_disable_interrupts(struct ath10k *ar)
1410 : : {
1411 : 79 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
1412 : 79 : struct ath10k_ce_pipe *ce_state;
1413 : 79 : u32 ctrl_addr;
1414 : 79 : int ce_id;
1415 : :
1416 [ + + ]: 711 : for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
1417 : 632 : ce_state = &ce->ce_states[ce_id];
1418 [ + + ]: 632 : if (ce_state->attr_flags & CE_ATTR_POLL)
1419 : 79 : continue;
1420 : :
1421 : 553 : ctrl_addr = ath10k_ce_base_address(ar, ce_id);
1422 : :
1423 : 553 : ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
1424 : 553 : ath10k_ce_error_intr_disable(ar, ctrl_addr);
1425 : 553 : ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
1426 : : }
1427 : :
1428 : 79 : return 0;
1429 : : }
1430 : : EXPORT_SYMBOL(ath10k_ce_disable_interrupts);
1431 : :
1432 : 0 : void ath10k_ce_enable_interrupts(struct ath10k *ar)
1433 : : {
1434 : 0 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
1435 : 0 : int ce_id;
1436 : 0 : struct ath10k_ce_pipe *ce_state;
1437 : :
1438 : : /* Enable interrupts for copy engine that
1439 : : * are not using polling mode.
1440 : : */
1441 [ # # ]: 0 : for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
1442 : 0 : ce_state = &ce->ce_states[ce_id];
1443 [ # # ]: 0 : if (ce_state->attr_flags & CE_ATTR_POLL)
1444 : 0 : continue;
1445 : :
1446 : 0 : ath10k_ce_per_engine_handler_adjust(ce_state);
1447 : : }
1448 : 0 : }
1449 : : EXPORT_SYMBOL(ath10k_ce_enable_interrupts);
1450 : :
1451 : : static int ath10k_ce_init_src_ring(struct ath10k *ar,
1452 : : unsigned int ce_id,
1453 : : const struct ce_attr *attr)
1454 : : {
1455 : : struct ath10k_ce *ce = ath10k_ce_priv(ar);
1456 : : struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
1457 : : struct ath10k_ce_ring *src_ring = ce_state->src_ring;
1458 : : u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id);
1459 : :
1460 : : nentries = roundup_pow_of_two(attr->src_nentries);
1461 : :
1462 : : if (ar->hw_params.target_64bit)
1463 : : memset(src_ring->base_addr_owner_space, 0,
1464 : : nentries * sizeof(struct ce_desc_64));
1465 : : else
1466 : : memset(src_ring->base_addr_owner_space, 0,
1467 : : nentries * sizeof(struct ce_desc));
1468 : :
1469 : : src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
1470 : : src_ring->sw_index &= src_ring->nentries_mask;
1471 : : printk(KERN_INFO "UPDATE 4 write_index %x, sw_index %x\n",
1472 : : src_ring->write_index, src_ring->sw_index);
1473 : : src_ring->hw_index = src_ring->sw_index;
1474 : :
1475 : : src_ring->write_index =
1476 : : ath10k_ce_src_ring_write_index_get(ar, ctrl_addr);
1477 : : src_ring->write_index &= src_ring->nentries_mask;
1478 : :
1479 : : ath10k_ce_src_ring_base_addr_set(ar, ce_id,
1480 : : src_ring->base_addr_ce_space);
1481 : : ath10k_ce_src_ring_size_set(ar, ctrl_addr, nentries);
1482 : : ath10k_ce_src_ring_dmax_set(ar, ctrl_addr, attr->src_sz_max);
1483 : : ath10k_ce_src_ring_byte_swap_set(ar, ctrl_addr, 0);
1484 : : ath10k_ce_src_ring_lowmark_set(ar, ctrl_addr, 0);
1485 : : ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, nentries);
1486 : :
1487 : : ath10k_dbg(ar, ATH10K_DBG_BOOT,
1488 : : "boot init ce src ring id %d entries %d base_addr %pK\n",
1489 : : ce_id, nentries, src_ring->base_addr_owner_space);
1490 : :
1491 : : return 0;
1492 : : }
1493 : :
1494 : : static int ath10k_ce_init_dest_ring(struct ath10k *ar,
1495 : : unsigned int ce_id,
1496 : : const struct ce_attr *attr)
1497 : : {
1498 : : struct ath10k_ce *ce = ath10k_ce_priv(ar);
1499 : : struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
1500 : : struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
1501 : : u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id);
1502 : :
1503 : : nentries = roundup_pow_of_two(attr->dest_nentries);
1504 : :
1505 : : if (ar->hw_params.target_64bit)
1506 : : memset(dest_ring->base_addr_owner_space, 0,
1507 : : nentries * sizeof(struct ce_desc_64));
1508 : : else
1509 : : memset(dest_ring->base_addr_owner_space, 0,
1510 : : nentries * sizeof(struct ce_desc));
1511 : :
1512 : : dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr);
1513 : : dest_ring->sw_index &= dest_ring->nentries_mask;
1514 : : dest_ring->write_index =
1515 : : ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr);
1516 : : dest_ring->write_index &= dest_ring->nentries_mask;
1517 : :
1518 : : ath10k_ce_dest_ring_base_addr_set(ar, ce_id,
1519 : : dest_ring->base_addr_ce_space);
1520 : : ath10k_ce_dest_ring_size_set(ar, ctrl_addr, nentries);
1521 : : ath10k_ce_dest_ring_byte_swap_set(ar, ctrl_addr, 0);
1522 : : ath10k_ce_dest_ring_lowmark_set(ar, ctrl_addr, 0);
1523 : : ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries);
1524 : :
1525 : : ath10k_dbg(ar, ATH10K_DBG_BOOT,
1526 : : "boot ce dest ring id %d entries %d base_addr %pK\n",
1527 : : ce_id, nentries, dest_ring->base_addr_owner_space);
1528 : :
1529 : : return 0;
1530 : : }
1531 : :
1532 : 0 : static int ath10k_ce_alloc_shadow_base(struct ath10k *ar,
1533 : : struct ath10k_ce_ring *src_ring,
1534 : : u32 nentries)
1535 : : {
1536 : 0 : src_ring->shadow_base_unaligned = kcalloc(nentries,
1537 : : sizeof(struct ce_desc_64),
1538 : : GFP_KERNEL);
1539 [ # # # # ]: 0 : if (!src_ring->shadow_base_unaligned)
1540 : : return -ENOMEM;
1541 : :
1542 : 0 : src_ring->shadow_base = (struct ce_desc_64 *)
1543 : 0 : PTR_ALIGN(src_ring->shadow_base_unaligned,
1544 : : CE_DESC_RING_ALIGN);
1545 : 0 : return 0;
1546 : : }
1547 : :
1548 : : static struct ath10k_ce_ring *
1549 : 112 : ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id,
1550 : : const struct ce_attr *attr)
1551 : : {
1552 : 112 : struct ath10k_ce_ring *src_ring;
1553 : 112 : u32 nentries = attr->src_nentries;
1554 : 112 : dma_addr_t base_addr;
1555 : 112 : int ret;
1556 : :
1557 [ - + - - : 112 : nentries = roundup_pow_of_two(nentries);
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - ]
1558 : :
1559 [ - + ]: 112 : src_ring = kzalloc(struct_size(src_ring, per_transfer_context,
1560 : : nentries), GFP_KERNEL);
1561 [ + - ]: 112 : if (src_ring == NULL)
1562 : : return ERR_PTR(-ENOMEM);
1563 : :
1564 : 112 : src_ring->nentries = nentries;
1565 : 112 : src_ring->nentries_mask = nentries - 1;
1566 : :
1567 : : /*
1568 : : * Legacy platforms that do not support cache
1569 : : * coherent DMA are unsupported
1570 : : */
1571 : 224 : src_ring->base_addr_owner_space_unaligned =
1572 : 112 : dma_alloc_coherent(ar->dev,
1573 : 112 : (nentries * sizeof(struct ce_desc) +
1574 : : CE_DESC_RING_ALIGN),
1575 : : &base_addr, GFP_KERNEL);
1576 [ - + ]: 112 : if (!src_ring->base_addr_owner_space_unaligned) {
1577 : 0 : kfree(src_ring);
1578 : 0 : return ERR_PTR(-ENOMEM);
1579 : : }
1580 : :
1581 : 112 : src_ring->base_addr_ce_space_unaligned = base_addr;
1582 : :
1583 : 112 : src_ring->base_addr_owner_space =
1584 : 112 : PTR_ALIGN(src_ring->base_addr_owner_space_unaligned,
1585 : : CE_DESC_RING_ALIGN);
1586 : 112 : src_ring->base_addr_ce_space =
1587 : 112 : ALIGN(src_ring->base_addr_ce_space_unaligned,
1588 : : CE_DESC_RING_ALIGN);
1589 : :
1590 [ - + ]: 112 : if (ar->hw_params.shadow_reg_support) {
1591 : 0 : ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries);
1592 : 0 : if (ret) {
1593 : 0 : dma_free_coherent(ar->dev,
1594 : 0 : (nentries * sizeof(struct ce_desc_64) +
1595 : : CE_DESC_RING_ALIGN),
1596 : : src_ring->base_addr_owner_space_unaligned,
1597 : : base_addr);
1598 : 0 : kfree(src_ring);
1599 : 0 : return ERR_PTR(ret);
1600 : : }
1601 : : }
1602 : :
1603 : : return src_ring;
1604 : : }
1605 : :
1606 : : static struct ath10k_ce_ring *
1607 : 0 : ath10k_ce_alloc_src_ring_64(struct ath10k *ar, unsigned int ce_id,
1608 : : const struct ce_attr *attr)
1609 : : {
1610 : 0 : struct ath10k_ce_ring *src_ring;
1611 : 0 : u32 nentries = attr->src_nentries;
1612 : 0 : dma_addr_t base_addr;
1613 : 0 : int ret;
1614 : :
1615 [ # # # # : 0 : nentries = roundup_pow_of_two(nentries);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1616 : :
1617 [ # # ]: 0 : src_ring = kzalloc(struct_size(src_ring, per_transfer_context,
1618 : : nentries), GFP_KERNEL);
1619 [ # # ]: 0 : if (!src_ring)
1620 : : return ERR_PTR(-ENOMEM);
1621 : :
1622 : 0 : src_ring->nentries = nentries;
1623 : 0 : src_ring->nentries_mask = nentries - 1;
1624 : :
1625 : : /* Legacy platforms that do not support cache
1626 : : * coherent DMA are unsupported
1627 : : */
1628 : 0 : src_ring->base_addr_owner_space_unaligned =
1629 : 0 : dma_alloc_coherent(ar->dev,
1630 : 0 : (nentries * sizeof(struct ce_desc_64) +
1631 : : CE_DESC_RING_ALIGN),
1632 : : &base_addr, GFP_KERNEL);
1633 [ # # ]: 0 : if (!src_ring->base_addr_owner_space_unaligned) {
1634 : 0 : kfree(src_ring);
1635 : 0 : return ERR_PTR(-ENOMEM);
1636 : : }
1637 : :
1638 : 0 : src_ring->base_addr_ce_space_unaligned = base_addr;
1639 : :
1640 : 0 : src_ring->base_addr_owner_space =
1641 : 0 : PTR_ALIGN(src_ring->base_addr_owner_space_unaligned,
1642 : : CE_DESC_RING_ALIGN);
1643 : 0 : src_ring->base_addr_ce_space =
1644 : 0 : ALIGN(src_ring->base_addr_ce_space_unaligned,
1645 : : CE_DESC_RING_ALIGN);
1646 : :
1647 [ # # ]: 0 : if (ar->hw_params.shadow_reg_support) {
1648 : 0 : ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries);
1649 : 0 : if (ret) {
1650 : 0 : dma_free_coherent(ar->dev,
1651 : : (nentries * sizeof(struct ce_desc_64) +
1652 : : CE_DESC_RING_ALIGN),
1653 : : src_ring->base_addr_owner_space_unaligned,
1654 : : base_addr);
1655 : 0 : kfree(src_ring);
1656 : 0 : return ERR_PTR(ret);
1657 : : }
1658 : : }
1659 : :
1660 : : return src_ring;
1661 : : }
1662 : :
1663 : : static struct ath10k_ce_ring *
1664 : 84 : ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id,
1665 : : const struct ce_attr *attr)
1666 : : {
1667 : 84 : struct ath10k_ce_ring *dest_ring;
1668 : 84 : u32 nentries;
1669 : 84 : dma_addr_t base_addr;
1670 : :
1671 [ - + - - : 84 : nentries = roundup_pow_of_two(attr->dest_nentries);
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - ]
1672 : :
1673 [ - + ]: 84 : dest_ring = kzalloc(struct_size(dest_ring, per_transfer_context,
1674 : : nentries), GFP_KERNEL);
1675 [ + - ]: 84 : if (dest_ring == NULL)
1676 : : return ERR_PTR(-ENOMEM);
1677 : :
1678 : 84 : dest_ring->nentries = nentries;
1679 : 84 : dest_ring->nentries_mask = nentries - 1;
1680 : :
1681 : : /*
1682 : : * Legacy platforms that do not support cache
1683 : : * coherent DMA are unsupported
1684 : : */
1685 : 168 : dest_ring->base_addr_owner_space_unaligned =
1686 : 84 : dma_alloc_coherent(ar->dev,
1687 : 84 : (nentries * sizeof(struct ce_desc) +
1688 : : CE_DESC_RING_ALIGN),
1689 : : &base_addr, GFP_KERNEL);
1690 [ - + ]: 84 : if (!dest_ring->base_addr_owner_space_unaligned) {
1691 : 0 : kfree(dest_ring);
1692 : 0 : return ERR_PTR(-ENOMEM);
1693 : : }
1694 : :
1695 : 84 : dest_ring->base_addr_ce_space_unaligned = base_addr;
1696 : :
1697 : 84 : dest_ring->base_addr_owner_space =
1698 : 84 : PTR_ALIGN(dest_ring->base_addr_owner_space_unaligned,
1699 : : CE_DESC_RING_ALIGN);
1700 : 84 : dest_ring->base_addr_ce_space =
1701 : 84 : ALIGN(dest_ring->base_addr_ce_space_unaligned,
1702 : : CE_DESC_RING_ALIGN);
1703 : :
1704 : 84 : return dest_ring;
1705 : : }
1706 : :
1707 : : static struct ath10k_ce_ring *
1708 : 0 : ath10k_ce_alloc_dest_ring_64(struct ath10k *ar, unsigned int ce_id,
1709 : : const struct ce_attr *attr)
1710 : : {
1711 : 0 : struct ath10k_ce_ring *dest_ring;
1712 : 0 : u32 nentries;
1713 : 0 : dma_addr_t base_addr;
1714 : :
1715 [ # # # # : 0 : nentries = roundup_pow_of_two(attr->dest_nentries);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1716 : :
1717 [ # # ]: 0 : dest_ring = kzalloc(struct_size(dest_ring, per_transfer_context,
1718 : : nentries), GFP_KERNEL);
1719 [ # # ]: 0 : if (!dest_ring)
1720 : : return ERR_PTR(-ENOMEM);
1721 : :
1722 : 0 : dest_ring->nentries = nentries;
1723 : 0 : dest_ring->nentries_mask = nentries - 1;
1724 : :
1725 : : /* Legacy platforms that do not support cache
1726 : : * coherent DMA are unsupported
1727 : : */
1728 : 0 : dest_ring->base_addr_owner_space_unaligned =
1729 : 0 : dma_alloc_coherent(ar->dev,
1730 : 0 : (nentries * sizeof(struct ce_desc_64) +
1731 : : CE_DESC_RING_ALIGN),
1732 : : &base_addr, GFP_KERNEL);
1733 [ # # ]: 0 : if (!dest_ring->base_addr_owner_space_unaligned) {
1734 : 0 : kfree(dest_ring);
1735 : 0 : return ERR_PTR(-ENOMEM);
1736 : : }
1737 : :
1738 : 0 : dest_ring->base_addr_ce_space_unaligned = base_addr;
1739 : :
1740 : : /* Correctly initialize memory to 0 to prevent garbage
1741 : : * data crashing system when download firmware
1742 : : */
1743 : 0 : dest_ring->base_addr_owner_space =
1744 : 0 : PTR_ALIGN(dest_ring->base_addr_owner_space_unaligned,
1745 : : CE_DESC_RING_ALIGN);
1746 : 0 : dest_ring->base_addr_ce_space =
1747 : 0 : ALIGN(dest_ring->base_addr_ce_space_unaligned,
1748 : : CE_DESC_RING_ALIGN);
1749 : :
1750 : 0 : return dest_ring;
1751 : : }
1752 : :
1753 : : /*
1754 : : * Initialize a Copy Engine based on caller-supplied attributes.
1755 : : * This may be called once to initialize both source and destination
1756 : : * rings or it may be called twice for separate source and destination
1757 : : * initialization. It may be that only one side or the other is
1758 : : * initialized by software/firmware.
1759 : : */
1760 : 968 : int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
1761 : : const struct ce_attr *attr)
1762 : : {
1763 : 968 : int ret;
1764 : :
1765 [ + + ]: 968 : if (attr->src_nentries) {
1766 : 484 : ret = ath10k_ce_init_src_ring(ar, ce_id, attr);
1767 [ - + ]: 484 : if (ret) {
1768 : 0 : ath10k_err(ar, "Failed to initialize CE src ring for ID: %d (%d)\n",
1769 : : ce_id, ret);
1770 : 0 : return ret;
1771 : : }
1772 : : }
1773 : :
1774 [ + + ]: 968 : if (attr->dest_nentries) {
1775 : 363 : ret = ath10k_ce_init_dest_ring(ar, ce_id, attr);
1776 [ - + ]: 363 : if (ret) {
1777 : 0 : ath10k_err(ar, "Failed to initialize CE dest ring for ID: %d (%d)\n",
1778 : : ce_id, ret);
1779 : 0 : return ret;
1780 : : }
1781 : : }
1782 : :
1783 : : return 0;
1784 : : }
1785 : : EXPORT_SYMBOL(ath10k_ce_init_pipe);
1786 : :
1787 : 320 : static void ath10k_ce_deinit_src_ring(struct ath10k *ar, unsigned int ce_id)
1788 : : {
1789 : 320 : u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id);
1790 : :
1791 : 320 : ath10k_ce_src_ring_base_addr_set(ar, ce_id, 0);
1792 : 320 : ath10k_ce_src_ring_size_set(ar, ctrl_addr, 0);
1793 : 320 : ath10k_ce_src_ring_dmax_set(ar, ctrl_addr, 0);
1794 : 320 : ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, 0);
1795 : 320 : }
1796 : :
1797 : 320 : static void ath10k_ce_deinit_dest_ring(struct ath10k *ar, unsigned int ce_id)
1798 : : {
1799 : 320 : u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id);
1800 : :
1801 : 320 : ath10k_ce_dest_ring_base_addr_set(ar, ce_id, 0);
1802 : 320 : ath10k_ce_dest_ring_size_set(ar, ctrl_addr, 0);
1803 : 320 : ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, 0);
1804 : 320 : }
1805 : :
1806 : 320 : void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id)
1807 : : {
1808 : 320 : ath10k_ce_deinit_src_ring(ar, ce_id);
1809 : 320 : ath10k_ce_deinit_dest_ring(ar, ce_id);
1810 : 320 : }
1811 : : EXPORT_SYMBOL(ath10k_ce_deinit_pipe);
1812 : :
1813 : 24 : static void _ath10k_ce_free_pipe(struct ath10k *ar, int ce_id)
1814 : : {
1815 [ + + ]: 24 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
1816 : 24 : struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
1817 : :
1818 [ + + ]: 24 : if (ce_state->src_ring) {
1819 [ - + ]: 12 : if (ar->hw_params.shadow_reg_support)
1820 : 0 : kfree(ce_state->src_ring->shadow_base_unaligned);
1821 : 12 : dma_free_coherent(ar->dev,
1822 : 12 : (ce_state->src_ring->nentries *
1823 : 12 : sizeof(struct ce_desc) +
1824 : : CE_DESC_RING_ALIGN),
1825 : : ce_state->src_ring->base_addr_owner_space,
1826 : 12 : ce_state->src_ring->base_addr_ce_space);
1827 : 12 : kfree(ce_state->src_ring);
1828 : : }
1829 : :
1830 [ + + ]: 24 : if (ce_state->dest_ring) {
1831 : 9 : dma_free_coherent(ar->dev,
1832 : 9 : (ce_state->dest_ring->nentries *
1833 : 9 : sizeof(struct ce_desc) +
1834 : : CE_DESC_RING_ALIGN),
1835 : : ce_state->dest_ring->base_addr_owner_space,
1836 : : ce_state->dest_ring->base_addr_ce_space);
1837 : 9 : kfree(ce_state->dest_ring);
1838 : : }
1839 : :
1840 : 24 : ce_state->src_ring = NULL;
1841 : 24 : ce_state->dest_ring = NULL;
1842 : 24 : }
1843 : :
1844 : 0 : static void _ath10k_ce_free_pipe_64(struct ath10k *ar, int ce_id)
1845 : : {
1846 [ # # ]: 0 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
1847 : 0 : struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
1848 : :
1849 [ # # ]: 0 : if (ce_state->src_ring) {
1850 [ # # ]: 0 : if (ar->hw_params.shadow_reg_support)
1851 : 0 : kfree(ce_state->src_ring->shadow_base_unaligned);
1852 : 0 : dma_free_coherent(ar->dev,
1853 : 0 : (ce_state->src_ring->nentries *
1854 : : sizeof(struct ce_desc_64) +
1855 : : CE_DESC_RING_ALIGN),
1856 : : ce_state->src_ring->base_addr_owner_space,
1857 : 0 : ce_state->src_ring->base_addr_ce_space);
1858 : 0 : kfree(ce_state->src_ring);
1859 : : }
1860 : :
1861 [ # # ]: 0 : if (ce_state->dest_ring) {
1862 : 0 : dma_free_coherent(ar->dev,
1863 : 0 : (ce_state->dest_ring->nentries *
1864 : : sizeof(struct ce_desc_64) +
1865 : : CE_DESC_RING_ALIGN),
1866 : : ce_state->dest_ring->base_addr_owner_space,
1867 : : ce_state->dest_ring->base_addr_ce_space);
1868 : 0 : kfree(ce_state->dest_ring);
1869 : : }
1870 : :
1871 : 0 : ce_state->src_ring = NULL;
1872 : 0 : ce_state->dest_ring = NULL;
1873 : 0 : }
1874 : :
1875 : 24 : void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id)
1876 : : {
1877 : 24 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
1878 : 24 : struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
1879 : :
1880 : 24 : ce_state->ops->ce_free_pipe(ar, ce_id);
1881 : 24 : }
1882 : : EXPORT_SYMBOL(ath10k_ce_free_pipe);
1883 : :
1884 : 4 : void ath10k_ce_dump_registers(struct ath10k *ar,
1885 : : struct ath10k_fw_crash_data *crash_data)
1886 : : {
1887 : 4 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
1888 : 4 : struct ath10k_ce_crash_data ce_data;
1889 : 4 : u32 addr, id;
1890 : :
1891 : 4 : lockdep_assert_held(&ar->dump_mutex);
1892 : :
1893 : 4 : ath10k_err(ar, "Copy Engine register dump:\n");
1894 : :
1895 : 4 : spin_lock_bh(&ce->ce_lock);
1896 [ + + ]: 40 : for (id = 0; id < CE_COUNT; id++) {
1897 : 32 : addr = ath10k_ce_base_address(ar, id);
1898 : 32 : ce_data.base_addr = cpu_to_le32(addr);
1899 : :
1900 : 32 : ce_data.src_wr_idx =
1901 : : cpu_to_le32(ath10k_ce_src_ring_write_index_get(ar, addr));
1902 : 32 : ce_data.src_r_idx =
1903 : 32 : cpu_to_le32(ath10k_ce_src_ring_read_index_get(ar, addr));
1904 : 32 : ce_data.dst_wr_idx =
1905 : : cpu_to_le32(ath10k_ce_dest_ring_write_index_get(ar, addr));
1906 : 32 : ce_data.dst_r_idx =
1907 : 32 : cpu_to_le32(ath10k_ce_dest_ring_read_index_get(ar, addr));
1908 : :
1909 [ + - ]: 32 : if (crash_data)
1910 : 32 : crash_data->ce_crash_data[id] = ce_data;
1911 : :
1912 : 32 : ath10k_err(ar, "[%02d]: 0x%08x %3u %3u %3u %3u", id,
1913 : : le32_to_cpu(ce_data.base_addr),
1914 : : le32_to_cpu(ce_data.src_wr_idx),
1915 : : le32_to_cpu(ce_data.src_r_idx),
1916 : : le32_to_cpu(ce_data.dst_wr_idx),
1917 : : le32_to_cpu(ce_data.dst_r_idx));
1918 : : }
1919 : :
1920 : 4 : spin_unlock_bh(&ce->ce_lock);
1921 : 4 : }
1922 : : EXPORT_SYMBOL(ath10k_ce_dump_registers);
1923 : :
1924 : : static const struct ath10k_ce_ops ce_ops = {
1925 : : .ce_alloc_src_ring = ath10k_ce_alloc_src_ring,
1926 : : .ce_alloc_dst_ring = ath10k_ce_alloc_dest_ring,
1927 : : .ce_rx_post_buf = __ath10k_ce_rx_post_buf,
1928 : : .ce_completed_recv_next_nolock = _ath10k_ce_completed_recv_next_nolock,
1929 : : .ce_revoke_recv_next = _ath10k_ce_revoke_recv_next,
1930 : : .ce_extract_desc_data = ath10k_ce_extract_desc_data,
1931 : : .ce_free_pipe = _ath10k_ce_free_pipe,
1932 : : .ce_send_nolock = _ath10k_ce_send_nolock,
1933 : : .ce_set_src_ring_base_addr_hi = NULL,
1934 : : .ce_set_dest_ring_base_addr_hi = NULL,
1935 : : .ce_completed_send_next_nolock = _ath10k_ce_completed_send_next_nolock,
1936 : : };
1937 : :
1938 : : static const struct ath10k_ce_ops ce_64_ops = {
1939 : : .ce_alloc_src_ring = ath10k_ce_alloc_src_ring_64,
1940 : : .ce_alloc_dst_ring = ath10k_ce_alloc_dest_ring_64,
1941 : : .ce_rx_post_buf = __ath10k_ce_rx_post_buf_64,
1942 : : .ce_completed_recv_next_nolock =
1943 : : _ath10k_ce_completed_recv_next_nolock_64,
1944 : : .ce_revoke_recv_next = _ath10k_ce_revoke_recv_next_64,
1945 : : .ce_extract_desc_data = ath10k_ce_extract_desc_data_64,
1946 : : .ce_free_pipe = _ath10k_ce_free_pipe_64,
1947 : : .ce_send_nolock = _ath10k_ce_send_nolock_64,
1948 : : .ce_set_src_ring_base_addr_hi = ath10k_ce_set_src_ring_base_addr_hi,
1949 : : .ce_set_dest_ring_base_addr_hi = ath10k_ce_set_dest_ring_base_addr_hi,
1950 : : .ce_completed_send_next_nolock = _ath10k_ce_completed_send_next_nolock_64,
1951 : : };
1952 : :
1953 : 224 : static void ath10k_ce_set_ops(struct ath10k *ar,
1954 : : struct ath10k_ce_pipe *ce_state)
1955 : : {
1956 : 224 : switch (ar->hw_rev) {
1957 : 0 : case ATH10K_HW_WCN3990:
1958 : 0 : ce_state->ops = &ce_64_ops;
1959 : 0 : break;
1960 : 224 : default:
1961 : 224 : ce_state->ops = &ce_ops;
1962 : 224 : break;
1963 : : }
1964 : : }
1965 : :
1966 : 224 : int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
1967 : : const struct ce_attr *attr)
1968 : : {
1969 [ - + ]: 224 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
1970 : 224 : struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
1971 : 224 : int ret;
1972 : :
1973 [ - + ]: 224 : ath10k_ce_set_ops(ar, ce_state);
1974 : : /* Make sure there's enough CE ringbuffer entries for HTT TX to avoid
1975 : : * additional TX locking checks.
1976 : : *
1977 : : * For the lack of a better place do the check here.
1978 : : */
1979 : 224 : BUILD_BUG_ON(2 * TARGET_NUM_MSDU_DESC >
1980 : : (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
1981 : 224 : BUILD_BUG_ON(2 * TARGET_10_4_NUM_MSDU_DESC_PFC >
1982 : : (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
1983 : 224 : BUILD_BUG_ON(2 * TARGET_TLV_NUM_MSDU_DESC >
1984 : : (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
1985 : :
1986 : 224 : ce_state->ar = ar;
1987 : 224 : ce_state->id = ce_id;
1988 [ + + ]: 224 : ce_state->ctrl_addr = ath10k_ce_base_address(ar, ce_id);
1989 : 224 : ce_state->attr_flags = attr->flags;
1990 : 224 : ce_state->src_sz_max = attr->src_sz_max;
1991 : :
1992 [ + + ]: 224 : if (attr->src_nentries)
1993 : 112 : ce_state->send_cb = attr->send_cb;
1994 : :
1995 [ + + ]: 224 : if (attr->dest_nentries)
1996 : 84 : ce_state->recv_cb = attr->recv_cb;
1997 : :
1998 [ + + ]: 224 : if (attr->src_nentries) {
1999 : 224 : ce_state->src_ring =
2000 : 112 : ce_state->ops->ce_alloc_src_ring(ar, ce_id, attr);
2001 [ - + ]: 112 : if (IS_ERR(ce_state->src_ring)) {
2002 : 0 : ret = PTR_ERR(ce_state->src_ring);
2003 : 0 : ath10k_err(ar, "failed to alloc CE src ring %d: %d\n",
2004 : : ce_id, ret);
2005 : 0 : ce_state->src_ring = NULL;
2006 : 0 : return ret;
2007 : : }
2008 : : }
2009 : :
2010 [ + + ]: 224 : if (attr->dest_nentries) {
2011 : 84 : ce_state->dest_ring = ce_state->ops->ce_alloc_dst_ring(ar,
2012 : : ce_id,
2013 : : attr);
2014 [ - + ]: 84 : if (IS_ERR(ce_state->dest_ring)) {
2015 : 0 : ret = PTR_ERR(ce_state->dest_ring);
2016 : 0 : ath10k_err(ar, "failed to alloc CE dest ring %d: %d\n",
2017 : : ce_id, ret);
2018 : 0 : ce_state->dest_ring = NULL;
2019 : 0 : return ret;
2020 : : }
2021 : : }
2022 : :
2023 : : return 0;
2024 : : }
2025 : : EXPORT_SYMBOL(ath10k_ce_alloc_pipe);
2026 : :
2027 : 0 : void ath10k_ce_alloc_rri(struct ath10k *ar)
2028 : : {
2029 : 0 : int i;
2030 : 0 : u32 value;
2031 : 0 : u32 ctrl1_regs;
2032 : 0 : u32 ce_base_addr;
2033 : 0 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
2034 : :
2035 : 0 : ce->vaddr_rri = dma_alloc_coherent(ar->dev,
2036 : 0 : (CE_COUNT * sizeof(u32)),
2037 : : &ce->paddr_rri, GFP_KERNEL);
2038 : :
2039 [ # # ]: 0 : if (!ce->vaddr_rri)
2040 : : return;
2041 : :
2042 : 0 : ath10k_ce_write32(ar, ar->hw_ce_regs->ce_rri_low,
2043 : 0 : lower_32_bits(ce->paddr_rri));
2044 : 0 : ath10k_ce_write32(ar, ar->hw_ce_regs->ce_rri_high,
2045 : 0 : (upper_32_bits(ce->paddr_rri) &
2046 : : CE_DESC_ADDR_HI_MASK));
2047 : :
2048 [ # # ]: 0 : for (i = 0; i < CE_COUNT; i++) {
2049 : 0 : ctrl1_regs = ar->hw_ce_regs->ctrl1_regs->addr;
2050 : 0 : ce_base_addr = ath10k_ce_base_address(ar, i);
2051 : 0 : value = ath10k_ce_read32(ar, ce_base_addr + ctrl1_regs);
2052 : 0 : value |= ar->hw_ce_regs->upd->mask;
2053 : 0 : ath10k_ce_write32(ar, ce_base_addr + ctrl1_regs, value);
2054 : : }
2055 : : }
2056 : : EXPORT_SYMBOL(ath10k_ce_alloc_rri);
2057 : :
2058 : 0 : void ath10k_ce_free_rri(struct ath10k *ar)
2059 : : {
2060 : 0 : struct ath10k_ce *ce = ath10k_ce_priv(ar);
2061 : :
2062 : 0 : dma_free_coherent(ar->dev, (CE_COUNT * sizeof(u32)),
2063 : 0 : ce->vaddr_rri,
2064 : : ce->paddr_rri);
2065 : 0 : }
2066 : : EXPORT_SYMBOL(ath10k_ce_free_rri);
|