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
43 * Call before any other calls to initialize the packet
44 * output system. This does chip global config, and should only be
48 void cvmx_pko_initialize_global(void)
51 uint64_t priority
= 8;
52 union cvmx_pko_reg_cmd_buf config
;
55 * Set the size of the PKO command buffers to an odd number of
56 * 64bit words. This allows the normal two word send to stay
57 * aligned and never span a comamnd word buffer.
60 config
.s
.pool
= CVMX_FPA_OUTPUT_BUFFER_POOL
;
61 config
.s
.size
= CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE
/ 8 - 1;
63 cvmx_write_csr(CVMX_PKO_REG_CMD_BUF
, config
.u64
);
65 for (i
= 0; i
< CVMX_PKO_MAX_OUTPUT_QUEUES
; i
++)
66 cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID
, i
, 1,
70 * If we aren't using all of the queues optimize PKO's
73 if (OCTEON_IS_MODEL(OCTEON_CN38XX
) || OCTEON_IS_MODEL(OCTEON_CN58XX
)
74 || OCTEON_IS_MODEL(OCTEON_CN56XX
)
75 || OCTEON_IS_MODEL(OCTEON_CN52XX
)) {
76 int num_interfaces
= cvmx_helper_get_number_of_interfaces();
78 cvmx_helper_get_last_ipd_port(num_interfaces
- 1);
80 cvmx_pko_get_base_queue(last_port
) +
81 cvmx_pko_get_num_queues(last_port
);
82 if (OCTEON_IS_MODEL(OCTEON_CN38XX
)) {
84 cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE
, 2);
85 else if (max_queues
<= 64)
86 cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE
, 1);
89 cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE
, 2);
90 else if (max_queues
<= 128)
91 cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE
, 1);
97 * This function does per-core initialization required by the PKO routines.
98 * This must be called on all cores that will do packet output, and must
99 * be called after the FPA has been initialized and filled with pages.
101 * Returns 0 on success
104 int cvmx_pko_initialize_local(void)
111 * Enables the packet output hardware. It must already be
114 void cvmx_pko_enable(void)
116 union cvmx_pko_reg_flags flags
;
118 flags
.u64
= cvmx_read_csr(CVMX_PKO_REG_FLAGS
);
121 ("Warning: Enabling PKO when PKO already enabled.\n");
126 * always enable big endian for 3-word command. Does nothing
129 flags
.s
.store_be
= 1;
130 cvmx_write_csr(CVMX_PKO_REG_FLAGS
, flags
.u64
);
134 * Disables the packet output. Does not affect any configuration.
136 void cvmx_pko_disable(void)
138 union cvmx_pko_reg_flags pko_reg_flags
;
139 pko_reg_flags
.u64
= cvmx_read_csr(CVMX_PKO_REG_FLAGS
);
140 pko_reg_flags
.s
.ena_pko
= 0;
141 cvmx_write_csr(CVMX_PKO_REG_FLAGS
, pko_reg_flags
.u64
);
143 EXPORT_SYMBOL_GPL(cvmx_pko_disable
);
146 * Reset the packet output.
148 static void __cvmx_pko_reset(void)
150 union cvmx_pko_reg_flags pko_reg_flags
;
151 pko_reg_flags
.u64
= cvmx_read_csr(CVMX_PKO_REG_FLAGS
);
152 pko_reg_flags
.s
.reset
= 1;
153 cvmx_write_csr(CVMX_PKO_REG_FLAGS
, pko_reg_flags
.u64
);
157 * Shutdown and free resources required by packet output.
159 void cvmx_pko_shutdown(void)
161 union cvmx_pko_mem_queue_ptrs config
;
166 for (queue
= 0; queue
< CVMX_PKO_MAX_OUTPUT_QUEUES
; queue
++) {
170 config
.s
.port
= CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID
;
171 config
.s
.queue
= queue
& 0x7f;
172 config
.s
.qos_mask
= 0;
173 config
.s
.buf_ptr
= 0;
174 if (!OCTEON_IS_MODEL(OCTEON_CN3XXX
)) {
175 union cvmx_pko_reg_queue_ptrs1 config1
;
177 config1
.s
.qid7
= queue
>> 7;
178 cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1
, config1
.u64
);
180 cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS
, config
.u64
);
181 cvmx_cmd_queue_shutdown(CVMX_CMD_QUEUE_PKO(queue
));
185 EXPORT_SYMBOL_GPL(cvmx_pko_shutdown
);
188 * Configure a output port and the associated queues for use.
190 * @port: Port to configure.
191 * @base_queue: First queue number to associate with this port.
192 * @num_queues: Number of queues to associate with this port
193 * @priority: Array of priority levels for each queue. Values are
194 * allowed to be 0-8. A value of 8 get 8 times the traffic
195 * of a value of 1. A value of 0 indicates that no rounds
196 * will be participated in. These priorities can be changed
197 * on the fly while the pko is enabled. A priority of 9
198 * indicates that static priority should be used. If static
199 * priority is used all queues with static priority must be
200 * contiguous starting at the base_queue, and lower numbered
201 * queues have higher priority than higher numbered queues.
202 * There must be num_queues elements in the array.
204 cvmx_pko_status_t
cvmx_pko_config_port(uint64_t port
, uint64_t base_queue
,
206 const uint64_t priority
[])
208 cvmx_pko_status_t result_code
;
210 union cvmx_pko_mem_queue_ptrs config
;
211 union cvmx_pko_reg_queue_ptrs1 config1
;
212 int static_priority_base
= -1;
213 int static_priority_end
= -1;
215 if ((port
>= CVMX_PKO_NUM_OUTPUT_PORTS
)
216 && (port
!= CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID
)) {
217 cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid port %llu\n",
218 (unsigned long long)port
);
219 return CVMX_PKO_INVALID_PORT
;
222 if (base_queue
+ num_queues
> CVMX_PKO_MAX_OUTPUT_QUEUES
) {
224 ("ERROR: cvmx_pko_config_port: Invalid queue range %llu\n",
225 (unsigned long long)(base_queue
+ num_queues
));
226 return CVMX_PKO_INVALID_QUEUE
;
229 if (port
!= CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID
) {
231 * Validate the static queue priority setup and set
232 * static_priority_base and static_priority_end
235 for (queue
= 0; queue
< num_queues
; queue
++) {
236 /* Find first queue of static priority */
237 if (static_priority_base
== -1
238 && priority
[queue
] ==
239 CVMX_PKO_QUEUE_STATIC_PRIORITY
)
240 static_priority_base
= queue
;
241 /* Find last queue of static priority */
242 if (static_priority_base
!= -1
243 && static_priority_end
== -1
244 && priority
[queue
] != CVMX_PKO_QUEUE_STATIC_PRIORITY
246 static_priority_end
= queue
- 1;
247 else if (static_priority_base
!= -1
248 && static_priority_end
== -1
249 && queue
== num_queues
- 1)
250 /* all queues are static priority */
251 static_priority_end
= queue
;
253 * Check to make sure all static priority
254 * queues are contiguous. Also catches some
255 * cases of static priorites not starting at
258 if (static_priority_end
!= -1
259 && (int)queue
> static_priority_end
260 && priority
[queue
] ==
261 CVMX_PKO_QUEUE_STATIC_PRIORITY
) {
262 cvmx_dprintf("ERROR: cvmx_pko_config_port: "
263 "Static priority queues aren't "
264 "contiguous or don't start at "
265 "base queue. q: %d, eq: %d\n",
266 (int)queue
, static_priority_end
);
267 return CVMX_PKO_INVALID_PRIORITY
;
270 if (static_priority_base
> 0) {
271 cvmx_dprintf("ERROR: cvmx_pko_config_port: Static "
272 "priority queues don't start at base "
274 static_priority_base
);
275 return CVMX_PKO_INVALID_PRIORITY
;
278 cvmx_dprintf("Port %d: Static priority queue base: %d, "
280 static_priority_base
, static_priority_end
);
284 * At this point, static_priority_base and static_priority_end
285 * are either both -1, or are valid start/end queue
289 result_code
= CVMX_PKO_SUCCESS
;
292 cvmx_dprintf("num queues: %d (%lld,%lld)\n", num_queues
,
293 CVMX_PKO_QUEUES_PER_PORT_INTERFACE0
,
294 CVMX_PKO_QUEUES_PER_PORT_INTERFACE1
);
297 for (queue
= 0; queue
< num_queues
; queue
++) {
298 uint64_t *buf_ptr
= NULL
;
301 config1
.s
.idx3
= queue
>> 3;
302 config1
.s
.qid7
= (base_queue
+ queue
) >> 7;
305 config
.s
.tail
= queue
== (num_queues
- 1);
306 config
.s
.index
= queue
;
307 config
.s
.port
= port
;
308 config
.s
.queue
= base_queue
+ queue
;
310 if (!cvmx_octeon_is_pass1()) {
311 config
.s
.static_p
= static_priority_base
>= 0;
312 config
.s
.static_q
= (int)queue
<= static_priority_end
;
313 config
.s
.s_tail
= (int)queue
== static_priority_end
;
316 * Convert the priority into an enable bit field. Try
317 * to space the bits out evenly so the packet don't
320 switch ((int)priority
[queue
]) {
322 config
.s
.qos_mask
= 0x00;
325 config
.s
.qos_mask
= 0x01;
328 config
.s
.qos_mask
= 0x11;
331 config
.s
.qos_mask
= 0x49;
334 config
.s
.qos_mask
= 0x55;
337 config
.s
.qos_mask
= 0x57;
340 config
.s
.qos_mask
= 0x77;
343 config
.s
.qos_mask
= 0x7f;
346 config
.s
.qos_mask
= 0xff;
348 case CVMX_PKO_QUEUE_STATIC_PRIORITY
:
349 /* Pass 1 will fall through to the error case */
350 if (!cvmx_octeon_is_pass1()) {
351 config
.s
.qos_mask
= 0xff;
355 cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid "
357 (unsigned long long)priority
[queue
]);
358 config
.s
.qos_mask
= 0xff;
359 result_code
= CVMX_PKO_INVALID_PRIORITY
;
363 if (port
!= CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID
) {
364 cvmx_cmd_queue_result_t cmd_res
=
365 cvmx_cmd_queue_initialize(CVMX_CMD_QUEUE_PKO
366 (base_queue
+ queue
),
367 CVMX_PKO_MAX_QUEUE_DEPTH
,
368 CVMX_FPA_OUTPUT_BUFFER_POOL
,
369 CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE
371 CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST
373 if (cmd_res
!= CVMX_CMD_QUEUE_SUCCESS
) {
375 case CVMX_CMD_QUEUE_NO_MEMORY
:
376 cvmx_dprintf("ERROR: "
377 "cvmx_pko_config_port: "
378 "Unable to allocate "
380 return CVMX_PKO_NO_MEMORY
;
381 case CVMX_CMD_QUEUE_ALREADY_SETUP
:
383 ("ERROR: cvmx_pko_config_port: Port already setup.\n");
384 return CVMX_PKO_PORT_ALREADY_SETUP
;
385 case CVMX_CMD_QUEUE_INVALID_PARAM
:
388 ("ERROR: cvmx_pko_config_port: Command queue initialization failed.\n");
389 return CVMX_PKO_CMD_QUEUE_INIT_ERROR
;
395 cvmx_cmd_queue_buffer(CVMX_CMD_QUEUE_PKO
396 (base_queue
+ queue
));
397 config
.s
.buf_ptr
= cvmx_ptr_to_phys(buf_ptr
);
399 config
.s
.buf_ptr
= 0;
403 if (!OCTEON_IS_MODEL(OCTEON_CN3XXX
))
404 cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1
, config1
.u64
);
405 cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS
, config
.u64
);
413 * Show map of ports -> queues for different cores.
415 void cvmx_pko_show_queue_map()
418 int pko_output_ports
= 36;
420 cvmx_dprintf("port");
421 for (port
= 0; port
< pko_output_ports
; port
++)
422 cvmx_dprintf("%3d ", port
);
425 for (core
= 0; core
< CVMX_MAX_CORES
; core
++) {
426 cvmx_dprintf("\n%2d: ", core
);
427 for (port
= 0; port
< pko_output_ports
; port
++) {
429 cvmx_pko_get_base_queue_per_core(port
,
438 * Rate limit a PKO port to a max packets/sec. This function is only
439 * supported on CN51XX and higher, excluding CN58XX.
441 * @port: Port to rate limit
442 * @packets_s: Maximum packet/sec
443 * @burst: Maximum number of packets to burst in a row before rate
446 * Returns Zero on success, negative on failure
448 int cvmx_pko_rate_limit_packets(int port
, int packets_s
, int burst
)
450 union cvmx_pko_mem_port_rate0 pko_mem_port_rate0
;
451 union cvmx_pko_mem_port_rate1 pko_mem_port_rate1
;
453 pko_mem_port_rate0
.u64
= 0;
454 pko_mem_port_rate0
.s
.pid
= port
;
455 pko_mem_port_rate0
.s
.rate_pkt
=
456 cvmx_sysinfo_get()->cpu_clock_hz
/ packets_s
/ 16;
457 /* No cost per word since we are limited by packets/sec, not bits/sec */
458 pko_mem_port_rate0
.s
.rate_word
= 0;
460 pko_mem_port_rate1
.u64
= 0;
461 pko_mem_port_rate1
.s
.pid
= port
;
462 pko_mem_port_rate1
.s
.rate_lim
=
463 ((uint64_t) pko_mem_port_rate0
.s
.rate_pkt
* burst
) >> 8;
465 cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0
, pko_mem_port_rate0
.u64
);
466 cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1
, pko_mem_port_rate1
.u64
);
471 * Rate limit a PKO port to a max bits/sec. This function is only
472 * supported on CN51XX and higher, excluding CN58XX.
474 * @port: Port to rate limit
475 * @bits_s: PKO rate limit in bits/sec
476 * @burst: Maximum number of bits to burst before rate
479 * Returns Zero on success, negative on failure
481 int cvmx_pko_rate_limit_bits(int port
, uint64_t bits_s
, int burst
)
483 union cvmx_pko_mem_port_rate0 pko_mem_port_rate0
;
484 union cvmx_pko_mem_port_rate1 pko_mem_port_rate1
;
485 uint64_t clock_rate
= cvmx_sysinfo_get()->cpu_clock_hz
;
486 uint64_t tokens_per_bit
= clock_rate
* 16 / bits_s
;
488 pko_mem_port_rate0
.u64
= 0;
489 pko_mem_port_rate0
.s
.pid
= port
;
491 * Each packet has a 12 bytes of interframe gap, an 8 byte
492 * preamble, and a 4 byte CRC. These are not included in the
493 * per word count. Multiply by 8 to covert to bits and divide
494 * by 256 for limit granularity.
496 pko_mem_port_rate0
.s
.rate_pkt
= (12 + 8 + 4) * 8 * tokens_per_bit
/ 256;
497 /* Each 8 byte word has 64bits */
498 pko_mem_port_rate0
.s
.rate_word
= 64 * tokens_per_bit
;
500 pko_mem_port_rate1
.u64
= 0;
501 pko_mem_port_rate1
.s
.pid
= port
;
502 pko_mem_port_rate1
.s
.rate_lim
= tokens_per_bit
* burst
/ 256;
504 cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0
, pko_mem_port_rate0
.u64
);
505 cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1
, pko_mem_port_rate1
.u64
);