1d8899132SKalle Valo // SPDX-License-Identifier: BSD-3-Clause-Clear
2d8899132SKalle Valo /*
3d8899132SKalle Valo * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4d8899132SKalle Valo * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
5d8899132SKalle Valo */
6d8899132SKalle Valo
7d8899132SKalle Valo #include "dp_rx.h"
8d8899132SKalle Valo #include "debug.h"
9d8899132SKalle Valo #include "hif.h"
10d8899132SKalle Valo
11d8899132SKalle Valo const struct ce_attr ath12k_host_ce_config_qcn9274[] = {
12d8899132SKalle Valo /* CE0: host->target HTC control and raw streams */
13d8899132SKalle Valo {
14d8899132SKalle Valo .flags = CE_ATTR_FLAGS,
15d8899132SKalle Valo .src_nentries = 16,
16d8899132SKalle Valo .src_sz_max = 2048,
17d8899132SKalle Valo .dest_nentries = 0,
18d8899132SKalle Valo },
19d8899132SKalle Valo
20d8899132SKalle Valo /* CE1: target->host HTT + HTC control */
21d8899132SKalle Valo {
22d8899132SKalle Valo .flags = CE_ATTR_FLAGS,
23d8899132SKalle Valo .src_nentries = 0,
24d8899132SKalle Valo .src_sz_max = 2048,
25d8899132SKalle Valo .dest_nentries = 512,
26d8899132SKalle Valo .recv_cb = ath12k_htc_rx_completion_handler,
27d8899132SKalle Valo },
28d8899132SKalle Valo
29d8899132SKalle Valo /* CE2: target->host WMI */
30d8899132SKalle Valo {
31d8899132SKalle Valo .flags = CE_ATTR_FLAGS,
32d8899132SKalle Valo .src_nentries = 0,
33d8899132SKalle Valo .src_sz_max = 2048,
34d8899132SKalle Valo .dest_nentries = 128,
35d8899132SKalle Valo .recv_cb = ath12k_htc_rx_completion_handler,
36d8899132SKalle Valo },
37d8899132SKalle Valo
38d8899132SKalle Valo /* CE3: host->target WMI (mac0) */
39d8899132SKalle Valo {
40d8899132SKalle Valo .flags = CE_ATTR_FLAGS,
41d8899132SKalle Valo .src_nentries = 32,
42d8899132SKalle Valo .src_sz_max = 2048,
43d8899132SKalle Valo .dest_nentries = 0,
44d8899132SKalle Valo },
45d8899132SKalle Valo
46d8899132SKalle Valo /* CE4: host->target HTT */
47d8899132SKalle Valo {
48d8899132SKalle Valo .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
49d8899132SKalle Valo .src_nentries = 2048,
50d8899132SKalle Valo .src_sz_max = 256,
51d8899132SKalle Valo .dest_nentries = 0,
52d8899132SKalle Valo },
53d8899132SKalle Valo
54d8899132SKalle Valo /* CE5: target->host pktlog */
55d8899132SKalle Valo {
56d8899132SKalle Valo .flags = CE_ATTR_FLAGS,
57d8899132SKalle Valo .src_nentries = 0,
58d8899132SKalle Valo .src_sz_max = 2048,
59d8899132SKalle Valo .dest_nentries = 512,
60d8899132SKalle Valo .recv_cb = ath12k_dp_htt_htc_t2h_msg_handler,
61d8899132SKalle Valo },
62d8899132SKalle Valo
63d8899132SKalle Valo /* CE6: target autonomous hif_memcpy */
64d8899132SKalle Valo {
65d8899132SKalle Valo .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
66d8899132SKalle Valo .src_nentries = 0,
67d8899132SKalle Valo .src_sz_max = 0,
68d8899132SKalle Valo .dest_nentries = 0,
69d8899132SKalle Valo },
70d8899132SKalle Valo
71d8899132SKalle Valo /* CE7: host->target WMI (mac1) */
72d8899132SKalle Valo {
73d8899132SKalle Valo .flags = CE_ATTR_FLAGS,
74d8899132SKalle Valo .src_nentries = 32,
75d8899132SKalle Valo .src_sz_max = 2048,
76d8899132SKalle Valo .dest_nentries = 0,
77d8899132SKalle Valo },
78d8899132SKalle Valo
79d8899132SKalle Valo /* CE8: target autonomous hif_memcpy */
80d8899132SKalle Valo {
81d8899132SKalle Valo .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
82d8899132SKalle Valo .src_nentries = 0,
83d8899132SKalle Valo .src_sz_max = 0,
84d8899132SKalle Valo .dest_nentries = 0,
85d8899132SKalle Valo },
86d8899132SKalle Valo
87d8899132SKalle Valo /* CE9: MHI */
88d8899132SKalle Valo {
89d8899132SKalle Valo .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
90d8899132SKalle Valo .src_nentries = 0,
91d8899132SKalle Valo .src_sz_max = 0,
92d8899132SKalle Valo .dest_nentries = 0,
93d8899132SKalle Valo },
94d8899132SKalle Valo
95d8899132SKalle Valo /* CE10: MHI */
96d8899132SKalle Valo {
97d8899132SKalle Valo .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
98d8899132SKalle Valo .src_nentries = 0,
99d8899132SKalle Valo .src_sz_max = 0,
100d8899132SKalle Valo .dest_nentries = 0,
101d8899132SKalle Valo },
102d8899132SKalle Valo
103d8899132SKalle Valo /* CE11: MHI */
104d8899132SKalle Valo {
105d8899132SKalle Valo .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
106d8899132SKalle Valo .src_nentries = 0,
107d8899132SKalle Valo .src_sz_max = 0,
108d8899132SKalle Valo .dest_nentries = 0,
109d8899132SKalle Valo },
110d8899132SKalle Valo
111d8899132SKalle Valo /* CE12: CV Prefetch */
112d8899132SKalle Valo {
113d8899132SKalle Valo .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
114d8899132SKalle Valo .src_nentries = 0,
115d8899132SKalle Valo .src_sz_max = 0,
116d8899132SKalle Valo .dest_nentries = 0,
117d8899132SKalle Valo },
118d8899132SKalle Valo
119d8899132SKalle Valo /* CE13: CV Prefetch */
120d8899132SKalle Valo {
121d8899132SKalle Valo .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
122d8899132SKalle Valo .src_nentries = 0,
123d8899132SKalle Valo .src_sz_max = 0,
124d8899132SKalle Valo .dest_nentries = 0,
125d8899132SKalle Valo },
126d8899132SKalle Valo
127d8899132SKalle Valo /* CE14: target->host dbg log */
128d8899132SKalle Valo {
129d8899132SKalle Valo .flags = CE_ATTR_FLAGS,
130d8899132SKalle Valo .src_nentries = 0,
131d8899132SKalle Valo .src_sz_max = 2048,
132d8899132SKalle Valo .dest_nentries = 512,
133d8899132SKalle Valo .recv_cb = ath12k_htc_rx_completion_handler,
134d8899132SKalle Valo },
135d8899132SKalle Valo
136d8899132SKalle Valo /* CE15: reserved for future use */
137d8899132SKalle Valo {
138d8899132SKalle Valo .flags = (CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
139d8899132SKalle Valo .src_nentries = 0,
140d8899132SKalle Valo .src_sz_max = 0,
141d8899132SKalle Valo .dest_nentries = 0,
142d8899132SKalle Valo },
143d8899132SKalle Valo };
144d8899132SKalle Valo
145d8899132SKalle Valo const struct ce_attr ath12k_host_ce_config_wcn7850[] = {
146d8899132SKalle Valo /* CE0: host->target HTC control and raw streams */
147d8899132SKalle Valo {
148d8899132SKalle Valo .flags = CE_ATTR_FLAGS,
149d8899132SKalle Valo .src_nentries = 16,
150d8899132SKalle Valo .src_sz_max = 2048,
151d8899132SKalle Valo .dest_nentries = 0,
152d8899132SKalle Valo },
153d8899132SKalle Valo
154d8899132SKalle Valo /* CE1: target->host HTT + HTC control */
155d8899132SKalle Valo {
156d8899132SKalle Valo .flags = CE_ATTR_FLAGS,
157d8899132SKalle Valo .src_nentries = 0,
158d8899132SKalle Valo .src_sz_max = 2048,
159d8899132SKalle Valo .dest_nentries = 512,
160d8899132SKalle Valo .recv_cb = ath12k_htc_rx_completion_handler,
161d8899132SKalle Valo },
162d8899132SKalle Valo
163d8899132SKalle Valo /* CE2: target->host WMI */
164d8899132SKalle Valo {
165d8899132SKalle Valo .flags = CE_ATTR_FLAGS,
166d8899132SKalle Valo .src_nentries = 0,
167d8899132SKalle Valo .src_sz_max = 2048,
168d8899132SKalle Valo .dest_nentries = 64,
169d8899132SKalle Valo .recv_cb = ath12k_htc_rx_completion_handler,
170d8899132SKalle Valo },
171d8899132SKalle Valo
172d8899132SKalle Valo /* CE3: host->target WMI (mac0) */
173d8899132SKalle Valo {
174d8899132SKalle Valo .flags = CE_ATTR_FLAGS,
175d8899132SKalle Valo .src_nentries = 32,
176d8899132SKalle Valo .src_sz_max = 2048,
177d8899132SKalle Valo .dest_nentries = 0,
178d8899132SKalle Valo },
179d8899132SKalle Valo
180d8899132SKalle Valo /* CE4: host->target HTT */
181d8899132SKalle Valo {
182d8899132SKalle Valo .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
183d8899132SKalle Valo .src_nentries = 2048,
184d8899132SKalle Valo .src_sz_max = 256,
185d8899132SKalle Valo .dest_nentries = 0,
186d8899132SKalle Valo },
187d8899132SKalle Valo
188d8899132SKalle Valo /* CE5: target->host pktlog */
189d8899132SKalle Valo {
190d8899132SKalle Valo .flags = CE_ATTR_FLAGS,
191d8899132SKalle Valo .src_nentries = 0,
192d8899132SKalle Valo .src_sz_max = 0,
193d8899132SKalle Valo .dest_nentries = 0,
194d8899132SKalle Valo },
195d8899132SKalle Valo
196d8899132SKalle Valo /* CE6: target autonomous hif_memcpy */
197d8899132SKalle Valo {
198d8899132SKalle Valo .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
199d8899132SKalle Valo .src_nentries = 0,
200d8899132SKalle Valo .src_sz_max = 0,
201d8899132SKalle Valo .dest_nentries = 0,
202d8899132SKalle Valo },
203d8899132SKalle Valo
204d8899132SKalle Valo /* CE7: host->target WMI (mac1) */
205d8899132SKalle Valo {
206d8899132SKalle Valo .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
207d8899132SKalle Valo .src_nentries = 0,
208d8899132SKalle Valo .src_sz_max = 2048,
209d8899132SKalle Valo .dest_nentries = 0,
210d8899132SKalle Valo },
211d8899132SKalle Valo
212d8899132SKalle Valo /* CE8: target autonomous hif_memcpy */
213d8899132SKalle Valo {
214d8899132SKalle Valo .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
215d8899132SKalle Valo .src_nentries = 0,
216d8899132SKalle Valo .src_sz_max = 0,
217d8899132SKalle Valo .dest_nentries = 0,
218d8899132SKalle Valo },
219d8899132SKalle Valo
220d8899132SKalle Valo };
221d8899132SKalle Valo
ath12k_ce_rx_buf_enqueue_pipe(struct ath12k_ce_pipe * pipe,struct sk_buff * skb,dma_addr_t paddr)222d8899132SKalle Valo static int ath12k_ce_rx_buf_enqueue_pipe(struct ath12k_ce_pipe *pipe,
223d8899132SKalle Valo struct sk_buff *skb, dma_addr_t paddr)
224d8899132SKalle Valo {
225d8899132SKalle Valo struct ath12k_base *ab = pipe->ab;
226d8899132SKalle Valo struct ath12k_ce_ring *ring = pipe->dest_ring;
227d8899132SKalle Valo struct hal_srng *srng;
228d8899132SKalle Valo unsigned int write_index;
229d8899132SKalle Valo unsigned int nentries_mask = ring->nentries_mask;
230d8899132SKalle Valo struct hal_ce_srng_dest_desc *desc;
231d8899132SKalle Valo int ret;
232d8899132SKalle Valo
233d8899132SKalle Valo lockdep_assert_held(&ab->ce.ce_lock);
234d8899132SKalle Valo
235d8899132SKalle Valo write_index = ring->write_index;
236d8899132SKalle Valo
237d8899132SKalle Valo srng = &ab->hal.srng_list[ring->hal_ring_id];
238d8899132SKalle Valo
239d8899132SKalle Valo spin_lock_bh(&srng->lock);
240d8899132SKalle Valo
241d8899132SKalle Valo ath12k_hal_srng_access_begin(ab, srng);
242d8899132SKalle Valo
243d8899132SKalle Valo if (unlikely(ath12k_hal_srng_src_num_free(ab, srng, false) < 1)) {
244d8899132SKalle Valo ret = -ENOSPC;
245d8899132SKalle Valo goto exit;
246d8899132SKalle Valo }
247d8899132SKalle Valo
248d8899132SKalle Valo desc = ath12k_hal_srng_src_get_next_entry(ab, srng);
249d8899132SKalle Valo if (!desc) {
250d8899132SKalle Valo ret = -ENOSPC;
251d8899132SKalle Valo goto exit;
252d8899132SKalle Valo }
253d8899132SKalle Valo
254d8899132SKalle Valo ath12k_hal_ce_dst_set_desc(desc, paddr);
255d8899132SKalle Valo
256d8899132SKalle Valo ring->skb[write_index] = skb;
257d8899132SKalle Valo write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
258d8899132SKalle Valo ring->write_index = write_index;
259d8899132SKalle Valo
260d8899132SKalle Valo pipe->rx_buf_needed--;
261d8899132SKalle Valo
262d8899132SKalle Valo ret = 0;
263d8899132SKalle Valo exit:
264d8899132SKalle Valo ath12k_hal_srng_access_end(ab, srng);
265d8899132SKalle Valo
266d8899132SKalle Valo spin_unlock_bh(&srng->lock);
267d8899132SKalle Valo
268d8899132SKalle Valo return ret;
269d8899132SKalle Valo }
270d8899132SKalle Valo
ath12k_ce_rx_post_pipe(struct ath12k_ce_pipe * pipe)271d8899132SKalle Valo static int ath12k_ce_rx_post_pipe(struct ath12k_ce_pipe *pipe)
272d8899132SKalle Valo {
273d8899132SKalle Valo struct ath12k_base *ab = pipe->ab;
274d8899132SKalle Valo struct sk_buff *skb;
275d8899132SKalle Valo dma_addr_t paddr;
276d8899132SKalle Valo int ret = 0;
277d8899132SKalle Valo
278d8899132SKalle Valo if (!(pipe->dest_ring || pipe->status_ring))
279d8899132SKalle Valo return 0;
280d8899132SKalle Valo
281d8899132SKalle Valo spin_lock_bh(&ab->ce.ce_lock);
282d8899132SKalle Valo while (pipe->rx_buf_needed) {
283d8899132SKalle Valo skb = dev_alloc_skb(pipe->buf_sz);
284d8899132SKalle Valo if (!skb) {
285d8899132SKalle Valo ret = -ENOMEM;
286d8899132SKalle Valo goto exit;
287d8899132SKalle Valo }
288d8899132SKalle Valo
289d8899132SKalle Valo WARN_ON_ONCE(!IS_ALIGNED((unsigned long)skb->data, 4));
290d8899132SKalle Valo
291d8899132SKalle Valo paddr = dma_map_single(ab->dev, skb->data,
292d8899132SKalle Valo skb->len + skb_tailroom(skb),
293d8899132SKalle Valo DMA_FROM_DEVICE);
294d8899132SKalle Valo if (unlikely(dma_mapping_error(ab->dev, paddr))) {
295d8899132SKalle Valo ath12k_warn(ab, "failed to dma map ce rx buf\n");
296d8899132SKalle Valo dev_kfree_skb_any(skb);
297d8899132SKalle Valo ret = -EIO;
298d8899132SKalle Valo goto exit;
299d8899132SKalle Valo }
300d8899132SKalle Valo
301d8899132SKalle Valo ATH12K_SKB_RXCB(skb)->paddr = paddr;
302d8899132SKalle Valo
303d8899132SKalle Valo ret = ath12k_ce_rx_buf_enqueue_pipe(pipe, skb, paddr);
304d8899132SKalle Valo if (ret) {
305d8899132SKalle Valo ath12k_warn(ab, "failed to enqueue rx buf: %d\n", ret);
306d8899132SKalle Valo dma_unmap_single(ab->dev, paddr,
307d8899132SKalle Valo skb->len + skb_tailroom(skb),
308d8899132SKalle Valo DMA_FROM_DEVICE);
309d8899132SKalle Valo dev_kfree_skb_any(skb);
310d8899132SKalle Valo goto exit;
311d8899132SKalle Valo }
312d8899132SKalle Valo }
313d8899132SKalle Valo
314d8899132SKalle Valo exit:
315d8899132SKalle Valo spin_unlock_bh(&ab->ce.ce_lock);
316d8899132SKalle Valo return ret;
317d8899132SKalle Valo }
318d8899132SKalle Valo
ath12k_ce_completed_recv_next(struct ath12k_ce_pipe * pipe,struct sk_buff ** skb,int * nbytes)319d8899132SKalle Valo static int ath12k_ce_completed_recv_next(struct ath12k_ce_pipe *pipe,
320d8899132SKalle Valo struct sk_buff **skb, int *nbytes)
321d8899132SKalle Valo {
322d8899132SKalle Valo struct ath12k_base *ab = pipe->ab;
323d8899132SKalle Valo struct hal_ce_srng_dst_status_desc *desc;
324d8899132SKalle Valo struct hal_srng *srng;
325d8899132SKalle Valo unsigned int sw_index;
326d8899132SKalle Valo unsigned int nentries_mask;
327d8899132SKalle Valo int ret = 0;
328d8899132SKalle Valo
329d8899132SKalle Valo spin_lock_bh(&ab->ce.ce_lock);
330d8899132SKalle Valo
331d8899132SKalle Valo sw_index = pipe->dest_ring->sw_index;
332d8899132SKalle Valo nentries_mask = pipe->dest_ring->nentries_mask;
333d8899132SKalle Valo
334d8899132SKalle Valo srng = &ab->hal.srng_list[pipe->status_ring->hal_ring_id];
335d8899132SKalle Valo
336d8899132SKalle Valo spin_lock_bh(&srng->lock);
337d8899132SKalle Valo
338d8899132SKalle Valo ath12k_hal_srng_access_begin(ab, srng);
339d8899132SKalle Valo
340d8899132SKalle Valo desc = ath12k_hal_srng_dst_get_next_entry(ab, srng);
341d8899132SKalle Valo if (!desc) {
342d8899132SKalle Valo ret = -EIO;
343d8899132SKalle Valo goto err;
344d8899132SKalle Valo }
345d8899132SKalle Valo
346d8899132SKalle Valo *nbytes = ath12k_hal_ce_dst_status_get_length(desc);
347d8899132SKalle Valo if (*nbytes == 0) {
348d8899132SKalle Valo ret = -EIO;
349d8899132SKalle Valo goto err;
350d8899132SKalle Valo }
351d8899132SKalle Valo
352d8899132SKalle Valo *skb = pipe->dest_ring->skb[sw_index];
353d8899132SKalle Valo pipe->dest_ring->skb[sw_index] = NULL;
354d8899132SKalle Valo
355d8899132SKalle Valo sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
356d8899132SKalle Valo pipe->dest_ring->sw_index = sw_index;
357d8899132SKalle Valo
358d8899132SKalle Valo pipe->rx_buf_needed++;
359d8899132SKalle Valo err:
360d8899132SKalle Valo ath12k_hal_srng_access_end(ab, srng);
361d8899132SKalle Valo
362d8899132SKalle Valo spin_unlock_bh(&srng->lock);
363d8899132SKalle Valo
364d8899132SKalle Valo spin_unlock_bh(&ab->ce.ce_lock);
365d8899132SKalle Valo
366d8899132SKalle Valo return ret;
367d8899132SKalle Valo }
368d8899132SKalle Valo
ath12k_ce_recv_process_cb(struct ath12k_ce_pipe * pipe)369d8899132SKalle Valo static void ath12k_ce_recv_process_cb(struct ath12k_ce_pipe *pipe)
370d8899132SKalle Valo {
371d8899132SKalle Valo struct ath12k_base *ab = pipe->ab;
372d8899132SKalle Valo struct sk_buff *skb;
373d8899132SKalle Valo struct sk_buff_head list;
374d8899132SKalle Valo unsigned int nbytes, max_nbytes;
375d8899132SKalle Valo int ret;
376d8899132SKalle Valo
377d8899132SKalle Valo __skb_queue_head_init(&list);
378d8899132SKalle Valo while (ath12k_ce_completed_recv_next(pipe, &skb, &nbytes) == 0) {
379d8899132SKalle Valo max_nbytes = skb->len + skb_tailroom(skb);
380d8899132SKalle Valo dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(skb)->paddr,
381d8899132SKalle Valo max_nbytes, DMA_FROM_DEVICE);
382d8899132SKalle Valo
383d8899132SKalle Valo if (unlikely(max_nbytes < nbytes)) {
384d8899132SKalle Valo ath12k_warn(ab, "rxed more than expected (nbytes %d, max %d)",
385d8899132SKalle Valo nbytes, max_nbytes);
386d8899132SKalle Valo dev_kfree_skb_any(skb);
387d8899132SKalle Valo continue;
388d8899132SKalle Valo }
389d8899132SKalle Valo
390d8899132SKalle Valo skb_put(skb, nbytes);
391d8899132SKalle Valo __skb_queue_tail(&list, skb);
392d8899132SKalle Valo }
393d8899132SKalle Valo
394d8899132SKalle Valo while ((skb = __skb_dequeue(&list))) {
395d8899132SKalle Valo ath12k_dbg(ab, ATH12K_DBG_AHB, "rx ce pipe %d len %d\n",
396d8899132SKalle Valo pipe->pipe_num, skb->len);
397d8899132SKalle Valo pipe->recv_cb(ab, skb);
398d8899132SKalle Valo }
399d8899132SKalle Valo
400d8899132SKalle Valo ret = ath12k_ce_rx_post_pipe(pipe);
401d8899132SKalle Valo if (ret && ret != -ENOSPC) {
402d8899132SKalle Valo ath12k_warn(ab, "failed to post rx buf to pipe: %d err: %d\n",
403d8899132SKalle Valo pipe->pipe_num, ret);
404d8899132SKalle Valo mod_timer(&ab->rx_replenish_retry,
405d8899132SKalle Valo jiffies + ATH12K_CE_RX_POST_RETRY_JIFFIES);
406d8899132SKalle Valo }
407d8899132SKalle Valo }
408d8899132SKalle Valo
ath12k_ce_completed_send_next(struct ath12k_ce_pipe * pipe)409d8899132SKalle Valo static struct sk_buff *ath12k_ce_completed_send_next(struct ath12k_ce_pipe *pipe)
410d8899132SKalle Valo {
411d8899132SKalle Valo struct ath12k_base *ab = pipe->ab;
412d8899132SKalle Valo struct hal_ce_srng_src_desc *desc;
413d8899132SKalle Valo struct hal_srng *srng;
414d8899132SKalle Valo unsigned int sw_index;
415d8899132SKalle Valo unsigned int nentries_mask;
416d8899132SKalle Valo struct sk_buff *skb;
417d8899132SKalle Valo
418d8899132SKalle Valo spin_lock_bh(&ab->ce.ce_lock);
419d8899132SKalle Valo
420d8899132SKalle Valo sw_index = pipe->src_ring->sw_index;
421d8899132SKalle Valo nentries_mask = pipe->src_ring->nentries_mask;
422d8899132SKalle Valo
423d8899132SKalle Valo srng = &ab->hal.srng_list[pipe->src_ring->hal_ring_id];
424d8899132SKalle Valo
425d8899132SKalle Valo spin_lock_bh(&srng->lock);
426d8899132SKalle Valo
427d8899132SKalle Valo ath12k_hal_srng_access_begin(ab, srng);
428d8899132SKalle Valo
429d8899132SKalle Valo desc = ath12k_hal_srng_src_reap_next(ab, srng);
430d8899132SKalle Valo if (!desc) {
431d8899132SKalle Valo skb = ERR_PTR(-EIO);
432d8899132SKalle Valo goto err_unlock;
433d8899132SKalle Valo }
434d8899132SKalle Valo
435d8899132SKalle Valo skb = pipe->src_ring->skb[sw_index];
436d8899132SKalle Valo
437d8899132SKalle Valo pipe->src_ring->skb[sw_index] = NULL;
438d8899132SKalle Valo
439d8899132SKalle Valo sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
440d8899132SKalle Valo pipe->src_ring->sw_index = sw_index;
441d8899132SKalle Valo
442d8899132SKalle Valo err_unlock:
443d8899132SKalle Valo spin_unlock_bh(&srng->lock);
444d8899132SKalle Valo
445d8899132SKalle Valo spin_unlock_bh(&ab->ce.ce_lock);
446d8899132SKalle Valo
447d8899132SKalle Valo return skb;
448d8899132SKalle Valo }
449d8899132SKalle Valo
ath12k_ce_send_done_cb(struct ath12k_ce_pipe * pipe)450d8899132SKalle Valo static void ath12k_ce_send_done_cb(struct ath12k_ce_pipe *pipe)
451d8899132SKalle Valo {
452d8899132SKalle Valo struct ath12k_base *ab = pipe->ab;
453d8899132SKalle Valo struct sk_buff *skb;
454d8899132SKalle Valo
455d8899132SKalle Valo while (!IS_ERR(skb = ath12k_ce_completed_send_next(pipe))) {
456d8899132SKalle Valo if (!skb)
457d8899132SKalle Valo continue;
458d8899132SKalle Valo
459d8899132SKalle Valo dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr, skb->len,
460d8899132SKalle Valo DMA_TO_DEVICE);
461d8899132SKalle Valo dev_kfree_skb_any(skb);
462d8899132SKalle Valo }
463d8899132SKalle Valo }
464d8899132SKalle Valo
ath12k_ce_srng_msi_ring_params_setup(struct ath12k_base * ab,u32 ce_id,struct hal_srng_params * ring_params)465d8899132SKalle Valo static void ath12k_ce_srng_msi_ring_params_setup(struct ath12k_base *ab, u32 ce_id,
466d8899132SKalle Valo struct hal_srng_params *ring_params)
467d8899132SKalle Valo {
468d8899132SKalle Valo u32 msi_data_start;
469d8899132SKalle Valo u32 msi_data_count, msi_data_idx;
470d8899132SKalle Valo u32 msi_irq_start;
471d8899132SKalle Valo u32 addr_lo;
472d8899132SKalle Valo u32 addr_hi;
473d8899132SKalle Valo int ret;
474d8899132SKalle Valo
475d8899132SKalle Valo ret = ath12k_hif_get_user_msi_vector(ab, "CE",
476d8899132SKalle Valo &msi_data_count, &msi_data_start,
477d8899132SKalle Valo &msi_irq_start);
478d8899132SKalle Valo
479d8899132SKalle Valo if (ret)
480d8899132SKalle Valo return;
481d8899132SKalle Valo
482d8899132SKalle Valo ath12k_hif_get_msi_address(ab, &addr_lo, &addr_hi);
483d8899132SKalle Valo ath12k_hif_get_ce_msi_idx(ab, ce_id, &msi_data_idx);
484d8899132SKalle Valo
485d8899132SKalle Valo ring_params->msi_addr = addr_lo;
486d8899132SKalle Valo ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32);
487d8899132SKalle Valo ring_params->msi_data = (msi_data_idx % msi_data_count) + msi_data_start;
488d8899132SKalle Valo ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR;
489d8899132SKalle Valo }
490d8899132SKalle Valo
ath12k_ce_init_ring(struct ath12k_base * ab,struct ath12k_ce_ring * ce_ring,int ce_id,enum hal_ring_type type)491d8899132SKalle Valo static int ath12k_ce_init_ring(struct ath12k_base *ab,
492d8899132SKalle Valo struct ath12k_ce_ring *ce_ring,
493d8899132SKalle Valo int ce_id, enum hal_ring_type type)
494d8899132SKalle Valo {
495d8899132SKalle Valo struct hal_srng_params params = { 0 };
496d8899132SKalle Valo int ret;
497d8899132SKalle Valo
498d8899132SKalle Valo params.ring_base_paddr = ce_ring->base_addr_ce_space;
499d8899132SKalle Valo params.ring_base_vaddr = ce_ring->base_addr_owner_space;
500d8899132SKalle Valo params.num_entries = ce_ring->nentries;
501d8899132SKalle Valo
502d8899132SKalle Valo if (!(CE_ATTR_DIS_INTR & ab->hw_params->host_ce_config[ce_id].flags))
503d8899132SKalle Valo ath12k_ce_srng_msi_ring_params_setup(ab, ce_id, ¶ms);
504d8899132SKalle Valo
505d8899132SKalle Valo switch (type) {
506d8899132SKalle Valo case HAL_CE_SRC:
507d8899132SKalle Valo if (!(CE_ATTR_DIS_INTR & ab->hw_params->host_ce_config[ce_id].flags))
508d8899132SKalle Valo params.intr_batch_cntr_thres_entries = 1;
509d8899132SKalle Valo break;
510d8899132SKalle Valo case HAL_CE_DST:
511d8899132SKalle Valo params.max_buffer_len = ab->hw_params->host_ce_config[ce_id].src_sz_max;
512d8899132SKalle Valo if (!(ab->hw_params->host_ce_config[ce_id].flags & CE_ATTR_DIS_INTR)) {
513d8899132SKalle Valo params.intr_timer_thres_us = 1024;
514d8899132SKalle Valo params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN;
515d8899132SKalle Valo params.low_threshold = ce_ring->nentries - 3;
516d8899132SKalle Valo }
517d8899132SKalle Valo break;
518d8899132SKalle Valo case HAL_CE_DST_STATUS:
519d8899132SKalle Valo if (!(ab->hw_params->host_ce_config[ce_id].flags & CE_ATTR_DIS_INTR)) {
520d8899132SKalle Valo params.intr_batch_cntr_thres_entries = 1;
521d8899132SKalle Valo params.intr_timer_thres_us = 0x1000;
522d8899132SKalle Valo }
523d8899132SKalle Valo break;
524d8899132SKalle Valo default:
525d8899132SKalle Valo ath12k_warn(ab, "Invalid CE ring type %d\n", type);
526d8899132SKalle Valo return -EINVAL;
527d8899132SKalle Valo }
528d8899132SKalle Valo
529d8899132SKalle Valo /* TODO: Init other params needed by HAL to init the ring */
530d8899132SKalle Valo
531d8899132SKalle Valo ret = ath12k_hal_srng_setup(ab, type, ce_id, 0, ¶ms);
532d8899132SKalle Valo if (ret < 0) {
533d8899132SKalle Valo ath12k_warn(ab, "failed to setup srng: %d ring_id %d\n",
534d8899132SKalle Valo ret, ce_id);
535d8899132SKalle Valo return ret;
536d8899132SKalle Valo }
537d8899132SKalle Valo
538d8899132SKalle Valo ce_ring->hal_ring_id = ret;
539d8899132SKalle Valo
540d8899132SKalle Valo return 0;
541d8899132SKalle Valo }
542d8899132SKalle Valo
543d8899132SKalle Valo static struct ath12k_ce_ring *
ath12k_ce_alloc_ring(struct ath12k_base * ab,int nentries,int desc_sz)544d8899132SKalle Valo ath12k_ce_alloc_ring(struct ath12k_base *ab, int nentries, int desc_sz)
545d8899132SKalle Valo {
546d8899132SKalle Valo struct ath12k_ce_ring *ce_ring;
547d8899132SKalle Valo dma_addr_t base_addr;
548d8899132SKalle Valo
549d8899132SKalle Valo ce_ring = kzalloc(struct_size(ce_ring, skb, nentries), GFP_KERNEL);
550d8899132SKalle Valo if (!ce_ring)
551d8899132SKalle Valo return ERR_PTR(-ENOMEM);
552d8899132SKalle Valo
553d8899132SKalle Valo ce_ring->nentries = nentries;
554d8899132SKalle Valo ce_ring->nentries_mask = nentries - 1;
555d8899132SKalle Valo
556d8899132SKalle Valo /* Legacy platforms that do not support cache
557d8899132SKalle Valo * coherent DMA are unsupported
558d8899132SKalle Valo */
559d8899132SKalle Valo ce_ring->base_addr_owner_space_unaligned =
560d8899132SKalle Valo dma_alloc_coherent(ab->dev,
561d8899132SKalle Valo nentries * desc_sz + CE_DESC_RING_ALIGN,
562d8899132SKalle Valo &base_addr, GFP_KERNEL);
563d8899132SKalle Valo if (!ce_ring->base_addr_owner_space_unaligned) {
564d8899132SKalle Valo kfree(ce_ring);
565d8899132SKalle Valo return ERR_PTR(-ENOMEM);
566d8899132SKalle Valo }
567d8899132SKalle Valo
568d8899132SKalle Valo ce_ring->base_addr_ce_space_unaligned = base_addr;
569d8899132SKalle Valo
570d8899132SKalle Valo ce_ring->base_addr_owner_space =
571d8899132SKalle Valo PTR_ALIGN(ce_ring->base_addr_owner_space_unaligned,
572d8899132SKalle Valo CE_DESC_RING_ALIGN);
573d8899132SKalle Valo
574d8899132SKalle Valo ce_ring->base_addr_ce_space = ALIGN(ce_ring->base_addr_ce_space_unaligned,
575d8899132SKalle Valo CE_DESC_RING_ALIGN);
576d8899132SKalle Valo
577d8899132SKalle Valo return ce_ring;
578d8899132SKalle Valo }
579d8899132SKalle Valo
ath12k_ce_alloc_pipe(struct ath12k_base * ab,int ce_id)580d8899132SKalle Valo static int ath12k_ce_alloc_pipe(struct ath12k_base *ab, int ce_id)
581d8899132SKalle Valo {
582d8899132SKalle Valo struct ath12k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id];
583d8899132SKalle Valo const struct ce_attr *attr = &ab->hw_params->host_ce_config[ce_id];
584d8899132SKalle Valo struct ath12k_ce_ring *ring;
585d8899132SKalle Valo int nentries;
586d8899132SKalle Valo int desc_sz;
587d8899132SKalle Valo
588d8899132SKalle Valo pipe->attr_flags = attr->flags;
589d8899132SKalle Valo
590d8899132SKalle Valo if (attr->src_nentries) {
591d8899132SKalle Valo pipe->send_cb = ath12k_ce_send_done_cb;
592d8899132SKalle Valo nentries = roundup_pow_of_two(attr->src_nentries);
593d8899132SKalle Valo desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_SRC);
594d8899132SKalle Valo ring = ath12k_ce_alloc_ring(ab, nentries, desc_sz);
595d8899132SKalle Valo if (IS_ERR(ring))
596d8899132SKalle Valo return PTR_ERR(ring);
597d8899132SKalle Valo pipe->src_ring = ring;
598d8899132SKalle Valo }
599d8899132SKalle Valo
600d8899132SKalle Valo if (attr->dest_nentries) {
601d8899132SKalle Valo pipe->recv_cb = attr->recv_cb;
602d8899132SKalle Valo nentries = roundup_pow_of_two(attr->dest_nentries);
603d8899132SKalle Valo desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_DST);
604d8899132SKalle Valo ring = ath12k_ce_alloc_ring(ab, nentries, desc_sz);
605d8899132SKalle Valo if (IS_ERR(ring))
606d8899132SKalle Valo return PTR_ERR(ring);
607d8899132SKalle Valo pipe->dest_ring = ring;
608d8899132SKalle Valo
609d8899132SKalle Valo desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_DST_STATUS);
610d8899132SKalle Valo ring = ath12k_ce_alloc_ring(ab, nentries, desc_sz);
611d8899132SKalle Valo if (IS_ERR(ring))
612d8899132SKalle Valo return PTR_ERR(ring);
613d8899132SKalle Valo pipe->status_ring = ring;
614d8899132SKalle Valo }
615d8899132SKalle Valo
616d8899132SKalle Valo return 0;
617d8899132SKalle Valo }
618d8899132SKalle Valo
ath12k_ce_per_engine_service(struct ath12k_base * ab,u16 ce_id)619d8899132SKalle Valo void ath12k_ce_per_engine_service(struct ath12k_base *ab, u16 ce_id)
620d8899132SKalle Valo {
621d8899132SKalle Valo struct ath12k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id];
622d8899132SKalle Valo
623d8899132SKalle Valo if (pipe->send_cb)
624d8899132SKalle Valo pipe->send_cb(pipe);
625d8899132SKalle Valo
626d8899132SKalle Valo if (pipe->recv_cb)
627d8899132SKalle Valo ath12k_ce_recv_process_cb(pipe);
628d8899132SKalle Valo }
629d8899132SKalle Valo
ath12k_ce_poll_send_completed(struct ath12k_base * ab,u8 pipe_id)630d8899132SKalle Valo void ath12k_ce_poll_send_completed(struct ath12k_base *ab, u8 pipe_id)
631d8899132SKalle Valo {
632d8899132SKalle Valo struct ath12k_ce_pipe *pipe = &ab->ce.ce_pipe[pipe_id];
633d8899132SKalle Valo
634d8899132SKalle Valo if ((pipe->attr_flags & CE_ATTR_DIS_INTR) && pipe->send_cb)
635d8899132SKalle Valo pipe->send_cb(pipe);
636d8899132SKalle Valo }
637d8899132SKalle Valo
ath12k_ce_send(struct ath12k_base * ab,struct sk_buff * skb,u8 pipe_id,u16 transfer_id)638d8899132SKalle Valo int ath12k_ce_send(struct ath12k_base *ab, struct sk_buff *skb, u8 pipe_id,
639d8899132SKalle Valo u16 transfer_id)
640d8899132SKalle Valo {
641d8899132SKalle Valo struct ath12k_ce_pipe *pipe = &ab->ce.ce_pipe[pipe_id];
642d8899132SKalle Valo struct hal_ce_srng_src_desc *desc;
643d8899132SKalle Valo struct hal_srng *srng;
644d8899132SKalle Valo unsigned int write_index, sw_index;
645d8899132SKalle Valo unsigned int nentries_mask;
646d8899132SKalle Valo int ret = 0;
647d8899132SKalle Valo u8 byte_swap_data = 0;
648d8899132SKalle Valo int num_used;
649d8899132SKalle Valo
650d8899132SKalle Valo /* Check if some entries could be regained by handling tx completion if
651d8899132SKalle Valo * the CE has interrupts disabled and the used entries is more than the
652d8899132SKalle Valo * defined usage threshold.
653d8899132SKalle Valo */
654d8899132SKalle Valo if (pipe->attr_flags & CE_ATTR_DIS_INTR) {
655d8899132SKalle Valo spin_lock_bh(&ab->ce.ce_lock);
656d8899132SKalle Valo write_index = pipe->src_ring->write_index;
657d8899132SKalle Valo
658d8899132SKalle Valo sw_index = pipe->src_ring->sw_index;
659d8899132SKalle Valo
660d8899132SKalle Valo if (write_index >= sw_index)
661d8899132SKalle Valo num_used = write_index - sw_index;
662d8899132SKalle Valo else
663d8899132SKalle Valo num_used = pipe->src_ring->nentries - sw_index +
664d8899132SKalle Valo write_index;
665d8899132SKalle Valo
666d8899132SKalle Valo spin_unlock_bh(&ab->ce.ce_lock);
667d8899132SKalle Valo
668d8899132SKalle Valo if (num_used > ATH12K_CE_USAGE_THRESHOLD)
669d8899132SKalle Valo ath12k_ce_poll_send_completed(ab, pipe->pipe_num);
670d8899132SKalle Valo }
671d8899132SKalle Valo
672d8899132SKalle Valo if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags))
673d8899132SKalle Valo return -ESHUTDOWN;
674d8899132SKalle Valo
675d8899132SKalle Valo spin_lock_bh(&ab->ce.ce_lock);
676d8899132SKalle Valo
677d8899132SKalle Valo write_index = pipe->src_ring->write_index;
678d8899132SKalle Valo nentries_mask = pipe->src_ring->nentries_mask;
679d8899132SKalle Valo
680d8899132SKalle Valo srng = &ab->hal.srng_list[pipe->src_ring->hal_ring_id];
681d8899132SKalle Valo
682d8899132SKalle Valo spin_lock_bh(&srng->lock);
683d8899132SKalle Valo
684d8899132SKalle Valo ath12k_hal_srng_access_begin(ab, srng);
685d8899132SKalle Valo
686d8899132SKalle Valo if (unlikely(ath12k_hal_srng_src_num_free(ab, srng, false) < 1)) {
687d8899132SKalle Valo ath12k_hal_srng_access_end(ab, srng);
688d8899132SKalle Valo ret = -ENOBUFS;
689d8899132SKalle Valo goto unlock;
690d8899132SKalle Valo }
691d8899132SKalle Valo
692d8899132SKalle Valo desc = ath12k_hal_srng_src_get_next_reaped(ab, srng);
693d8899132SKalle Valo if (!desc) {
694d8899132SKalle Valo ath12k_hal_srng_access_end(ab, srng);
695d8899132SKalle Valo ret = -ENOBUFS;
696d8899132SKalle Valo goto unlock;
697d8899132SKalle Valo }
698d8899132SKalle Valo
699d8899132SKalle Valo if (pipe->attr_flags & CE_ATTR_BYTE_SWAP_DATA)
700d8899132SKalle Valo byte_swap_data = 1;
701d8899132SKalle Valo
702d8899132SKalle Valo ath12k_hal_ce_src_set_desc(desc, ATH12K_SKB_CB(skb)->paddr,
703d8899132SKalle Valo skb->len, transfer_id, byte_swap_data);
704d8899132SKalle Valo
705d8899132SKalle Valo pipe->src_ring->skb[write_index] = skb;
706d8899132SKalle Valo pipe->src_ring->write_index = CE_RING_IDX_INCR(nentries_mask,
707d8899132SKalle Valo write_index);
708d8899132SKalle Valo
709d8899132SKalle Valo ath12k_hal_srng_access_end(ab, srng);
710d8899132SKalle Valo
711d8899132SKalle Valo unlock:
712d8899132SKalle Valo spin_unlock_bh(&srng->lock);
713d8899132SKalle Valo
714d8899132SKalle Valo spin_unlock_bh(&ab->ce.ce_lock);
715d8899132SKalle Valo
716d8899132SKalle Valo return ret;
717d8899132SKalle Valo }
718d8899132SKalle Valo
ath12k_ce_rx_pipe_cleanup(struct ath12k_ce_pipe * pipe)719d8899132SKalle Valo static void ath12k_ce_rx_pipe_cleanup(struct ath12k_ce_pipe *pipe)
720d8899132SKalle Valo {
721d8899132SKalle Valo struct ath12k_base *ab = pipe->ab;
722d8899132SKalle Valo struct ath12k_ce_ring *ring = pipe->dest_ring;
723d8899132SKalle Valo struct sk_buff *skb;
724d8899132SKalle Valo int i;
725d8899132SKalle Valo
726d8899132SKalle Valo if (!(ring && pipe->buf_sz))
727d8899132SKalle Valo return;
728d8899132SKalle Valo
729d8899132SKalle Valo for (i = 0; i < ring->nentries; i++) {
730d8899132SKalle Valo skb = ring->skb[i];
731d8899132SKalle Valo if (!skb)
732d8899132SKalle Valo continue;
733d8899132SKalle Valo
734d8899132SKalle Valo ring->skb[i] = NULL;
735d8899132SKalle Valo dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(skb)->paddr,
736d8899132SKalle Valo skb->len + skb_tailroom(skb), DMA_FROM_DEVICE);
737d8899132SKalle Valo dev_kfree_skb_any(skb);
738d8899132SKalle Valo }
739d8899132SKalle Valo }
740d8899132SKalle Valo
ath12k_ce_cleanup_pipes(struct ath12k_base * ab)741d8899132SKalle Valo void ath12k_ce_cleanup_pipes(struct ath12k_base *ab)
742d8899132SKalle Valo {
743d8899132SKalle Valo struct ath12k_ce_pipe *pipe;
744d8899132SKalle Valo int pipe_num;
745d8899132SKalle Valo
746d8899132SKalle Valo for (pipe_num = 0; pipe_num < ab->hw_params->ce_count; pipe_num++) {
747d8899132SKalle Valo pipe = &ab->ce.ce_pipe[pipe_num];
748d8899132SKalle Valo ath12k_ce_rx_pipe_cleanup(pipe);
749d8899132SKalle Valo
750d8899132SKalle Valo /* Cleanup any src CE's which have interrupts disabled */
751d8899132SKalle Valo ath12k_ce_poll_send_completed(ab, pipe_num);
752d8899132SKalle Valo
753d8899132SKalle Valo /* NOTE: Should we also clean up tx buffer in all pipes? */
754d8899132SKalle Valo }
755d8899132SKalle Valo }
756d8899132SKalle Valo
ath12k_ce_rx_post_buf(struct ath12k_base * ab)757d8899132SKalle Valo void ath12k_ce_rx_post_buf(struct ath12k_base *ab)
758d8899132SKalle Valo {
759d8899132SKalle Valo struct ath12k_ce_pipe *pipe;
760d8899132SKalle Valo int i;
761d8899132SKalle Valo int ret;
762d8899132SKalle Valo
763d8899132SKalle Valo for (i = 0; i < ab->hw_params->ce_count; i++) {
764d8899132SKalle Valo pipe = &ab->ce.ce_pipe[i];
765d8899132SKalle Valo ret = ath12k_ce_rx_post_pipe(pipe);
766d8899132SKalle Valo if (ret) {
767d8899132SKalle Valo if (ret == -ENOSPC)
768d8899132SKalle Valo continue;
769d8899132SKalle Valo
770d8899132SKalle Valo ath12k_warn(ab, "failed to post rx buf to pipe: %d err: %d\n",
771d8899132SKalle Valo i, ret);
772d8899132SKalle Valo mod_timer(&ab->rx_replenish_retry,
773d8899132SKalle Valo jiffies + ATH12K_CE_RX_POST_RETRY_JIFFIES);
774d8899132SKalle Valo
775d8899132SKalle Valo return;
776d8899132SKalle Valo }
777d8899132SKalle Valo }
778d8899132SKalle Valo }
779d8899132SKalle Valo
ath12k_ce_rx_replenish_retry(struct timer_list * t)780d8899132SKalle Valo void ath12k_ce_rx_replenish_retry(struct timer_list *t)
781d8899132SKalle Valo {
782d8899132SKalle Valo struct ath12k_base *ab = from_timer(ab, t, rx_replenish_retry);
783d8899132SKalle Valo
784d8899132SKalle Valo ath12k_ce_rx_post_buf(ab);
785d8899132SKalle Valo }
786d8899132SKalle Valo
ath12k_ce_shadow_config(struct ath12k_base * ab)787d8899132SKalle Valo static void ath12k_ce_shadow_config(struct ath12k_base *ab)
788d8899132SKalle Valo {
789d8899132SKalle Valo int i;
790d8899132SKalle Valo
791d8899132SKalle Valo for (i = 0; i < ab->hw_params->ce_count; i++) {
792d8899132SKalle Valo if (ab->hw_params->host_ce_config[i].src_nentries)
793d8899132SKalle Valo ath12k_hal_srng_update_shadow_config(ab, HAL_CE_SRC, i);
794d8899132SKalle Valo
795d8899132SKalle Valo if (ab->hw_params->host_ce_config[i].dest_nentries) {
796d8899132SKalle Valo ath12k_hal_srng_update_shadow_config(ab, HAL_CE_DST, i);
797d8899132SKalle Valo ath12k_hal_srng_update_shadow_config(ab, HAL_CE_DST_STATUS, i);
798d8899132SKalle Valo }
799d8899132SKalle Valo }
800d8899132SKalle Valo }
801d8899132SKalle Valo
ath12k_ce_get_shadow_config(struct ath12k_base * ab,u32 ** shadow_cfg,u32 * shadow_cfg_len)802d8899132SKalle Valo void ath12k_ce_get_shadow_config(struct ath12k_base *ab,
803d8899132SKalle Valo u32 **shadow_cfg, u32 *shadow_cfg_len)
804d8899132SKalle Valo {
805d8899132SKalle Valo if (!ab->hw_params->supports_shadow_regs)
806d8899132SKalle Valo return;
807d8899132SKalle Valo
808d8899132SKalle Valo ath12k_hal_srng_get_shadow_config(ab, shadow_cfg, shadow_cfg_len);
809d8899132SKalle Valo
810d8899132SKalle Valo /* shadow is already configured */
811d8899132SKalle Valo if (*shadow_cfg_len)
812d8899132SKalle Valo return;
813d8899132SKalle Valo
814d8899132SKalle Valo /* shadow isn't configured yet, configure now.
815d8899132SKalle Valo * non-CE srngs are configured firstly, then
816d8899132SKalle Valo * all CE srngs.
817d8899132SKalle Valo */
818d8899132SKalle Valo ath12k_hal_srng_shadow_config(ab);
819d8899132SKalle Valo ath12k_ce_shadow_config(ab);
820d8899132SKalle Valo
821d8899132SKalle Valo /* get the shadow configuration */
822d8899132SKalle Valo ath12k_hal_srng_get_shadow_config(ab, shadow_cfg, shadow_cfg_len);
823d8899132SKalle Valo }
824d8899132SKalle Valo
ath12k_ce_init_pipes(struct ath12k_base * ab)825d8899132SKalle Valo int ath12k_ce_init_pipes(struct ath12k_base *ab)
826d8899132SKalle Valo {
827d8899132SKalle Valo struct ath12k_ce_pipe *pipe;
828d8899132SKalle Valo int i;
829d8899132SKalle Valo int ret;
830d8899132SKalle Valo
831d8899132SKalle Valo ath12k_ce_get_shadow_config(ab, &ab->qmi.ce_cfg.shadow_reg_v3,
832d8899132SKalle Valo &ab->qmi.ce_cfg.shadow_reg_v3_len);
833d8899132SKalle Valo
834d8899132SKalle Valo for (i = 0; i < ab->hw_params->ce_count; i++) {
835d8899132SKalle Valo pipe = &ab->ce.ce_pipe[i];
836d8899132SKalle Valo
837d8899132SKalle Valo if (pipe->src_ring) {
838d8899132SKalle Valo ret = ath12k_ce_init_ring(ab, pipe->src_ring, i,
839d8899132SKalle Valo HAL_CE_SRC);
840d8899132SKalle Valo if (ret) {
841d8899132SKalle Valo ath12k_warn(ab, "failed to init src ring: %d\n",
842d8899132SKalle Valo ret);
843d8899132SKalle Valo /* Should we clear any partial init */
844d8899132SKalle Valo return ret;
845d8899132SKalle Valo }
846d8899132SKalle Valo
847d8899132SKalle Valo pipe->src_ring->write_index = 0;
848d8899132SKalle Valo pipe->src_ring->sw_index = 0;
849d8899132SKalle Valo }
850d8899132SKalle Valo
851d8899132SKalle Valo if (pipe->dest_ring) {
852d8899132SKalle Valo ret = ath12k_ce_init_ring(ab, pipe->dest_ring, i,
853d8899132SKalle Valo HAL_CE_DST);
854d8899132SKalle Valo if (ret) {
855d8899132SKalle Valo ath12k_warn(ab, "failed to init dest ring: %d\n",
856d8899132SKalle Valo ret);
857d8899132SKalle Valo /* Should we clear any partial init */
858d8899132SKalle Valo return ret;
859d8899132SKalle Valo }
860d8899132SKalle Valo
861d8899132SKalle Valo pipe->rx_buf_needed = pipe->dest_ring->nentries ?
862d8899132SKalle Valo pipe->dest_ring->nentries - 2 : 0;
863d8899132SKalle Valo
864d8899132SKalle Valo pipe->dest_ring->write_index = 0;
865d8899132SKalle Valo pipe->dest_ring->sw_index = 0;
866d8899132SKalle Valo }
867d8899132SKalle Valo
868d8899132SKalle Valo if (pipe->status_ring) {
869d8899132SKalle Valo ret = ath12k_ce_init_ring(ab, pipe->status_ring, i,
870d8899132SKalle Valo HAL_CE_DST_STATUS);
871d8899132SKalle Valo if (ret) {
872d8899132SKalle Valo ath12k_warn(ab, "failed to init dest status ing: %d\n",
873d8899132SKalle Valo ret);
874d8899132SKalle Valo /* Should we clear any partial init */
875d8899132SKalle Valo return ret;
876d8899132SKalle Valo }
877d8899132SKalle Valo
878d8899132SKalle Valo pipe->status_ring->write_index = 0;
879d8899132SKalle Valo pipe->status_ring->sw_index = 0;
880d8899132SKalle Valo }
881d8899132SKalle Valo }
882d8899132SKalle Valo
883d8899132SKalle Valo return 0;
884d8899132SKalle Valo }
885d8899132SKalle Valo
ath12k_ce_free_pipes(struct ath12k_base * ab)886d8899132SKalle Valo void ath12k_ce_free_pipes(struct ath12k_base *ab)
887d8899132SKalle Valo {
888d8899132SKalle Valo struct ath12k_ce_pipe *pipe;
889d8899132SKalle Valo int desc_sz;
890d8899132SKalle Valo int i;
891d8899132SKalle Valo
892d8899132SKalle Valo for (i = 0; i < ab->hw_params->ce_count; i++) {
893d8899132SKalle Valo pipe = &ab->ce.ce_pipe[i];
894d8899132SKalle Valo
895d8899132SKalle Valo if (pipe->src_ring) {
896d8899132SKalle Valo desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_SRC);
897d8899132SKalle Valo dma_free_coherent(ab->dev,
898d8899132SKalle Valo pipe->src_ring->nentries * desc_sz +
899d8899132SKalle Valo CE_DESC_RING_ALIGN,
900d8899132SKalle Valo pipe->src_ring->base_addr_owner_space,
901d8899132SKalle Valo pipe->src_ring->base_addr_ce_space);
902d8899132SKalle Valo kfree(pipe->src_ring);
903d8899132SKalle Valo pipe->src_ring = NULL;
904d8899132SKalle Valo }
905d8899132SKalle Valo
906d8899132SKalle Valo if (pipe->dest_ring) {
907d8899132SKalle Valo desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_DST);
908d8899132SKalle Valo dma_free_coherent(ab->dev,
909d8899132SKalle Valo pipe->dest_ring->nentries * desc_sz +
910d8899132SKalle Valo CE_DESC_RING_ALIGN,
911d8899132SKalle Valo pipe->dest_ring->base_addr_owner_space,
912d8899132SKalle Valo pipe->dest_ring->base_addr_ce_space);
913d8899132SKalle Valo kfree(pipe->dest_ring);
914d8899132SKalle Valo pipe->dest_ring = NULL;
915d8899132SKalle Valo }
916d8899132SKalle Valo
917d8899132SKalle Valo if (pipe->status_ring) {
918d8899132SKalle Valo desc_sz =
919d8899132SKalle Valo ath12k_hal_ce_get_desc_size(HAL_CE_DESC_DST_STATUS);
920d8899132SKalle Valo dma_free_coherent(ab->dev,
921d8899132SKalle Valo pipe->status_ring->nentries * desc_sz +
922d8899132SKalle Valo CE_DESC_RING_ALIGN,
923d8899132SKalle Valo pipe->status_ring->base_addr_owner_space,
924d8899132SKalle Valo pipe->status_ring->base_addr_ce_space);
925d8899132SKalle Valo kfree(pipe->status_ring);
926d8899132SKalle Valo pipe->status_ring = NULL;
927d8899132SKalle Valo }
928d8899132SKalle Valo }
929d8899132SKalle Valo }
930d8899132SKalle Valo
ath12k_ce_alloc_pipes(struct ath12k_base * ab)931d8899132SKalle Valo int ath12k_ce_alloc_pipes(struct ath12k_base *ab)
932d8899132SKalle Valo {
933d8899132SKalle Valo struct ath12k_ce_pipe *pipe;
934d8899132SKalle Valo int i;
935d8899132SKalle Valo int ret;
936d8899132SKalle Valo const struct ce_attr *attr;
937d8899132SKalle Valo
938d8899132SKalle Valo spin_lock_init(&ab->ce.ce_lock);
939d8899132SKalle Valo
940d8899132SKalle Valo for (i = 0; i < ab->hw_params->ce_count; i++) {
941d8899132SKalle Valo attr = &ab->hw_params->host_ce_config[i];
942d8899132SKalle Valo pipe = &ab->ce.ce_pipe[i];
943d8899132SKalle Valo pipe->pipe_num = i;
944d8899132SKalle Valo pipe->ab = ab;
945d8899132SKalle Valo pipe->buf_sz = attr->src_sz_max;
946d8899132SKalle Valo
947d8899132SKalle Valo ret = ath12k_ce_alloc_pipe(ab, i);
948d8899132SKalle Valo if (ret) {
949*480c9df5SColin Ian King /* Free any partial successful allocation */
950d8899132SKalle Valo ath12k_ce_free_pipes(ab);
951d8899132SKalle Valo return ret;
952d8899132SKalle Valo }
953d8899132SKalle Valo }
954d8899132SKalle Valo
955d8899132SKalle Valo return 0;
956d8899132SKalle Valo }
957d8899132SKalle Valo
ath12k_ce_get_attr_flags(struct ath12k_base * ab,int ce_id)958d8899132SKalle Valo int ath12k_ce_get_attr_flags(struct ath12k_base *ab, int ce_id)
959d8899132SKalle Valo {
960d8899132SKalle Valo if (ce_id >= ab->hw_params->ce_count)
961d8899132SKalle Valo return -EINVAL;
962d8899132SKalle Valo
963d8899132SKalle Valo return ab->hw_params->host_ce_config[ce_id].flags;
964d8899132SKalle Valo }
965