1  /*
2   * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3   * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4   *
5   * Permission to use, copy, modify, and/or distribute this software for
6   * any purpose with or without fee is hereby granted, provided that the
7   * above copyright notice and this permission notice appear in all
8   * copies.
9   *
10   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11   * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12   * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13   * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14   * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15   * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16   * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17   * PERFORMANCE OF THIS SOFTWARE.
18   */
19  #include "hif_io32.h"
20  #include "reg_struct.h"
21  #include "ce_api.h"
22  #include "ce_main.h"
23  #include "ce_internal.h"
24  #include "ce_reg.h"
25  #include "qdf_lock.h"
26  #include "regtable.h"
27  #include "hif_main.h"
28  #include "hif_debug.h"
29  #include "hal_api.h"
30  #include "pld_common.h"
31  #include "qdf_module.h"
32  #include "hif.h"
33  
34  /*
35   * Support for Copy Engine hardware, which is mainly used for
36   * communication between Host and Target over a PCIe interconnect.
37   */
38  
39  /*
40   * A single CopyEngine (CE) comprises two "rings":
41   *   a source ring
42   *   a destination ring
43   *
44   * Each ring consists of a number of descriptors which specify
45   * an address, length, and meta-data.
46   *
47   * Typically, one side of the PCIe interconnect (Host or Target)
48   * controls one ring and the other side controls the other ring.
49   * The source side chooses when to initiate a transfer and it
50   * chooses what to send (buffer address, length). The destination
51   * side keeps a supply of "anonymous receive buffers" available and
52   * it handles incoming data as it arrives (when the destination
53   * receives an interrupt).
54   *
55   * The sender may send a simple buffer (address/length) or it may
56   * send a small list of buffers.  When a small list is sent, hardware
57   * "gathers" these and they end up in a single destination buffer
58   * with a single interrupt.
59   *
60   * There are several "contexts" managed by this layer -- more, it
61   * may seem -- than should be needed. These are provided mainly for
62   * maximum flexibility and especially to facilitate a simpler HIF
63   * implementation. There are per-CopyEngine recv, send, and watermark
64   * contexts. These are supplied by the caller when a recv, send,
65   * or watermark handler is established and they are echoed back to
66   * the caller when the respective callbacks are invoked. There is
67   * also a per-transfer context supplied by the caller when a buffer
68   * (or sendlist) is sent and when a buffer is enqueued for recv.
69   * These per-transfer contexts are echoed back to the caller when
70   * the buffer is sent/received.
71   * Target TX harsh result toeplitz_hash_result
72   */
73  
74  #define CE_ADDR_COPY(desc, dma_addr) do {\
75  		(desc)->buffer_addr_lo = (uint32_t)((dma_addr) &\
76  							  0xFFFFFFFF);\
77  		(desc)->buffer_addr_hi =\
78  			(uint32_t)(((dma_addr) >> 32) & 0xFF);\
79  	} while (0)
80  
hif_display_ctrl_traffic_pipes_state(struct hif_opaque_softc * hif_ctx)81  void hif_display_ctrl_traffic_pipes_state(struct hif_opaque_softc *hif_ctx)
82  {
83  	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
84  	struct CE_state *CE_state;
85  	uint32_t hp = 0, tp = 0;
86  
87  	CE_state = scn->ce_id_to_state[2];
88  	hal_get_sw_hptp(scn->hal_soc,
89  			CE_state->status_ring->srng_ctx,
90  			&tp, &hp);
91  	hif_info_high("CE-2 Dest status ring current snapshot HP:%u TP:%u",
92  		      hp, tp);
93  
94  	hp = 0;
95  	tp = 0;
96  	CE_state = scn->ce_id_to_state[3];
97  	hal_get_sw_hptp(scn->hal_soc, CE_state->src_ring->srng_ctx, &tp, &hp);
98  	hif_info_high("CE-3 Source ring current snapshot HP:%u TP:%u", hp, tp);
99  }
100  
101  #if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)
hif_record_ce_srng_desc_event(struct hif_softc * scn,int ce_id,enum hif_ce_event_type type,union ce_srng_desc * descriptor,void * memory,int index,int len,void * hal_ring)102  void hif_record_ce_srng_desc_event(struct hif_softc *scn, int ce_id,
103  				   enum hif_ce_event_type type,
104  				   union ce_srng_desc *descriptor,
105  				   void *memory, int index,
106  				   int len, void *hal_ring)
107  {
108  	int record_index;
109  	struct hif_ce_desc_event *event;
110  	struct ce_desc_hist *ce_hist = &scn->hif_ce_desc_hist;
111  	struct hif_ce_desc_event *hist_ev = NULL;
112  
113  	if (ce_id < CE_COUNT_MAX)
114  		hist_ev = (struct hif_ce_desc_event *)ce_hist->hist_ev[ce_id];
115  	else
116  		return;
117  
118  	if (ce_id >= CE_COUNT_MAX)
119  		return;
120  
121  	if (!ce_hist->enable[ce_id])
122  		return;
123  
124  	if (!hist_ev)
125  		return;
126  
127  	record_index = get_next_record_index(
128  			&ce_hist->history_index[ce_id], HIF_CE_HISTORY_MAX);
129  
130  	event = &hist_ev[record_index];
131  
132  	hif_clear_ce_desc_debug_data(event);
133  
134  	event->type = type;
135  	event->time = qdf_get_log_timestamp();
136  	event->cpu_id = qdf_get_cpu();
137  
138  	if (descriptor)
139  		qdf_mem_copy(&event->descriptor, descriptor,
140  			     hal_get_entrysize_from_srng(hal_ring));
141  
142  	if (hal_ring)
143  		hal_get_sw_hptp(scn->hal_soc, hal_ring, &event->current_tp,
144  				&event->current_hp);
145  
146  	event->memory = memory;
147  	event->index = index;
148  
149  	if (event->type == HIF_CE_SRC_RING_BUFFER_POST)
150  		hif_ce_desc_record_rx_paddr(scn, event, memory);
151  
152  	if (ce_hist->data_enable[ce_id])
153  		hif_ce_desc_data_record(event, len);
154  
155  	hif_record_latest_evt(ce_hist, type, ce_id, event->time,
156  			      event->current_hp, event->current_tp);
157  }
158  #endif /* HIF_CONFIG_SLUB_DEBUG_ON || HIF_CE_DEBUG_DATA_BUF */
159  
160  static QDF_STATUS
ce_send_nolock_srng(struct CE_handle * copyeng,void * per_transfer_context,qdf_dma_addr_t buffer,uint32_t nbytes,uint32_t transfer_id,uint32_t flags,uint32_t user_flags)161  ce_send_nolock_srng(struct CE_handle *copyeng,
162  			   void *per_transfer_context,
163  			   qdf_dma_addr_t buffer,
164  			   uint32_t nbytes,
165  			   uint32_t transfer_id,
166  			   uint32_t flags,
167  			   uint32_t user_flags)
168  {
169  	QDF_STATUS status;
170  	struct CE_state *CE_state = (struct CE_state *)copyeng;
171  	struct CE_ring_state *src_ring = CE_state->src_ring;
172  	unsigned int nentries_mask = src_ring->nentries_mask;
173  	unsigned int write_index = src_ring->write_index;
174  	uint64_t dma_addr = buffer;
175  	struct hif_softc *scn = CE_state->scn;
176  
177  	if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
178  		return QDF_STATUS_E_FAILURE;
179  	if (unlikely(hal_srng_src_num_avail(scn->hal_soc, src_ring->srng_ctx,
180  					false) <= 0)) {
181  		OL_ATH_CE_PKT_ERROR_COUNT_INCR(scn, CE_RING_DELTA_FAIL);
182  		Q_TARGET_ACCESS_END(scn);
183  		return QDF_STATUS_E_FAILURE;
184  	}
185  	{
186  		enum hif_ce_event_type event_type = HIF_CE_SRC_RING_BUFFER_POST;
187  		struct ce_srng_src_desc *src_desc;
188  
189  		if (hal_srng_access_start(scn->hal_soc, src_ring->srng_ctx)) {
190  			Q_TARGET_ACCESS_END(scn);
191  			return QDF_STATUS_E_FAILURE;
192  		}
193  
194  		src_desc = hal_srng_src_get_next_reaped(scn->hal_soc,
195  				src_ring->srng_ctx);
196  		if (!src_desc) {
197  			Q_TARGET_ACCESS_END(scn);
198  			return QDF_STATUS_E_INVAL;
199  		}
200  
201  		/* Update low 32 bits source descriptor address */
202  		src_desc->buffer_addr_lo =
203  			(uint32_t)(dma_addr & 0xFFFFFFFF);
204  		src_desc->buffer_addr_hi =
205  			(uint32_t)((dma_addr >> 32) & 0xFF);
206  
207  		src_desc->meta_data = transfer_id;
208  
209  		/*
210  		 * Set the swap bit if:
211  		 * typical sends on this CE are swapped (host is big-endian)
212  		 * and this send doesn't disable the swapping
213  		 * (data is not bytestream)
214  		 */
215  		src_desc->byte_swap =
216  			(((CE_state->attr_flags & CE_ATTR_BYTE_SWAP_DATA)
217  			  != 0) & ((flags & CE_SEND_FLAG_SWAP_DISABLE) == 0));
218  		src_desc->gather = ((flags & CE_SEND_FLAG_GATHER) != 0);
219  		src_desc->nbytes = nbytes;
220  
221  		src_ring->per_transfer_context[write_index] =
222  			per_transfer_context;
223  		write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
224  
225  		hal_srng_access_end(scn->hal_soc, src_ring->srng_ctx);
226  
227  		/* src_ring->write index hasn't been updated event though
228  		 * the register has already been written to.
229  		 */
230  		hif_record_ce_srng_desc_event(scn, CE_state->id, event_type,
231  					      (union ce_srng_desc *)src_desc,
232  					      per_transfer_context,
233  					      src_ring->write_index, nbytes,
234  					      src_ring->srng_ctx);
235  
236  		src_ring->write_index = write_index;
237  		status = QDF_STATUS_SUCCESS;
238  	}
239  	Q_TARGET_ACCESS_END(scn);
240  	return status;
241  }
242  
243  static QDF_STATUS
ce_sendlist_send_srng(struct CE_handle * copyeng,void * per_transfer_context,struct ce_sendlist * sendlist,unsigned int transfer_id)244  ce_sendlist_send_srng(struct CE_handle *copyeng,
245  		 void *per_transfer_context,
246  		 struct ce_sendlist *sendlist, unsigned int transfer_id)
247  {
248  	QDF_STATUS status = QDF_STATUS_E_NOMEM;
249  	struct ce_sendlist_s *sl = (struct ce_sendlist_s *)sendlist;
250  	struct CE_state *CE_state = (struct CE_state *)copyeng;
251  	struct CE_ring_state *src_ring = CE_state->src_ring;
252  	unsigned int num_items = sl->num_items;
253  	unsigned int sw_index;
254  	unsigned int write_index;
255  	struct hif_softc *scn = CE_state->scn;
256  
257  	QDF_ASSERT((num_items > 0) && (num_items < src_ring->nentries));
258  
259  	qdf_spin_lock_bh(&CE_state->ce_index_lock);
260  	sw_index = src_ring->sw_index;
261  	write_index = src_ring->write_index;
262  
263  	if (hal_srng_src_num_avail(scn->hal_soc, src_ring->srng_ctx, false) >=
264  	    num_items) {
265  		struct ce_sendlist_item *item;
266  		int i;
267  
268  		/* handle all but the last item uniformly */
269  		for (i = 0; i < num_items - 1; i++) {
270  			item = &sl->item[i];
271  			/* TBDXXX: Support extensible sendlist_types? */
272  			QDF_ASSERT(item->send_type == CE_SIMPLE_BUFFER_TYPE);
273  			status = ce_send_nolock_srng(copyeng,
274  					CE_SENDLIST_ITEM_CTXT,
275  				(qdf_dma_addr_t) item->data,
276  				item->u.nbytes, transfer_id,
277  				item->flags | CE_SEND_FLAG_GATHER,
278  				item->user_flags);
279  			QDF_ASSERT(status == QDF_STATUS_SUCCESS);
280  		}
281  		/* provide valid context pointer for final item */
282  		item = &sl->item[i];
283  		/* TBDXXX: Support extensible sendlist_types? */
284  		QDF_ASSERT(item->send_type == CE_SIMPLE_BUFFER_TYPE);
285  		status = ce_send_nolock_srng(copyeng, per_transfer_context,
286  					(qdf_dma_addr_t) item->data,
287  					item->u.nbytes,
288  					transfer_id, item->flags,
289  					item->user_flags);
290  		QDF_ASSERT(status == QDF_STATUS_SUCCESS);
291  		QDF_NBUF_UPDATE_TX_PKT_COUNT((qdf_nbuf_t)per_transfer_context,
292  					QDF_NBUF_TX_PKT_CE);
293  		DPTRACE(qdf_dp_trace((qdf_nbuf_t)per_transfer_context,
294  			QDF_DP_TRACE_CE_PACKET_PTR_RECORD,
295  			QDF_TRACE_DEFAULT_PDEV_ID,
296  			(uint8_t *)(((qdf_nbuf_t)per_transfer_context)->data),
297  			sizeof(((qdf_nbuf_t)per_transfer_context)->data), QDF_TX));
298  	} else {
299  		/*
300  		 * Probably not worth the additional complexity to support
301  		 * partial sends with continuation or notification.  We expect
302  		 * to use large rings and small sendlists. If we can't handle
303  		 * the entire request at once, punt it back to the caller.
304  		 */
305  	}
306  	qdf_spin_unlock_bh(&CE_state->ce_index_lock);
307  
308  	return status;
309  }
310  
311  #define SLOTS_PER_DATAPATH_TX 2
312  
313  #ifndef AH_NEED_TX_DATA_SWAP
314  #define AH_NEED_TX_DATA_SWAP 0
315  #endif
316  /**
317   * ce_recv_buf_enqueue_srng() - enqueue a recv buffer into a copy engine
318   * @copyeng: copy engine handle
319   * @per_recv_context: virtual address of the nbuf
320   * @buffer: physical address of the nbuf
321   *
322   * Return: QDF_STATUS_SUCCESS if the buffer is enqueued
323   */
324  static QDF_STATUS
ce_recv_buf_enqueue_srng(struct CE_handle * copyeng,void * per_recv_context,qdf_dma_addr_t buffer)325  ce_recv_buf_enqueue_srng(struct CE_handle *copyeng,
326  		    void *per_recv_context, qdf_dma_addr_t buffer)
327  {
328  	QDF_STATUS status;
329  	struct CE_state *CE_state = (struct CE_state *)copyeng;
330  	struct CE_ring_state *dest_ring = CE_state->dest_ring;
331  	unsigned int nentries_mask = dest_ring->nentries_mask;
332  	unsigned int write_index;
333  	unsigned int sw_index;
334  	uint64_t dma_addr = buffer;
335  	struct hif_softc *scn = CE_state->scn;
336  	struct ce_srng_dest_desc *dest_desc = NULL;
337  
338  	qdf_spin_lock_bh(&CE_state->ce_index_lock);
339  	write_index = dest_ring->write_index;
340  	sw_index = dest_ring->sw_index;
341  
342  	if (Q_TARGET_ACCESS_BEGIN(scn) < 0) {
343  		qdf_spin_unlock_bh(&CE_state->ce_index_lock);
344  		return QDF_STATUS_E_IO;
345  	}
346  
347  	/* HP/TP update if any should happen only once per interrupt,
348  	 * therefore checking for CE receive_count.
349  	 */
350  	hal_srng_check_and_update_hptp(scn->hal_soc, dest_ring->srng_ctx,
351  				       !CE_state->receive_count);
352  
353  	if (hal_srng_access_start(scn->hal_soc, dest_ring->srng_ctx)) {
354  		qdf_spin_unlock_bh(&CE_state->ce_index_lock);
355  		return QDF_STATUS_E_FAILURE;
356  	}
357  
358  	if ((hal_srng_src_num_avail(scn->hal_soc,
359  					dest_ring->srng_ctx, false) > 0)) {
360  		dest_desc = hal_srng_src_get_next(scn->hal_soc,
361  						  dest_ring->srng_ctx);
362  
363  		if (!dest_desc) {
364  			status = QDF_STATUS_E_FAILURE;
365  		} else {
366  
367  			CE_ADDR_COPY(dest_desc, dma_addr);
368  
369  			dest_ring->per_transfer_context[write_index] =
370  				per_recv_context;
371  
372  			/* Update Destination Ring Write Index */
373  			write_index = CE_RING_IDX_INCR(nentries_mask,
374  								write_index);
375  			status = QDF_STATUS_SUCCESS;
376  		}
377  	} else {
378  		dest_desc = NULL;
379  		status = QDF_STATUS_E_FAILURE;
380  	}
381  
382  	dest_ring->write_index = write_index;
383  	hal_srng_access_end(scn->hal_soc, dest_ring->srng_ctx);
384  	hif_record_ce_srng_desc_event(scn, CE_state->id,
385  				      HIF_CE_DEST_RING_BUFFER_POST,
386  				      (union ce_srng_desc *)dest_desc,
387  				      per_recv_context,
388  				      dest_ring->write_index, 0,
389  				      dest_ring->srng_ctx);
390  
391  	Q_TARGET_ACCESS_END(scn);
392  	qdf_spin_unlock_bh(&CE_state->ce_index_lock);
393  	return status;
394  }
395  
396  /*
397   * Guts of ce_recv_entries_done.
398   * The caller takes responsibility for any necessary locking.
399   */
400  static unsigned int
ce_recv_entries_done_nolock_srng(struct hif_softc * scn,struct CE_state * CE_state)401  ce_recv_entries_done_nolock_srng(struct hif_softc *scn,
402  			    struct CE_state *CE_state)
403  {
404  	struct CE_ring_state *status_ring = CE_state->status_ring;
405  
406  	return hal_srng_dst_num_valid(scn->hal_soc,
407  				status_ring->srng_ctx, false);
408  }
409  
410  /*
411   * Guts of ce_send_entries_done.
412   * The caller takes responsibility for any necessary locking.
413   */
414  static unsigned int
ce_send_entries_done_nolock_srng(struct hif_softc * scn,struct CE_state * CE_state)415  ce_send_entries_done_nolock_srng(struct hif_softc *scn,
416  					struct CE_state *CE_state)
417  {
418  
419  	struct CE_ring_state *src_ring = CE_state->src_ring;
420  	int count = 0;
421  
422  	if (hal_srng_access_start(scn->hal_soc, src_ring->srng_ctx))
423  		return 0;
424  
425  	count = hal_srng_src_done_val(scn->hal_soc, src_ring->srng_ctx);
426  
427  	hal_srng_access_end_reap(scn->hal_soc, src_ring->srng_ctx);
428  
429  	return count;
430  }
431  
432  /*
433   * Guts of ce_completed_recv_next.
434   * The caller takes responsibility for any necessary locking.
435   */
436  static QDF_STATUS
ce_completed_recv_next_nolock_srng(struct CE_state * CE_state,void ** per_CE_contextp,void ** per_transfer_contextp,qdf_dma_addr_t * bufferp,unsigned int * nbytesp,unsigned int * transfer_idp,unsigned int * flagsp)437  ce_completed_recv_next_nolock_srng(struct CE_state *CE_state,
438  			      void **per_CE_contextp,
439  			      void **per_transfer_contextp,
440  			      qdf_dma_addr_t *bufferp,
441  			      unsigned int *nbytesp,
442  			      unsigned int *transfer_idp,
443  			      unsigned int *flagsp)
444  {
445  	QDF_STATUS status;
446  	struct CE_ring_state *dest_ring = CE_state->dest_ring;
447  	struct CE_ring_state *status_ring = CE_state->status_ring;
448  	unsigned int nentries_mask = dest_ring->nentries_mask;
449  	unsigned int sw_index = dest_ring->sw_index;
450  	struct hif_softc *scn = CE_state->scn;
451  	struct ce_srng_dest_status_desc *dest_status = NULL;
452  	int nbytes;
453  	struct ce_srng_dest_status_desc dest_status_info;
454  
455  	/* HP/TP update if any should happen only once per interrupt,
456  	 * therefore checking for CE receive_count.
457  	 */
458  	hal_srng_check_and_update_hptp(scn->hal_soc, status_ring->srng_ctx,
459  				       !CE_state->receive_count);
460  
461  	if (hal_srng_access_start(scn->hal_soc, status_ring->srng_ctx))
462  		return QDF_STATUS_E_FAILURE;
463  
464  	dest_status = hal_srng_dst_peek(scn->hal_soc, status_ring->srng_ctx);
465  	if (!dest_status) {
466  		hal_srng_access_end_reap(scn->hal_soc, status_ring->srng_ctx);
467  		return QDF_STATUS_E_FAILURE;
468  	}
469  
470  	/*
471  	 * By copying the dest_desc_info element to local memory, we could
472  	 * avoid extra memory read from non-cachable memory.
473  	 */
474  	dest_status_info = *dest_status;
475  	nbytes = dest_status_info.nbytes;
476  	if (nbytes == 0) {
477  		uint32_t hp, tp;
478  
479  		/*
480  		 * This closes a relatively unusual race where the Host
481  		 * sees the updated DRRI before the update to the
482  		 * corresponding descriptor has completed. We treat this
483  		 * as a descriptor that is not yet done.
484  		 */
485  		hal_get_sw_hptp(scn->hal_soc, status_ring->srng_ctx,
486  				&tp, &hp);
487  		hif_info_rl("No data to reap, hp %d tp %d", hp, tp);
488  		status = QDF_STATUS_E_FAILURE;
489  		hal_srng_access_end_reap(scn->hal_soc, status_ring->srng_ctx);
490  		goto done;
491  	}
492  
493  	/*
494  	 * Move the tail pointer since nbytes is non-zero and
495  	 * this entry is processed.
496  	 */
497  	hal_srng_dst_get_next(scn->hal_soc, status_ring->srng_ctx);
498  
499  	dest_status->nbytes = 0;
500  
501  	*nbytesp = nbytes;
502  	*transfer_idp = dest_status_info.meta_data;
503  	*flagsp = (dest_status_info.byte_swap) ? CE_RECV_FLAG_SWAPPED : 0;
504  
505  	if (per_CE_contextp)
506  		*per_CE_contextp = CE_state->recv_context;
507  
508  	/* NOTE: sw_index is more like a read_index in this context. It has a
509  	 * one-to-one mapping with status ring.
510  	 * Get the per trasnfer context from dest_ring.
511  	 */
512  	if (per_transfer_contextp)
513  		*per_transfer_contextp =
514  			dest_ring->per_transfer_context[sw_index];
515  
516  	dest_ring->per_transfer_context[sw_index] = 0;  /* sanity */
517  
518  	/* Update sw_index */
519  	sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
520  	dest_ring->sw_index = sw_index;
521  	status = QDF_STATUS_SUCCESS;
522  
523  	hal_srng_access_end(scn->hal_soc, status_ring->srng_ctx);
524  	hif_record_ce_srng_desc_event(scn, CE_state->id,
525  				      HIF_CE_DEST_RING_BUFFER_REAP,
526  				      NULL,
527  				      dest_ring->
528  				      per_transfer_context[sw_index],
529  				      dest_ring->sw_index, nbytes,
530  				      dest_ring->srng_ctx);
531  
532  done:
533  	hif_record_ce_srng_desc_event(scn, CE_state->id,
534  				      HIF_CE_DEST_STATUS_RING_REAP,
535  				      (union ce_srng_desc *)dest_status,
536  				      NULL,
537  				      -1, 0,
538  				      status_ring->srng_ctx);
539  
540  	return status;
541  }
542  
543  static QDF_STATUS
ce_revoke_recv_next_srng(struct CE_handle * copyeng,void ** per_CE_contextp,void ** per_transfer_contextp,qdf_dma_addr_t * bufferp)544  ce_revoke_recv_next_srng(struct CE_handle *copyeng,
545  		    void **per_CE_contextp,
546  		    void **per_transfer_contextp, qdf_dma_addr_t *bufferp)
547  {
548  	struct CE_state *CE_state = (struct CE_state *)copyeng;
549  	struct CE_ring_state *dest_ring = CE_state->dest_ring;
550  	unsigned int sw_index;
551  
552  	if (!dest_ring)
553  		return QDF_STATUS_E_FAILURE;
554  
555  	sw_index = dest_ring->sw_index;
556  
557  	if (per_CE_contextp)
558  		*per_CE_contextp = CE_state->recv_context;
559  
560  	/* NOTE: sw_index is more like a read_index in this context. It has a
561  	 * one-to-one mapping with status ring.
562  	 * Get the per trasnfer context from dest_ring.
563  	 */
564  	if (per_transfer_contextp)
565  		*per_transfer_contextp =
566  			dest_ring->per_transfer_context[sw_index];
567  
568  	if (!dest_ring->per_transfer_context[sw_index])
569  		return QDF_STATUS_E_FAILURE;
570  
571  	/* provide end condition */
572  	dest_ring->per_transfer_context[sw_index] = NULL;
573  
574  	/* Update sw_index */
575  	sw_index = CE_RING_IDX_INCR(dest_ring->nentries_mask, sw_index);
576  	dest_ring->sw_index = sw_index;
577  	return QDF_STATUS_SUCCESS;
578  }
579  
580  /*
581   * Guts of ce_completed_send_next.
582   * The caller takes responsibility for any necessary locking.
583   */
584  static QDF_STATUS
ce_completed_send_next_nolock_srng(struct CE_state * CE_state,void ** per_CE_contextp,void ** per_transfer_contextp,qdf_dma_addr_t * bufferp,unsigned int * nbytesp,unsigned int * transfer_idp,unsigned int * sw_idx,unsigned int * hw_idx,uint32_t * toeplitz_hash_result)585  ce_completed_send_next_nolock_srng(struct CE_state *CE_state,
586  			      void **per_CE_contextp,
587  			      void **per_transfer_contextp,
588  			      qdf_dma_addr_t *bufferp,
589  			      unsigned int *nbytesp,
590  			      unsigned int *transfer_idp,
591  			      unsigned int *sw_idx,
592  			      unsigned int *hw_idx,
593  			      uint32_t *toeplitz_hash_result)
594  {
595  	QDF_STATUS status = QDF_STATUS_E_FAILURE;
596  	struct CE_ring_state *src_ring = CE_state->src_ring;
597  	unsigned int nentries_mask = src_ring->nentries_mask;
598  	unsigned int sw_index = src_ring->sw_index;
599  	unsigned int swi = src_ring->sw_index;
600  	struct hif_softc *scn = CE_state->scn;
601  	struct ce_srng_src_desc *src_desc;
602  
603  	if (hal_srng_access_start(scn->hal_soc, src_ring->srng_ctx)) {
604  		status = QDF_STATUS_E_FAILURE;
605  		return status;
606  	}
607  
608  	src_desc = hal_srng_src_reap_next(scn->hal_soc, src_ring->srng_ctx);
609  	if (src_desc) {
610  		hif_record_ce_srng_desc_event(scn, CE_state->id,
611  					      HIF_TX_DESC_COMPLETION,
612  					      (union ce_srng_desc *)src_desc,
613  					      src_ring->
614  					      per_transfer_context[swi],
615  					      swi, src_desc->nbytes,
616  					      src_ring->srng_ctx);
617  
618  		/* Return data from completed source descriptor */
619  		*bufferp = (qdf_dma_addr_t)
620  			(((uint64_t)(src_desc)->buffer_addr_lo +
621  			  ((uint64_t)((src_desc)->buffer_addr_hi &
622  				  0xFF) << 32)));
623  		*nbytesp = src_desc->nbytes;
624  		*transfer_idp = src_desc->meta_data;
625  		*toeplitz_hash_result = 0; /*src_desc->toeplitz_hash_result;*/
626  
627  		if (per_CE_contextp)
628  			*per_CE_contextp = CE_state->send_context;
629  
630  		/* sw_index is used more like read index */
631  		if (per_transfer_contextp)
632  			*per_transfer_contextp =
633  				src_ring->per_transfer_context[sw_index];
634  
635  		src_ring->per_transfer_context[sw_index] = 0;   /* sanity */
636  
637  		/* Update sw_index */
638  		sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
639  		src_ring->sw_index = sw_index;
640  		status = QDF_STATUS_SUCCESS;
641  	}
642  	hal_srng_access_end_reap(scn->hal_soc, src_ring->srng_ctx);
643  
644  	return status;
645  }
646  
647  /* NB: Modelled after ce_completed_send_next */
648  static QDF_STATUS
ce_cancel_send_next_srng(struct CE_handle * copyeng,void ** per_CE_contextp,void ** per_transfer_contextp,qdf_dma_addr_t * bufferp,unsigned int * nbytesp,unsigned int * transfer_idp,uint32_t * toeplitz_hash_result)649  ce_cancel_send_next_srng(struct CE_handle *copyeng,
650  		void **per_CE_contextp,
651  		void **per_transfer_contextp,
652  		qdf_dma_addr_t *bufferp,
653  		unsigned int *nbytesp,
654  		unsigned int *transfer_idp,
655  		uint32_t *toeplitz_hash_result)
656  {
657  	struct CE_state *CE_state;
658  	QDF_STATUS status = QDF_STATUS_E_FAILURE;
659  	struct CE_ring_state *src_ring;
660  	unsigned int nentries_mask;
661  	unsigned int sw_index;
662  	struct hif_softc *scn;
663  	struct ce_srng_src_desc *src_desc;
664  
665  	CE_state = (struct CE_state *)copyeng;
666  	src_ring = CE_state->src_ring;
667  	if (!src_ring)
668  		return QDF_STATUS_E_FAILURE;
669  
670  	nentries_mask = src_ring->nentries_mask;
671  	sw_index = src_ring->sw_index;
672  	scn = CE_state->scn;
673  
674  	if (hal_srng_access_start(scn->hal_soc, src_ring->srng_ctx)) {
675  		status = QDF_STATUS_E_FAILURE;
676  		return status;
677  	}
678  
679  	src_desc = hal_srng_src_pending_reap_next(scn->hal_soc,
680  			src_ring->srng_ctx);
681  	if (src_desc) {
682  		/* Return data from completed source descriptor */
683  		*bufferp = (qdf_dma_addr_t)
684  			(((uint64_t)(src_desc)->buffer_addr_lo +
685  			  ((uint64_t)((src_desc)->buffer_addr_hi &
686  				  0xFF) << 32)));
687  		*nbytesp = src_desc->nbytes;
688  		*transfer_idp = src_desc->meta_data;
689  		*toeplitz_hash_result = 0; /*src_desc->toeplitz_hash_result;*/
690  
691  		if (per_CE_contextp)
692  			*per_CE_contextp = CE_state->send_context;
693  
694  		/* sw_index is used more like read index */
695  		if (per_transfer_contextp)
696  			*per_transfer_contextp =
697  				src_ring->per_transfer_context[sw_index];
698  
699  		src_ring->per_transfer_context[sw_index] = 0;   /* sanity */
700  
701  		/* Update sw_index */
702  		sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
703  		src_ring->sw_index = sw_index;
704  		status = QDF_STATUS_SUCCESS;
705  	}
706  	hal_srng_access_end_reap(scn->hal_soc, src_ring->srng_ctx);
707  
708  	return status;
709  }
710  
711  /*
712   * Adjust interrupts for the copy complete handler.
713   * If it's needed for either send or recv, then unmask
714   * this interrupt; otherwise, mask it.
715   *
716   * Called with target_lock held.
717   */
718  static void
ce_per_engine_handler_adjust_srng(struct CE_state * CE_state,int disable_copy_compl_intr)719  ce_per_engine_handler_adjust_srng(struct CE_state *CE_state,
720  			     int disable_copy_compl_intr)
721  {
722  }
723  
ce_check_int_watermark_srng(struct CE_state * CE_state,unsigned int * flags)724  static bool ce_check_int_watermark_srng(struct CE_state *CE_state,
725  					unsigned int *flags)
726  {
727  	/*TODO*/
728  	return false;
729  }
730  
ce_get_desc_size_srng(uint8_t ring_type)731  static uint32_t ce_get_desc_size_srng(uint8_t ring_type)
732  {
733  	switch (ring_type) {
734  	case CE_RING_SRC:
735  		return sizeof(struct ce_srng_src_desc);
736  	case CE_RING_DEST:
737  		return sizeof(struct ce_srng_dest_desc);
738  	case CE_RING_STATUS:
739  		return sizeof(struct ce_srng_dest_status_desc);
740  	default:
741  		return 0;
742  	}
743  	return 0;
744  }
745  
ce_srng_msi_ring_params_setup(struct hif_softc * scn,uint32_t ce_id,struct hal_srng_params * ring_params)746  static void ce_srng_msi_ring_params_setup(struct hif_softc *scn, uint32_t ce_id,
747  			      struct hal_srng_params *ring_params)
748  {
749  	uint32_t addr_low;
750  	uint32_t addr_high;
751  	uint32_t msi_data_start;
752  	uint32_t msi_data_count;
753  	uint32_t msi_irq_start;
754  	int ret;
755  	int irq_id;
756  
757  	ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
758  					  &msi_data_count, &msi_data_start,
759  					  &msi_irq_start);
760  
761  	/* msi config not found */
762  	if (ret)
763  		return;
764  
765  	irq_id = scn->int_assignment->msi_idx[ce_id];
766  	pld_get_msi_address(scn->qdf_dev->dev, &addr_low, &addr_high);
767  
768  	ring_params->msi_addr = addr_low;
769  	ring_params->msi_addr |= (qdf_dma_addr_t)(((uint64_t)addr_high) << 32);
770  	ring_params->msi_data =  irq_id + msi_data_start;
771  	ring_params->flags |= HAL_SRNG_MSI_INTR;
772  
773  	hif_debug("ce_id %d irq_id %d, msi_addr %pK, msi_data %d", ce_id,
774  		  irq_id, (void *)ring_params->msi_addr, ring_params->msi_data);
775  }
776  
ce_srng_src_ring_setup(struct hif_softc * scn,uint32_t ce_id,struct CE_ring_state * src_ring,struct CE_attr * attr)777  static void ce_srng_src_ring_setup(struct hif_softc *scn, uint32_t ce_id,
778  				   struct CE_ring_state *src_ring,
779  				   struct CE_attr *attr)
780  {
781  	struct hal_srng_params ring_params = {0};
782  
783  	hif_debug("%s: ce_id %d", __func__, ce_id);
784  
785  	ring_params.ring_base_paddr = src_ring->base_addr_CE_space;
786  	ring_params.ring_base_vaddr = src_ring->base_addr_owner_space;
787  	ring_params.num_entries = src_ring->nentries;
788  	/*
789  	 * The minimum increment for the timer is 8us
790  	 * A default value of 0 disables the timer
791  	 * A valid default value caused continuous interrupts to
792  	 * fire with MSI enabled. Need to revisit usage of the timer
793  	 */
794  
795  	if (!(CE_ATTR_DISABLE_INTR & attr->flags)) {
796  		ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params);
797  
798  		ring_params.intr_timer_thres_us = 0;
799  		ring_params.intr_batch_cntr_thres_entries = 1;
800  		ring_params.prefetch_timer = HAL_SRNG_PREFETCH_TIMER;
801  	}
802  
803  	src_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_SRC, ce_id, 0,
804  					    &ring_params, 0);
805  }
806  
807  #ifdef WLAN_WAR_CE_DISABLE_SRNG_TIMER_IRQ
808  static void
ce_srng_initialize_dest_ring_thresh(struct CE_ring_state * dest_ring,struct hal_srng_params * ring_params)809  ce_srng_initialize_dest_ring_thresh(struct CE_ring_state *dest_ring,
810  				    struct hal_srng_params *ring_params)
811  {
812  	ring_params->low_threshold = dest_ring->nentries >> 3;
813  	ring_params->intr_timer_thres_us = 0;
814  	ring_params->intr_batch_cntr_thres_entries = 1;
815  	ring_params->flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE;
816  }
817  #else
818  static void
ce_srng_initialize_dest_ring_thresh(struct CE_ring_state * dest_ring,struct hal_srng_params * ring_params)819  ce_srng_initialize_dest_ring_thresh(struct CE_ring_state *dest_ring,
820  				    struct hal_srng_params *ring_params)
821  {
822  	ring_params->low_threshold = dest_ring->nentries >> 3;
823  	ring_params->intr_timer_thres_us = 100000;
824  	ring_params->intr_batch_cntr_thres_entries = 0;
825  	ring_params->flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE;
826  }
827  #endif
828  
829  #ifdef WLAN_DISABLE_STATUS_RING_TIMER_WAR
ce_is_status_ring_timer_thresh_war_needed(void)830  static inline bool ce_is_status_ring_timer_thresh_war_needed(void)
831  {
832  	return false;
833  }
834  #else
ce_is_status_ring_timer_thresh_war_needed(void)835  static inline bool ce_is_status_ring_timer_thresh_war_needed(void)
836  {
837  	return true;
838  }
839  #endif
840  
841  /**
842   * ce_srng_initialize_dest_timer_interrupt_war() - war initialization
843   * @dest_ring: ring being initialized
844   * @ring_params: pointer to initialized parameters
845   *
846   * For Napier & Hawkeye v1, the status ring timer interrupts do not work
847   * As a workaround host configures the destination rings to be a proxy for
848   * work needing to be done.
849   *
850   * The interrupts are setup such that if the destination ring is less than fully
851   * posted, there is likely undone work for the status ring that the host should
852   * process.
853   *
854   * There is a timing bug in srng based copy engines such that a fully posted
855   * srng based copy engine has 2 empty entries instead of just one.  The copy
856   * engine data structures work with 1 empty entry, but the software frequently
857   * fails to post the last entry due to the race condition.
858   */
ce_srng_initialize_dest_timer_interrupt_war(struct CE_ring_state * dest_ring,struct hal_srng_params * ring_params)859  static void ce_srng_initialize_dest_timer_interrupt_war(
860  					struct CE_ring_state *dest_ring,
861  					struct hal_srng_params *ring_params)
862  {
863  	int num_buffers_when_fully_posted = dest_ring->nentries - 2;
864  
865  	ring_params->low_threshold = num_buffers_when_fully_posted - 1;
866  	ring_params->intr_timer_thres_us = 1024;
867  	ring_params->intr_batch_cntr_thres_entries = 0;
868  	ring_params->flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE;
869  }
870  
ce_srng_dest_ring_setup(struct hif_softc * scn,uint32_t ce_id,struct CE_ring_state * dest_ring,struct CE_attr * attr)871  static void ce_srng_dest_ring_setup(struct hif_softc *scn,
872  				    uint32_t ce_id,
873  				    struct CE_ring_state *dest_ring,
874  				    struct CE_attr *attr)
875  {
876  	struct hal_srng_params ring_params = {0};
877  
878  	hif_debug("ce_id: %d", ce_id);
879  
880  	ring_params.ring_base_paddr = dest_ring->base_addr_CE_space;
881  	ring_params.ring_base_vaddr = dest_ring->base_addr_owner_space;
882  	ring_params.num_entries = dest_ring->nentries;
883  	ring_params.max_buffer_length = attr->src_sz_max;
884  
885  	if (!(CE_ATTR_DISABLE_INTR & attr->flags)) {
886  		ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params);
887  		if (ce_is_status_ring_timer_thresh_war_needed()) {
888  			ce_srng_initialize_dest_timer_interrupt_war(
889  					dest_ring, &ring_params);
890  		} else {
891  			/* normal behavior for future chips */
892  			ce_srng_initialize_dest_ring_thresh(dest_ring,
893  							    &ring_params);
894  		}
895  		ring_params.prefetch_timer = HAL_SRNG_PREFETCH_TIMER;
896  	}
897  
898  	/*Dest ring is also source ring*/
899  	dest_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_DST, ce_id, 0,
900  					     &ring_params, 0);
901  }
902  
903  #ifdef WLAN_CE_INTERRUPT_THRESHOLD_CONFIG
904  /**
905   * ce_status_ring_config_int_threshold() - configure ce status ring interrupt
906   *                                         thresholds
907   * @scn: hif handle
908   * @ring_params: ce srng params
909   *
910   * Return: None
911   */
912  static inline
ce_status_ring_config_int_threshold(struct hif_softc * scn,struct hal_srng_params * ring_params)913  void ce_status_ring_config_int_threshold(struct hif_softc *scn,
914  					 struct hal_srng_params *ring_params)
915  {
916  	ring_params->intr_timer_thres_us =
917  			scn->ini_cfg.ce_status_ring_timer_threshold;
918  	ring_params->intr_batch_cntr_thres_entries =
919  			scn->ini_cfg.ce_status_ring_batch_count_threshold;
920  }
921  #else
922  static inline
ce_status_ring_config_int_threshold(struct hif_softc * scn,struct hal_srng_params * ring_params)923  void ce_status_ring_config_int_threshold(struct hif_softc *scn,
924  					 struct hal_srng_params *ring_params)
925  {
926  	ring_params->intr_timer_thres_us = 0x1000;
927  	ring_params->intr_batch_cntr_thres_entries = 0x1;
928  }
929  #endif /* WLAN_CE_INTERRUPT_THRESHOLD_CONFIG */
930  
ce_srng_status_ring_setup(struct hif_softc * scn,uint32_t ce_id,struct CE_ring_state * status_ring,struct CE_attr * attr)931  static void ce_srng_status_ring_setup(struct hif_softc *scn, uint32_t ce_id,
932  				struct CE_ring_state *status_ring,
933  				struct CE_attr *attr)
934  {
935  	struct hal_srng_params ring_params = {0};
936  
937  	hif_debug("ce_id: %d", ce_id);
938  
939  	ring_params.ring_base_paddr = status_ring->base_addr_CE_space;
940  	ring_params.ring_base_vaddr = status_ring->base_addr_owner_space;
941  	ring_params.num_entries = status_ring->nentries;
942  
943  	if (!(CE_ATTR_DISABLE_INTR & attr->flags)) {
944  		ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params);
945  		ce_status_ring_config_int_threshold(scn, &ring_params);
946  	}
947  
948  	status_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_DST_STATUS,
949  					       ce_id, 0, &ring_params, 0);
950  }
951  
ce_ring_setup_srng(struct hif_softc * scn,uint8_t ring_type,uint32_t ce_id,struct CE_ring_state * ring,struct CE_attr * attr)952  static int ce_ring_setup_srng(struct hif_softc *scn, uint8_t ring_type,
953  		uint32_t ce_id, struct CE_ring_state *ring,
954  		struct CE_attr *attr)
955  {
956  	switch (ring_type) {
957  	case CE_RING_SRC:
958  		ce_srng_src_ring_setup(scn, ce_id, ring, attr);
959  		break;
960  	case CE_RING_DEST:
961  		ce_srng_dest_ring_setup(scn, ce_id, ring, attr);
962  		break;
963  	case CE_RING_STATUS:
964  		ce_srng_status_ring_setup(scn, ce_id, ring, attr);
965  		break;
966  	default:
967  		qdf_assert(0);
968  		break;
969  	}
970  
971  	return 0;
972  }
973  
ce_ring_cleanup_srng(struct hif_softc * scn,struct CE_state * CE_state,uint8_t ring_type)974  static void ce_ring_cleanup_srng(struct hif_softc *scn,
975  				 struct CE_state *CE_state,
976  				 uint8_t ring_type)
977  {
978  	hal_ring_handle_t hal_srng = NULL;
979  
980  	switch (ring_type) {
981  	case CE_RING_SRC:
982  		hal_srng = (hal_ring_handle_t)CE_state->src_ring->srng_ctx;
983  	break;
984  	case CE_RING_DEST:
985  		hal_srng = (hal_ring_handle_t)CE_state->dest_ring->srng_ctx;
986  	break;
987  	case CE_RING_STATUS:
988  		hal_srng = (hal_ring_handle_t)CE_state->status_ring->srng_ctx;
989  	break;
990  	}
991  
992  	if (hal_srng)
993  		hal_srng_cleanup(scn->hal_soc, hal_srng, 0);
994  }
995  
ce_construct_shadow_config_srng(struct hif_softc * scn)996  static void ce_construct_shadow_config_srng(struct hif_softc *scn)
997  {
998  	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
999  	int ce_id;
1000  
1001  	for (ce_id = 0; ce_id < scn->ce_count; ce_id++) {
1002  		if (hif_state->host_ce_config[ce_id].src_nentries)
1003  			hal_set_one_shadow_config(scn->hal_soc,
1004  						  CE_SRC, ce_id);
1005  
1006  		if (hif_state->host_ce_config[ce_id].dest_nentries) {
1007  			hal_set_one_shadow_config(scn->hal_soc,
1008  						  CE_DST, ce_id);
1009  
1010  			hal_set_one_shadow_config(scn->hal_soc,
1011  						  CE_DST_STATUS, ce_id);
1012  		}
1013  	}
1014  }
1015  
ce_prepare_shadow_register_v2_cfg_srng(struct hif_softc * scn,struct pld_shadow_reg_v2_cfg ** shadow_config,int * num_shadow_registers_configured)1016  static void ce_prepare_shadow_register_v2_cfg_srng(struct hif_softc *scn,
1017  		struct pld_shadow_reg_v2_cfg **shadow_config,
1018  		int *num_shadow_registers_configured)
1019  {
1020  	if (!scn->hal_soc) {
1021  		hif_err("hal not initialized: not initializing shadow config");
1022  		return;
1023  	}
1024  
1025  	hal_get_shadow_config(scn->hal_soc, shadow_config,
1026  			      num_shadow_registers_configured);
1027  
1028  	if (*num_shadow_registers_configured != 0) {
1029  		hif_err("hal shadow register configuration already constructed");
1030  
1031  		/* return with original configuration*/
1032  		return;
1033  	}
1034  	hal_construct_srng_shadow_regs(scn->hal_soc);
1035  	ce_construct_shadow_config_srng(scn);
1036  	hal_set_shadow_regs(scn->hal_soc);
1037  	hal_construct_shadow_regs(scn->hal_soc);
1038  	/* get updated configuration */
1039  	hal_get_shadow_config(scn->hal_soc, shadow_config,
1040  			      num_shadow_registers_configured);
1041  }
1042  
1043  #ifdef CONFIG_SHADOW_V3
ce_prepare_shadow_register_v3_cfg_srng(struct hif_softc * scn,struct pld_shadow_reg_v3_cfg ** shadow_config,int * num_shadow_registers_configured)1044  static void ce_prepare_shadow_register_v3_cfg_srng(struct hif_softc *scn,
1045  		struct pld_shadow_reg_v3_cfg **shadow_config,
1046  		int *num_shadow_registers_configured)
1047  {
1048  	if (!scn->hal_soc) {
1049  		hif_err("hal not initialized: not initializing shadow config");
1050  		return;
1051  	}
1052  
1053  	hal_get_shadow_v3_config(scn->hal_soc, shadow_config,
1054  				 num_shadow_registers_configured);
1055  
1056  	if (*num_shadow_registers_configured != 0) {
1057  		hif_err("hal shadow register configuration already constructed");
1058  
1059  		/* return with original configuration*/
1060  		return;
1061  	}
1062  	hal_construct_srng_shadow_regs(scn->hal_soc);
1063  	ce_construct_shadow_config_srng(scn);
1064  	hal_set_shadow_regs(scn->hal_soc);
1065  	hal_construct_shadow_regs(scn->hal_soc);
1066  	/* get updated configuration */
1067  	hal_get_shadow_v3_config(scn->hal_soc, shadow_config,
1068  				 num_shadow_registers_configured);
1069  }
1070  #endif
1071  
1072  #ifdef HIF_CE_LOG_INFO
1073  /**
1074   * ce_get_index_info_srng(): Get CE index info
1075   * @scn: HIF Context
1076   * @ce_state: CE opaque handle
1077   * @info: CE info
1078   *
1079   * Return: 0 for success and non zero for failure
1080   */
1081  static
ce_get_index_info_srng(struct hif_softc * scn,void * ce_state,struct ce_index * info)1082  int ce_get_index_info_srng(struct hif_softc *scn, void *ce_state,
1083  			   struct ce_index *info)
1084  {
1085  	struct CE_state *CE_state = (struct CE_state *)ce_state;
1086  	uint32_t tp, hp;
1087  
1088  	info->id = CE_state->id;
1089  	if (CE_state->src_ring) {
1090  		hal_get_sw_hptp(scn->hal_soc, CE_state->src_ring->srng_ctx,
1091  				&tp, &hp);
1092  		info->u.srng_info.tp = tp;
1093  		info->u.srng_info.hp = hp;
1094  	} else if (CE_state->dest_ring && CE_state->status_ring) {
1095  		hal_get_sw_hptp(scn->hal_soc, CE_state->status_ring->srng_ctx,
1096  				&tp, &hp);
1097  		info->u.srng_info.status_tp = tp;
1098  		info->u.srng_info.status_hp = hp;
1099  		hal_get_sw_hptp(scn->hal_soc, CE_state->dest_ring->srng_ctx,
1100  				&tp, &hp);
1101  		info->u.srng_info.tp = tp;
1102  		info->u.srng_info.hp = hp;
1103  	}
1104  
1105  	return 0;
1106  }
1107  #endif
1108  
1109  #ifdef FEATURE_DIRECT_LINK
1110  /**
1111   * ce_set_srng_msi_irq_config_by_ceid(): Set srng MSI irq configuration for CE
1112   *  given by id
1113   * @scn: HIF Context
1114   * @ce_id:
1115   * @addr:
1116   * @data:
1117   *
1118   * Return: 0 for success and non zero for failure
1119   */
1120  static QDF_STATUS
ce_set_srng_msi_irq_config_by_ceid(struct hif_softc * scn,uint8_t ce_id,uint64_t addr,uint32_t data)1121  ce_set_srng_msi_irq_config_by_ceid(struct hif_softc *scn, uint8_t ce_id,
1122  				   uint64_t addr, uint32_t data)
1123  {
1124  	struct CE_state *ce_state;
1125  	hal_ring_handle_t ring_hdl;
1126  	struct hal_srng_params ring_params = {0};
1127  
1128  	ce_state = scn->ce_id_to_state[ce_id];
1129  	if (!ce_state)
1130  		return QDF_STATUS_E_NOSUPPORT;
1131  
1132  	ring_params.msi_addr = addr;
1133  	ring_params.msi_data = data;
1134  
1135  	if (ce_state->src_ring) {
1136  		ring_hdl = ce_state->src_ring->srng_ctx;
1137  
1138  		ring_params.intr_timer_thres_us = 0;
1139  		ring_params.intr_batch_cntr_thres_entries = 1;
1140  		ring_params.prefetch_timer = HAL_SRNG_PREFETCH_TIMER;
1141  	} else if (ce_state->dest_ring) {
1142  		ring_hdl = ce_state->status_ring->srng_ctx;
1143  
1144  		ce_status_ring_config_int_threshold(scn, &ring_params);
1145  
1146  		hal_srng_set_msi_irq_config(scn->hal_soc, ring_hdl,
1147  					    &ring_params);
1148  
1149  		if (ce_is_status_ring_timer_thresh_war_needed()) {
1150  			ce_srng_initialize_dest_timer_interrupt_war(
1151  					ce_state->dest_ring, &ring_params);
1152  		} else {
1153  			ce_srng_initialize_dest_ring_thresh(ce_state->dest_ring,
1154  							    &ring_params);
1155  		}
1156  		ring_params.prefetch_timer = HAL_SRNG_PREFETCH_TIMER;
1157  		ring_hdl = ce_state->dest_ring->srng_ctx;
1158  	} else {
1159  		return QDF_STATUS_E_FAILURE;
1160  	}
1161  
1162  	hal_srng_set_msi_irq_config(scn->hal_soc, ring_hdl, &ring_params);
1163  
1164  	return QDF_STATUS_SUCCESS;
1165  }
1166  
1167  static
ce_get_direct_link_dest_srng_buffers(struct hif_softc * scn,uint64_t ** dma_addr,uint32_t * buf_size)1168  uint16_t ce_get_direct_link_dest_srng_buffers(struct hif_softc *scn,
1169  					      uint64_t **dma_addr,
1170  					      uint32_t *buf_size)
1171  {
1172  	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
1173  	struct CE_state *ce_state;
1174  	struct service_to_pipe *tgt_svc_cfg;
1175  	uint64_t *dma_addr_arr = NULL;
1176  	uint32_t i;
1177  	uint32_t j = 0;
1178  
1179  	tgt_svc_cfg = hif_state->tgt_svc_map;
1180  
1181  	for (i = 0; i < hif_state->sz_tgt_svc_map; i++) {
1182  		if (tgt_svc_cfg[i].service_id != LPASS_DATA_MSG_SVC ||
1183  		    tgt_svc_cfg[i].pipedir != PIPEDIR_IN)
1184  			continue;
1185  
1186  		ce_state = scn->ce_id_to_state[tgt_svc_cfg[i].pipenum];
1187  		if (!ce_state || !ce_state->dest_ring) {
1188  			hif_err("Direct Link CE pipe %d not initialized",
1189  				tgt_svc_cfg[i].pipenum);
1190  			return QDF_STATUS_E_FAILURE;
1191  		}
1192  
1193  		QDF_ASSERT(scn->dl_recv_pages.dma_pages);
1194  
1195  		dma_addr_arr = qdf_mem_malloc(sizeof(*dma_addr_arr) *
1196  					      scn->dl_recv_pages.num_pages);
1197  		if (!dma_addr_arr)
1198  			return 0;
1199  
1200  		for (j = 0; j < scn->dl_recv_pages.num_pages; j++)
1201  			dma_addr_arr[j] =
1202  				scn->dl_recv_pages.dma_pages[j].page_p_addr;
1203  
1204  		*buf_size = ce_state->src_sz_max;
1205  
1206  		break;
1207  	}
1208  
1209  	*dma_addr = dma_addr_arr;
1210  
1211  	return j;
1212  }
1213  
1214  /**
1215   * ce_save_srng_info() - Get and save srng information
1216   * @hif_ctx: hif context
1217   * @srng_info: Direct Link CE srng information
1218   * @srng_ctx: Direct Link CE srng context
1219   *
1220   * Return: QDF status
1221   */
1222  static void
ce_save_srng_info(struct hif_softc * hif_ctx,struct hif_ce_ring_info * srng_info,void * srng_ctx)1223  ce_save_srng_info(struct hif_softc *hif_ctx, struct hif_ce_ring_info *srng_info,
1224  		  void *srng_ctx)
1225  {
1226  	struct hal_srng_params params;
1227  
1228  	hal_get_srng_params(hif_ctx->hal_soc, srng_ctx, &params);
1229  
1230  	srng_info->ring_id = params.ring_id;
1231  	srng_info->ring_dir = params.ring_dir;
1232  	srng_info->num_entries = params.num_entries;
1233  	srng_info->entry_size = params.entry_size;
1234  	srng_info->ring_base_paddr = params.ring_base_paddr;
1235  	srng_info->hp_paddr =
1236  		      hal_srng_get_hp_addr(hif_ctx->hal_soc, srng_ctx);
1237  	srng_info->tp_paddr =
1238  		      hal_srng_get_tp_addr(hif_ctx->hal_soc, srng_ctx);
1239  }
1240  
1241  static
ce_get_direct_link_srng_info(struct hif_softc * scn,struct hif_direct_link_ce_info * info,uint8_t max_ce_info_len)1242  QDF_STATUS ce_get_direct_link_srng_info(struct hif_softc *scn,
1243  					struct hif_direct_link_ce_info *info,
1244  					uint8_t max_ce_info_len)
1245  {
1246  	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
1247  	struct CE_state *ce_state;
1248  	struct service_to_pipe *tgt_svc_cfg;
1249  	uint8_t ce_info_idx = 0;
1250  	uint32_t i;
1251  
1252  	tgt_svc_cfg = hif_state->tgt_svc_map;
1253  
1254  	for (i = 0; i < hif_state->sz_tgt_svc_map; i++) {
1255  		if (tgt_svc_cfg[i].service_id != LPASS_DATA_MSG_SVC)
1256  			continue;
1257  
1258  		ce_state = scn->ce_id_to_state[tgt_svc_cfg[i].pipenum];
1259  		if (!ce_state) {
1260  			hif_err("Direct Link CE pipe %d not initialized",
1261  				tgt_svc_cfg[i].pipenum);
1262  			return QDF_STATUS_E_FAILURE;
1263  		}
1264  
1265  		if (ce_info_idx > max_ce_info_len)
1266  			return QDF_STATUS_E_FAILURE;
1267  
1268  		info[ce_info_idx].ce_id = ce_state->id;
1269  		info[ce_info_idx].pipe_dir = tgt_svc_cfg[i].pipedir;
1270  
1271  		if (ce_state->src_ring)
1272  			ce_save_srng_info(scn, &info[ce_info_idx].ring_info,
1273  					  ce_state->src_ring->srng_ctx);
1274  		else
1275  			ce_save_srng_info(scn, &info[ce_info_idx].ring_info,
1276  					  ce_state->dest_ring->srng_ctx);
1277  
1278  		ce_info_idx++;
1279  
1280  		if (!ce_state->status_ring)
1281  			continue;
1282  
1283  		if (ce_info_idx > max_ce_info_len)
1284  			return QDF_STATUS_E_FAILURE;
1285  
1286  		info[ce_info_idx].ce_id = ce_state->id;
1287  		info[ce_info_idx].pipe_dir = tgt_svc_cfg[i].pipedir;
1288  
1289  		ce_save_srng_info(scn, &info[ce_info_idx].ring_info,
1290  				  ce_state->status_ring->srng_ctx);
1291  		ce_info_idx++;
1292  	}
1293  
1294  	return QDF_STATUS_SUCCESS;
1295  }
1296  #endif
1297  
1298  static struct ce_ops ce_service_srng = {
1299  	.ce_get_desc_size = ce_get_desc_size_srng,
1300  	.ce_ring_setup = ce_ring_setup_srng,
1301  	.ce_srng_cleanup = ce_ring_cleanup_srng,
1302  	.ce_sendlist_send = ce_sendlist_send_srng,
1303  	.ce_completed_recv_next_nolock = ce_completed_recv_next_nolock_srng,
1304  	.ce_revoke_recv_next = ce_revoke_recv_next_srng,
1305  	.ce_cancel_send_next = ce_cancel_send_next_srng,
1306  	.ce_recv_buf_enqueue = ce_recv_buf_enqueue_srng,
1307  	.ce_per_engine_handler_adjust = ce_per_engine_handler_adjust_srng,
1308  	.ce_send_nolock = ce_send_nolock_srng,
1309  	.watermark_int = ce_check_int_watermark_srng,
1310  	.ce_completed_send_next_nolock = ce_completed_send_next_nolock_srng,
1311  	.ce_recv_entries_done_nolock = ce_recv_entries_done_nolock_srng,
1312  	.ce_send_entries_done_nolock = ce_send_entries_done_nolock_srng,
1313  	.ce_prepare_shadow_register_v2_cfg =
1314  		ce_prepare_shadow_register_v2_cfg_srng,
1315  #ifdef CONFIG_SHADOW_V3
1316  	.ce_prepare_shadow_register_v3_cfg =
1317  		ce_prepare_shadow_register_v3_cfg_srng,
1318  #endif
1319  #ifdef HIF_CE_LOG_INFO
1320  	.ce_get_index_info =
1321  		ce_get_index_info_srng,
1322  #endif
1323  #ifdef FEATURE_DIRECT_LINK
1324  	.ce_set_irq_config_by_ceid = ce_set_srng_msi_irq_config_by_ceid,
1325  	.ce_get_direct_link_dest_buffers = ce_get_direct_link_dest_srng_buffers,
1326  	.ce_get_direct_link_ring_info = ce_get_direct_link_srng_info,
1327  #endif
1328  };
1329  
ce_services_srng(void)1330  struct ce_ops *ce_services_srng(void)
1331  {
1332  	return &ce_service_srng;
1333  }
1334  qdf_export_symbol(ce_services_srng);
1335  
ce_service_srng_init(void)1336  void ce_service_srng_init(void)
1337  {
1338  	ce_service_register_module(CE_SVC_SRNG, &ce_services_srng);
1339  }
1340