1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2018-2022 Marvell International Ltd.
4  */
5 
6 #include <errno.h>
7 #include <log.h>
8 #include <time.h>
9 #include <linux/delay.h>
10 
11 #include <mach/cvmx-regs.h>
12 #include <mach/cvmx-csr.h>
13 #include <mach/cvmx-bootmem.h>
14 #include <mach/octeon-model.h>
15 #include <mach/cvmx-fuse.h>
16 #include <mach/octeon-feature.h>
17 #include <mach/cvmx-qlm.h>
18 #include <mach/octeon_qlm.h>
19 #include <mach/cvmx-pcie.h>
20 #include <mach/cvmx-coremask.h>
21 
22 #include <mach/cvmx-agl-defs.h>
23 #include <mach/cvmx-bgxx-defs.h>
24 #include <mach/cvmx-ciu-defs.h>
25 #include <mach/cvmx-gmxx-defs.h>
26 #include <mach/cvmx-gserx-defs.h>
27 #include <mach/cvmx-ilk-defs.h>
28 #include <mach/cvmx-ipd-defs.h>
29 #include <mach/cvmx-pcsx-defs.h>
30 #include <mach/cvmx-pcsxx-defs.h>
31 #include <mach/cvmx-pki-defs.h>
32 #include <mach/cvmx-pko-defs.h>
33 #include <mach/cvmx-xcv-defs.h>
34 
35 #include <mach/cvmx-hwpko.h>
36 #include <mach/cvmx-ilk.h>
37 #include <mach/cvmx-pki.h>
38 #include <mach/cvmx-pko3.h>
39 #include <mach/cvmx-pko3-queue.h>
40 #include <mach/cvmx-pko3-resources.h>
41 
42 #include <mach/cvmx-helper.h>
43 #include <mach/cvmx-helper-board.h>
44 #include <mach/cvmx-helper-cfg.h>
45 
46 #include <mach/cvmx-helper-bgx.h>
47 #include <mach/cvmx-helper-cfg.h>
48 #include <mach/cvmx-helper-util.h>
49 #include <mach/cvmx-helper-pki.h>
50 
51 /* Smalles Round-Robin quantum to use +1 */
52 #define CVMX_PKO3_RR_QUANTUM_MIN 0x10
53 
54 static int debug; /* 1 for basic, 2 for detailed trace */
55 
56 struct cvmx_pko3_dq {
57 	unsigned dq_count : 6; /* Number of descriptor queues */
58 	unsigned dq_base : 10; /* Descriptor queue start number */
59 #define CVMX_PKO3_SWIZZLE_IPD 0x0
60 };
61 
62 /*
63  * @INTERNAL
64  * Descriptor Queue to IPD port mapping table.
65  *
66  * This pointer is per-core, contains the virtual address
67  * of a global named block which has 2^12 entries per each
68  * possible node.
69  */
70 struct cvmx_pko3_dq *__cvmx_pko3_dq_table;
71 
cvmx_pko3_get_queue_base(int ipd_port)72 int cvmx_pko3_get_queue_base(int ipd_port)
73 {
74 	struct cvmx_pko3_dq *dq_table;
75 	int ret = -1;
76 	unsigned int i;
77 	struct cvmx_xport xp = cvmx_helper_ipd_port_to_xport(ipd_port);
78 
79 	/* get per-node table */
80 	if (cvmx_unlikely(!__cvmx_pko3_dq_table))
81 		__cvmx_pko3_dq_table_setup();
82 
83 	i = CVMX_PKO3_SWIZZLE_IPD ^ xp.port;
84 
85 	/* get per-node table */
86 	dq_table = __cvmx_pko3_dq_table + CVMX_PKO3_IPD_NUM_MAX * xp.node;
87 
88 	if (cvmx_likely(dq_table[i].dq_count > 0))
89 		ret = xp.node << 10 | dq_table[i].dq_base;
90 	else if (debug)
91 		cvmx_printf("ERROR: %s: no queues for ipd_port=%#x\n", __func__,
92 			    ipd_port);
93 
94 	return ret;
95 }
96 
cvmx_pko3_get_queue_num(int ipd_port)97 int cvmx_pko3_get_queue_num(int ipd_port)
98 {
99 	struct cvmx_pko3_dq *dq_table;
100 	int ret = -1;
101 	unsigned int i;
102 	struct cvmx_xport xp = cvmx_helper_ipd_port_to_xport(ipd_port);
103 
104 	/* get per-node table */
105 	if (cvmx_unlikely(!__cvmx_pko3_dq_table))
106 		__cvmx_pko3_dq_table_setup();
107 
108 	i = CVMX_PKO3_SWIZZLE_IPD ^ xp.port;
109 
110 	/* get per-node table */
111 	dq_table = __cvmx_pko3_dq_table + CVMX_PKO3_IPD_NUM_MAX * xp.node;
112 
113 	if (cvmx_likely(dq_table[i].dq_count > 0))
114 		ret = dq_table[i].dq_count;
115 	else if (debug)
116 		debug("ERROR: %s: no queues for ipd_port=%#x\n", __func__,
117 		      ipd_port);
118 
119 	return ret;
120 }
121 
122 /**
123  * @INTERNAL
124  *
125  * Initialize port/dq table contents
126  */
__cvmx_pko3_dq_table_init(void * ptr)127 static void __cvmx_pko3_dq_table_init(void *ptr)
128 {
129 	unsigned int size = sizeof(struct cvmx_pko3_dq) *
130 			    CVMX_PKO3_IPD_NUM_MAX * CVMX_MAX_NODES;
131 
132 	memset(ptr, 0, size);
133 }
134 
135 /**
136  * @INTERNAL
137  *
138  * Find or allocate global port/dq map table
139  * which is a named table, contains entries for
140  * all possible OCI nodes.
141  *
142  * The table global pointer is stored in core-local variable
143  * so that every core will call this function once, on first use.
144  */
__cvmx_pko3_dq_table_setup(void)145 int __cvmx_pko3_dq_table_setup(void)
146 {
147 	void *ptr;
148 
149 	ptr = cvmx_bootmem_alloc_named_range_once(
150 		/* size */
151 		sizeof(struct cvmx_pko3_dq) * CVMX_PKO3_IPD_NUM_MAX *
152 			CVMX_MAX_NODES,
153 		/* min_addr, max_addr, align */
154 		0ull, 0ull, sizeof(struct cvmx_pko3_dq),
155 		/* name */
156 		"cvmx_pko3_global_dq_table", __cvmx_pko3_dq_table_init);
157 
158 	if (debug)
159 		debug("%s: dq_table_ptr=%p\n", __func__, ptr);
160 
161 	if (!ptr)
162 		return -1;
163 
164 	__cvmx_pko3_dq_table = ptr;
165 	return 0;
166 }
167 
168 /*
169  * @INTERNAL
170  * Register a range of Descriptor Queues with an interface port
171  *
172  * This function populates the DQ-to-IPD translation table
173  * used by the application to retrieve the DQ range (typically ordered
174  * by priority) for a given IPD-port, which is either a physical port,
175  * or a channel on a channelized interface (i.e. ILK).
176  *
177  * @param xiface is the physical interface number
178  * @param index is either a physical port on an interface
179  *        or a channel of an ILK interface
180  * @param dq_base is the first Descriptor Queue number in a consecutive range
181  * @param dq_count is the number of consecutive Descriptor Queues leading
182  *        the same channel or port.
183  *
184  * Only a consecutive range of Descriptor Queues can be associated with any
185  * given channel/port, and usually they are ordered from most to least
186  * in terms of scheduling priority.
187  *
188  * Note: thus function only populates the node-local translation table.
189  * NOTE: This function would be cleaner if it had a single ipd_port argument
190  *
191  * @returns 0 on success, -1 on failure.
192  */
__cvmx_pko3_ipd_dq_register(int xiface,int index,unsigned int dq_base,unsigned int dq_count)193 int __cvmx_pko3_ipd_dq_register(int xiface, int index, unsigned int dq_base,
194 				unsigned int dq_count)
195 {
196 	struct cvmx_pko3_dq *dq_table;
197 	int ipd_port;
198 	unsigned int i;
199 	struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
200 	struct cvmx_xport xp;
201 
202 	if (__cvmx_helper_xiface_is_null(xiface)) {
203 		ipd_port = cvmx_helper_node_to_ipd_port(xi.node,
204 							CVMX_PKO3_IPD_PORT_NULL);
205 	} else {
206 		int p;
207 
208 		p = cvmx_helper_get_ipd_port(xiface, index);
209 		if (p < 0) {
210 			cvmx_printf("ERROR: %s: xiface %#x has no IPD port\n",
211 				    __func__, xiface);
212 			return -1;
213 		}
214 		ipd_port = p;
215 	}
216 
217 	xp = cvmx_helper_ipd_port_to_xport(ipd_port);
218 
219 	i = CVMX_PKO3_SWIZZLE_IPD ^ xp.port;
220 
221 	/* get per-node table */
222 	if (!__cvmx_pko3_dq_table)
223 		__cvmx_pko3_dq_table_setup();
224 
225 	dq_table = __cvmx_pko3_dq_table + CVMX_PKO3_IPD_NUM_MAX * xi.node;
226 
227 	if (debug)
228 		debug("%s: ipd_port=%#x ix=%#x dq %u cnt %u\n", __func__,
229 		      ipd_port, i, dq_base, dq_count);
230 
231 	/* Check the IPD port has not already been configured */
232 	if (dq_table[i].dq_count > 0) {
233 		cvmx_printf("%s: ERROR: IPD %#x already registered\n", __func__,
234 			    ipd_port);
235 		return -1;
236 	}
237 
238 	/* Store DQ# range in the queue lookup table */
239 	dq_table[i].dq_base = dq_base;
240 	dq_table[i].dq_count = dq_count;
241 
242 	return 0;
243 }
244 
245 /*
246  * @INTERNAL
247  * Convert normal CHAN_E (i.e. IPD port) value to compressed channel form
248  * that is used to populate PKO_LUT.
249  *
250  * Note: This code may be model specific.
251  */
cvmx_pko3_chan_2_xchan(uint16_t ipd_port)252 static int cvmx_pko3_chan_2_xchan(uint16_t ipd_port)
253 {
254 	u16 xchan;
255 	u8 off;
256 	static const u8 *xchan_base;
257 	static const u8 xchan_base_cn78xx[16] = {
258 		/* IPD 0x000 */ 0x3c0 >> 4, /* LBK */
259 		/* IPD 0x100 */ 0x380 >> 4, /* DPI */
260 		/* IPD 0x200 */ 0xfff >> 4, /* not used */
261 		/* IPD 0x300 */ 0xfff >> 4, /* not used */
262 		/* IPD 0x400 */ 0x000 >> 4, /* ILK0 */
263 		/* IPD 0x500 */ 0x100 >> 4, /* ILK1 */
264 		/* IPD 0x600 */ 0xfff >> 4, /* not used */
265 		/* IPD 0x700 */ 0xfff >> 4, /* not used */
266 		/* IPD 0x800 */ 0x200 >> 4, /* BGX0 */
267 		/* IPD 0x900 */ 0x240 >> 4, /* BGX1 */
268 		/* IPD 0xa00 */ 0x280 >> 4, /* BGX2 */
269 		/* IPD 0xb00 */ 0x2c0 >> 4, /* BGX3 */
270 		/* IPD 0xc00 */ 0x300 >> 4, /* BGX4 */
271 		/* IPD 0xd00 */ 0x340 >> 4, /* BGX5 */
272 		/* IPD 0xe00 */ 0xfff >> 4, /* not used */
273 		/* IPD 0xf00 */ 0xfff >> 4  /* not used */
274 	};
275 	static const u8 xchan_base_cn73xx[16] = {
276 		/* IPD 0x000 */ 0x0c0 >> 4, /* LBK */
277 		/* IPD 0x100 */ 0x100 >> 4, /* DPI */
278 		/* IPD 0x200 */ 0xfff >> 4, /* not used */
279 		/* IPD 0x300 */ 0xfff >> 4, /* not used */
280 		/* IPD 0x400 */ 0xfff >> 4, /* not used */
281 		/* IPD 0x500 */ 0xfff >> 4, /* not used */
282 		/* IPD 0x600 */ 0xfff >> 4, /* not used */
283 		/* IPD 0x700 */ 0xfff >> 4, /* not used */
284 		/* IPD 0x800 */ 0x000 >> 4, /* BGX0 */
285 		/* IPD 0x900 */ 0x040 >> 4, /* BGX1 */
286 		/* IPD 0xa00 */ 0x080 >> 4, /* BGX2 */
287 		/* IPD 0xb00 */ 0xfff >> 4, /* not used */
288 		/* IPD 0xc00 */ 0xfff >> 4, /* not used */
289 		/* IPD 0xd00 */ 0xfff >> 4, /* not used */
290 		/* IPD 0xe00 */ 0xfff >> 4, /* not used */
291 		/* IPD 0xf00 */ 0xfff >> 4  /* not used */
292 	};
293 	static const u8 xchan_base_cn75xx[16] = {
294 		/* IPD 0x000 */ 0x040 >> 4, /* LBK */
295 		/* IPD 0x100 */ 0x080 >> 4, /* DPI */
296 		/* IPD 0x200 */ 0xeee >> 4, /* SRIO0  noop */
297 		/* IPD 0x300 */ 0xfff >> 4, /* not used */
298 		/* IPD 0x400 */ 0xfff >> 4, /* not used */
299 		/* IPD 0x500 */ 0xfff >> 4, /* not used */
300 		/* IPD 0x600 */ 0xfff >> 4, /* not used */
301 		/* IPD 0x700 */ 0xfff >> 4, /* not used */
302 		/* IPD 0x800 */ 0x000 >> 4, /* BGX0 */
303 		/* IPD 0x900 */ 0xfff >> 4, /* not used */
304 		/* IPD 0xa00 */ 0xfff >> 4, /* not used */
305 		/* IPD 0xb00 */ 0xfff >> 4, /* not used */
306 		/* IPD 0xc00 */ 0xfff >> 4, /* not used */
307 		/* IPD 0xd00 */ 0xfff >> 4, /* not used */
308 		/* IPD 0xe00 */ 0xfff >> 4, /* not used */
309 		/* IPD 0xf00 */ 0xfff >> 4  /* not used */
310 	};
311 
312 	if (OCTEON_IS_MODEL(OCTEON_CN73XX))
313 		xchan_base = xchan_base_cn73xx;
314 	if (OCTEON_IS_MODEL(OCTEON_CNF75XX))
315 		xchan_base = xchan_base_cn75xx;
316 	if (OCTEON_IS_MODEL(OCTEON_CN78XX))
317 		xchan_base = xchan_base_cn78xx;
318 
319 	if (!xchan_base)
320 		return -1;
321 
322 	xchan = ipd_port >> 8;
323 
324 	/* ILKx, DPI has 8 bits logical channels, others just 6 */
325 	if (((xchan & 0xfe) == 0x04) || xchan == 0x01)
326 		off = ipd_port & 0xff;
327 	else
328 		off = ipd_port & 0x3f;
329 
330 	xchan = xchan_base[xchan & 0xf];
331 
332 	if (xchan == 0xff)
333 		return -1; /* Invalid IPD_PORT */
334 	else if (xchan == 0xee)
335 		return -2; /* LUT not used */
336 	else
337 		return (xchan << 4) | off;
338 }
339 
340 /*
341  * Map channel number in PKO
342  *
343  * @param node is to specify the node to which this configuration is applied.
344  * @param pq_num specifies the Port Queue (i.e. L1) queue number.
345  * @param l2_l3_q_num  specifies L2/L3 queue number.
346  * @param channel specifies the channel number to map to the queue.
347  *
348  * The channel assignment applies to L2 or L3 Shaper Queues depending
349  * on the setting of channel credit level.
350  *
351  * @return returns none.
352  */
cvmx_pko3_map_channel(unsigned int node,unsigned int pq_num,unsigned int l2_l3_q_num,uint16_t channel)353 void cvmx_pko3_map_channel(unsigned int node, unsigned int pq_num,
354 			   unsigned int l2_l3_q_num, uint16_t channel)
355 {
356 	union cvmx_pko_l3_l2_sqx_channel sqx_channel;
357 	cvmx_pko_lutx_t lutx;
358 	int xchan;
359 
360 	sqx_channel.u64 =
361 		csr_rd_node(node, CVMX_PKO_L3_L2_SQX_CHANNEL(l2_l3_q_num));
362 
363 	sqx_channel.s.cc_channel = channel;
364 
365 	csr_wr_node(node, CVMX_PKO_L3_L2_SQX_CHANNEL(l2_l3_q_num),
366 		    sqx_channel.u64);
367 
368 	/* Convert CHAN_E into compressed channel */
369 	xchan = cvmx_pko3_chan_2_xchan(channel);
370 
371 	if (debug)
372 		debug("%s: ipd_port=%#x xchan=%#x\n", __func__, channel, xchan);
373 
374 	if (xchan < 0) {
375 		if (xchan == -1)
376 			cvmx_printf("%s: ERROR: channel %#x not recognized\n",
377 				    __func__, channel);
378 		return;
379 	}
380 
381 	lutx.u64 = 0;
382 	lutx.s.valid = 1;
383 	lutx.s.pq_idx = pq_num;
384 	lutx.s.queue_number = l2_l3_q_num;
385 
386 	csr_wr_node(node, CVMX_PKO_LUTX(xchan), lutx.u64);
387 
388 	if (debug)
389 		debug("%s: channel %#x (compressed=%#x) mapped L2/L3 SQ=%u, PQ=%u\n",
390 		      __func__, channel, xchan, l2_l3_q_num, pq_num);
391 }
392 
393 /*
394  * @INTERNAL
395  * This function configures port queue scheduling and topology parameters
396  * in hardware.
397  *
398  * @param node is to specify the node to which this configuration is applied.
399  * @param port_queue is the port queue number to be configured.
400  * @param mac_num is the mac number of the mac that will be tied to this port_queue.
401  */
cvmx_pko_configure_port_queue(int node,int port_queue,int mac_num)402 static void cvmx_pko_configure_port_queue(int node, int port_queue, int mac_num)
403 {
404 	cvmx_pko_l1_sqx_topology_t pko_l1_topology;
405 	cvmx_pko_l1_sqx_shape_t pko_l1_shape;
406 	cvmx_pko_l1_sqx_link_t pko_l1_link;
407 
408 	pko_l1_topology.u64 = 0;
409 	pko_l1_topology.s.link = mac_num;
410 	csr_wr_node(node, CVMX_PKO_L1_SQX_TOPOLOGY(port_queue),
411 		    pko_l1_topology.u64);
412 
413 	pko_l1_shape.u64 = 0;
414 	pko_l1_shape.s.link = mac_num;
415 	csr_wr_node(node, CVMX_PKO_L1_SQX_SHAPE(port_queue), pko_l1_shape.u64);
416 
417 	pko_l1_link.u64 = 0;
418 	pko_l1_link.s.link = mac_num;
419 	csr_wr_node(node, CVMX_PKO_L1_SQX_LINK(port_queue), pko_l1_link.u64);
420 }
421 
422 /*
423  * @INTERNAL
424  * This function configures level 2 queues scheduling and topology parameters
425  * in hardware.
426  *
427  * @param node is to specify the node to which this configuration is applied.
428  * @param queue is the level3 queue number to be configured.
429  * @param parent_queue is the parent queue at next level for this l3 queue.
430  * @param prio is this queue's priority in parent's scheduler.
431  * @param rr_quantum is this queue's round robin quantum value.
432  * @param child_base is the first child queue number in the static prioriy children.
433  * @param child_rr_prio is the round robin children priority.
434  */
cvmx_pko_configure_l2_queue(int node,int queue,int parent_queue,int prio,int rr_quantum,int child_base,int child_rr_prio)435 static void cvmx_pko_configure_l2_queue(int node, int queue, int parent_queue,
436 					int prio, int rr_quantum,
437 					int child_base, int child_rr_prio)
438 {
439 	cvmx_pko_l2_sqx_schedule_t pko_sq_sched;
440 	cvmx_pko_l2_sqx_topology_t pko_child_topology;
441 	cvmx_pko_l1_sqx_topology_t pko_parent_topology;
442 
443 	/* parent topology configuration */
444 	pko_parent_topology.u64 =
445 		csr_rd_node(node, CVMX_PKO_L1_SQX_TOPOLOGY(parent_queue));
446 	pko_parent_topology.s.prio_anchor = child_base;
447 	pko_parent_topology.s.rr_prio = child_rr_prio;
448 	csr_wr_node(node, CVMX_PKO_L1_SQX_TOPOLOGY(parent_queue),
449 		    pko_parent_topology.u64);
450 
451 	if (debug > 1)
452 		debug("CVMX_PKO_L1_SQX_TOPOLOGY(%u): PRIO_ANCHOR=%u PARENT=%u\n",
453 		      parent_queue, pko_parent_topology.s.prio_anchor,
454 		      pko_parent_topology.s.link);
455 
456 	/* scheduler configuration for this sq in the parent queue */
457 	pko_sq_sched.u64 = 0;
458 	pko_sq_sched.s.prio = prio;
459 	pko_sq_sched.s.rr_quantum = rr_quantum;
460 	csr_wr_node(node, CVMX_PKO_L2_SQX_SCHEDULE(queue), pko_sq_sched.u64);
461 
462 	/* child topology configuration */
463 	pko_child_topology.u64 = 0;
464 	pko_child_topology.s.parent = parent_queue;
465 	csr_wr_node(node, CVMX_PKO_L2_SQX_TOPOLOGY(queue),
466 		    pko_child_topology.u64);
467 }
468 
469 /*
470  * @INTERNAL
471  * This function configures level 3 queues scheduling and topology parameters
472  * in hardware.
473  *
474  * @param node is to specify the node to which this configuration is applied.
475  * @param queue is the level3 queue number to be configured.
476  * @param parent_queue is the parent queue at next level for this l3 queue.
477  * @param prio is this queue's priority in parent's scheduler.
478  * @param rr_quantum is this queue's round robin quantum value.
479  * @param child_base is the first child queue number in the static prioriy children.
480  * @param child_rr_prio is the round robin children priority.
481  */
cvmx_pko_configure_l3_queue(int node,int queue,int parent_queue,int prio,int rr_quantum,int child_base,int child_rr_prio)482 static void cvmx_pko_configure_l3_queue(int node, int queue, int parent_queue,
483 					int prio, int rr_quantum,
484 					int child_base, int child_rr_prio)
485 {
486 	cvmx_pko_l3_sqx_schedule_t pko_sq_sched;
487 	cvmx_pko_l3_sqx_topology_t pko_child_topology;
488 	cvmx_pko_l2_sqx_topology_t pko_parent_topology;
489 
490 	/* parent topology configuration */
491 	pko_parent_topology.u64 =
492 		csr_rd_node(node, CVMX_PKO_L2_SQX_TOPOLOGY(parent_queue));
493 	pko_parent_topology.s.prio_anchor = child_base;
494 	pko_parent_topology.s.rr_prio = child_rr_prio;
495 	csr_wr_node(node, CVMX_PKO_L2_SQX_TOPOLOGY(parent_queue),
496 		    pko_parent_topology.u64);
497 
498 	if (debug > 1)
499 		debug("CVMX_PKO_L2_SQX_TOPOLOGY(%u): PRIO_ANCHOR=%u PARENT=%u\n",
500 		      parent_queue, pko_parent_topology.s.prio_anchor,
501 		      pko_parent_topology.s.parent);
502 
503 	/* scheduler configuration for this sq in the parent queue */
504 	pko_sq_sched.u64 = 0;
505 	pko_sq_sched.s.prio = prio;
506 	pko_sq_sched.s.rr_quantum = rr_quantum;
507 	csr_wr_node(node, CVMX_PKO_L3_SQX_SCHEDULE(queue), pko_sq_sched.u64);
508 
509 	/* child topology configuration */
510 	pko_child_topology.u64 = 0;
511 	pko_child_topology.s.parent = parent_queue;
512 	csr_wr_node(node, CVMX_PKO_L3_SQX_TOPOLOGY(queue),
513 		    pko_child_topology.u64);
514 }
515 
516 /*
517  * @INTERNAL
518  * This function configures level 4 queues scheduling and topology parameters
519  * in hardware.
520  *
521  * @param node is to specify the node to which this configuration is applied.
522  * @param queue is the level4 queue number to be configured.
523  * @param parent_queue is the parent queue at next level for this l4 queue.
524  * @param prio is this queue's priority in parent's scheduler.
525  * @param rr_quantum is this queue's round robin quantum value.
526  * @param child_base is the first child queue number in the static prioriy children.
527  * @param child_rr_prio is the round robin children priority.
528  */
cvmx_pko_configure_l4_queue(int node,int queue,int parent_queue,int prio,int rr_quantum,int child_base,int child_rr_prio)529 static void cvmx_pko_configure_l4_queue(int node, int queue, int parent_queue,
530 					int prio, int rr_quantum,
531 					int child_base, int child_rr_prio)
532 {
533 	cvmx_pko_l4_sqx_schedule_t pko_sq_sched;
534 	cvmx_pko_l4_sqx_topology_t pko_child_topology;
535 	cvmx_pko_l3_sqx_topology_t pko_parent_topology;
536 
537 	/* parent topology configuration */
538 	pko_parent_topology.u64 =
539 		csr_rd_node(node, CVMX_PKO_L3_SQX_TOPOLOGY(parent_queue));
540 	pko_parent_topology.s.prio_anchor = child_base;
541 	pko_parent_topology.s.rr_prio = child_rr_prio;
542 	csr_wr_node(node, CVMX_PKO_L3_SQX_TOPOLOGY(parent_queue),
543 		    pko_parent_topology.u64);
544 
545 	if (debug > 1)
546 		debug("CVMX_PKO_L3_SQX_TOPOLOGY(%u): PRIO_ANCHOR=%u PARENT=%u\n",
547 		      parent_queue, pko_parent_topology.s.prio_anchor,
548 		      pko_parent_topology.s.parent);
549 
550 	/* scheduler configuration for this sq in the parent queue */
551 	pko_sq_sched.u64 = 0;
552 	pko_sq_sched.s.prio = prio;
553 	pko_sq_sched.s.rr_quantum = rr_quantum;
554 	csr_wr_node(node, CVMX_PKO_L4_SQX_SCHEDULE(queue), pko_sq_sched.u64);
555 
556 	/* topology configuration */
557 	pko_child_topology.u64 = 0;
558 	pko_child_topology.s.parent = parent_queue;
559 	csr_wr_node(node, CVMX_PKO_L4_SQX_TOPOLOGY(queue),
560 		    pko_child_topology.u64);
561 }
562 
563 /*
564  * @INTERNAL
565  * This function configures level 5 queues scheduling and topology parameters
566  * in hardware.
567  *
568  * @param node is to specify the node to which this configuration is applied.
569  * @param queue is the level5 queue number to be configured.
570  * @param parent_queue is the parent queue at next level for this l5 queue.
571  * @param prio is this queue's priority in parent's scheduler.
572  * @param rr_quantum is this queue's round robin quantum value.
573  * @param child_base is the first child queue number in the static prioriy children.
574  * @param child_rr_prio is the round robin children priority.
575  */
cvmx_pko_configure_l5_queue(int node,int queue,int parent_queue,int prio,int rr_quantum,int child_base,int child_rr_prio)576 static void cvmx_pko_configure_l5_queue(int node, int queue, int parent_queue,
577 					int prio, int rr_quantum,
578 					int child_base, int child_rr_prio)
579 {
580 	cvmx_pko_l5_sqx_schedule_t pko_sq_sched;
581 	cvmx_pko_l4_sqx_topology_t pko_parent_topology;
582 	cvmx_pko_l5_sqx_topology_t pko_child_topology;
583 
584 	/* parent topology configuration */
585 	pko_parent_topology.u64 =
586 		csr_rd_node(node, CVMX_PKO_L4_SQX_TOPOLOGY(parent_queue));
587 	pko_parent_topology.s.prio_anchor = child_base;
588 	pko_parent_topology.s.rr_prio = child_rr_prio;
589 	csr_wr_node(node, CVMX_PKO_L4_SQX_TOPOLOGY(parent_queue),
590 		    pko_parent_topology.u64);
591 
592 	if (debug > 1)
593 		debug("CVMX_PKO_L4_SQX_TOPOLOGY(%u): PRIO_ANCHOR=%u PARENT=%u\n",
594 		      parent_queue, pko_parent_topology.s.prio_anchor,
595 		      pko_parent_topology.s.parent);
596 
597 	/* scheduler configuration for this sq in the parent queue */
598 	pko_sq_sched.u64 = 0;
599 	pko_sq_sched.s.prio = prio;
600 	pko_sq_sched.s.rr_quantum = rr_quantum;
601 	csr_wr_node(node, CVMX_PKO_L5_SQX_SCHEDULE(queue), pko_sq_sched.u64);
602 
603 	/* topology configuration */
604 	pko_child_topology.u64 = 0;
605 	pko_child_topology.s.parent = parent_queue;
606 	csr_wr_node(node, CVMX_PKO_L5_SQX_TOPOLOGY(queue),
607 		    pko_child_topology.u64);
608 }
609 
610 /*
611  * @INTERNAL
612  * This function configures descriptor queues scheduling and topology parameters
613  * in hardware.
614  *
615  * @param node is to specify the node to which this configuration is applied.
616  * @param dq is the descriptor queue number to be configured.
617  * @param parent_queue is the parent queue at next level for this dq.
618  * @param prio is this queue's priority in parent's scheduler.
619  * @param rr_quantum is this queue's round robin quantum value.
620  * @param child_base is the first child queue number in the static prioriy children.
621  * @param child_rr_prio is the round robin children priority.
622  */
cvmx_pko_configure_dq(int node,int dq,int parent_queue,int prio,int rr_quantum,int child_base,int child_rr_prio)623 static void cvmx_pko_configure_dq(int node, int dq, int parent_queue, int prio,
624 				  int rr_quantum, int child_base,
625 				  int child_rr_prio)
626 {
627 	cvmx_pko_dqx_schedule_t pko_dq_sched;
628 	cvmx_pko_dqx_topology_t pko_dq_topology;
629 	cvmx_pko_l5_sqx_topology_t pko_parent_topology;
630 	cvmx_pko_dqx_wm_ctl_t pko_dq_wm_ctl;
631 	unsigned long long parent_topology_reg;
632 	char lvl;
633 
634 	if (debug)
635 		debug("%s: dq %u parent %u child_base %u\n", __func__, dq,
636 		      parent_queue, child_base);
637 
638 	if (__cvmx_pko3_sq_lvl_max() == CVMX_PKO_L5_QUEUES) {
639 		parent_topology_reg = CVMX_PKO_L5_SQX_TOPOLOGY(parent_queue);
640 		lvl = 5;
641 	} else if (__cvmx_pko3_sq_lvl_max() == CVMX_PKO_L3_QUEUES) {
642 		parent_topology_reg = CVMX_PKO_L3_SQX_TOPOLOGY(parent_queue);
643 		lvl = 3;
644 	} else {
645 		return;
646 	}
647 
648 	if (debug)
649 		debug("%s: parent_topology_reg=%#llx\n", __func__,
650 		      parent_topology_reg);
651 
652 	/* parent topology configuration */
653 	pko_parent_topology.u64 = csr_rd_node(node, parent_topology_reg);
654 	pko_parent_topology.s.prio_anchor = child_base;
655 	pko_parent_topology.s.rr_prio = child_rr_prio;
656 	csr_wr_node(node, parent_topology_reg, pko_parent_topology.u64);
657 
658 	if (debug > 1)
659 		debug("CVMX_PKO_L%d_SQX_TOPOLOGY(%u): PRIO_ANCHOR=%u PARENT=%u\n",
660 		      lvl, parent_queue, pko_parent_topology.s.prio_anchor,
661 		      pko_parent_topology.s.parent);
662 
663 	/* scheduler configuration for this dq in the parent queue */
664 	pko_dq_sched.u64 = 0;
665 	pko_dq_sched.s.prio = prio;
666 	pko_dq_sched.s.rr_quantum = rr_quantum;
667 	csr_wr_node(node, CVMX_PKO_DQX_SCHEDULE(dq), pko_dq_sched.u64);
668 
669 	/* topology configuration */
670 	pko_dq_topology.u64 = 0;
671 	pko_dq_topology.s.parent = parent_queue;
672 	csr_wr_node(node, CVMX_PKO_DQX_TOPOLOGY(dq), pko_dq_topology.u64);
673 
674 	/* configure for counting packets, not bytes at this level */
675 	pko_dq_wm_ctl.u64 = 0;
676 	pko_dq_wm_ctl.s.kind = 1;
677 	pko_dq_wm_ctl.s.enable = 0;
678 	csr_wr_node(node, CVMX_PKO_DQX_WM_CTL(dq), pko_dq_wm_ctl.u64);
679 
680 	if (debug > 1) {
681 		pko_dq_sched.u64 = csr_rd_node(node, CVMX_PKO_DQX_SCHEDULE(dq));
682 		pko_dq_topology.u64 =
683 			csr_rd_node(node, CVMX_PKO_DQX_TOPOLOGY(dq));
684 		debug("CVMX_PKO_DQX_TOPOLOGY(%u)PARENT=%u CVMX_PKO_DQX_SCHEDULE(%u) PRIO=%u Q=%u\n",
685 		      dq, pko_dq_topology.s.parent, dq, pko_dq_sched.s.prio,
686 		      pko_dq_sched.s.rr_quantum);
687 	}
688 }
689 
690 /*
691  * @INTERNAL
692  * The following structure selects the Scheduling Queue configuration
693  * routine for each of the supported levels.
694  * The initial content of the table will be setup in accordance
695  * to the specific SoC model and its implemented resources
696  */
697 struct pko3_cfg_tab_s {
698 	/* function pointer for to configure the given level, last=DQ */
699 	struct {
700 		u8 parent_level;
701 		void (*cfg_sq_func)(int node, int queue, int parent_queue,
702 				    int prio, int rr_quantum, int child_base,
703 				    int child_rr_prio);
704 		//XXX for debugging exagerated size
705 	} lvl[256];
706 };
707 
708 static const struct pko3_cfg_tab_s pko3_cn78xx_cfg = {
709 	{ [CVMX_PKO_L2_QUEUES] = { CVMX_PKO_PORT_QUEUES,
710 				   cvmx_pko_configure_l2_queue },
711 	  [CVMX_PKO_L3_QUEUES] = { CVMX_PKO_L2_QUEUES,
712 				   cvmx_pko_configure_l3_queue },
713 	  [CVMX_PKO_L4_QUEUES] = { CVMX_PKO_L3_QUEUES,
714 				   cvmx_pko_configure_l4_queue },
715 	  [CVMX_PKO_L5_QUEUES] = { CVMX_PKO_L4_QUEUES,
716 				   cvmx_pko_configure_l5_queue },
717 	  [CVMX_PKO_DESCR_QUEUES] = { CVMX_PKO_L5_QUEUES,
718 				      cvmx_pko_configure_dq } }
719 };
720 
721 static const struct pko3_cfg_tab_s pko3_cn73xx_cfg = {
722 	{ [CVMX_PKO_L2_QUEUES] = { CVMX_PKO_PORT_QUEUES,
723 				   cvmx_pko_configure_l2_queue },
724 	  [CVMX_PKO_L3_QUEUES] = { CVMX_PKO_L2_QUEUES,
725 				   cvmx_pko_configure_l3_queue },
726 	  [CVMX_PKO_DESCR_QUEUES] = { CVMX_PKO_L3_QUEUES,
727 				      cvmx_pko_configure_dq } }
728 };
729 
730 /*
731  * Configure Port Queue and its children Scheduler Queue
732  *
733  * Port Queues (a.k.a L1) are assigned 1-to-1 to MACs.
734  * L2 Scheduler Queues are used for specifying channels, and thus there
735  * could be multiple L2 SQs attached to a single L1 PQ, either in a
736  * fair round-robin scheduling, or with static and/or round-robin priorities.
737  *
738  * @param node on which to operate
739  * @param mac_num is the LMAC number to that is associated with the Port Queue,
740  * @param pq_num is the number of the L1 PQ attached to the MAC
741  *
742  * @returns 0 on success, -1 on failure.
743  */
cvmx_pko3_pq_config(unsigned int node,unsigned int mac_num,unsigned int pq_num)744 int cvmx_pko3_pq_config(unsigned int node, unsigned int mac_num,
745 			unsigned int pq_num)
746 {
747 	char b1[10];
748 
749 	if (debug)
750 		debug("%s: MAC%u -> %s\n", __func__, mac_num,
751 		      __cvmx_pko3_sq_str(b1, CVMX_PKO_PORT_QUEUES, pq_num));
752 
753 	cvmx_pko_configure_port_queue(node, pq_num, mac_num);
754 
755 	return 0;
756 }
757 
758 /*
759  * Configure L3 through L5 Scheduler Queues and Descriptor Queues
760  *
761  * The Scheduler Queues in Levels 3 to 5 and Descriptor Queues are
762  * configured one-to-one or many-to-one to a single parent Scheduler
763  * Queues. The level of the parent SQ is specified in an argument,
764  * as well as the number of childer to attach to the specific parent.
765  * The children can have fair round-robin or priority-based scheduling
766  * when multiple children are assigned a single parent.
767  *
768  * @param node on which to operate
769  * @param child_level  is the level of the child queue
770  * @param parent_queue is the number of the parent Scheduler Queue
771  * @param child_base is the number of the first child SQ or DQ to assign to
772  * @param child_count is the number of consecutive children to assign
773  * @param stat_prio_count is the priority setting for the children L2 SQs
774  *
775  * If <stat_prio_count> is -1, the Ln children will have equal Round-Robin
776  * relationship with eachother. If <stat_prio_count> is 0, all Ln children
777  * will be arranged in Weighted-Round-Robin, with the first having the most
778  * precedence. If <stat_prio_count> is between 1 and 8, it indicates how
779  * many children will have static priority settings (with the first having
780  * the most precedence), with the remaining Ln children having WRR scheduling.
781  *
782  * @returns 0 on success, -1 on failure.
783  *
784  * Note: this function supports the configuration of node-local unit.
785  */
cvmx_pko3_sq_config_children(unsigned int node,enum cvmx_pko3_level_e child_level,unsigned int parent_queue,unsigned int child_base,unsigned int child_count,int stat_prio_count)786 int cvmx_pko3_sq_config_children(unsigned int node,
787 				 enum cvmx_pko3_level_e child_level,
788 				 unsigned int parent_queue,
789 				 unsigned int child_base,
790 				 unsigned int child_count, int stat_prio_count)
791 {
792 	enum cvmx_pko3_level_e parent_level;
793 	unsigned int num_elem = 0;
794 	unsigned int rr_quantum, rr_count;
795 	unsigned int child, prio, rr_prio;
796 	const struct pko3_cfg_tab_s *cfg_tbl = NULL;
797 	char b1[10], b2[10];
798 
799 	if (OCTEON_IS_MODEL(OCTEON_CN78XX)) {
800 		num_elem = NUM_ELEMENTS(pko3_cn78xx_cfg.lvl);
801 		cfg_tbl = &pko3_cn78xx_cfg;
802 	}
803 	if (OCTEON_IS_MODEL(OCTEON_CN73XX) || OCTEON_IS_MODEL(OCTEON_CNF75XX)) {
804 		num_elem = NUM_ELEMENTS(pko3_cn73xx_cfg.lvl);
805 		cfg_tbl = &pko3_cn73xx_cfg;
806 	}
807 
808 	if (!cfg_tbl || child_level >= num_elem) {
809 		cvmx_printf("ERROR: %s: model or level %#x invalid\n", __func__,
810 			    child_level);
811 		return -1;
812 	}
813 
814 	parent_level = cfg_tbl->lvl[child_level].parent_level;
815 
816 	if (!cfg_tbl->lvl[child_level].cfg_sq_func ||
817 	    cfg_tbl->lvl[child_level].parent_level == 0) {
818 		cvmx_printf("ERROR: %s: queue level %#x invalid\n", __func__,
819 			    child_level);
820 		return -1;
821 	}
822 
823 	/* First static priority is 0 - top precedence */
824 	prio = 0;
825 
826 	if (stat_prio_count > (signed int)child_count)
827 		stat_prio_count = child_count;
828 
829 	/* Valid PRIO field is 0..9, limit maximum static priorities */
830 	if (stat_prio_count > 9)
831 		stat_prio_count = 9;
832 
833 	/* Special case of a single child */
834 	if (child_count == 1) {
835 		rr_count = 0;
836 		rr_prio = 0xF;
837 		/* Special case for Fair-RR */
838 	} else if (stat_prio_count < 0) {
839 		rr_count = child_count;
840 		rr_prio = 0;
841 	} else {
842 		rr_count = child_count - stat_prio_count;
843 		rr_prio = stat_prio_count;
844 	}
845 
846 	/* Compute highest RR_QUANTUM */
847 	if (stat_prio_count > 0)
848 		rr_quantum = CVMX_PKO3_RR_QUANTUM_MIN * rr_count;
849 	else
850 		rr_quantum = CVMX_PKO3_RR_QUANTUM_MIN;
851 
852 	if (debug)
853 		debug("%s: Parent %s child_base %u rr_pri %u\n", __func__,
854 		      __cvmx_pko3_sq_str(b1, parent_level, parent_queue),
855 		      child_base, rr_prio);
856 
857 	/* Parent is configured with child */
858 
859 	for (child = child_base; child < (child_base + child_count); child++) {
860 		if (debug)
861 			debug("%s: Child %s of %s prio %u rr_quantum %#x\n",
862 			      __func__,
863 			      __cvmx_pko3_sq_str(b1, child_level, child),
864 			      __cvmx_pko3_sq_str(b2, parent_level,
865 						 parent_queue),
866 			      prio, rr_quantum);
867 
868 		cfg_tbl->lvl[child_level].cfg_sq_func(node, child, parent_queue,
869 						      prio, rr_quantum,
870 						      child_base, rr_prio);
871 
872 		if (prio < rr_prio)
873 			prio++;
874 		else if (stat_prio_count > 0)
875 			rr_quantum -= CVMX_PKO3_RR_QUANTUM_MIN;
876 	} /* for child */
877 
878 	return 0;
879 }
880