1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2020 Marvell International Ltd.
4  */
5 
6 #ifndef __CVMX_HELPER_UTIL_H__
7 #define __CVMX_HELPER_UTIL_H__
8 
9 #include "cvmx-mio-defs.h"
10 #include "cvmx-helper.h"
11 #include "cvmx-fpa.h"
12 
13 typedef char cvmx_pknd_t;
14 typedef char cvmx_bpid_t;
15 
16 #define CVMX_INVALID_PKND ((cvmx_pknd_t)-1)
17 #define CVMX_INVALID_BPID ((cvmx_bpid_t)-1)
18 #define CVMX_MAX_PKND	  ((cvmx_pknd_t)64)
19 #define CVMX_MAX_BPID	  ((cvmx_bpid_t)64)
20 
21 #define CVMX_HELPER_MAX_IFACE 11
22 #define CVMX_HELPER_MAX_PORTS 16
23 
24 /* Maximum range for normalized (a.k.a. IPD) port numbers (12-bit field) */
25 #define CVMX_PKO3_IPD_NUM_MAX 0x1000 //FIXME- take it from someplace else ?
26 #define CVMX_PKO3_DQ_NUM_MAX  0x400  // 78xx has 1024 queues
27 
28 #define CVMX_PKO3_IPD_PORT_NULL (CVMX_PKO3_IPD_NUM_MAX - 1)
29 #define CVMX_PKO3_IPD_PORT_LOOP 0
30 
31 struct cvmx_xport {
32 	int node;
33 	int port;
34 };
35 
36 typedef struct cvmx_xport cvmx_xport_t;
37 
cvmx_helper_ipd_port_to_xport(int ipd_port)38 static inline struct cvmx_xport cvmx_helper_ipd_port_to_xport(int ipd_port)
39 {
40 	struct cvmx_xport r;
41 
42 	r.port = ipd_port & (CVMX_PKO3_IPD_NUM_MAX - 1);
43 	r.node = (ipd_port >> 12) & CVMX_NODE_MASK;
44 	return r;
45 }
46 
cvmx_helper_node_to_ipd_port(int node,int index)47 static inline int cvmx_helper_node_to_ipd_port(int node, int index)
48 {
49 	return (node << 12) + index;
50 }
51 
52 struct cvmx_xdq {
53 	int node;
54 	int queue;
55 };
56 
57 typedef struct cvmx_xdq cvmx_xdq_t;
58 
cvmx_helper_queue_to_xdq(int queue)59 static inline struct cvmx_xdq cvmx_helper_queue_to_xdq(int queue)
60 {
61 	struct cvmx_xdq r;
62 
63 	r.queue = queue & (CVMX_PKO3_DQ_NUM_MAX - 1);
64 	r.node = (queue >> 10) & CVMX_NODE_MASK;
65 	return r;
66 }
67 
cvmx_helper_node_to_dq(int node,int queue)68 static inline int cvmx_helper_node_to_dq(int node, int queue)
69 {
70 	return (node << 10) + queue;
71 }
72 
73 struct cvmx_xiface {
74 	int node;
75 	int interface;
76 };
77 
78 typedef struct cvmx_xiface cvmx_xiface_t;
79 
80 /**
81  * Return node and interface number from XIFACE.
82  *
83  * @param xiface interface with node information
84  *
85  * @return struct that contains node and interface number.
86  */
cvmx_helper_xiface_to_node_interface(int xiface)87 static inline struct cvmx_xiface cvmx_helper_xiface_to_node_interface(int xiface)
88 {
89 	cvmx_xiface_t interface_node;
90 
91 	/*
92 	 * If the majic number 0xde0000 is not present in the
93 	 * interface, then assume it is node 0.
94 	 */
95 
96 	if (((xiface >> 0x8) & 0xff) == 0xde) {
97 		interface_node.node = (xiface >> 16) & CVMX_NODE_MASK;
98 		interface_node.interface = xiface & 0xff;
99 	} else {
100 		interface_node.node = cvmx_get_node_num();
101 		interface_node.interface = xiface & 0xff;
102 	}
103 	return interface_node;
104 }
105 
106 /* Used internally only*/
__cvmx_helper_xiface_is_null(int xiface)107 static inline bool __cvmx_helper_xiface_is_null(int xiface)
108 {
109 	return (xiface & 0xff) == 0xff;
110 }
111 
112 #define __CVMX_XIFACE_NULL 0xff
113 
114 /**
115  * Return interface with majic number and node information (XIFACE)
116  *
117  * @param node       node of the interface referred to
118  * @param interface  interface to use.
119  *
120  * @return
121  */
cvmx_helper_node_interface_to_xiface(int node,int interface)122 static inline int cvmx_helper_node_interface_to_xiface(int node, int interface)
123 {
124 	return ((node & CVMX_NODE_MASK) << 16) | (0xde << 8) | (interface & 0xff);
125 }
126 
127 /**
128  * Free the pip packet buffers contained in a work queue entry.
129  * The work queue entry is not freed.
130  *
131  * @param work   Work queue entry with packet to free
132  */
cvmx_helper_free_pip_pkt_data(cvmx_wqe_t * work)133 static inline void cvmx_helper_free_pip_pkt_data(cvmx_wqe_t *work)
134 {
135 	u64 number_buffers;
136 	cvmx_buf_ptr_t buffer_ptr;
137 	cvmx_buf_ptr_t next_buffer_ptr;
138 	u64 start_of_buffer;
139 
140 	number_buffers = work->word2.s.bufs;
141 	if (number_buffers == 0)
142 		return;
143 
144 	buffer_ptr = work->packet_ptr;
145 
146 	/* Since the number of buffers is not zero, we know this is not a dynamic
147 	   short packet. We need to check if it is a packet received with
148 	   IPD_CTL_STATUS[NO_WPTR]. If this is true, we need to free all buffers
149 	   except for the first one. The caller doesn't expect their WQE pointer
150 	   to be freed */
151 	start_of_buffer = ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7;
152 	if (cvmx_ptr_to_phys(work) == start_of_buffer) {
153 		next_buffer_ptr = *(cvmx_buf_ptr_t *)cvmx_phys_to_ptr(buffer_ptr.s.addr - 8);
154 		buffer_ptr = next_buffer_ptr;
155 		number_buffers--;
156 	}
157 
158 	while (number_buffers--) {
159 		/* Remember the back pointer is in cache lines, not 64bit words */
160 		start_of_buffer = ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7;
161 		/* Read pointer to next buffer before we free the current buffer. */
162 		next_buffer_ptr = *(cvmx_buf_ptr_t *)cvmx_phys_to_ptr(buffer_ptr.s.addr - 8);
163 		cvmx_fpa_free(cvmx_phys_to_ptr(start_of_buffer), buffer_ptr.s.pool, 0);
164 		buffer_ptr = next_buffer_ptr;
165 	}
166 }
167 
168 /**
169  * Free the pki packet buffers contained in a work queue entry.
170  * If first packet buffer contains wqe, wqe gets freed too so do not access
171  * wqe after calling this function.
172  * This function asssumes that buffers to be freed are from
173  * Naturally aligned pool/aura.
174  * It does not use don't write back.
175  * @param work   Work queue entry with packet to free
176  */
cvmx_helper_free_pki_pkt_data(cvmx_wqe_t * work)177 static inline void cvmx_helper_free_pki_pkt_data(cvmx_wqe_t *work)
178 {
179 	u64 number_buffers;
180 	u64 start_of_buffer;
181 	cvmx_buf_ptr_pki_t next_buffer_ptr;
182 	cvmx_buf_ptr_pki_t buffer_ptr;
183 	cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
184 
185 	if (!octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
186 		return;
187 	}
188 	/* Make sure errata pki-20776 has been applied*/
189 	cvmx_wqe_pki_errata_20776(work);
190 	buffer_ptr = wqe->packet_ptr;
191 	number_buffers = cvmx_wqe_get_bufs(work);
192 
193 	while (number_buffers--) {
194 		/* FIXME: change WQE function prototype */
195 		unsigned int x = cvmx_wqe_get_aura(work);
196 		cvmx_fpa3_gaura_t aura = __cvmx_fpa3_gaura(x >> 10, x & 0x3ff);
197 		/* XXX- assumes the buffer is cache-line aligned and naturally aligned mode*/
198 		start_of_buffer = (buffer_ptr.addr >> 7) << 7;
199 		/* Read pointer to next buffer before we free the current buffer. */
200 		next_buffer_ptr = *(cvmx_buf_ptr_pki_t *)cvmx_phys_to_ptr(buffer_ptr.addr - 8);
201 		/* FPA AURA comes from WQE, includes node */
202 		cvmx_fpa3_free(cvmx_phys_to_ptr(start_of_buffer), aura, 0);
203 		buffer_ptr = next_buffer_ptr;
204 	}
205 }
206 
207 /**
208  * Free the pki wqe entry buffer.
209  * If wqe buffers contains first packet buffer, wqe does not get freed here.
210  * This function asssumes that buffers to be freed are from
211  * Naturally aligned pool/aura.
212  * It does not use don't write back.
213  * @param work   Work queue entry to free
214  */
cvmx_wqe_pki_free(cvmx_wqe_t * work)215 static inline void cvmx_wqe_pki_free(cvmx_wqe_t *work)
216 {
217 	cvmx_wqe_78xx_t *wqe = (cvmx_wqe_78xx_t *)work;
218 	unsigned int x;
219 	cvmx_fpa3_gaura_t aura;
220 
221 	if (!octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
222 		return;
223 	}
224 	/* Do nothing if the first packet buffer shares WQE buffer */
225 	if (!wqe->packet_ptr.packet_outside_wqe)
226 		return;
227 
228 	/* FIXME change WQE function prototype */
229 	x = cvmx_wqe_get_aura(work);
230 	aura = __cvmx_fpa3_gaura(x >> 10, x & 0x3ff);
231 
232 	cvmx_fpa3_free(work, aura, 0);
233 }
234 
235 /**
236  * Convert a interface mode into a human readable string
237  *
238  * @param mode   Mode to convert
239  *
240  * @return String
241  */
242 const char *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t mode);
243 
244 /**
245  * Debug routine to dump the packet structure to the console
246  *
247  * @param work   Work queue entry containing the packet to dump
248  * @return
249  */
250 int cvmx_helper_dump_packet(cvmx_wqe_t *work);
251 
252 /**
253  * Get the version of the CVMX libraries.
254  *
255  * @return Version string. Note this buffer is allocated statically
256  *         and will be shared by all callers.
257  */
258 const char *cvmx_helper_get_version(void);
259 
260 /**
261  * @INTERNAL
262  * Setup the common GMX settings that determine the number of
263  * ports. These setting apply to almost all configurations of all
264  * chips.
265  *
266  * @param xiface Interface to configure
267  * @param num_ports Number of ports on the interface
268  *
269  * @return Zero on success, negative on failure
270  */
271 int __cvmx_helper_setup_gmx(int xiface, int num_ports);
272 
273 /**
274  * @INTERNAL
275  * Get the number of pko_ports on an interface.
276  *
277  * @param interface
278  *
279  * @return the number of pko_ports on the interface.
280  */
281 int __cvmx_helper_get_num_pko_ports(int interface);
282 
283 /**
284  * Returns the IPD port number for a port on the given
285  * interface.
286  *
287  * @param interface Interface to use
288  * @param port      Port on the interface
289  *
290  * @return IPD port number
291  */
292 int cvmx_helper_get_ipd_port(int interface, int port);
293 
294 /**
295  * Returns the PKO port number for a port on the given interface,
296  * This is the base pko_port for o68 and ipd_port for older models.
297  *
298  * @param interface Interface to use
299  * @param port      Port on the interface
300  *
301  * @return PKO port number and -1 on error.
302  */
303 int cvmx_helper_get_pko_port(int interface, int port);
304 
305 /**
306  * Returns the IPD/PKO port number for the first port on the given
307  * interface.
308  *
309  * @param interface Interface to use
310  *
311  * @return IPD/PKO port number
312  */
cvmx_helper_get_first_ipd_port(int interface)313 static inline int cvmx_helper_get_first_ipd_port(int interface)
314 {
315 	return cvmx_helper_get_ipd_port(interface, 0);
316 }
317 
318 int cvmx_helper_ports_on_interface(int interface);
319 
320 /**
321  * Returns the IPD/PKO port number for the last port on the given
322  * interface.
323  *
324  * @param interface Interface to use
325  *
326  * @return IPD/PKO port number
327  *
328  * Note: for o68, the last ipd port on an interface does not always equal to
329  * the first plus the number of ports as the ipd ports are not contiguous in
330  * some cases, e.g., SGMII.
331  *
332  * Note: code that makes the assumption of contiguous ipd port numbers needs to
333  * be aware of this.
334  */
cvmx_helper_get_last_ipd_port(int interface)335 static inline int cvmx_helper_get_last_ipd_port(int interface)
336 {
337 	return cvmx_helper_get_ipd_port(interface, cvmx_helper_ports_on_interface(interface) - 1);
338 }
339 
340 /**
341  * Free the packet buffers contained in a work queue entry.
342  * The work queue entry is not freed.
343  * Note that this function will not free the work queue entry
344  * even if it contains a non-redundant data packet, and hence
345  * it is not really comparable to how the PKO would free a packet
346  * buffers if requested.
347  *
348  * @param work   Work queue entry with packet to free
349  */
350 void cvmx_helper_free_packet_data(cvmx_wqe_t *work);
351 
352 /**
353  * Returns the interface number for an IPD/PKO port number.
354  *
355  * @param ipd_port IPD/PKO port number
356  *
357  * @return Interface number
358  */
359 int cvmx_helper_get_interface_num(int ipd_port);
360 
361 /**
362  * Returns the interface index number for an IPD/PKO port
363  * number.
364  *
365  * @param ipd_port IPD/PKO port number
366  *
367  * @return Interface index number
368  */
369 int cvmx_helper_get_interface_index_num(int ipd_port);
370 
371 /**
372  * Get port kind for a given port in an interface.
373  *
374  * @param xiface  Interface
375  * @param index   index of the port in the interface
376  *
377  * @return port kind on sucicess  and -1 on failure
378  */
379 int cvmx_helper_get_pknd(int xiface, int index);
380 
381 /**
382  * Get bpid for a given port in an interface.
383  *
384  * @param interface  Interface
385  * @param port       index of the port in the interface
386  *
387  * @return port kind on sucicess  and -1 on failure
388  */
389 int cvmx_helper_get_bpid(int interface, int port);
390 
391 /**
392  * Internal functions.
393  */
394 int __cvmx_helper_post_init_interfaces(void);
395 int cvmx_helper_setup_red(int pass_thresh, int drop_thresh);
396 void cvmx_helper_show_stats(int port);
397 
398 /*
399  * Return number of array alements
400  */
401 #define NUM_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0]))
402 
403 /**
404  * Prints out a buffer with the address, hex bytes, and ASCII
405  *
406  * @param	addr	Start address to print on the left
407  * @param[in]	buffer	array of bytes to print
408  * @param	count	Number of bytes to print
409  */
410 void cvmx_print_buffer_u8(unsigned int addr, const u8 *buffer, size_t count);
411 
412 #endif /* __CVMX_HELPER_H__ */
413