^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /***********************license start***************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Author: Cavium Networks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Contact: support@caviumnetworks.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file is part of the OCTEON SDK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2003-2008 Cavium Networks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This file is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * it under the terms of the GNU General Public License, Version 2, as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * This file is distributed in the hope that it will be useful, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * NONINFRINGEMENT. See the GNU General Public License for more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * You should have received a copy of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * along with this file; if not, write to the Free Software
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * or visit http://www.gnu.org/licenses/.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * This file may also be available under a different license from Cavium.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * Contact Cavium Networks for more information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) ***********************license end**************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * Support library for the hardware Packet Output unit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <asm/octeon/octeon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <asm/octeon/cvmx-config.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/octeon/cvmx-pko.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/octeon/cvmx-helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * Internal state of packet output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int __cvmx_pko_int(int interface, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) switch (interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return index + 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return index + 0x0c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return index + 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return 0x1c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return 0x1d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return 0x1e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static void __cvmx_pko_iport_config(int pko_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) const int num_queues = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) const int base_queue = pko_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) const int static_priority_end = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) const int static_priority_base = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) for (queue = 0; queue < num_queues; queue++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) union cvmx_pko_mem_iqueue_ptrs config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) cvmx_cmd_queue_result_t cmd_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) uint64_t *buf_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) config.u64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) config.s.index = queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) config.s.qid = base_queue + queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) config.s.ipid = pko_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) config.s.tail = (queue == (num_queues - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) config.s.s_tail = (queue == static_priority_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) config.s.static_p = (static_priority_base >= 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) config.s.static_q = (queue <= static_priority_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) config.s.qos_mask = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) cmd_res = cvmx_cmd_queue_initialize(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) CVMX_CMD_QUEUE_PKO(base_queue + queue),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) CVMX_PKO_MAX_QUEUE_DEPTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) CVMX_FPA_OUTPUT_BUFFER_POOL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) (CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST * 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) WARN(cmd_res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) "%s: cmd_res=%d pko_port=%d base_queue=%d num_queues=%d queue=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) __func__, (int)cmd_res, pko_port, base_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) num_queues, queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) buf_ptr = (uint64_t *)cvmx_cmd_queue_buffer(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) CVMX_CMD_QUEUE_PKO(base_queue + queue));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr) >> 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) CVMX_SYNCWS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) cvmx_write_csr(CVMX_PKO_MEM_IQUEUE_PTRS, config.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static void __cvmx_pko_queue_alloc_o68(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) for (port = 0; port < 48; port++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) __cvmx_pko_iport_config(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static void __cvmx_pko_port_map_o68(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int interface, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) cvmx_helper_interface_mode_t mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) union cvmx_pko_mem_iport_ptrs config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * Initialize every iport with the invalid eid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) config.u64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) config.s.eid = 31; /* Invalid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) for (port = 0; port < 128; port++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) config.s.ipid = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS, config.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * Set up PKO_MEM_IPORT_PTRS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) for (port = 0; port < 48; port++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) interface = cvmx_helper_get_interface_num(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) index = cvmx_helper_get_interface_index_num(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) mode = cvmx_helper_interface_get_mode(interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (mode == CVMX_HELPER_INTERFACE_MODE_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) config.s.ipid = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) config.s.qos_mask = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) config.s.crc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) config.s.min_pkt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) config.s.intr = __cvmx_pko_int(interface, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) config.s.eid = config.s.intr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) config.s.pipe = (mode == CVMX_HELPER_INTERFACE_MODE_LOOP) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) index : port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS, config.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static void __cvmx_pko_chip_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) __cvmx_pko_port_map_o68();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) __cvmx_pko_queue_alloc_o68();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * Initialize queues
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) const uint64_t priority = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) &priority);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * Call before any other calls to initialize the packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * output system. This does chip global config, and should only be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * done by one core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) void cvmx_pko_initialize_global(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) union cvmx_pko_reg_cmd_buf config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * Set the size of the PKO command buffers to an odd number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * 64bit words. This allows the normal two word send to stay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * aligned and never span a command word buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) config.u64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) config.s.pool = CVMX_FPA_OUTPUT_BUFFER_POOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) config.s.size = CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE / 8 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) cvmx_write_csr(CVMX_PKO_REG_CMD_BUF, config.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * Chip-specific setup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) __cvmx_pko_chip_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * If we aren't using all of the queues optimize PKO's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * internal memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) || OCTEON_IS_MODEL(OCTEON_CN56XX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int num_interfaces = cvmx_helper_get_number_of_interfaces();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) int last_port =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) cvmx_helper_get_last_ipd_port(num_interfaces - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int max_queues =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) cvmx_pko_get_base_queue(last_port) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) cvmx_pko_get_num_queues(last_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (OCTEON_IS_MODEL(OCTEON_CN38XX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (max_queues <= 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) else if (max_queues <= 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (max_queues <= 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) else if (max_queues <= 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * This function does per-core initialization required by the PKO routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * This must be called on all cores that will do packet output, and must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * be called after the FPA has been initialized and filled with pages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * Returns 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * !0 on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int cvmx_pko_initialize_local(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* Nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * Enables the packet output hardware. It must already be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * configured.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) void cvmx_pko_enable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) union cvmx_pko_reg_flags flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (flags.s.ena_pko)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) cvmx_dprintf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ("Warning: Enabling PKO when PKO already enabled.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) flags.s.ena_dwb = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) flags.s.ena_pko = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * always enable big endian for 3-word command. Does nothing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * for 2-word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) flags.s.store_be = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) cvmx_write_csr(CVMX_PKO_REG_FLAGS, flags.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * Disables the packet output. Does not affect any configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) void cvmx_pko_disable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) union cvmx_pko_reg_flags pko_reg_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) pko_reg_flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) pko_reg_flags.s.ena_pko = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) EXPORT_SYMBOL_GPL(cvmx_pko_disable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * Reset the packet output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static void __cvmx_pko_reset(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) union cvmx_pko_reg_flags pko_reg_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) pko_reg_flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) pko_reg_flags.s.reset = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * Shutdown and free resources required by packet output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) void cvmx_pko_shutdown(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) union cvmx_pko_mem_queue_ptrs config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) int queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) cvmx_pko_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) for (queue = 0; queue < CVMX_PKO_MAX_OUTPUT_QUEUES; queue++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) config.u64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) config.s.tail = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) config.s.index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) config.s.port = CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) config.s.queue = queue & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) config.s.qos_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) config.s.buf_ptr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (!OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) union cvmx_pko_reg_queue_ptrs1 config1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) config1.u64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) config1.s.qid7 = queue >> 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) cvmx_cmd_queue_shutdown(CVMX_CMD_QUEUE_PKO(queue));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) __cvmx_pko_reset();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) EXPORT_SYMBOL_GPL(cvmx_pko_shutdown);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * Configure a output port and the associated queues for use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * @port: Port to configure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * @base_queue: First queue number to associate with this port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * @num_queues: Number of queues to associate with this port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * @priority: Array of priority levels for each queue. Values are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * allowed to be 0-8. A value of 8 get 8 times the traffic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * of a value of 1. A value of 0 indicates that no rounds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * will be participated in. These priorities can be changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * on the fly while the pko is enabled. A priority of 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * indicates that static priority should be used. If static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * priority is used all queues with static priority must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * contiguous starting at the base_queue, and lower numbered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * queues have higher priority than higher numbered queues.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * There must be num_queues elements in the array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) uint64_t num_queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) const uint64_t priority[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) cvmx_pko_status_t result_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) uint64_t queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) union cvmx_pko_mem_queue_ptrs config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) union cvmx_pko_reg_queue_ptrs1 config1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) int static_priority_base = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) int static_priority_end = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (OCTEON_IS_MODEL(OCTEON_CN68XX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return CVMX_PKO_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if ((port >= CVMX_PKO_NUM_OUTPUT_PORTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) && (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid port %llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) (unsigned long long)port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return CVMX_PKO_INVALID_PORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (base_queue + num_queues > CVMX_PKO_MAX_OUTPUT_QUEUES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) cvmx_dprintf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) ("ERROR: cvmx_pko_config_port: Invalid queue range %llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) (unsigned long long)(base_queue + num_queues));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return CVMX_PKO_INVALID_QUEUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * Validate the static queue priority setup and set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * static_priority_base and static_priority_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) for (queue = 0; queue < num_queues; queue++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* Find first queue of static priority */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (static_priority_base == -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) && priority[queue] ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) CVMX_PKO_QUEUE_STATIC_PRIORITY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static_priority_base = queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /* Find last queue of static priority */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (static_priority_base != -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) && static_priority_end == -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) && priority[queue] != CVMX_PKO_QUEUE_STATIC_PRIORITY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) && queue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static_priority_end = queue - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) else if (static_priority_base != -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) && static_priority_end == -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) && queue == num_queues - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* all queues are static priority */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static_priority_end = queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * Check to make sure all static priority
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * queues are contiguous. Also catches some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * cases of static priorites not starting at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * queue 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (static_priority_end != -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) && (int)queue > static_priority_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) && priority[queue] ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) CVMX_PKO_QUEUE_STATIC_PRIORITY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) cvmx_dprintf("ERROR: cvmx_pko_config_port: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) "Static priority queues aren't "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) "contiguous or don't start at "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) "base queue. q: %d, eq: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) (int)queue, static_priority_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return CVMX_PKO_INVALID_PRIORITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (static_priority_base > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) cvmx_dprintf("ERROR: cvmx_pko_config_port: Static "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) "priority queues don't start at base "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) "queue. sq: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) static_priority_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return CVMX_PKO_INVALID_PRIORITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) cvmx_dprintf("Port %d: Static priority queue base: %d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) "end: %d\n", port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static_priority_base, static_priority_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * At this point, static_priority_base and static_priority_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * are either both -1, or are valid start/end queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * numbers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) result_code = CVMX_PKO_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) #ifdef PKO_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) cvmx_dprintf("num queues: %d (%lld,%lld)\n", num_queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) CVMX_PKO_QUEUES_PER_PORT_INTERFACE0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) CVMX_PKO_QUEUES_PER_PORT_INTERFACE1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) for (queue = 0; queue < num_queues; queue++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) uint64_t *buf_ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) config1.u64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) config1.s.idx3 = queue >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) config1.s.qid7 = (base_queue + queue) >> 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) config.u64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) config.s.tail = queue == (num_queues - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) config.s.index = queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) config.s.port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) config.s.queue = base_queue + queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (!cvmx_octeon_is_pass1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) config.s.static_p = static_priority_base >= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) config.s.static_q = (int)queue <= static_priority_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) config.s.s_tail = (int)queue == static_priority_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * Convert the priority into an enable bit field. Try
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * to space the bits out evenly so the packet don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * get grouped up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) switch ((int)priority[queue]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) config.s.qos_mask = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) config.s.qos_mask = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) config.s.qos_mask = 0x11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) config.s.qos_mask = 0x49;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) config.s.qos_mask = 0x55;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) config.s.qos_mask = 0x57;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) config.s.qos_mask = 0x77;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) config.s.qos_mask = 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) config.s.qos_mask = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) case CVMX_PKO_QUEUE_STATIC_PRIORITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (!cvmx_octeon_is_pass1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) config.s.qos_mask = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) fallthrough; /* to the error case, when Pass 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) "priority %llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) (unsigned long long)priority[queue]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) config.s.qos_mask = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) result_code = CVMX_PKO_INVALID_PRIORITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) cvmx_cmd_queue_result_t cmd_res =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) cvmx_cmd_queue_initialize(CVMX_CMD_QUEUE_PKO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) (base_queue + queue),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) CVMX_PKO_MAX_QUEUE_DEPTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) CVMX_FPA_OUTPUT_BUFFER_POOL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (cmd_res != CVMX_CMD_QUEUE_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) switch (cmd_res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) case CVMX_CMD_QUEUE_NO_MEMORY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) cvmx_dprintf("ERROR: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) "cvmx_pko_config_port: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) "Unable to allocate "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) "output buffer.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return CVMX_PKO_NO_MEMORY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) case CVMX_CMD_QUEUE_ALREADY_SETUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) cvmx_dprintf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) ("ERROR: cvmx_pko_config_port: Port already setup.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return CVMX_PKO_PORT_ALREADY_SETUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) case CVMX_CMD_QUEUE_INVALID_PARAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) cvmx_dprintf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) ("ERROR: cvmx_pko_config_port: Command queue initialization failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return CVMX_PKO_CMD_QUEUE_INIT_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) buf_ptr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) (uint64_t *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) cvmx_cmd_queue_buffer(CVMX_CMD_QUEUE_PKO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) (base_queue + queue));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) config.s.buf_ptr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) CVMX_SYNCWS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (!OCTEON_IS_MODEL(OCTEON_CN3XXX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return result_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) #ifdef PKO_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * Show map of ports -> queues for different cores.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) void cvmx_pko_show_queue_map()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) int core, port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) int pko_output_ports = 36;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) cvmx_dprintf("port");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) for (port = 0; port < pko_output_ports; port++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) cvmx_dprintf("%3d ", port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) cvmx_dprintf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) for (core = 0; core < CVMX_MAX_CORES; core++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) cvmx_dprintf("\n%2d: ", core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) for (port = 0; port < pko_output_ports; port++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) cvmx_dprintf("%3d ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) cvmx_pko_get_base_queue_per_core(port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) core));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) cvmx_dprintf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * Rate limit a PKO port to a max packets/sec. This function is only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * supported on CN51XX and higher, excluding CN58XX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * @port: Port to rate limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * @packets_s: Maximum packet/sec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * @burst: Maximum number of packets to burst in a row before rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * limiting cuts in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * Returns Zero on success, negative on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) int cvmx_pko_rate_limit_packets(int port, int packets_s, int burst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) union cvmx_pko_mem_port_rate0 pko_mem_port_rate0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) union cvmx_pko_mem_port_rate1 pko_mem_port_rate1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) pko_mem_port_rate0.u64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) pko_mem_port_rate0.s.pid = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) pko_mem_port_rate0.s.rate_pkt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) cvmx_sysinfo_get()->cpu_clock_hz / packets_s / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /* No cost per word since we are limited by packets/sec, not bits/sec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) pko_mem_port_rate0.s.rate_word = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) pko_mem_port_rate1.u64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) pko_mem_port_rate1.s.pid = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) pko_mem_port_rate1.s.rate_lim =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) ((uint64_t) pko_mem_port_rate0.s.rate_pkt * burst) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0, pko_mem_port_rate0.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1, pko_mem_port_rate1.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * Rate limit a PKO port to a max bits/sec. This function is only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * supported on CN51XX and higher, excluding CN58XX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * @port: Port to rate limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * @bits_s: PKO rate limit in bits/sec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * @burst: Maximum number of bits to burst before rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * limiting cuts in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * Returns Zero on success, negative on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) int cvmx_pko_rate_limit_bits(int port, uint64_t bits_s, int burst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) union cvmx_pko_mem_port_rate0 pko_mem_port_rate0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) union cvmx_pko_mem_port_rate1 pko_mem_port_rate1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) uint64_t clock_rate = cvmx_sysinfo_get()->cpu_clock_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) uint64_t tokens_per_bit = clock_rate * 16 / bits_s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) pko_mem_port_rate0.u64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) pko_mem_port_rate0.s.pid = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * Each packet has a 12 bytes of interframe gap, an 8 byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * preamble, and a 4 byte CRC. These are not included in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) * per word count. Multiply by 8 to covert to bits and divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * by 256 for limit granularity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) pko_mem_port_rate0.s.rate_pkt = (12 + 8 + 4) * 8 * tokens_per_bit / 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /* Each 8 byte word has 64bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) pko_mem_port_rate0.s.rate_word = 64 * tokens_per_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) pko_mem_port_rate1.u64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) pko_mem_port_rate1.s.pid = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) pko_mem_port_rate1.s.rate_lim = tokens_per_bit * burst / 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0, pko_mem_port_rate0.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1, pko_mem_port_rate1.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }