1 /***********************license start***************
2 * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * * Neither the name of Cavium Networks nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
23 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
24 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
25 * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
26 * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
27 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
28 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
29 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
30 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
31 * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
32 * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
35 * For any questions regarding licensing please contact marketing@caviumnetworks.com
37 ***********************license end**************************************/
47 * Support library for the hardware Packet Output unit.
49 * <hr>$Revision: 42150 $<hr>
53 #include "cvmx-sysinfo.h"
54 #include "cvmx-helper.h"
57 * Internal state of packet output
60 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
63 * Call before any other calls to initialize the packet
64 * output system. This does chip global config, and should only be
68 void cvmx_pko_initialize_global(void)
71 uint64_t priority = 8;
72 cvmx_pko_pool_cfg_t config;
74 /* Set the size of the PKO command buffers to an odd number of 64bit
75 words. This allows the normal two word send to stay aligned and never
76 span a comamnd word buffer. */
78 config.s.pool = CVMX_FPA_OUTPUT_BUFFER_POOL;
79 config.s.size = CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE / 8 - 1;
81 cvmx_write_csr(CVMX_PKO_REG_CMD_BUF, config.u64);
83 for (i=0; i<CVMX_PKO_MAX_OUTPUT_QUEUES; i++)
84 cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1, &priority);
86 /* If we aren't using all of the queues optimize PKO's internal memory */
87 if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
89 int num_interfaces = cvmx_helper_get_number_of_interfaces();
90 int last_port = cvmx_helper_get_last_ipd_port(num_interfaces-1);
91 int max_queues = cvmx_pko_get_base_queue(last_port) + cvmx_pko_get_num_queues(last_port);
92 if (OCTEON_IS_MODEL(OCTEON_CN38XX))
95 cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 2);
96 else if (max_queues <= 64)
97 cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 1);
101 if (max_queues <= 64)
102 cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 2);
103 else if (max_queues <= 128)
104 cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 1);
110 * This function does per-core initialization required by the PKO routines.
111 * This must be called on all cores that will do packet output, and must
112 * be called after the FPA has been initialized and filled with pages.
114 * @return 0 on success
117 int cvmx_pko_initialize_local(void)
125 * Enables the packet output hardware. It must already be
128 void cvmx_pko_enable(void)
130 cvmx_pko_reg_flags_t flags;
132 flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS);
134 cvmx_dprintf("Warning: Enabling PKO when PKO already enabled.\n");
138 flags.s.store_be =1; /* always enable big endian for 3-word command. Does nothing for 2-word */
139 cvmx_write_csr(CVMX_PKO_REG_FLAGS, flags.u64);
144 * Disables the packet output. Does not affect any configuration.
146 void cvmx_pko_disable(void)
148 cvmx_pko_reg_flags_t pko_reg_flags;
149 pko_reg_flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS);
150 pko_reg_flags.s.ena_pko = 0;
151 cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64);
155 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
158 * Reset the packet output.
160 static void __cvmx_pko_reset(void)
162 cvmx_pko_reg_flags_t pko_reg_flags;
163 pko_reg_flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS);
164 pko_reg_flags.s.reset = 1;
165 cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64);
170 * Shutdown and free resources required by packet output.
172 void cvmx_pko_shutdown(void)
174 cvmx_pko_queue_cfg_t config;
179 for (queue=0; queue<CVMX_PKO_MAX_OUTPUT_QUEUES; queue++)
184 config.s.port = CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID;
185 config.s.queue = queue & 0x7f;
186 config.s.qos_mask = 0;
187 config.s.buf_ptr = 0;
188 if (!OCTEON_IS_MODEL(OCTEON_CN3XXX))
190 cvmx_pko_reg_queue_ptrs1_t config1;
192 config1.s.qid7 = queue >> 7;
193 cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64);
195 cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64);
196 cvmx_cmd_queue_shutdown(CVMX_CMD_QUEUE_PKO(queue));
203 * Configure a output port and the associated queues for use.
205 * @param port Port to configure.
206 * @param base_queue First queue number to associate with this port.
207 * @param num_queues Number of queues to associate with this port
208 * @param priority Array of priority levels for each queue. Values are
209 * allowed to be 0-8. A value of 8 get 8 times the traffic
210 * of a value of 1. A value of 0 indicates that no rounds
211 * will be participated in. These priorities can be changed
212 * on the fly while the pko is enabled. A priority of 9
213 * indicates that static priority should be used. If static
214 * priority is used all queues with static priority must be
215 * contiguous starting at the base_queue, and lower numbered
216 * queues have higher priority than higher numbered queues.
217 * There must be num_queues elements in the array.
219 cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue, uint64_t num_queues, const uint64_t priority[])
221 cvmx_pko_status_t result_code;
223 cvmx_pko_queue_cfg_t config;
224 cvmx_pko_reg_queue_ptrs1_t config1;
225 int static_priority_base = -1;
226 int static_priority_end = -1;
229 if ((port >= CVMX_PKO_NUM_OUTPUT_PORTS) && (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID))
231 cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid port %llu\n", (unsigned long long)port);
232 return CVMX_PKO_INVALID_PORT;
235 if (base_queue + num_queues > CVMX_PKO_MAX_OUTPUT_QUEUES)
237 cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid queue range %llu\n", (unsigned long long)(base_queue + num_queues));
238 return CVMX_PKO_INVALID_QUEUE;
241 if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID)
243 /* Validate the static queue priority setup and set static_priority_base and static_priority_end
245 for (queue = 0; queue < num_queues; queue++)
247 /* Find first queue of static priority */
248 if (static_priority_base == -1 && priority[queue] == CVMX_PKO_QUEUE_STATIC_PRIORITY)
249 static_priority_base = queue;
250 /* Find last queue of static priority */
251 if (static_priority_base != -1 && static_priority_end == -1 && priority[queue] != CVMX_PKO_QUEUE_STATIC_PRIORITY && queue)
252 static_priority_end = queue - 1;
253 else if (static_priority_base != -1 && static_priority_end == -1 && queue == num_queues - 1)
254 static_priority_end = queue; /* all queues are static priority */
255 /* Check to make sure all static priority queues are contiguous. Also catches some cases of
256 ** static priorites not starting at queue 0. */
257 if (static_priority_end != -1 && (int)queue > static_priority_end && priority[queue] == CVMX_PKO_QUEUE_STATIC_PRIORITY)
259 cvmx_dprintf("ERROR: cvmx_pko_config_port: Static priority queues aren't contiguous or don't start at base queue. q: %d, eq: %d\n", (int)queue, static_priority_end);
260 return CVMX_PKO_INVALID_PRIORITY;
263 if (static_priority_base > 0)
265 cvmx_dprintf("ERROR: cvmx_pko_config_port: Static priority queues don't start at base queue. sq: %d\n", static_priority_base);
266 return CVMX_PKO_INVALID_PRIORITY;
269 cvmx_dprintf("Port %d: Static priority queue base: %d, end: %d\n", port, static_priority_base, static_priority_end);
272 /* At this point, static_priority_base and static_priority_end are either both -1,
273 ** or are valid start/end queue numbers */
275 result_code = CVMX_PKO_SUCCESS;
278 cvmx_dprintf("num queues: %d (%lld,%lld)\n", num_queues, CVMX_PKO_QUEUES_PER_PORT_INTERFACE0, CVMX_PKO_QUEUES_PER_PORT_INTERFACE1);
281 for (queue = 0; queue < num_queues; queue++)
283 uint64_t *buf_ptr = NULL;
286 config1.s.idx3 = queue >> 3;
287 config1.s.qid7 = (base_queue + queue) >> 7;
290 config.s.tail = queue == (num_queues - 1);
291 config.s.index = queue;
292 config.s.port = port;
293 config.s.queue = base_queue + queue;
295 if (!cvmx_octeon_is_pass1())
297 config.s.static_p = static_priority_base >= 0;
298 config.s.static_q = (int)queue <= static_priority_end;
299 config.s.s_tail = (int)queue == static_priority_end;
301 /* Convert the priority into an enable bit field. Try to space the bits
302 out evenly so the packet don't get grouped up */
303 switch ((int)priority[queue])
305 case 0: config.s.qos_mask = 0x00; break;
306 case 1: config.s.qos_mask = 0x01; break;
307 case 2: config.s.qos_mask = 0x11; break;
308 case 3: config.s.qos_mask = 0x49; break;
309 case 4: config.s.qos_mask = 0x55; break;
310 case 5: config.s.qos_mask = 0x57; break;
311 case 6: config.s.qos_mask = 0x77; break;
312 case 7: config.s.qos_mask = 0x7f; break;
313 case 8: config.s.qos_mask = 0xff; break;
314 case CVMX_PKO_QUEUE_STATIC_PRIORITY:
315 if (!cvmx_octeon_is_pass1()) /* Pass 1 will fall through to the error case */
317 config.s.qos_mask = 0xff;
321 cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid priority %llu\n", (unsigned long long)priority[queue]);
322 config.s.qos_mask = 0xff;
323 result_code = CVMX_PKO_INVALID_PRIORITY;
327 if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID)
329 cvmx_cmd_queue_result_t cmd_res = cvmx_cmd_queue_initialize(CVMX_CMD_QUEUE_PKO(base_queue + queue),
330 CVMX_PKO_MAX_QUEUE_DEPTH,
331 CVMX_FPA_OUTPUT_BUFFER_POOL,
332 CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE - CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST*8);
333 if (cmd_res != CVMX_CMD_QUEUE_SUCCESS)
337 case CVMX_CMD_QUEUE_NO_MEMORY:
338 cvmx_dprintf("ERROR: cvmx_pko_config_port: Unable to allocate output buffer.\n");
339 return(CVMX_PKO_NO_MEMORY);
340 case CVMX_CMD_QUEUE_ALREADY_SETUP:
341 cvmx_dprintf("ERROR: cvmx_pko_config_port: Port already setup.\n");
342 return(CVMX_PKO_PORT_ALREADY_SETUP);
343 case CVMX_CMD_QUEUE_INVALID_PARAM:
345 cvmx_dprintf("ERROR: cvmx_pko_config_port: Command queue initialization failed.\n");
346 return(CVMX_PKO_CMD_QUEUE_INIT_ERROR);
350 buf_ptr = (uint64_t*)cvmx_cmd_queue_buffer(CVMX_CMD_QUEUE_PKO(base_queue + queue));
351 config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr);
354 config.s.buf_ptr = 0;
358 if (!OCTEON_IS_MODEL(OCTEON_CN3XXX))
360 cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64);
362 cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64);
370 * Show map of ports -> queues for different cores.
372 void cvmx_pko_show_queue_map()
375 int pko_output_ports = 36;
377 cvmx_dprintf("port");
378 for(port=0; port<pko_output_ports; port++)
379 cvmx_dprintf("%3d ", port);
382 for(core=0; core<CVMX_MAX_CORES; core++)
384 cvmx_dprintf("\n%2d: ", core);
385 for(port=0; port<pko_output_ports; port++)
387 cvmx_dprintf("%3d ", cvmx_pko_get_base_queue_per_core(port, core));
396 * Rate limit a PKO port to a max packets/sec. This function is only
397 * supported on CN51XX and higher, excluding CN58XX.
399 * @param port Port to rate limit
400 * @param packets_s Maximum packet/sec
401 * @param burst Maximum number of packets to burst in a row before rate
404 * @return Zero on success, negative on failure
406 int cvmx_pko_rate_limit_packets(int port, int packets_s, int burst)
408 cvmx_pko_mem_port_rate0_t pko_mem_port_rate0;
409 cvmx_pko_mem_port_rate1_t pko_mem_port_rate1;
411 pko_mem_port_rate0.u64 = 0;
412 pko_mem_port_rate0.s.pid = port;
413 pko_mem_port_rate0.s.rate_pkt = cvmx_sysinfo_get()->cpu_clock_hz / packets_s / 16;
414 /* No cost per word since we are limited by packets/sec, not bits/sec */
415 pko_mem_port_rate0.s.rate_word = 0;
417 pko_mem_port_rate1.u64 = 0;
418 pko_mem_port_rate1.s.pid = port;
419 pko_mem_port_rate1.s.rate_lim = ((uint64_t)pko_mem_port_rate0.s.rate_pkt * burst) >> 8;
421 cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0, pko_mem_port_rate0.u64);
422 cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1, pko_mem_port_rate1.u64);
428 * Rate limit a PKO port to a max bits/sec. This function is only
429 * supported on CN51XX and higher, excluding CN58XX.
431 * @param port Port to rate limit
432 * @param bits_s PKO rate limit in bits/sec
433 * @param burst Maximum number of bits to burst before rate
436 * @return Zero on success, negative on failure
438 int cvmx_pko_rate_limit_bits(int port, uint64_t bits_s, int burst)
440 cvmx_pko_mem_port_rate0_t pko_mem_port_rate0;
441 cvmx_pko_mem_port_rate1_t pko_mem_port_rate1;
442 uint64_t clock_rate = cvmx_sysinfo_get()->cpu_clock_hz;
443 uint64_t tokens_per_bit = clock_rate*16 / bits_s;
445 pko_mem_port_rate0.u64 = 0;
446 pko_mem_port_rate0.s.pid = port;
447 /* Each packet has a 12 bytes of interframe gap, an 8 byte preamble, and a
448 4 byte CRC. These are not included in the per word count. Multiply
449 by 8 to covert to bits and divide by 256 for limit granularity */
450 pko_mem_port_rate0.s.rate_pkt = (12 + 8 + 4) * 8 * tokens_per_bit / 256;
451 /* Each 8 byte word has 64bits */
452 pko_mem_port_rate0.s.rate_word = 64 * tokens_per_bit;
454 pko_mem_port_rate1.u64 = 0;
455 pko_mem_port_rate1.s.pid = port;
456 pko_mem_port_rate1.s.rate_lim = tokens_per_bit * burst / 256;
458 cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0, pko_mem_port_rate0.u64);
459 cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1, pko_mem_port_rate1.u64);
463 #endif /* CVMX_ENABLE_PKO_FUNCTIONS */