1 /***********************license start***************
2 * Author: Cavium Networks
4 * Contact: support@caviumnetworks.com
5 * This file is part of the OCTEON SDK
7 * Copyright (c) 2003-2008 Cavium Networks
9 * This file is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License, Version 2, as
11 * published by the Free Software Foundation.
13 * This file is distributed in the hope that it will be useful, but
14 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16 * NONINFRINGEMENT. See the GNU General Public License for more
19 * You should have received a copy of the GNU General Public License
20 * along with this file; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * or visit http://www.gnu.org/licenses/.
24 * This file may also be available under a different license from Cavium.
25 * Contact Cavium Networks for more information
26 ***********************license end**************************************/
29 * Support library for the hardware Packet Output unit.
32 #include <asm/octeon/octeon.h>
34 #include <asm/octeon/cvmx-config.h>
35 #include <asm/octeon/cvmx-pko.h>
36 #include <asm/octeon/cvmx-helper.h>
39 * Internal state of packet output
42 static int __cvmx_pko_int(int interface
, int index
)
68 static void __cvmx_pko_iport_config(int pko_port
)
71 const int num_queues
= 1;
72 const int base_queue
= pko_port
;
73 const int static_priority_end
= 1;
74 const int static_priority_base
= 1;
76 for (queue
= 0; queue
< num_queues
; queue
++) {
77 union cvmx_pko_mem_iqueue_ptrs config
;
78 cvmx_cmd_queue_result_t cmd_res
;
82 config
.s
.index
= queue
;
83 config
.s
.qid
= base_queue
+ queue
;
84 config
.s
.ipid
= pko_port
;
85 config
.s
.tail
= (queue
== (num_queues
- 1));
86 config
.s
.s_tail
= (queue
== static_priority_end
);
87 config
.s
.static_p
= (static_priority_base
>= 0);
88 config
.s
.static_q
= (queue
<= static_priority_end
);
89 config
.s
.qos_mask
= 0xff;
91 cmd_res
= cvmx_cmd_queue_initialize(
92 CVMX_CMD_QUEUE_PKO(base_queue
+ queue
),
93 CVMX_PKO_MAX_QUEUE_DEPTH
,
94 CVMX_FPA_OUTPUT_BUFFER_POOL
,
95 (CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE
-
96 CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST
* 8));
99 "%s: cmd_res=%d pko_port=%d base_queue=%d num_queues=%d queue=%d\n",
100 __func__
, (int)cmd_res
, pko_port
, base_queue
,
103 buf_ptr
= (uint64_t *)cvmx_cmd_queue_buffer(
104 CVMX_CMD_QUEUE_PKO(base_queue
+ queue
));
105 config
.s
.buf_ptr
= cvmx_ptr_to_phys(buf_ptr
) >> 7;
107 cvmx_write_csr(CVMX_PKO_MEM_IQUEUE_PTRS
, config
.u64
);
111 static void __cvmx_pko_queue_alloc_o68(void)
115 for (port
= 0; port
< 48; port
++)
116 __cvmx_pko_iport_config(port
);
119 static void __cvmx_pko_port_map_o68(void)
122 int interface
, index
;
123 cvmx_helper_interface_mode_t mode
;
124 union cvmx_pko_mem_iport_ptrs config
;
127 * Initialize every iport with the invalid eid.
130 config
.s
.eid
= 31; /* Invalid */
131 for (port
= 0; port
< 128; port
++) {
132 config
.s
.ipid
= port
;
133 cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS
, config
.u64
);
137 * Set up PKO_MEM_IPORT_PTRS
139 for (port
= 0; port
< 48; port
++) {
140 interface
= cvmx_helper_get_interface_num(port
);
141 index
= cvmx_helper_get_interface_index_num(port
);
142 mode
= cvmx_helper_interface_get_mode(interface
);
143 if (mode
== CVMX_HELPER_INTERFACE_MODE_DISABLED
)
146 config
.s
.ipid
= port
;
147 config
.s
.qos_mask
= 0xff;
149 config
.s
.min_pkt
= 1;
150 config
.s
.intr
= __cvmx_pko_int(interface
, index
);
151 config
.s
.eid
= config
.s
.intr
;
152 config
.s
.pipe
= (mode
== CVMX_HELPER_INTERFACE_MODE_LOOP
) ?
154 cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS
, config
.u64
);
158 static void __cvmx_pko_chip_init(void)
162 if (OCTEON_IS_MODEL(OCTEON_CN68XX
)) {
163 __cvmx_pko_port_map_o68();
164 __cvmx_pko_queue_alloc_o68();
171 for (i
= 0; i
< CVMX_PKO_MAX_OUTPUT_QUEUES
; i
++) {
172 const uint64_t priority
= 8;
174 cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID
, i
, 1,
180 * Call before any other calls to initialize the packet
181 * output system. This does chip global config, and should only be
185 void cvmx_pko_initialize_global(void)
187 union cvmx_pko_reg_cmd_buf config
;
190 * Set the size of the PKO command buffers to an odd number of
191 * 64bit words. This allows the normal two word send to stay
192 * aligned and never span a command word buffer.
195 config
.s
.pool
= CVMX_FPA_OUTPUT_BUFFER_POOL
;
196 config
.s
.size
= CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE
/ 8 - 1;
198 cvmx_write_csr(CVMX_PKO_REG_CMD_BUF
, config
.u64
);
201 * Chip-specific setup.
203 __cvmx_pko_chip_init();
206 * If we aren't using all of the queues optimize PKO's
209 if (OCTEON_IS_MODEL(OCTEON_CN38XX
) || OCTEON_IS_MODEL(OCTEON_CN58XX
)
210 || OCTEON_IS_MODEL(OCTEON_CN56XX
)
211 || OCTEON_IS_MODEL(OCTEON_CN52XX
)) {
212 int num_interfaces
= cvmx_helper_get_number_of_interfaces();
214 cvmx_helper_get_last_ipd_port(num_interfaces
- 1);
216 cvmx_pko_get_base_queue(last_port
) +
217 cvmx_pko_get_num_queues(last_port
);
218 if (OCTEON_IS_MODEL(OCTEON_CN38XX
)) {
219 if (max_queues
<= 32)
220 cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE
, 2);
221 else if (max_queues
<= 64)
222 cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE
, 1);
224 if (max_queues
<= 64)
225 cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE
, 2);
226 else if (max_queues
<= 128)
227 cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE
, 1);
233 * Enables the packet output hardware. It must already be
236 void cvmx_pko_enable(void)
238 union cvmx_pko_reg_flags flags
;
240 flags
.u64
= cvmx_read_csr(CVMX_PKO_REG_FLAGS
);
243 ("Warning: Enabling PKO when PKO already enabled.\n");
248 * always enable big endian for 3-word command. Does nothing
251 flags
.s
.store_be
= 1;
252 cvmx_write_csr(CVMX_PKO_REG_FLAGS
, flags
.u64
);
256 * Disables the packet output. Does not affect any configuration.
258 void cvmx_pko_disable(void)
260 union cvmx_pko_reg_flags pko_reg_flags
;
261 pko_reg_flags
.u64
= cvmx_read_csr(CVMX_PKO_REG_FLAGS
);
262 pko_reg_flags
.s
.ena_pko
= 0;
263 cvmx_write_csr(CVMX_PKO_REG_FLAGS
, pko_reg_flags
.u64
);
265 EXPORT_SYMBOL_GPL(cvmx_pko_disable
);
268 * Reset the packet output.
270 static void __cvmx_pko_reset(void)
272 union cvmx_pko_reg_flags pko_reg_flags
;
273 pko_reg_flags
.u64
= cvmx_read_csr(CVMX_PKO_REG_FLAGS
);
274 pko_reg_flags
.s
.reset
= 1;
275 cvmx_write_csr(CVMX_PKO_REG_FLAGS
, pko_reg_flags
.u64
);
279 * Shutdown and free resources required by packet output.
281 void cvmx_pko_shutdown(void)
283 union cvmx_pko_mem_queue_ptrs config
;
288 for (queue
= 0; queue
< CVMX_PKO_MAX_OUTPUT_QUEUES
; queue
++) {
292 config
.s
.port
= CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID
;
293 config
.s
.queue
= queue
& 0x7f;
294 config
.s
.qos_mask
= 0;
295 config
.s
.buf_ptr
= 0;
296 if (!OCTEON_IS_MODEL(OCTEON_CN3XXX
)) {
297 union cvmx_pko_reg_queue_ptrs1 config1
;
299 config1
.s
.qid7
= queue
>> 7;
300 cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1
, config1
.u64
);
302 cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS
, config
.u64
);
303 cvmx_cmd_queue_shutdown(CVMX_CMD_QUEUE_PKO(queue
));
307 EXPORT_SYMBOL_GPL(cvmx_pko_shutdown
);
310 * Configure a output port and the associated queues for use.
312 * @port: Port to configure.
313 * @base_queue: First queue number to associate with this port.
314 * @num_queues: Number of queues to associate with this port
315 * @priority: Array of priority levels for each queue. Values are
316 * allowed to be 0-8. A value of 8 get 8 times the traffic
317 * of a value of 1. A value of 0 indicates that no rounds
318 * will be participated in. These priorities can be changed
319 * on the fly while the pko is enabled. A priority of 9
320 * indicates that static priority should be used. If static
321 * priority is used all queues with static priority must be
322 * contiguous starting at the base_queue, and lower numbered
323 * queues have higher priority than higher numbered queues.
324 * There must be num_queues elements in the array.
326 cvmx_pko_status_t
cvmx_pko_config_port(uint64_t port
, uint64_t base_queue
,
328 const uint64_t priority
[])
330 cvmx_pko_status_t result_code
;
332 union cvmx_pko_mem_queue_ptrs config
;
333 union cvmx_pko_reg_queue_ptrs1 config1
;
334 int static_priority_base
= -1;
335 int static_priority_end
= -1;
337 if (OCTEON_IS_MODEL(OCTEON_CN68XX
))
338 return CVMX_PKO_SUCCESS
;
340 if ((port
>= CVMX_PKO_NUM_OUTPUT_PORTS
)
341 && (port
!= CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID
)) {
342 cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid port %llu\n",
343 (unsigned long long)port
);
344 return CVMX_PKO_INVALID_PORT
;
347 if (base_queue
+ num_queues
> CVMX_PKO_MAX_OUTPUT_QUEUES
) {
349 ("ERROR: cvmx_pko_config_port: Invalid queue range %llu\n",
350 (unsigned long long)(base_queue
+ num_queues
));
351 return CVMX_PKO_INVALID_QUEUE
;
354 if (port
!= CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID
) {
356 * Validate the static queue priority setup and set
357 * static_priority_base and static_priority_end
360 for (queue
= 0; queue
< num_queues
; queue
++) {
361 /* Find first queue of static priority */
362 if (static_priority_base
== -1
363 && priority
[queue
] ==
364 CVMX_PKO_QUEUE_STATIC_PRIORITY
)
365 static_priority_base
= queue
;
366 /* Find last queue of static priority */
367 if (static_priority_base
!= -1
368 && static_priority_end
== -1
369 && priority
[queue
] != CVMX_PKO_QUEUE_STATIC_PRIORITY
371 static_priority_end
= queue
- 1;
372 else if (static_priority_base
!= -1
373 && static_priority_end
== -1
374 && queue
== num_queues
- 1)
375 /* all queues are static priority */
376 static_priority_end
= queue
;
378 * Check to make sure all static priority
379 * queues are contiguous. Also catches some
380 * cases of static priorities not starting at
383 if (static_priority_end
!= -1
384 && (int)queue
> static_priority_end
385 && priority
[queue
] ==
386 CVMX_PKO_QUEUE_STATIC_PRIORITY
) {
387 cvmx_dprintf("ERROR: cvmx_pko_config_port: "
388 "Static priority queues aren't "
389 "contiguous or don't start at "
390 "base queue. q: %d, eq: %d\n",
391 (int)queue
, static_priority_end
);
392 return CVMX_PKO_INVALID_PRIORITY
;
395 if (static_priority_base
> 0) {
396 cvmx_dprintf("ERROR: cvmx_pko_config_port: Static "
397 "priority queues don't start at base "
399 static_priority_base
);
400 return CVMX_PKO_INVALID_PRIORITY
;
403 cvmx_dprintf("Port %d: Static priority queue base: %d, "
405 static_priority_base
, static_priority_end
);
409 * At this point, static_priority_base and static_priority_end
410 * are either both -1, or are valid start/end queue
414 result_code
= CVMX_PKO_SUCCESS
;
417 cvmx_dprintf("num queues: %d (%lld,%lld)\n", num_queues
,
418 CVMX_PKO_QUEUES_PER_PORT_INTERFACE0
,
419 CVMX_PKO_QUEUES_PER_PORT_INTERFACE1
);
422 for (queue
= 0; queue
< num_queues
; queue
++) {
423 uint64_t *buf_ptr
= NULL
;
426 config1
.s
.idx3
= queue
>> 3;
427 config1
.s
.qid7
= (base_queue
+ queue
) >> 7;
430 config
.s
.tail
= queue
== (num_queues
- 1);
431 config
.s
.index
= queue
;
432 config
.s
.port
= port
;
433 config
.s
.queue
= base_queue
+ queue
;
435 if (!cvmx_octeon_is_pass1()) {
436 config
.s
.static_p
= static_priority_base
>= 0;
437 config
.s
.static_q
= (int)queue
<= static_priority_end
;
438 config
.s
.s_tail
= (int)queue
== static_priority_end
;
441 * Convert the priority into an enable bit field. Try
442 * to space the bits out evenly so the packet don't
445 switch ((int)priority
[queue
]) {
447 config
.s
.qos_mask
= 0x00;
450 config
.s
.qos_mask
= 0x01;
453 config
.s
.qos_mask
= 0x11;
456 config
.s
.qos_mask
= 0x49;
459 config
.s
.qos_mask
= 0x55;
462 config
.s
.qos_mask
= 0x57;
465 config
.s
.qos_mask
= 0x77;
468 config
.s
.qos_mask
= 0x7f;
471 config
.s
.qos_mask
= 0xff;
473 case CVMX_PKO_QUEUE_STATIC_PRIORITY
:
474 if (!cvmx_octeon_is_pass1()) {
475 config
.s
.qos_mask
= 0xff;
478 fallthrough
; /* to the error case, when Pass 1 */
480 cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid "
482 (unsigned long long)priority
[queue
]);
483 config
.s
.qos_mask
= 0xff;
484 result_code
= CVMX_PKO_INVALID_PRIORITY
;
488 if (port
!= CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID
) {
489 cvmx_cmd_queue_result_t cmd_res
=
490 cvmx_cmd_queue_initialize(CVMX_CMD_QUEUE_PKO
491 (base_queue
+ queue
),
492 CVMX_PKO_MAX_QUEUE_DEPTH
,
493 CVMX_FPA_OUTPUT_BUFFER_POOL
,
494 CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE
496 CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST
498 if (cmd_res
!= CVMX_CMD_QUEUE_SUCCESS
) {
500 case CVMX_CMD_QUEUE_NO_MEMORY
:
501 cvmx_dprintf("ERROR: "
502 "cvmx_pko_config_port: "
503 "Unable to allocate "
505 return CVMX_PKO_NO_MEMORY
;
506 case CVMX_CMD_QUEUE_ALREADY_SETUP
:
508 ("ERROR: cvmx_pko_config_port: Port already setup.\n");
509 return CVMX_PKO_PORT_ALREADY_SETUP
;
510 case CVMX_CMD_QUEUE_INVALID_PARAM
:
513 ("ERROR: cvmx_pko_config_port: Command queue initialization failed.\n");
514 return CVMX_PKO_CMD_QUEUE_INIT_ERROR
;
520 cvmx_cmd_queue_buffer(CVMX_CMD_QUEUE_PKO
521 (base_queue
+ queue
));
522 config
.s
.buf_ptr
= cvmx_ptr_to_phys(buf_ptr
);
524 config
.s
.buf_ptr
= 0;
528 if (!OCTEON_IS_MODEL(OCTEON_CN3XXX
))
529 cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1
, config1
.u64
);
530 cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS
, config
.u64
);
538 * Show map of ports -> queues for different cores.
540 void cvmx_pko_show_queue_map()
543 int pko_output_ports
= 36;
545 cvmx_dprintf("port");
546 for (port
= 0; port
< pko_output_ports
; port
++)
547 cvmx_dprintf("%3d ", port
);
550 for (core
= 0; core
< CVMX_MAX_CORES
; core
++) {
551 cvmx_dprintf("\n%2d: ", core
);
552 for (port
= 0; port
< pko_output_ports
; port
++) {
554 cvmx_pko_get_base_queue_per_core(port
,
563 * Rate limit a PKO port to a max packets/sec. This function is only
564 * supported on CN51XX and higher, excluding CN58XX.
566 * @port: Port to rate limit
567 * @packets_s: Maximum packet/sec
568 * @burst: Maximum number of packets to burst in a row before rate
571 * Returns Zero on success, negative on failure
573 int cvmx_pko_rate_limit_packets(int port
, int packets_s
, int burst
)
575 union cvmx_pko_mem_port_rate0 pko_mem_port_rate0
;
576 union cvmx_pko_mem_port_rate1 pko_mem_port_rate1
;
578 pko_mem_port_rate0
.u64
= 0;
579 pko_mem_port_rate0
.s
.pid
= port
;
580 pko_mem_port_rate0
.s
.rate_pkt
=
581 cvmx_sysinfo_get()->cpu_clock_hz
/ packets_s
/ 16;
582 /* No cost per word since we are limited by packets/sec, not bits/sec */
583 pko_mem_port_rate0
.s
.rate_word
= 0;
585 pko_mem_port_rate1
.u64
= 0;
586 pko_mem_port_rate1
.s
.pid
= port
;
587 pko_mem_port_rate1
.s
.rate_lim
=
588 ((uint64_t) pko_mem_port_rate0
.s
.rate_pkt
* burst
) >> 8;
590 cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0
, pko_mem_port_rate0
.u64
);
591 cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1
, pko_mem_port_rate1
.u64
);
596 * Rate limit a PKO port to a max bits/sec. This function is only
597 * supported on CN51XX and higher, excluding CN58XX.
599 * @port: Port to rate limit
600 * @bits_s: PKO rate limit in bits/sec
601 * @burst: Maximum number of bits to burst before rate
604 * Returns Zero on success, negative on failure
606 int cvmx_pko_rate_limit_bits(int port
, uint64_t bits_s
, int burst
)
608 union cvmx_pko_mem_port_rate0 pko_mem_port_rate0
;
609 union cvmx_pko_mem_port_rate1 pko_mem_port_rate1
;
610 uint64_t clock_rate
= cvmx_sysinfo_get()->cpu_clock_hz
;
611 uint64_t tokens_per_bit
= clock_rate
* 16 / bits_s
;
613 pko_mem_port_rate0
.u64
= 0;
614 pko_mem_port_rate0
.s
.pid
= port
;
616 * Each packet has a 12 bytes of interframe gap, an 8 byte
617 * preamble, and a 4 byte CRC. These are not included in the
618 * per word count. Multiply by 8 to convert to bits and divide
619 * by 256 for limit granularity.
621 pko_mem_port_rate0
.s
.rate_pkt
= (12 + 8 + 4) * 8 * tokens_per_bit
/ 256;
622 /* Each 8 byte word has 64bits */
623 pko_mem_port_rate0
.s
.rate_word
= 64 * tokens_per_bit
;
625 pko_mem_port_rate1
.u64
= 0;
626 pko_mem_port_rate1
.s
.pid
= port
;
627 pko_mem_port_rate1
.s
.rate_lim
= tokens_per_bit
* burst
/ 256;
629 cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0
, pko_mem_port_rate0
.u64
);
630 cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1
, pko_mem_port_rate1
.u64
);