18c2ecf20Sopenharmony_ci/***********************license start*************** 28c2ecf20Sopenharmony_ci * Author: Cavium Networks 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Contact: support@caviumnetworks.com 58c2ecf20Sopenharmony_ci * This file is part of the OCTEON SDK 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2003-2008 Cavium Networks 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This file is free software; you can redistribute it and/or modify 108c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as 118c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but 148c2ecf20Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 158c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 168c2ecf20Sopenharmony_ci * NONINFRINGEMENT. See the GNU General Public License for more 178c2ecf20Sopenharmony_ci * details. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License 208c2ecf20Sopenharmony_ci * along with this file; if not, write to the Free Software 218c2ecf20Sopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 228c2ecf20Sopenharmony_ci * or visit http://www.gnu.org/licenses/. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * This file may also be available under a different license from Cavium. 258c2ecf20Sopenharmony_ci * Contact Cavium Networks for more information 268c2ecf20Sopenharmony_ci ***********************license end**************************************/ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/* 298c2ecf20Sopenharmony_ci * Support library for the hardware Packet Output unit. 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include <asm/octeon/octeon.h> 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-config.h> 358c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-pko.h> 368c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-helper.h> 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/** 398c2ecf20Sopenharmony_ci * Internal state of packet output 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic int __cvmx_pko_int(int interface, int index) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci switch (interface) { 458c2ecf20Sopenharmony_ci case 0: 468c2ecf20Sopenharmony_ci return index; 478c2ecf20Sopenharmony_ci case 1: 488c2ecf20Sopenharmony_ci return 4; 498c2ecf20Sopenharmony_ci case 2: 508c2ecf20Sopenharmony_ci return index + 0x08; 518c2ecf20Sopenharmony_ci case 3: 528c2ecf20Sopenharmony_ci return index + 0x0c; 538c2ecf20Sopenharmony_ci case 4: 548c2ecf20Sopenharmony_ci return index + 0x10; 558c2ecf20Sopenharmony_ci case 5: 568c2ecf20Sopenharmony_ci return 0x1c; 578c2ecf20Sopenharmony_ci case 6: 588c2ecf20Sopenharmony_ci return 0x1d; 598c2ecf20Sopenharmony_ci case 7: 608c2ecf20Sopenharmony_ci return 0x1e; 618c2ecf20Sopenharmony_ci case 8: 628c2ecf20Sopenharmony_ci return 0x1f; 638c2ecf20Sopenharmony_ci default: 648c2ecf20Sopenharmony_ci return -1; 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic void __cvmx_pko_iport_config(int pko_port) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci int queue; 718c2ecf20Sopenharmony_ci const int num_queues = 1; 728c2ecf20Sopenharmony_ci const int base_queue = pko_port; 738c2ecf20Sopenharmony_ci const int static_priority_end = 1; 748c2ecf20Sopenharmony_ci const int static_priority_base = 1; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci for (queue = 0; queue < num_queues; queue++) { 778c2ecf20Sopenharmony_ci union cvmx_pko_mem_iqueue_ptrs config; 788c2ecf20Sopenharmony_ci cvmx_cmd_queue_result_t cmd_res; 798c2ecf20Sopenharmony_ci uint64_t *buf_ptr; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci config.u64 = 0; 828c2ecf20Sopenharmony_ci config.s.index = queue; 838c2ecf20Sopenharmony_ci config.s.qid = base_queue + queue; 848c2ecf20Sopenharmony_ci config.s.ipid = pko_port; 858c2ecf20Sopenharmony_ci config.s.tail = (queue == (num_queues - 1)); 868c2ecf20Sopenharmony_ci config.s.s_tail = (queue == static_priority_end); 878c2ecf20Sopenharmony_ci config.s.static_p = (static_priority_base >= 0); 888c2ecf20Sopenharmony_ci config.s.static_q = (queue <= static_priority_end); 898c2ecf20Sopenharmony_ci config.s.qos_mask = 0xff; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci cmd_res = cvmx_cmd_queue_initialize( 928c2ecf20Sopenharmony_ci CVMX_CMD_QUEUE_PKO(base_queue + queue), 938c2ecf20Sopenharmony_ci CVMX_PKO_MAX_QUEUE_DEPTH, 948c2ecf20Sopenharmony_ci CVMX_FPA_OUTPUT_BUFFER_POOL, 958c2ecf20Sopenharmony_ci (CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE - 968c2ecf20Sopenharmony_ci CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST * 8)); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci WARN(cmd_res, 998c2ecf20Sopenharmony_ci "%s: cmd_res=%d pko_port=%d base_queue=%d num_queues=%d queue=%d\n", 1008c2ecf20Sopenharmony_ci __func__, (int)cmd_res, pko_port, base_queue, 1018c2ecf20Sopenharmony_ci num_queues, queue); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci buf_ptr = (uint64_t *)cvmx_cmd_queue_buffer( 1048c2ecf20Sopenharmony_ci CVMX_CMD_QUEUE_PKO(base_queue + queue)); 1058c2ecf20Sopenharmony_ci config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr) >> 7; 1068c2ecf20Sopenharmony_ci CVMX_SYNCWS; 1078c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_MEM_IQUEUE_PTRS, config.u64); 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic void __cvmx_pko_queue_alloc_o68(void) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci int port; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci for (port = 0; port < 48; port++) 1168c2ecf20Sopenharmony_ci __cvmx_pko_iport_config(port); 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic void __cvmx_pko_port_map_o68(void) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci int port; 1228c2ecf20Sopenharmony_ci int interface, index; 1238c2ecf20Sopenharmony_ci cvmx_helper_interface_mode_t mode; 1248c2ecf20Sopenharmony_ci union cvmx_pko_mem_iport_ptrs config; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* 1278c2ecf20Sopenharmony_ci * Initialize every iport with the invalid eid. 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_ci config.u64 = 0; 1308c2ecf20Sopenharmony_ci config.s.eid = 31; /* Invalid */ 1318c2ecf20Sopenharmony_ci for (port = 0; port < 128; port++) { 1328c2ecf20Sopenharmony_ci config.s.ipid = port; 1338c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS, config.u64); 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci /* 1378c2ecf20Sopenharmony_ci * Set up PKO_MEM_IPORT_PTRS 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci for (port = 0; port < 48; port++) { 1408c2ecf20Sopenharmony_ci interface = cvmx_helper_get_interface_num(port); 1418c2ecf20Sopenharmony_ci index = cvmx_helper_get_interface_index_num(port); 1428c2ecf20Sopenharmony_ci mode = cvmx_helper_interface_get_mode(interface); 1438c2ecf20Sopenharmony_ci if (mode == CVMX_HELPER_INTERFACE_MODE_DISABLED) 1448c2ecf20Sopenharmony_ci continue; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci config.s.ipid = port; 1478c2ecf20Sopenharmony_ci config.s.qos_mask = 0xff; 1488c2ecf20Sopenharmony_ci config.s.crc = 1; 1498c2ecf20Sopenharmony_ci config.s.min_pkt = 1; 1508c2ecf20Sopenharmony_ci config.s.intr = __cvmx_pko_int(interface, index); 1518c2ecf20Sopenharmony_ci config.s.eid = config.s.intr; 1528c2ecf20Sopenharmony_ci config.s.pipe = (mode == CVMX_HELPER_INTERFACE_MODE_LOOP) ? 1538c2ecf20Sopenharmony_ci index : port; 1548c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS, config.u64); 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic void __cvmx_pko_chip_init(void) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci int i; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { 1638c2ecf20Sopenharmony_ci __cvmx_pko_port_map_o68(); 1648c2ecf20Sopenharmony_ci __cvmx_pko_queue_alloc_o68(); 1658c2ecf20Sopenharmony_ci return; 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci /* 1698c2ecf20Sopenharmony_ci * Initialize queues 1708c2ecf20Sopenharmony_ci */ 1718c2ecf20Sopenharmony_ci for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++) { 1728c2ecf20Sopenharmony_ci const uint64_t priority = 8; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1, 1758c2ecf20Sopenharmony_ci &priority); 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci/** 1808c2ecf20Sopenharmony_ci * Call before any other calls to initialize the packet 1818c2ecf20Sopenharmony_ci * output system. This does chip global config, and should only be 1828c2ecf20Sopenharmony_ci * done by one core. 1838c2ecf20Sopenharmony_ci */ 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_civoid cvmx_pko_initialize_global(void) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci union cvmx_pko_reg_cmd_buf config; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci /* 1908c2ecf20Sopenharmony_ci * Set the size of the PKO command buffers to an odd number of 1918c2ecf20Sopenharmony_ci * 64bit words. This allows the normal two word send to stay 1928c2ecf20Sopenharmony_ci * aligned and never span a command word buffer. 1938c2ecf20Sopenharmony_ci */ 1948c2ecf20Sopenharmony_ci config.u64 = 0; 1958c2ecf20Sopenharmony_ci config.s.pool = CVMX_FPA_OUTPUT_BUFFER_POOL; 1968c2ecf20Sopenharmony_ci config.s.size = CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE / 8 - 1; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_REG_CMD_BUF, config.u64); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci /* 2018c2ecf20Sopenharmony_ci * Chip-specific setup. 2028c2ecf20Sopenharmony_ci */ 2038c2ecf20Sopenharmony_ci __cvmx_pko_chip_init(); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci /* 2068c2ecf20Sopenharmony_ci * If we aren't using all of the queues optimize PKO's 2078c2ecf20Sopenharmony_ci * internal memory. 2088c2ecf20Sopenharmony_ci */ 2098c2ecf20Sopenharmony_ci if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX) 2108c2ecf20Sopenharmony_ci || OCTEON_IS_MODEL(OCTEON_CN56XX) 2118c2ecf20Sopenharmony_ci || OCTEON_IS_MODEL(OCTEON_CN52XX)) { 2128c2ecf20Sopenharmony_ci int num_interfaces = cvmx_helper_get_number_of_interfaces(); 2138c2ecf20Sopenharmony_ci int last_port = 2148c2ecf20Sopenharmony_ci cvmx_helper_get_last_ipd_port(num_interfaces - 1); 2158c2ecf20Sopenharmony_ci int max_queues = 2168c2ecf20Sopenharmony_ci cvmx_pko_get_base_queue(last_port) + 2178c2ecf20Sopenharmony_ci cvmx_pko_get_num_queues(last_port); 2188c2ecf20Sopenharmony_ci if (OCTEON_IS_MODEL(OCTEON_CN38XX)) { 2198c2ecf20Sopenharmony_ci if (max_queues <= 32) 2208c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 2); 2218c2ecf20Sopenharmony_ci else if (max_queues <= 64) 2228c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 1); 2238c2ecf20Sopenharmony_ci } else { 2248c2ecf20Sopenharmony_ci if (max_queues <= 64) 2258c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 2); 2268c2ecf20Sopenharmony_ci else if (max_queues <= 128) 2278c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 1); 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci/** 2338c2ecf20Sopenharmony_ci * This function does per-core initialization required by the PKO routines. 2348c2ecf20Sopenharmony_ci * This must be called on all cores that will do packet output, and must 2358c2ecf20Sopenharmony_ci * be called after the FPA has been initialized and filled with pages. 2368c2ecf20Sopenharmony_ci * 2378c2ecf20Sopenharmony_ci * Returns 0 on success 2388c2ecf20Sopenharmony_ci * !0 on failure 2398c2ecf20Sopenharmony_ci */ 2408c2ecf20Sopenharmony_ciint cvmx_pko_initialize_local(void) 2418c2ecf20Sopenharmony_ci{ 2428c2ecf20Sopenharmony_ci /* Nothing to do */ 2438c2ecf20Sopenharmony_ci return 0; 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci/** 2478c2ecf20Sopenharmony_ci * Enables the packet output hardware. It must already be 2488c2ecf20Sopenharmony_ci * configured. 2498c2ecf20Sopenharmony_ci */ 2508c2ecf20Sopenharmony_civoid cvmx_pko_enable(void) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci union cvmx_pko_reg_flags flags; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS); 2558c2ecf20Sopenharmony_ci if (flags.s.ena_pko) 2568c2ecf20Sopenharmony_ci cvmx_dprintf 2578c2ecf20Sopenharmony_ci ("Warning: Enabling PKO when PKO already enabled.\n"); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci flags.s.ena_dwb = 1; 2608c2ecf20Sopenharmony_ci flags.s.ena_pko = 1; 2618c2ecf20Sopenharmony_ci /* 2628c2ecf20Sopenharmony_ci * always enable big endian for 3-word command. Does nothing 2638c2ecf20Sopenharmony_ci * for 2-word. 2648c2ecf20Sopenharmony_ci */ 2658c2ecf20Sopenharmony_ci flags.s.store_be = 1; 2668c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_REG_FLAGS, flags.u64); 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci/** 2708c2ecf20Sopenharmony_ci * Disables the packet output. Does not affect any configuration. 2718c2ecf20Sopenharmony_ci */ 2728c2ecf20Sopenharmony_civoid cvmx_pko_disable(void) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci union cvmx_pko_reg_flags pko_reg_flags; 2758c2ecf20Sopenharmony_ci pko_reg_flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS); 2768c2ecf20Sopenharmony_ci pko_reg_flags.s.ena_pko = 0; 2778c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64); 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_pko_disable); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci/** 2828c2ecf20Sopenharmony_ci * Reset the packet output. 2838c2ecf20Sopenharmony_ci */ 2848c2ecf20Sopenharmony_cistatic void __cvmx_pko_reset(void) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci union cvmx_pko_reg_flags pko_reg_flags; 2878c2ecf20Sopenharmony_ci pko_reg_flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS); 2888c2ecf20Sopenharmony_ci pko_reg_flags.s.reset = 1; 2898c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64); 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci/** 2938c2ecf20Sopenharmony_ci * Shutdown and free resources required by packet output. 2948c2ecf20Sopenharmony_ci */ 2958c2ecf20Sopenharmony_civoid cvmx_pko_shutdown(void) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci union cvmx_pko_mem_queue_ptrs config; 2988c2ecf20Sopenharmony_ci int queue; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci cvmx_pko_disable(); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci for (queue = 0; queue < CVMX_PKO_MAX_OUTPUT_QUEUES; queue++) { 3038c2ecf20Sopenharmony_ci config.u64 = 0; 3048c2ecf20Sopenharmony_ci config.s.tail = 1; 3058c2ecf20Sopenharmony_ci config.s.index = 0; 3068c2ecf20Sopenharmony_ci config.s.port = CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID; 3078c2ecf20Sopenharmony_ci config.s.queue = queue & 0x7f; 3088c2ecf20Sopenharmony_ci config.s.qos_mask = 0; 3098c2ecf20Sopenharmony_ci config.s.buf_ptr = 0; 3108c2ecf20Sopenharmony_ci if (!OCTEON_IS_MODEL(OCTEON_CN3XXX)) { 3118c2ecf20Sopenharmony_ci union cvmx_pko_reg_queue_ptrs1 config1; 3128c2ecf20Sopenharmony_ci config1.u64 = 0; 3138c2ecf20Sopenharmony_ci config1.s.qid7 = queue >> 7; 3148c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64); 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64); 3178c2ecf20Sopenharmony_ci cvmx_cmd_queue_shutdown(CVMX_CMD_QUEUE_PKO(queue)); 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci __cvmx_pko_reset(); 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_pko_shutdown); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci/** 3248c2ecf20Sopenharmony_ci * Configure a output port and the associated queues for use. 3258c2ecf20Sopenharmony_ci * 3268c2ecf20Sopenharmony_ci * @port: Port to configure. 3278c2ecf20Sopenharmony_ci * @base_queue: First queue number to associate with this port. 3288c2ecf20Sopenharmony_ci * @num_queues: Number of queues to associate with this port 3298c2ecf20Sopenharmony_ci * @priority: Array of priority levels for each queue. Values are 3308c2ecf20Sopenharmony_ci * allowed to be 0-8. A value of 8 get 8 times the traffic 3318c2ecf20Sopenharmony_ci * of a value of 1. A value of 0 indicates that no rounds 3328c2ecf20Sopenharmony_ci * will be participated in. These priorities can be changed 3338c2ecf20Sopenharmony_ci * on the fly while the pko is enabled. A priority of 9 3348c2ecf20Sopenharmony_ci * indicates that static priority should be used. If static 3358c2ecf20Sopenharmony_ci * priority is used all queues with static priority must be 3368c2ecf20Sopenharmony_ci * contiguous starting at the base_queue, and lower numbered 3378c2ecf20Sopenharmony_ci * queues have higher priority than higher numbered queues. 3388c2ecf20Sopenharmony_ci * There must be num_queues elements in the array. 3398c2ecf20Sopenharmony_ci */ 3408c2ecf20Sopenharmony_cicvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue, 3418c2ecf20Sopenharmony_ci uint64_t num_queues, 3428c2ecf20Sopenharmony_ci const uint64_t priority[]) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci cvmx_pko_status_t result_code; 3458c2ecf20Sopenharmony_ci uint64_t queue; 3468c2ecf20Sopenharmony_ci union cvmx_pko_mem_queue_ptrs config; 3478c2ecf20Sopenharmony_ci union cvmx_pko_reg_queue_ptrs1 config1; 3488c2ecf20Sopenharmony_ci int static_priority_base = -1; 3498c2ecf20Sopenharmony_ci int static_priority_end = -1; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 3528c2ecf20Sopenharmony_ci return CVMX_PKO_SUCCESS; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci if ((port >= CVMX_PKO_NUM_OUTPUT_PORTS) 3558c2ecf20Sopenharmony_ci && (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID)) { 3568c2ecf20Sopenharmony_ci cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid port %llu\n", 3578c2ecf20Sopenharmony_ci (unsigned long long)port); 3588c2ecf20Sopenharmony_ci return CVMX_PKO_INVALID_PORT; 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci if (base_queue + num_queues > CVMX_PKO_MAX_OUTPUT_QUEUES) { 3628c2ecf20Sopenharmony_ci cvmx_dprintf 3638c2ecf20Sopenharmony_ci ("ERROR: cvmx_pko_config_port: Invalid queue range %llu\n", 3648c2ecf20Sopenharmony_ci (unsigned long long)(base_queue + num_queues)); 3658c2ecf20Sopenharmony_ci return CVMX_PKO_INVALID_QUEUE; 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) { 3698c2ecf20Sopenharmony_ci /* 3708c2ecf20Sopenharmony_ci * Validate the static queue priority setup and set 3718c2ecf20Sopenharmony_ci * static_priority_base and static_priority_end 3728c2ecf20Sopenharmony_ci * accordingly. 3738c2ecf20Sopenharmony_ci */ 3748c2ecf20Sopenharmony_ci for (queue = 0; queue < num_queues; queue++) { 3758c2ecf20Sopenharmony_ci /* Find first queue of static priority */ 3768c2ecf20Sopenharmony_ci if (static_priority_base == -1 3778c2ecf20Sopenharmony_ci && priority[queue] == 3788c2ecf20Sopenharmony_ci CVMX_PKO_QUEUE_STATIC_PRIORITY) 3798c2ecf20Sopenharmony_ci static_priority_base = queue; 3808c2ecf20Sopenharmony_ci /* Find last queue of static priority */ 3818c2ecf20Sopenharmony_ci if (static_priority_base != -1 3828c2ecf20Sopenharmony_ci && static_priority_end == -1 3838c2ecf20Sopenharmony_ci && priority[queue] != CVMX_PKO_QUEUE_STATIC_PRIORITY 3848c2ecf20Sopenharmony_ci && queue) 3858c2ecf20Sopenharmony_ci static_priority_end = queue - 1; 3868c2ecf20Sopenharmony_ci else if (static_priority_base != -1 3878c2ecf20Sopenharmony_ci && static_priority_end == -1 3888c2ecf20Sopenharmony_ci && queue == num_queues - 1) 3898c2ecf20Sopenharmony_ci /* all queues are static priority */ 3908c2ecf20Sopenharmony_ci static_priority_end = queue; 3918c2ecf20Sopenharmony_ci /* 3928c2ecf20Sopenharmony_ci * Check to make sure all static priority 3938c2ecf20Sopenharmony_ci * queues are contiguous. Also catches some 3948c2ecf20Sopenharmony_ci * cases of static priorites not starting at 3958c2ecf20Sopenharmony_ci * queue 0. 3968c2ecf20Sopenharmony_ci */ 3978c2ecf20Sopenharmony_ci if (static_priority_end != -1 3988c2ecf20Sopenharmony_ci && (int)queue > static_priority_end 3998c2ecf20Sopenharmony_ci && priority[queue] == 4008c2ecf20Sopenharmony_ci CVMX_PKO_QUEUE_STATIC_PRIORITY) { 4018c2ecf20Sopenharmony_ci cvmx_dprintf("ERROR: cvmx_pko_config_port: " 4028c2ecf20Sopenharmony_ci "Static priority queues aren't " 4038c2ecf20Sopenharmony_ci "contiguous or don't start at " 4048c2ecf20Sopenharmony_ci "base queue. q: %d, eq: %d\n", 4058c2ecf20Sopenharmony_ci (int)queue, static_priority_end); 4068c2ecf20Sopenharmony_ci return CVMX_PKO_INVALID_PRIORITY; 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci if (static_priority_base > 0) { 4108c2ecf20Sopenharmony_ci cvmx_dprintf("ERROR: cvmx_pko_config_port: Static " 4118c2ecf20Sopenharmony_ci "priority queues don't start at base " 4128c2ecf20Sopenharmony_ci "queue. sq: %d\n", 4138c2ecf20Sopenharmony_ci static_priority_base); 4148c2ecf20Sopenharmony_ci return CVMX_PKO_INVALID_PRIORITY; 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci#if 0 4178c2ecf20Sopenharmony_ci cvmx_dprintf("Port %d: Static priority queue base: %d, " 4188c2ecf20Sopenharmony_ci "end: %d\n", port, 4198c2ecf20Sopenharmony_ci static_priority_base, static_priority_end); 4208c2ecf20Sopenharmony_ci#endif 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci /* 4238c2ecf20Sopenharmony_ci * At this point, static_priority_base and static_priority_end 4248c2ecf20Sopenharmony_ci * are either both -1, or are valid start/end queue 4258c2ecf20Sopenharmony_ci * numbers. 4268c2ecf20Sopenharmony_ci */ 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci result_code = CVMX_PKO_SUCCESS; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci#ifdef PKO_DEBUG 4318c2ecf20Sopenharmony_ci cvmx_dprintf("num queues: %d (%lld,%lld)\n", num_queues, 4328c2ecf20Sopenharmony_ci CVMX_PKO_QUEUES_PER_PORT_INTERFACE0, 4338c2ecf20Sopenharmony_ci CVMX_PKO_QUEUES_PER_PORT_INTERFACE1); 4348c2ecf20Sopenharmony_ci#endif 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci for (queue = 0; queue < num_queues; queue++) { 4378c2ecf20Sopenharmony_ci uint64_t *buf_ptr = NULL; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci config1.u64 = 0; 4408c2ecf20Sopenharmony_ci config1.s.idx3 = queue >> 3; 4418c2ecf20Sopenharmony_ci config1.s.qid7 = (base_queue + queue) >> 7; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci config.u64 = 0; 4448c2ecf20Sopenharmony_ci config.s.tail = queue == (num_queues - 1); 4458c2ecf20Sopenharmony_ci config.s.index = queue; 4468c2ecf20Sopenharmony_ci config.s.port = port; 4478c2ecf20Sopenharmony_ci config.s.queue = base_queue + queue; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci if (!cvmx_octeon_is_pass1()) { 4508c2ecf20Sopenharmony_ci config.s.static_p = static_priority_base >= 0; 4518c2ecf20Sopenharmony_ci config.s.static_q = (int)queue <= static_priority_end; 4528c2ecf20Sopenharmony_ci config.s.s_tail = (int)queue == static_priority_end; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci /* 4558c2ecf20Sopenharmony_ci * Convert the priority into an enable bit field. Try 4568c2ecf20Sopenharmony_ci * to space the bits out evenly so the packet don't 4578c2ecf20Sopenharmony_ci * get grouped up 4588c2ecf20Sopenharmony_ci */ 4598c2ecf20Sopenharmony_ci switch ((int)priority[queue]) { 4608c2ecf20Sopenharmony_ci case 0: 4618c2ecf20Sopenharmony_ci config.s.qos_mask = 0x00; 4628c2ecf20Sopenharmony_ci break; 4638c2ecf20Sopenharmony_ci case 1: 4648c2ecf20Sopenharmony_ci config.s.qos_mask = 0x01; 4658c2ecf20Sopenharmony_ci break; 4668c2ecf20Sopenharmony_ci case 2: 4678c2ecf20Sopenharmony_ci config.s.qos_mask = 0x11; 4688c2ecf20Sopenharmony_ci break; 4698c2ecf20Sopenharmony_ci case 3: 4708c2ecf20Sopenharmony_ci config.s.qos_mask = 0x49; 4718c2ecf20Sopenharmony_ci break; 4728c2ecf20Sopenharmony_ci case 4: 4738c2ecf20Sopenharmony_ci config.s.qos_mask = 0x55; 4748c2ecf20Sopenharmony_ci break; 4758c2ecf20Sopenharmony_ci case 5: 4768c2ecf20Sopenharmony_ci config.s.qos_mask = 0x57; 4778c2ecf20Sopenharmony_ci break; 4788c2ecf20Sopenharmony_ci case 6: 4798c2ecf20Sopenharmony_ci config.s.qos_mask = 0x77; 4808c2ecf20Sopenharmony_ci break; 4818c2ecf20Sopenharmony_ci case 7: 4828c2ecf20Sopenharmony_ci config.s.qos_mask = 0x7f; 4838c2ecf20Sopenharmony_ci break; 4848c2ecf20Sopenharmony_ci case 8: 4858c2ecf20Sopenharmony_ci config.s.qos_mask = 0xff; 4868c2ecf20Sopenharmony_ci break; 4878c2ecf20Sopenharmony_ci case CVMX_PKO_QUEUE_STATIC_PRIORITY: 4888c2ecf20Sopenharmony_ci if (!cvmx_octeon_is_pass1()) { 4898c2ecf20Sopenharmony_ci config.s.qos_mask = 0xff; 4908c2ecf20Sopenharmony_ci break; 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci fallthrough; /* to the error case, when Pass 1 */ 4938c2ecf20Sopenharmony_ci default: 4948c2ecf20Sopenharmony_ci cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid " 4958c2ecf20Sopenharmony_ci "priority %llu\n", 4968c2ecf20Sopenharmony_ci (unsigned long long)priority[queue]); 4978c2ecf20Sopenharmony_ci config.s.qos_mask = 0xff; 4988c2ecf20Sopenharmony_ci result_code = CVMX_PKO_INVALID_PRIORITY; 4998c2ecf20Sopenharmony_ci break; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) { 5038c2ecf20Sopenharmony_ci cvmx_cmd_queue_result_t cmd_res = 5048c2ecf20Sopenharmony_ci cvmx_cmd_queue_initialize(CVMX_CMD_QUEUE_PKO 5058c2ecf20Sopenharmony_ci (base_queue + queue), 5068c2ecf20Sopenharmony_ci CVMX_PKO_MAX_QUEUE_DEPTH, 5078c2ecf20Sopenharmony_ci CVMX_FPA_OUTPUT_BUFFER_POOL, 5088c2ecf20Sopenharmony_ci CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE 5098c2ecf20Sopenharmony_ci - 5108c2ecf20Sopenharmony_ci CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST 5118c2ecf20Sopenharmony_ci * 8); 5128c2ecf20Sopenharmony_ci if (cmd_res != CVMX_CMD_QUEUE_SUCCESS) { 5138c2ecf20Sopenharmony_ci switch (cmd_res) { 5148c2ecf20Sopenharmony_ci case CVMX_CMD_QUEUE_NO_MEMORY: 5158c2ecf20Sopenharmony_ci cvmx_dprintf("ERROR: " 5168c2ecf20Sopenharmony_ci "cvmx_pko_config_port: " 5178c2ecf20Sopenharmony_ci "Unable to allocate " 5188c2ecf20Sopenharmony_ci "output buffer.\n"); 5198c2ecf20Sopenharmony_ci return CVMX_PKO_NO_MEMORY; 5208c2ecf20Sopenharmony_ci case CVMX_CMD_QUEUE_ALREADY_SETUP: 5218c2ecf20Sopenharmony_ci cvmx_dprintf 5228c2ecf20Sopenharmony_ci ("ERROR: cvmx_pko_config_port: Port already setup.\n"); 5238c2ecf20Sopenharmony_ci return CVMX_PKO_PORT_ALREADY_SETUP; 5248c2ecf20Sopenharmony_ci case CVMX_CMD_QUEUE_INVALID_PARAM: 5258c2ecf20Sopenharmony_ci default: 5268c2ecf20Sopenharmony_ci cvmx_dprintf 5278c2ecf20Sopenharmony_ci ("ERROR: cvmx_pko_config_port: Command queue initialization failed.\n"); 5288c2ecf20Sopenharmony_ci return CVMX_PKO_CMD_QUEUE_INIT_ERROR; 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci } 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci buf_ptr = 5338c2ecf20Sopenharmony_ci (uint64_t *) 5348c2ecf20Sopenharmony_ci cvmx_cmd_queue_buffer(CVMX_CMD_QUEUE_PKO 5358c2ecf20Sopenharmony_ci (base_queue + queue)); 5368c2ecf20Sopenharmony_ci config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr); 5378c2ecf20Sopenharmony_ci } else 5388c2ecf20Sopenharmony_ci config.s.buf_ptr = 0; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci CVMX_SYNCWS; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci if (!OCTEON_IS_MODEL(OCTEON_CN3XXX)) 5438c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64); 5448c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64); 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci return result_code; 5488c2ecf20Sopenharmony_ci} 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci#ifdef PKO_DEBUG 5518c2ecf20Sopenharmony_ci/** 5528c2ecf20Sopenharmony_ci * Show map of ports -> queues for different cores. 5538c2ecf20Sopenharmony_ci */ 5548c2ecf20Sopenharmony_civoid cvmx_pko_show_queue_map() 5558c2ecf20Sopenharmony_ci{ 5568c2ecf20Sopenharmony_ci int core, port; 5578c2ecf20Sopenharmony_ci int pko_output_ports = 36; 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci cvmx_dprintf("port"); 5608c2ecf20Sopenharmony_ci for (port = 0; port < pko_output_ports; port++) 5618c2ecf20Sopenharmony_ci cvmx_dprintf("%3d ", port); 5628c2ecf20Sopenharmony_ci cvmx_dprintf("\n"); 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci for (core = 0; core < CVMX_MAX_CORES; core++) { 5658c2ecf20Sopenharmony_ci cvmx_dprintf("\n%2d: ", core); 5668c2ecf20Sopenharmony_ci for (port = 0; port < pko_output_ports; port++) { 5678c2ecf20Sopenharmony_ci cvmx_dprintf("%3d ", 5688c2ecf20Sopenharmony_ci cvmx_pko_get_base_queue_per_core(port, 5698c2ecf20Sopenharmony_ci core)); 5708c2ecf20Sopenharmony_ci } 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci cvmx_dprintf("\n"); 5738c2ecf20Sopenharmony_ci} 5748c2ecf20Sopenharmony_ci#endif 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci/** 5778c2ecf20Sopenharmony_ci * Rate limit a PKO port to a max packets/sec. This function is only 5788c2ecf20Sopenharmony_ci * supported on CN51XX and higher, excluding CN58XX. 5798c2ecf20Sopenharmony_ci * 5808c2ecf20Sopenharmony_ci * @port: Port to rate limit 5818c2ecf20Sopenharmony_ci * @packets_s: Maximum packet/sec 5828c2ecf20Sopenharmony_ci * @burst: Maximum number of packets to burst in a row before rate 5838c2ecf20Sopenharmony_ci * limiting cuts in. 5848c2ecf20Sopenharmony_ci * 5858c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure 5868c2ecf20Sopenharmony_ci */ 5878c2ecf20Sopenharmony_ciint cvmx_pko_rate_limit_packets(int port, int packets_s, int burst) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci union cvmx_pko_mem_port_rate0 pko_mem_port_rate0; 5908c2ecf20Sopenharmony_ci union cvmx_pko_mem_port_rate1 pko_mem_port_rate1; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci pko_mem_port_rate0.u64 = 0; 5938c2ecf20Sopenharmony_ci pko_mem_port_rate0.s.pid = port; 5948c2ecf20Sopenharmony_ci pko_mem_port_rate0.s.rate_pkt = 5958c2ecf20Sopenharmony_ci cvmx_sysinfo_get()->cpu_clock_hz / packets_s / 16; 5968c2ecf20Sopenharmony_ci /* No cost per word since we are limited by packets/sec, not bits/sec */ 5978c2ecf20Sopenharmony_ci pko_mem_port_rate0.s.rate_word = 0; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci pko_mem_port_rate1.u64 = 0; 6008c2ecf20Sopenharmony_ci pko_mem_port_rate1.s.pid = port; 6018c2ecf20Sopenharmony_ci pko_mem_port_rate1.s.rate_lim = 6028c2ecf20Sopenharmony_ci ((uint64_t) pko_mem_port_rate0.s.rate_pkt * burst) >> 8; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0, pko_mem_port_rate0.u64); 6058c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1, pko_mem_port_rate1.u64); 6068c2ecf20Sopenharmony_ci return 0; 6078c2ecf20Sopenharmony_ci} 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci/** 6108c2ecf20Sopenharmony_ci * Rate limit a PKO port to a max bits/sec. This function is only 6118c2ecf20Sopenharmony_ci * supported on CN51XX and higher, excluding CN58XX. 6128c2ecf20Sopenharmony_ci * 6138c2ecf20Sopenharmony_ci * @port: Port to rate limit 6148c2ecf20Sopenharmony_ci * @bits_s: PKO rate limit in bits/sec 6158c2ecf20Sopenharmony_ci * @burst: Maximum number of bits to burst before rate 6168c2ecf20Sopenharmony_ci * limiting cuts in. 6178c2ecf20Sopenharmony_ci * 6188c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure 6198c2ecf20Sopenharmony_ci */ 6208c2ecf20Sopenharmony_ciint cvmx_pko_rate_limit_bits(int port, uint64_t bits_s, int burst) 6218c2ecf20Sopenharmony_ci{ 6228c2ecf20Sopenharmony_ci union cvmx_pko_mem_port_rate0 pko_mem_port_rate0; 6238c2ecf20Sopenharmony_ci union cvmx_pko_mem_port_rate1 pko_mem_port_rate1; 6248c2ecf20Sopenharmony_ci uint64_t clock_rate = cvmx_sysinfo_get()->cpu_clock_hz; 6258c2ecf20Sopenharmony_ci uint64_t tokens_per_bit = clock_rate * 16 / bits_s; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci pko_mem_port_rate0.u64 = 0; 6288c2ecf20Sopenharmony_ci pko_mem_port_rate0.s.pid = port; 6298c2ecf20Sopenharmony_ci /* 6308c2ecf20Sopenharmony_ci * Each packet has a 12 bytes of interframe gap, an 8 byte 6318c2ecf20Sopenharmony_ci * preamble, and a 4 byte CRC. These are not included in the 6328c2ecf20Sopenharmony_ci * per word count. Multiply by 8 to covert to bits and divide 6338c2ecf20Sopenharmony_ci * by 256 for limit granularity. 6348c2ecf20Sopenharmony_ci */ 6358c2ecf20Sopenharmony_ci pko_mem_port_rate0.s.rate_pkt = (12 + 8 + 4) * 8 * tokens_per_bit / 256; 6368c2ecf20Sopenharmony_ci /* Each 8 byte word has 64bits */ 6378c2ecf20Sopenharmony_ci pko_mem_port_rate0.s.rate_word = 64 * tokens_per_bit; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci pko_mem_port_rate1.u64 = 0; 6408c2ecf20Sopenharmony_ci pko_mem_port_rate1.s.pid = port; 6418c2ecf20Sopenharmony_ci pko_mem_port_rate1.s.rate_lim = tokens_per_bit * burst / 256; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0, pko_mem_port_rate0.u64); 6448c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1, pko_mem_port_rate1.u64); 6458c2ecf20Sopenharmony_ci return 0; 6468c2ecf20Sopenharmony_ci} 647