1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2018-2022 Marvell International Ltd.
4  *
5  * PKOv3 helper file
6  */
7 
8 #include <errno.h>
9 #include <log.h>
10 #include <time.h>
11 #include <linux/delay.h>
12 
13 #include <mach/cvmx-regs.h>
14 #include <mach/cvmx-csr.h>
15 #include <mach/cvmx-bootmem.h>
16 #include <mach/octeon-model.h>
17 #include <mach/cvmx-fuse.h>
18 #include <mach/octeon-feature.h>
19 #include <mach/cvmx-qlm.h>
20 #include <mach/octeon_qlm.h>
21 #include <mach/cvmx-pcie.h>
22 #include <mach/cvmx-coremask.h>
23 #include <mach/cvmx-range.h>
24 #include <mach/cvmx-global-resources.h>
25 
26 #include <mach/cvmx-agl-defs.h>
27 #include <mach/cvmx-bgxx-defs.h>
28 #include <mach/cvmx-ciu-defs.h>
29 #include <mach/cvmx-gmxx-defs.h>
30 #include <mach/cvmx-gserx-defs.h>
31 #include <mach/cvmx-ilk-defs.h>
32 #include <mach/cvmx-ipd-defs.h>
33 #include <mach/cvmx-pcsx-defs.h>
34 #include <mach/cvmx-pcsxx-defs.h>
35 #include <mach/cvmx-pki-defs.h>
36 #include <mach/cvmx-pko-defs.h>
37 #include <mach/cvmx-xcv-defs.h>
38 
39 #include <mach/cvmx-hwpko.h>
40 #include <mach/cvmx-ilk.h>
41 #include <mach/cvmx-ipd.h>
42 #include <mach/cvmx-pki.h>
43 #include <mach/cvmx-pko3.h>
44 #include <mach/cvmx-pko3-queue.h>
45 #include <mach/cvmx-pko3-resources.h>
46 
47 #include <mach/cvmx-helper.h>
48 #include <mach/cvmx-helper-board.h>
49 #include <mach/cvmx-helper-cfg.h>
50 
51 #include <mach/cvmx-helper-bgx.h>
52 #include <mach/cvmx-helper-cfg.h>
53 #include <mach/cvmx-helper-util.h>
54 #include <mach/cvmx-helper-pki.h>
55 
56 /* channels are present at L2 queue level by default */
57 static const enum cvmx_pko3_level_e cvmx_pko_default_channel_level =
58 	CVMX_PKO_L2_QUEUES;
59 
60 static const int debug;
61 
62 static int __pko_pkt_budget, __pko_pkt_quota;
63 
64 /* These global variables are relevant for boot CPU only */
65 static cvmx_fpa3_gaura_t __cvmx_pko3_aura[CVMX_MAX_NODES];
66 
67 /* This constant can not be modified, defined here for clarity only */
68 #define CVMX_PKO3_POOL_BUFFER_SIZE 4096 /* 78XX PKO requires 4KB */
69 
70 /**
71  * @INTERNAL
72  *
73  * Build an owner tag based on interface/port
74  */
__cvmx_helper_pko3_res_owner(int ipd_port)75 static int __cvmx_helper_pko3_res_owner(int ipd_port)
76 {
77 	int res_owner;
78 	const int res_owner_pfix = 0x19d0 << 14;
79 
80 	ipd_port &= 0x3fff; /* 12-bit for local CHAN_E value + node */
81 
82 	res_owner = res_owner_pfix | ipd_port;
83 
84 	return res_owner;
85 }
86 
87 /**
88  * Configure an AURA/POOL designated for PKO internal use.
89  *
90  * This pool is used for (a) memory buffers that store PKO descriptor queues,
91  * (b) buffers for use with PKO_SEND_JUMP_S sub-header.
92  *
93  * The buffers of type (a) are never accessed by software, and their number
94  * should be at least equal to 4 times the number of descriptor queues
95  * in use.
96  *
97  * Type (b) buffers are consumed by PKO3 command-composition code,
98  * and are released by the hardware upon completion of transmission.
99  *
100  * @returns -1 if the pool could not be established or 12-bit AURA
101  * that includes the node number for use in PKO3 initialization call.
102  *
103  * NOTE: Linux kernel should pass its own aura to PKO3 initialization
104  * function so that the buffers can be mapped into kernel space
105  * for when software needs to adccess their contents.
106  *
107  */
__cvmx_pko3_config_memory(unsigned int node)108 static int __cvmx_pko3_config_memory(unsigned int node)
109 {
110 	cvmx_fpa3_gaura_t aura;
111 	int aura_num;
112 	unsigned int buf_count;
113 	bool small_mem;
114 	int i, num_intf = 0;
115 	const unsigned int pkt_per_buf =
116 		(CVMX_PKO3_POOL_BUFFER_SIZE / sizeof(u64) / 16);
117 	const unsigned int base_buf_count = 1024 * 4;
118 
119 	/* Simulator has limited memory, but uses one interface at a time */
120 	//	small_mem = cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM;
121 	small_mem = false;
122 
123 	/* Count the number of live interfaces */
124 	for (i = 0; i < cvmx_helper_get_number_of_interfaces(); i++) {
125 		int xiface = cvmx_helper_node_interface_to_xiface(node, i);
126 
127 		if (CVMX_HELPER_INTERFACE_MODE_DISABLED !=
128 		    cvmx_helper_interface_get_mode(xiface))
129 			num_intf++;
130 	}
131 
132 	buf_count = 1024;
133 	__pko_pkt_quota = buf_count * pkt_per_buf;
134 	__pko_pkt_budget = __pko_pkt_quota * num_intf;
135 	(void)small_mem;
136 	(void)base_buf_count;
137 
138 	if (debug)
139 		debug("%s: Creating AURA with %u buffers for up to %d total packets, %d packets per interface\n",
140 		      __func__, buf_count, __pko_pkt_budget, __pko_pkt_quota);
141 
142 	aura = cvmx_fpa3_setup_aura_and_pool(node, -1, "PKO3 AURA", NULL,
143 					     CVMX_PKO3_POOL_BUFFER_SIZE,
144 					     buf_count);
145 
146 	if (!__cvmx_fpa3_aura_valid(aura)) {
147 		printf("ERROR: %s AURA create failed\n", __func__);
148 		return -1;
149 	}
150 
151 	aura_num = aura.node << 10 | aura.laura;
152 
153 	/* Store handle for destruction */
154 	__cvmx_pko3_aura[node] = aura;
155 
156 	return aura_num;
157 }
158 
159 /** Initialize a channelized port
160  * This is intended for LOOP, ILK and NPI interfaces which have one MAC
161  * per interface and need a channel per subinterface (e.g. ring).
162  * Each channel then may have 'num_queues' descriptor queues
163  * attached to it, which can also be prioritized or fair.
164  */
__cvmx_pko3_config_chan_interface(int xiface,unsigned int num_chans,u8 num_queues,bool prioritized)165 static int __cvmx_pko3_config_chan_interface(int xiface, unsigned int num_chans,
166 					     u8 num_queues, bool prioritized)
167 {
168 	int l1_q_num;
169 	int l2_q_base;
170 	enum cvmx_pko3_level_e level;
171 	int res;
172 	int parent_q, child_q;
173 	unsigned int chan, dq;
174 	int pko_mac_num;
175 	u16 ipd_port;
176 	int res_owner, prio;
177 	unsigned int i;
178 	struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
179 	unsigned int node = xi.node;
180 	char b1[12];
181 
182 	if (num_queues == 0)
183 		num_queues = 1;
184 	if ((cvmx_pko3_num_level_queues(CVMX_PKO_DESCR_QUEUES) / num_chans) < 3)
185 		num_queues = 1;
186 
187 	if (prioritized && num_queues > 1)
188 		prio = num_queues;
189 	else
190 		prio = -1;
191 
192 	if (debug)
193 		debug("%s: configuring xiface %u:%u with %u chans %u queues each\n",
194 		      __func__, xi.node, xi.interface, num_chans, num_queues);
195 
196 	/* all channels all go to the same mac */
197 	pko_mac_num = __cvmx_pko3_get_mac_num(xiface, 0);
198 	if (pko_mac_num < 0) {
199 		printf("ERROR: %s: Invalid interface\n", __func__);
200 		return -1;
201 	}
202 
203 	/* Resources of all channels on this port have common owner */
204 	ipd_port = cvmx_helper_get_ipd_port(xiface, 0);
205 
206 	/* Build an identifiable owner */
207 	res_owner = __cvmx_helper_pko3_res_owner(ipd_port);
208 
209 	/* Start configuration at L1/PQ */
210 	level = CVMX_PKO_PORT_QUEUES;
211 
212 	/* Reserve port queue to make sure the MAC is not already configured */
213 	l1_q_num = cvmx_pko_alloc_queues(node, level, res_owner, -1, 1);
214 
215 	if (l1_q_num < 0) {
216 		printf("ERROR: %s: Reserving L1 PQ\n", __func__);
217 		return -1;
218 	}
219 
220 	res = cvmx_pko3_pq_config(node, pko_mac_num, l1_q_num);
221 	if (res < 0) {
222 		printf("ERROR: %s: Configuring L1 PQ\n", __func__);
223 		return -1;
224 	}
225 
226 	/* next queue level = L2/SQ */
227 	level = __cvmx_pko3_sq_lvl_next(level);
228 
229 	/* allocate level 2 queues, one per channel */
230 	l2_q_base =
231 		cvmx_pko_alloc_queues(node, level, res_owner, -1, num_chans);
232 	if (l2_q_base < 0) {
233 		printf("ERROR: %s: allocation L2 SQ\n", __func__);
234 		return -1;
235 	}
236 
237 	/* Configre <num_chans> L2 children for PQ, non-prioritized */
238 	res = cvmx_pko3_sq_config_children(node, level, l1_q_num, l2_q_base,
239 					   num_chans, -1);
240 
241 	if (res < 0) {
242 		printf("ERROR: %s: Failed channel queues\n", __func__);
243 		return -1;
244 	}
245 
246 	/* map channels to l2 queues */
247 	for (chan = 0; chan < num_chans; chan++) {
248 		ipd_port = cvmx_helper_get_ipd_port(xiface, chan);
249 		cvmx_pko3_map_channel(node, l1_q_num, l2_q_base + chan,
250 				      ipd_port);
251 	}
252 
253 	/* next queue level = L3/SQ */
254 	level = __cvmx_pko3_sq_lvl_next(level);
255 	parent_q = l2_q_base;
256 
257 	do {
258 		child_q = cvmx_pko_alloc_queues(node, level, res_owner, -1,
259 						num_chans);
260 
261 		if (child_q < 0) {
262 			printf("ERROR: %s: allocating %s\n", __func__,
263 			       __cvmx_pko3_sq_str(b1, level, child_q));
264 			return -1;
265 		}
266 
267 		for (i = 0; i < num_chans; i++) {
268 			res = cvmx_pko3_sq_config_children(
269 				node, level, parent_q + i, child_q + i, 1, 1);
270 
271 			if (res < 0) {
272 				printf("ERROR: %s: configuring %s\n", __func__,
273 				       __cvmx_pko3_sq_str(b1, level, child_q));
274 				return -1;
275 			}
276 
277 		} /* for i */
278 
279 		parent_q = child_q;
280 		level = __cvmx_pko3_sq_lvl_next(level);
281 
282 		/* Terminate loop on DQ level, it has special handling */
283 	} while (level != CVMX_PKO_DESCR_QUEUES &&
284 		 level != CVMX_PKO_LEVEL_INVAL);
285 
286 	if (level != CVMX_PKO_DESCR_QUEUES) {
287 		printf("ERROR: %s: level sequence error\n", __func__);
288 		return -1;
289 	}
290 
291 	/* Configure DQs, num_dqs per chan */
292 	for (chan = 0; chan < num_chans; chan++) {
293 		res = cvmx_pko_alloc_queues(node, level, res_owner, -1,
294 					    num_queues);
295 
296 		if (res < 0)
297 			goto _fail;
298 		dq = res;
299 
300 		if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0) && (dq & 7))
301 			debug("WARNING: %s: DQ# %u not integral of 8\n",
302 			      __func__, dq);
303 
304 		res = cvmx_pko3_sq_config_children(node, level, parent_q + chan,
305 						   dq, num_queues, prio);
306 		if (res < 0)
307 			goto _fail;
308 
309 		/* register DQ range with the translation table */
310 		res = __cvmx_pko3_ipd_dq_register(xiface, chan, dq, num_queues);
311 		if (res < 0)
312 			goto _fail;
313 	}
314 
315 	return 0;
316 _fail:
317 	debug("ERROR: %s: configuring queues for xiface %u:%u chan %u\n",
318 	      __func__, xi.node, xi.interface, i);
319 	return -1;
320 }
321 
322 /** Initialize a single Ethernet port with PFC-style channels
323  *
324  * One interface can contain multiple ports, this function is per-port
325  * Here, a physical port is allocated 8 logical channel, one per VLAN
326  * tag priority, one DQ is assigned to each channel, and all 8 DQs
327  * are registered for that IPD port.
328  * Note that the DQs are arrange such that the Ethernet QoS/PCP field
329  * can be used as an offset to the value returned by cvmx_pko_base_queue_get().
330  *
331  * For HighGig2 mode, 16 channels may be desired, instead of 8,
332  * but this function does not support that.
333  */
__cvmx_pko3_config_pfc_interface(int xiface,unsigned int port)334 static int __cvmx_pko3_config_pfc_interface(int xiface, unsigned int port)
335 {
336 	enum cvmx_pko3_level_e level;
337 	int pko_mac_num;
338 	int l1_q_num, l2_q_base;
339 	int child_q, parent_q;
340 	int dq_base;
341 	int res;
342 	const unsigned int num_chans = 8;
343 	cvmx_xiface_t xi = cvmx_helper_xiface_to_node_interface(xiface);
344 	unsigned int node = xi.node;
345 	u16 ipd_port;
346 	int res_owner;
347 	char b1[12];
348 	unsigned int i;
349 
350 	if (debug)
351 		debug("%s: configuring xiface %u:%u port %u with %u PFC channels\n",
352 		      __func__, node, xi.interface, port, num_chans);
353 
354 	/* Get MAC number for the iface/port */
355 	pko_mac_num = __cvmx_pko3_get_mac_num(xiface, port);
356 	if (pko_mac_num < 0) {
357 		printf("ERROR: %s: Invalid interface\n", __func__);
358 		return -1;
359 	}
360 
361 	ipd_port = cvmx_helper_get_ipd_port(xiface, port);
362 
363 	/* Build an identifiable owner identifier */
364 	res_owner = __cvmx_helper_pko3_res_owner(ipd_port);
365 
366 	level = CVMX_PKO_PORT_QUEUES;
367 
368 	/* Allocate port queue to make sure the MAC is not already configured */
369 	l1_q_num = cvmx_pko_alloc_queues(node, level, res_owner, -1, 1);
370 
371 	if (l1_q_num < 0) {
372 		printf("ERROR: %s: allocation L1 PQ\n", __func__);
373 		return -1;
374 	}
375 
376 	res = cvmx_pko3_pq_config(xi.node, pko_mac_num, l1_q_num);
377 	if (res < 0) {
378 		printf("ERROR: %s: Configuring %s\n", __func__,
379 		       __cvmx_pko3_sq_str(b1, level, l1_q_num));
380 		return -1;
381 	}
382 
383 	/* Determine the next queue level */
384 	level = __cvmx_pko3_sq_lvl_next(level);
385 
386 	/* Allocate 'num_chans' L2 queues, one per channel */
387 	l2_q_base =
388 		cvmx_pko_alloc_queues(node, level, res_owner, -1, num_chans);
389 	if (l2_q_base < 0) {
390 		printf("ERROR: %s: allocation L2 SQ\n", __func__);
391 		return -1;
392 	}
393 
394 	/* Configre <num_chans> L2 children for PQ, with static priority */
395 	res = cvmx_pko3_sq_config_children(node, level, l1_q_num, l2_q_base,
396 					   num_chans, num_chans);
397 
398 	if (res < 0) {
399 		printf("ERROR: %s: Configuring %s for PFC\n", __func__,
400 		       __cvmx_pko3_sq_str(b1, level, l1_q_num));
401 		return -1;
402 	}
403 
404 	/* Map each of the allocated channels */
405 	for (i = 0; i < num_chans; i++) {
406 		u16 chan;
407 
408 		/* Get CHAN_E value for this PFC channel, PCP in low 3 bits */
409 		chan = ipd_port | cvmx_helper_prio2qos(i);
410 
411 		cvmx_pko3_map_channel(node, l1_q_num, l2_q_base + i, chan);
412 	}
413 
414 	/* Iterate through the levels until DQ and allocate 'num_chans'
415 	 * consecutive queues at each level and hook them up
416 	 * one-to-one with the parent level queues
417 	 */
418 
419 	parent_q = l2_q_base;
420 	level = __cvmx_pko3_sq_lvl_next(level);
421 
422 	do {
423 		child_q = cvmx_pko_alloc_queues(node, level, res_owner, -1,
424 						num_chans);
425 
426 		if (child_q < 0) {
427 			printf("ERROR: %s: allocating %s\n", __func__,
428 			       __cvmx_pko3_sq_str(b1, level, child_q));
429 			return -1;
430 		}
431 
432 		for (i = 0; i < num_chans; i++) {
433 			res = cvmx_pko3_sq_config_children(
434 				node, level, parent_q + i, child_q + i, 1, 1);
435 
436 			if (res < 0) {
437 				printf("ERROR: %s: configuring %s\n", __func__,
438 				       __cvmx_pko3_sq_str(b1, level, child_q));
439 				return -1;
440 			}
441 
442 		} /* for i */
443 
444 		parent_q = child_q;
445 		level = __cvmx_pko3_sq_lvl_next(level);
446 
447 		/* Terminate loop on DQ level, it has special handling */
448 	} while (level != CVMX_PKO_DESCR_QUEUES &&
449 		 level != CVMX_PKO_LEVEL_INVAL);
450 
451 	if (level != CVMX_PKO_DESCR_QUEUES) {
452 		printf("ERROR: %s: level sequence error\n", __func__);
453 		return -1;
454 	}
455 
456 	dq_base = cvmx_pko_alloc_queues(node, level, res_owner, -1, num_chans);
457 	if (dq_base < 0) {
458 		printf("ERROR: %s: allocating %s\n", __func__,
459 		       __cvmx_pko3_sq_str(b1, level, dq_base));
460 		return -1;
461 	}
462 
463 	/* Configure DQs in QoS order, so that QoS/PCP can be index */
464 	for (i = 0; i < num_chans; i++) {
465 		int dq_num = dq_base + cvmx_helper_prio2qos(i);
466 
467 		res = cvmx_pko3_sq_config_children(node, level, parent_q + i,
468 						   dq_num, 1, 1);
469 		if (res < 0) {
470 			printf("ERROR: %s: configuring %s\n", __func__,
471 			       __cvmx_pko3_sq_str(b1, level, dq_num));
472 			return -1;
473 		}
474 	}
475 
476 	/* register entire DQ range with the IPD translation table */
477 	__cvmx_pko3_ipd_dq_register(xiface, port, dq_base, num_chans);
478 
479 	return 0;
480 }
481 
482 /**
483  * Initialize a simple interface with a a given number of
484  * fair or prioritized queues.
485  * This function will assign one channel per sub-interface.
486  */
__cvmx_pko3_config_gen_interface(int xiface,uint8_t subif,u8 num_queues,bool prioritized)487 int __cvmx_pko3_config_gen_interface(int xiface, uint8_t subif, u8 num_queues,
488 				     bool prioritized)
489 {
490 	cvmx_xiface_t xi = cvmx_helper_xiface_to_node_interface(xiface);
491 	u8 node = xi.node;
492 	int l1_q_num;
493 	int parent_q, child_q;
494 	int dq;
495 	int res, res_owner;
496 	int pko_mac_num;
497 	enum cvmx_pko3_level_e level;
498 	u16 ipd_port;
499 	int static_pri;
500 	char b1[12];
501 
502 	num_queues = 1;
503 
504 	if (num_queues == 0) {
505 		num_queues = 1;
506 		printf("WARNING: %s: xiface %#x misconfigured\n", __func__,
507 		       xiface);
508 	}
509 
510 	/* Configure DQs relative priority (a.k.a. scheduling) */
511 	if (prioritized) {
512 		/* With 8 queues or fewer, use static priority, else WRR */
513 		static_pri = (num_queues < 9) ? num_queues : 0;
514 	} else {
515 		/* Set equal-RR scheduling among queues */
516 		static_pri = -1;
517 	}
518 
519 	if (debug)
520 		debug("%s: configuring xiface %u:%u/%u nq=%u %s\n", __func__,
521 		      xi.node, xi.interface, subif, num_queues,
522 		      (prioritized) ? "qos" : "fair");
523 
524 	/* Get MAC number for the iface/port */
525 	pko_mac_num = __cvmx_pko3_get_mac_num(xiface, subif);
526 	if (pko_mac_num < 0) {
527 		printf("ERROR: %s: Invalid interface %u:%u\n", __func__,
528 		       xi.node, xi.interface);
529 		return -1;
530 	}
531 
532 	ipd_port = cvmx_helper_get_ipd_port(xiface, subif);
533 
534 	if (debug)
535 		debug("%s: xiface %u:%u/%u ipd_port=%#03x\n", __func__, xi.node,
536 		      xi.interface, subif, ipd_port);
537 
538 	/* Build an identifiable owner identifier */
539 	res_owner = __cvmx_helper_pko3_res_owner(ipd_port);
540 
541 	level = CVMX_PKO_PORT_QUEUES;
542 
543 	/* Reserve port queue to make sure the MAC is not already configured */
544 	l1_q_num = cvmx_pko_alloc_queues(node, level, res_owner, -1, 1);
545 
546 	if (l1_q_num < 0) {
547 		printf("ERROR %s: xiface %u:%u/%u failed allocation L1 PQ\n",
548 		       __func__, xi.node, xi.interface, subif);
549 		return -1;
550 	}
551 
552 	res = cvmx_pko3_pq_config(node, pko_mac_num, l1_q_num);
553 	if (res < 0) {
554 		printf("ERROR %s: Configuring L1 PQ\n", __func__);
555 		return -1;
556 	}
557 
558 	parent_q = l1_q_num;
559 
560 	/* Determine the next queue level */
561 	level = __cvmx_pko3_sq_lvl_next(level);
562 
563 	/* Simply chain queues 1-to-1 from L2 to one before DQ level */
564 	do {
565 		/* allocate next level queue */
566 		child_q = cvmx_pko_alloc_queues(node, level, res_owner, -1, 1);
567 
568 		if (child_q < 0) {
569 			printf("ERROR: %s: allocating %s\n", __func__,
570 			       __cvmx_pko3_sq_str(b1, level, child_q));
571 			return -1;
572 		}
573 
574 		/* Configre newly allocated queue */
575 		res = cvmx_pko3_sq_config_children(node, level, parent_q,
576 						   child_q, 1, 1);
577 
578 		if (res < 0) {
579 			printf("ERROR: %s: configuring %s\n", __func__,
580 			       __cvmx_pko3_sq_str(b1, level, child_q));
581 			return -1;
582 		}
583 
584 		/* map IPD/channel to L2/L3 queues */
585 		if (level == cvmx_pko_default_channel_level)
586 			cvmx_pko3_map_channel(node, l1_q_num, child_q,
587 					      ipd_port);
588 
589 		/* Prepare for next level */
590 		level = __cvmx_pko3_sq_lvl_next(level);
591 		parent_q = child_q;
592 
593 		/* Terminate loop on DQ level, it has special handling */
594 	} while (level != CVMX_PKO_DESCR_QUEUES &&
595 		 level != CVMX_PKO_LEVEL_INVAL);
596 
597 	if (level != CVMX_PKO_DESCR_QUEUES) {
598 		printf("ERROR: %s: level sequence error\n", __func__);
599 		return -1;
600 	}
601 
602 	/* Allocate descriptor queues for the port */
603 	dq = cvmx_pko_alloc_queues(node, level, res_owner, -1, num_queues);
604 	if (dq < 0) {
605 		printf("ERROR: %s: could not reserve DQs\n", __func__);
606 		return -1;
607 	}
608 
609 	res = cvmx_pko3_sq_config_children(node, level, parent_q, dq,
610 					   num_queues, static_pri);
611 	if (res < 0) {
612 		printf("ERROR: %s: configuring %s\n", __func__,
613 		       __cvmx_pko3_sq_str(b1, level, dq));
614 		return -1;
615 	}
616 
617 	/* register DQ/IPD translation */
618 	__cvmx_pko3_ipd_dq_register(xiface, subif, dq, num_queues);
619 
620 	if (debug)
621 		debug("%s: xiface %u:%u/%u qs %u-%u\n", __func__, xi.node,
622 		      xi.interface, subif, dq, dq + num_queues - 1);
623 	return 0;
624 }
625 
626 /** Initialize the NULL interface
627  *
628  * A NULL interface is a special case in that it is not
629  * one of the enumerated interfaces in the system, and does
630  * not apply to input either. Still, it can be very handy
631  * for dealing with packets that should be discarded in
632  * a generic, streamlined way.
633  *
634  * The Descriptor Queue 0 will be reserved for the NULL interface
635  * and the normalized (i.e. IPD) port number has the all-ones value.
636  */
__cvmx_pko3_config_null_interface(unsigned int node)637 static int __cvmx_pko3_config_null_interface(unsigned int node)
638 {
639 	int l1_q_num;
640 	int parent_q, child_q;
641 	enum cvmx_pko3_level_e level;
642 	int i, res, res_owner;
643 	int xiface, ipd_port;
644 	int num_dq = 1;	  /* # of DQs for NULL */
645 	const int dq = 0; /* Reserve DQ#0 for NULL */
646 	char pko_mac_num;
647 	char b1[12];
648 
649 	if (OCTEON_IS_MODEL(OCTEON_CN78XX))
650 		pko_mac_num = 0x1C; /* MAC# 28 virtual MAC for NULL */
651 	else if (OCTEON_IS_MODEL(OCTEON_CN73XX))
652 		pko_mac_num = 0x0F; /* MAC# 16 virtual MAC for NULL */
653 	else if (OCTEON_IS_MODEL(OCTEON_CNF75XX))
654 		pko_mac_num = 0x0A; /* MAC# 10 virtual MAC for NULL */
655 	else
656 		return -1;
657 
658 	if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0))
659 		num_dq = 8;
660 
661 	if (debug)
662 		debug("%s: null iface dq=%u-%u\n", __func__, dq,
663 		      dq + num_dq - 1);
664 
665 	ipd_port = cvmx_helper_node_to_ipd_port(node, CVMX_PKO3_IPD_PORT_NULL);
666 
667 	/* Build an identifiable owner identifier by MAC# for easy release */
668 	res_owner = __cvmx_helper_pko3_res_owner(ipd_port);
669 	if (res_owner < 0) {
670 		debug("%s: ERROR Invalid interface\n", __func__);
671 		return -1;
672 	}
673 
674 	level = CVMX_PKO_PORT_QUEUES;
675 
676 	/* Allocate a port queue */
677 	l1_q_num = cvmx_pko_alloc_queues(node, level, res_owner, -1, 1);
678 
679 	if (l1_q_num < 0) {
680 		debug("%s: ERROR reserving L1 SQ\n", __func__);
681 		return -1;
682 	}
683 
684 	res = cvmx_pko3_pq_config(node, pko_mac_num, l1_q_num);
685 	if (res < 0) {
686 		printf("ERROR: %s: PQ/L1 queue configuration\n", __func__);
687 		return -1;
688 	}
689 
690 	parent_q = l1_q_num;
691 
692 	/* Determine the next queue level */
693 	level = __cvmx_pko3_sq_lvl_next(level);
694 
695 	/* Simply chain queues 1-to-1 from L2 to one before DQ level */
696 	do {
697 		/* allocate next level queue */
698 		child_q = cvmx_pko_alloc_queues(node, level, res_owner, -1, 1);
699 
700 		if (child_q < 0) {
701 			printf("ERROR: %s: allocating %s\n", __func__,
702 			       __cvmx_pko3_sq_str(b1, level, child_q));
703 			return -1;
704 		}
705 
706 		/* Configre newly allocated queue */
707 		res = cvmx_pko3_sq_config_children(node, level, parent_q,
708 						   child_q, 1, 1);
709 
710 		if (res < 0) {
711 			printf("ERROR: %s: configuring %s\n", __func__,
712 			       __cvmx_pko3_sq_str(b1, level, child_q));
713 			return -1;
714 		}
715 
716 		/* Prepare for next level */
717 		level = __cvmx_pko3_sq_lvl_next(level);
718 		parent_q = child_q;
719 
720 		/* Terminate loop on DQ level, it has special handling */
721 	} while (level != CVMX_PKO_DESCR_QUEUES &&
722 		 level != CVMX_PKO_LEVEL_INVAL);
723 
724 	if (level != CVMX_PKO_DESCR_QUEUES) {
725 		printf("ERROR: %s: level sequence error\n", __func__);
726 		return -1;
727 	}
728 
729 	/* Reserve 'num_dq' DQ's at 0 by convention */
730 	res = cvmx_pko_alloc_queues(node, level, res_owner, dq, num_dq);
731 	if (dq != res) {
732 		debug("%s: ERROR: could not reserve DQs\n", __func__);
733 		return -1;
734 	}
735 
736 	res = cvmx_pko3_sq_config_children(node, level, parent_q, dq, num_dq,
737 					   num_dq);
738 	if (res < 0) {
739 		printf("ERROR: %s: configuring %s\n", __func__,
740 		       __cvmx_pko3_sq_str(b1, level, dq));
741 		return -1;
742 	}
743 
744 	/* NULL interface does not need to map to a CHAN_E */
745 
746 	/* register DQ/IPD translation */
747 	xiface = cvmx_helper_node_interface_to_xiface(node, __CVMX_XIFACE_NULL);
748 	__cvmx_pko3_ipd_dq_register(xiface, 0, dq, num_dq);
749 
750 	/* open the null DQs here */
751 	for (i = 0; i < num_dq; i++) {
752 		unsigned int limit = 128; /* NULL never really uses much */
753 
754 		cvmx_pko_dq_open(node, dq + i);
755 		cvmx_pko3_dq_set_limit(node, dq + i, limit);
756 	}
757 
758 	return 0;
759 }
760 
761 /** Open all descriptor queues belonging to an interface/port
762  * @INTERNAL
763  */
__cvmx_pko3_helper_dqs_activate(int xiface,int index,bool min_pad)764 int __cvmx_pko3_helper_dqs_activate(int xiface, int index, bool min_pad)
765 {
766 	int ipd_port, dq_base, dq_count, i;
767 	struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
768 	unsigned int limit;
769 
770 	/* Get local IPD port for the interface */
771 	ipd_port = cvmx_helper_get_ipd_port(xiface, index);
772 	if (ipd_port < 0) {
773 		printf("ERROR: %s: No IPD port for interface %d port %d\n",
774 		       __func__, xiface, index);
775 		return -1;
776 	}
777 
778 	/* Get DQ# range for the IPD port */
779 	dq_base = cvmx_pko3_get_queue_base(ipd_port);
780 	dq_count = cvmx_pko3_get_queue_num(ipd_port);
781 	if (dq_base < 0 || dq_count <= 0) {
782 		printf("ERROR: %s: No descriptor queues for interface %d port %d\n",
783 		       __func__, xiface, index);
784 		return -1;
785 	}
786 
787 	/* Mask out node from global DQ# */
788 	dq_base &= (1 << 10) - 1;
789 
790 	limit = __pko_pkt_quota / dq_count /
791 		cvmx_helper_interface_enumerate(xiface);
792 
793 	for (i = 0; i < dq_count; i++) {
794 		/* FIXME: 2ms at 1Gbps max packet rate, make speed dependent */
795 		cvmx_pko_dq_open(xi.node, dq_base + i);
796 		cvmx_pko3_dq_options(xi.node, dq_base + i, min_pad);
797 
798 		if (debug)
799 			debug("%s: DQ%u limit %d\n", __func__, dq_base + i,
800 			      limit);
801 
802 		cvmx_pko3_dq_set_limit(xi.node, dq_base + i, limit);
803 		__pko_pkt_budget -= limit;
804 	}
805 
806 	if (__pko_pkt_budget < 0)
807 		printf("WARNING: %s: PKO buffer deficit %d\n", __func__,
808 		       __pko_pkt_budget);
809 	else if (debug)
810 		debug("%s: PKO remaining packet budget: %d\n", __func__,
811 		      __pko_pkt_budget);
812 
813 	return i;
814 }
815 
816 /** Configure and initialize PKO3 for an interface
817  *
818  * @param xiface is the interface number to configure
819  * @return 0 on success.
820  */
cvmx_helper_pko3_init_interface(int xiface)821 int cvmx_helper_pko3_init_interface(int xiface)
822 {
823 	cvmx_helper_interface_mode_t mode;
824 	int node, iface, subif, num_ports;
825 	bool fcs_enable, pad_enable, pad_enable_pko;
826 	u8 fcs_sof_off = 0;
827 	u8 num_queues = 1;
828 	bool qos = false, pfc = false;
829 	int res = -1;
830 	cvmx_xiface_t xi = cvmx_helper_xiface_to_node_interface(xiface);
831 
832 	node = xi.node;
833 	iface = xi.interface;
834 	mode = cvmx_helper_interface_get_mode(xiface);
835 	num_ports = cvmx_helper_interface_enumerate(xiface);
836 	subif = 0;
837 
838 	if ((unsigned int)iface <
839 	    NUM_ELEMENTS(__cvmx_pko_queue_static_config[node].pknd.pko_cfg_iface)) {
840 		pfc = __cvmx_pko_queue_static_config[node]
841 			      .pknd.pko_cfg_iface[iface]
842 			      .pfc_enable;
843 		num_queues = __cvmx_pko_queue_static_config[node]
844 				     .pknd.pko_cfg_iface[iface]
845 				     .queues_per_port;
846 		qos = __cvmx_pko_queue_static_config[node]
847 			      .pknd.pko_cfg_iface[iface]
848 			      .qos_enable;
849 	}
850 
851 	/* Force 8 DQs per port for pass 1.0 to circumvent limitations */
852 	if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0))
853 		num_queues = 8;
854 
855 	/* For ILK there is one IPD port per channel */
856 	if (mode == CVMX_HELPER_INTERFACE_MODE_ILK)
857 		num_ports = __cvmx_helper_ilk_enumerate(xiface);
858 
859 	/* Skip non-existent interfaces */
860 	if (num_ports < 1) {
861 		debug("ERROR: %s: invalid iface %u:%u\n", __func__, node,
862 		      iface);
863 		return -1;
864 	}
865 
866 	if (mode == CVMX_HELPER_INTERFACE_MODE_LOOP) {
867 		num_queues = __cvmx_pko_queue_static_config[node]
868 				     .pknd.pko_cfg_loop.queues_per_port;
869 		qos = __cvmx_pko_queue_static_config[node]
870 			      .pknd.pko_cfg_loop.qos_enable;
871 
872 		if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0))
873 			num_queues = 8;
874 
875 		res = __cvmx_pko3_config_chan_interface(xiface, num_ports,
876 							num_queues, qos);
877 		if (res < 0)
878 			goto __cfg_error;
879 	} else if (mode == CVMX_HELPER_INTERFACE_MODE_NPI) {
880 		num_queues = __cvmx_pko_queue_static_config[node]
881 				     .pknd.pko_cfg_npi.queues_per_port;
882 		qos = __cvmx_pko_queue_static_config[node]
883 			      .pknd.pko_cfg_npi.qos_enable;
884 
885 		if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0))
886 			num_queues = 8;
887 
888 		res = __cvmx_pko3_config_chan_interface(xiface, num_ports,
889 							num_queues, qos);
890 		if (res < 0)
891 			goto __cfg_error;
892 	}
893 	/* ILK-specific queue configuration */
894 	else if (mode == CVMX_HELPER_INTERFACE_MODE_ILK) {
895 		unsigned int num_chans = __cvmx_helper_ilk_enumerate(xiface);
896 
897 		num_queues = 8;
898 		qos = true;
899 		pfc = false;
900 
901 		if (num_chans >= 128)
902 			num_queues = 1;
903 		else if (num_chans >= 64)
904 			num_queues = 2;
905 		else if (num_chans >= 32)
906 			num_queues = 4;
907 		else
908 			num_queues = 8;
909 
910 		res = __cvmx_pko3_config_chan_interface(xiface, num_chans,
911 							num_queues, qos);
912 	}
913 	/* Setup all ethernet configured for PFC */
914 	else if (pfc) {
915 		/* PFC interfaces have 8 prioritized queues */
916 		for (subif = 0; subif < num_ports; subif++) {
917 			res = __cvmx_pko3_config_pfc_interface(xiface, subif);
918 			if (res < 0)
919 				goto __cfg_error;
920 
921 			/* Enable PFC/CBFC on BGX */
922 			__cvmx_helper_bgx_xaui_config_pfc(node, iface, subif,
923 							  true);
924 		}
925 	} else {
926 		/* All other interfaces follow static configuration */
927 		for (subif = 0; subif < num_ports; subif++) {
928 			res = __cvmx_pko3_config_gen_interface(xiface, subif,
929 							       num_queues, qos);
930 			if (res < 0)
931 				goto __cfg_error;
932 		}
933 	}
934 
935 	fcs_enable = __cvmx_helper_get_has_fcs(xiface);
936 	pad_enable = __cvmx_helper_get_pko_padding(xiface);
937 
938 	/* Do not use PKO PAD/FCS generation on o78p1.x on BGX interfaces */
939 	if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X))
940 		pad_enable_pko = false;
941 	else
942 		pad_enable_pko = pad_enable;
943 
944 	if (debug)
945 		debug("%s: iface %u:%u FCS=%d pad=%d pko=%d\n", __func__, node,
946 		      iface, fcs_enable, pad_enable, pad_enable_pko);
947 
948 	/* Setup interface options */
949 	for (subif = 0; subif < num_ports; subif++) {
950 		/* Open interface/port DQs to allow transmission to begin */
951 		res = __cvmx_pko3_helper_dqs_activate(xiface, subif,
952 						      pad_enable_pko);
953 
954 		if (res < 0)
955 			goto __cfg_error;
956 
957 		/* ILK has only one MAC, subif == logical-channel */
958 		if (mode == CVMX_HELPER_INTERFACE_MODE_ILK && subif > 0)
959 			continue;
960 
961 		/* LOOP has only one MAC, subif == logical-channel */
962 		if (mode == CVMX_HELPER_INTERFACE_MODE_LOOP && subif > 0)
963 			continue;
964 
965 		/* NPI has only one MAC, subif == 'ring' */
966 		if (mode == CVMX_HELPER_INTERFACE_MODE_NPI && subif > 0)
967 			continue;
968 
969 		/* for sRIO there is 16 byte sRIO header, outside of FCS */
970 		if (mode == CVMX_HELPER_INTERFACE_MODE_SRIO)
971 			fcs_sof_off = 16;
972 
973 		if (iface >= CVMX_HELPER_MAX_GMX) {
974 			/* Non-BGX interface, use PKO for FCS/PAD */
975 			res = cvmx_pko3_interface_options(xiface, subif,
976 							  fcs_enable,
977 							  pad_enable_pko,
978 							  fcs_sof_off);
979 		} else if (pad_enable == pad_enable_pko) {
980 			/* BGX interface: FCS/PAD done by PKO */
981 			res = cvmx_pko3_interface_options(xiface, subif,
982 							  fcs_enable,
983 							  pad_enable,
984 							  fcs_sof_off);
985 			cvmx_helper_bgx_tx_options(node, iface, subif, false,
986 						   false);
987 		} else {
988 			/* BGX interface: FCS/PAD done by BGX */
989 			res = cvmx_pko3_interface_options(xiface, subif, false,
990 							  false, fcs_sof_off);
991 			cvmx_helper_bgx_tx_options(node, iface, subif,
992 						   fcs_enable, pad_enable);
993 		}
994 
995 		if (res < 0)
996 			debug("WARNING: %s: option set failed on iface %u:%u/%u\n",
997 			      __func__, node, iface, subif);
998 		if (debug)
999 			debug("%s: face %u:%u/%u fifo size %d\n", __func__,
1000 			      node, iface, subif,
1001 			      cvmx_pko3_port_fifo_size(xiface, subif));
1002 	}
1003 	return 0;
1004 
1005 __cfg_error:
1006 	debug("ERROR: %s: failed on iface %u:%u/%u\n", __func__, node, iface,
1007 	      subif);
1008 	return -1;
1009 }
1010 
1011 /**
1012  * Global initialization for PKO3
1013  *
1014  * Should only be called once on each node
1015  *
1016  * TBD: Resolve the kernel case.
1017  * When Linux eats up the entire memory, bootmem will be unable to
1018  * satisfy our request, and the memory needs to come from Linux free pages.
1019  */
__cvmx_helper_pko3_init_global(unsigned int node,uint16_t gaura)1020 int __cvmx_helper_pko3_init_global(unsigned int node, uint16_t gaura)
1021 {
1022 	int res;
1023 
1024 	res = cvmx_pko3_hw_init_global(node, gaura);
1025 	if (res < 0) {
1026 		debug("ERROR: %s:failed block initialization\n", __func__);
1027 		return res;
1028 	}
1029 
1030 	/* configure channel level */
1031 	cvmx_pko3_channel_credit_level(node, cvmx_pko_default_channel_level);
1032 
1033 	/* add NULL MAC/DQ setup */
1034 	res = __cvmx_pko3_config_null_interface(node);
1035 	if (res < 0)
1036 		debug("ERROR: %s: creating NULL interface\n", __func__);
1037 
1038 	return res;
1039 }
1040 
1041 /**
1042  * Global initialization for PKO3
1043  *
1044  * Should only be called once on each node
1045  *
1046  * When Linux eats up the entire memory, bootmem will be unable to
1047  * satisfy our request, and the memory needs to come from Linux free pages.
1048  */
cvmx_helper_pko3_init_global(unsigned int node)1049 int cvmx_helper_pko3_init_global(unsigned int node)
1050 {
1051 	void *ptr;
1052 	int res = -1;
1053 	unsigned int aura_num = ~0;
1054 	cvmx_fpa3_gaura_t aura;
1055 
1056 	/* Allocate memory required by PKO3 */
1057 	res = __cvmx_pko3_config_memory(node);
1058 	if (res < 0) {
1059 		debug("ERROR: %s: PKO3 memory allocation error\n", __func__);
1060 		return res;
1061 	}
1062 
1063 	aura_num = res;
1064 	aura = __cvmx_pko3_aura[node];
1065 
1066 	/* Exercise the FPA to make sure the AURA is functional */
1067 	ptr = cvmx_fpa3_alloc(aura);
1068 
1069 	if (!ptr) {
1070 		res = -1;
1071 	} else {
1072 		cvmx_fpa3_free_nosync(ptr, aura, 0);
1073 		res = 0;
1074 	}
1075 
1076 	if (res < 0) {
1077 		debug("ERROR: %s: FPA failure AURA=%u:%d\n", __func__,
1078 		      aura.node, aura.laura);
1079 		return -1;
1080 	}
1081 
1082 	res = __cvmx_helper_pko3_init_global(node, aura_num);
1083 
1084 	if (res < 0)
1085 		debug("ERROR: %s: failed to start PPKO\n", __func__);
1086 
1087 	return res;
1088 }
1089