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**************************************/
39 /*------------------------------------------------------------------
40 * octeon_pko.c Packet Output Unit
42 *------------------------------------------------------------------
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD$");
48 #include <sys/param.h>
49 #include <sys/systm.h>
53 #include <mips/cavium/octeon_pcmap_regs.h>
54 #include "octeon_fau.h"
55 #include "octeon_fpa.h"
56 #include "octeon_pko.h"
62 static void octeon_pko_clear_port_counts (u_int port)
65 octeon_pko_read_idx_t octeon_pko_idx;
67 octeon_pko_idx.word64 = 0;
68 octeon_pko_idx.bits.idx = port;
69 octeon_pko_idx.bits.inc = 0;
70 oct_write64(OCTEON_PKO_REG_READ_IDX, octeon_pko_idx.word64);
73 oct_write64(OCTEON_PKO_MEM_COUNT0, port_num);
75 oct_write64(OCTEON_PKO_MEM_COUNT1, port_num);
82 void octeon_pko_init (void)
85 octeon_pko_read_idx_t octeon_pko_idx;
86 octeon_pko_queue_cfg_t octeon_pko_queue_cfg;
88 for (port = 0; port < OCTEON_PKO_PORTS_MAX; port++) {
89 octeon_pko_clear_port_counts(port);
92 octeon_pko_idx.word64 = 0;
93 octeon_pko_idx.bits.idx = 0;
94 octeon_pko_idx.bits.inc = 1;
95 oct_write64(OCTEON_PKO_REG_READ_IDX, octeon_pko_idx.word64);
96 for (queue = 0; queue < OCTEON_PKO_QUEUES_MAX; queue++) {
98 octeon_pko_queue_cfg.word64 = 0;
99 octeon_pko_queue_cfg.bits.queue = queue;
100 octeon_pko_queue_cfg.bits.port = OCTEON_PKO_PORT_ILLEGAL;
101 octeon_pko_queue_cfg.bits.buf_ptr = 0;
102 oct_write64(OCTEON_PKO_MEM_QUEUE_PTRS, octeon_pko_queue_cfg.word64);
112 void octeon_pko_enable (void)
118 oct_write64(OCTEON_PKO_REG_FLAGS, 3); /* octeon_pko_enable() */
127 void octeon_pko_disable (void)
133 oct_write64(OCTEON_PKO_REG_FLAGS, 0); /* pko_disable() */
137 * octeon_pko_config_cmdbuf_global_defaults
140 void octeon_pko_config_cmdbuf_global_defaults (u_int cmdbuf_pool,
141 u_int cmdbuf_pool_elem_size )
143 octeon_pko_pool_cfg_t octeon_pko_pool_config;
145 octeon_pko_pool_config.word64 = 0;
146 octeon_pko_pool_config.bits.pool = cmdbuf_pool;
147 octeon_pko_pool_config.bits.size = cmdbuf_pool_elem_size;
148 oct_write64(OCTEON_PKO_CMD_BUF, octeon_pko_pool_config.word64);
152 * octeon_pko_config_rgmx_ports
154 * Configure rgmx pko. Always enables 4 + 4 ports
156 void octeon_pko_config_rgmx_ports (void)
158 octeon_pko_reg_gmx_port_mode_t octeon_pko_gmx_mode;
160 octeon_pko_gmx_mode.word64 = 0;
161 octeon_pko_gmx_mode.bits.mode0 = 2; /* 16 >> 2 == 4 ports */
162 octeon_pko_gmx_mode.bits.mode1 = 2; /* 16 >> 2 == 4 ports */
163 oct_write64(OCTEON_PKO_GMX_PORT_MODE, octeon_pko_gmx_mode.word64);
173 void octeon_pko_config (void)
178 * octeon_pko_get_port_status
180 * Get the status counters for a PKO port.
182 * port_num Port number to get statistics for.
183 * clear Set to 1 to clear the counters after they are read
184 * status Where to put the results.
186 void octeon_pko_get_port_status (u_int port, u_int clear,
187 octeon_pko_port_status_t *status)
189 octeon_word_t packet_num;
190 octeon_pko_read_idx_t octeon_pko_idx;
192 packet_num.word64 = 0;
194 octeon_pko_idx.word64 = 0;
195 octeon_pko_idx.bits.idx = port;
196 octeon_pko_idx.bits.inc = 0;
197 oct_write64(OCTEON_PKO_REG_READ_IDX, octeon_pko_idx.word64);
199 packet_num.word64 = oct_read64(OCTEON_PKO_MEM_COUNT0);
200 status->packets = packet_num.bits.word32lo;
202 status->octets = oct_read64(OCTEON_PKO_MEM_COUNT1);
203 status->doorbell = oct_read64(OCTEON_PKO_MEM_DEBUG9);
204 status->doorbell = (status->doorbell >> 8) & 0xfffff;
206 octeon_pko_clear_port_counts(port);
210 static void octeon_pko_doorbell_data_dump(uint64_t port);
212 static void octeon_pko_doorbell_data_dump (uint64_t port)
214 octeon_pko_port_status_t status;
216 octeon_pko_get_port_status(port, 0, &status);
217 printf("\n Port #%lld Pkts %ld Bytes %lld DoorBell %lld",
218 (unsigned long long)port, status.packets,
219 (unsigned long long)status.octets,
220 (unsigned long long)status.doorbell);
226 * Show the OCTEON_PKO status & configs
228 void octeon_pko_show (u_int start_port, u_int end_port)
230 u_int queue, queue_max, gmx_int0_ports, gmx_int1_ports;
233 octeon_pko_port_status_t status;
234 octeon_pko_pool_cfg_t octeon_pko_pool_config;
235 octeon_pko_read_idx_t octeon_pko_idx;
236 octeon_pko_queue_mode_t octeon_pko_queue_mode;
237 octeon_pko_reg_gmx_port_mode_t octeon_pko_gmx_mode;
238 octeon_pko_crc_ports_enable_t octeon_pko_crc_ports;
239 octeon_pko_queue_cfg_t octeon_pko_queue_cfg;
241 printf("\n\nPKO Status:");
242 val64 = oct_read64(OCTEON_PKO_REG_FLAGS);
243 if ((val64 & 0x3) != 0x3) {
249 octeon_pko_queue_mode.word64 = oct_read64(OCTEON_PKO_QUEUE_MODE);
250 queue_max = (128 >> octeon_pko_queue_mode.bits.mode);
251 octeon_pko_gmx_mode.word64 = oct_read64(OCTEON_PKO_GMX_PORT_MODE);
252 gmx_int0_ports = (16 >> octeon_pko_gmx_mode.bits.mode0);
253 gmx_int1_ports = (16 >> octeon_pko_gmx_mode.bits.mode1);
254 octeon_pko_crc_ports.word64 = oct_read64(OCTEON_PKO_REG_CRC_ENABLE);
255 printf("\n Total Queues: 0..%d Ports GMX0 %d GMX1 %d CRC 0x%X",
256 queue_max - 1, gmx_int0_ports, gmx_int1_ports,
257 octeon_pko_crc_ports.bits.crc_ports_mask);
259 octeon_pko_pool_config.word64 = oct_read64(OCTEON_PKO_CMD_BUF);
260 printf("\n CmdBuf Pool: %d CmdBuf Size in Words: %d Bytes: %d",
261 octeon_pko_pool_config.bits.pool, octeon_pko_pool_config.bits.size,
262 octeon_pko_pool_config.bits.size * 8);
264 octeon_pko_idx.word64 = 0;
265 octeon_pko_idx.bits.idx = 0;
266 octeon_pko_idx.bits.inc = 1;
267 oct_write64(OCTEON_PKO_REG_READ_IDX, octeon_pko_idx.word64);
268 for (queue = 0; queue < queue_max; queue++) {
270 octeon_pko_queue_cfg.word64 = oct_read64(OCTEON_PKO_MEM_QUEUE_PTRS);
271 if (!octeon_pko_queue_cfg.bits.buf_ptr) continue;
272 printf("\n Port # %d Queue %3d [%d] BufPtr: 0x%llX Mask: %X%s",
273 octeon_pko_queue_cfg.bits.port, octeon_pko_queue_cfg.bits.queue,
274 octeon_pko_queue_cfg.bits.index,
275 (unsigned long long)octeon_pko_queue_cfg.bits.buf_ptr,
276 octeon_pko_queue_cfg.bits.qos_mask,
277 (octeon_pko_queue_cfg.bits.tail)? " Last":"");
281 for (port = start_port; port < (end_port + 1); port++) {
283 octeon_pko_get_port_status(port, 0, &status);
284 octeon_pko_doorbell_data_dump(port);
293 * octeon_pko_config_port
295 * Configure a output port and the associated queues for use.
298 octeon_pko_status_t octeon_pko_config_port (u_int port,
301 const u_int priority[],
302 u_int pko_output_cmdbuf_fpa_pool,
303 octeon_pko_sw_queue_info_t sw_queues[])
305 octeon_pko_status_t result_code;
307 octeon_pko_queue_cfg_t qconfig;
309 if ((port >= OCTEON_PKO_PORTS_MAX) && (port != OCTEON_PKO_PORT_ILLEGAL)) {
310 printf("\n%% Error: octeon_pko_config_port: Invalid port %u", port);
311 return (OCTEON_PKO_INVALID_PORT);
314 if ((base_queue + num_queues) > OCTEON_PKO_QUEUES_MAX) {
315 printf("\n%% Error: octeon_pko_config_port: Invalid queue range");
316 return (OCTEON_PKO_INVALID_QUEUE);
319 result_code = OCTEON_PKO_SUCCESS;
321 for (queue = 0; queue < num_queues; queue++) {
322 uint64_t buf_ptr = 0;
325 qconfig.bits.tail = (queue == (num_queues - 1)) ? 1 : 0;
326 qconfig.bits.index = queue;
327 qconfig.bits.port = port;
328 qconfig.bits.queue = base_queue + queue;
330 /* Convert the priority into an enable bit field. */
331 /* Try to space the bits out evenly so the pkts don't get grouped up */
332 switch ((int)priority[queue]) {
333 case 0: qconfig.bits.qos_mask = 0x00; break;
334 case 1: qconfig.bits.qos_mask = 0x01; break;
335 case 2: qconfig.bits.qos_mask = 0x11; break;
336 case 3: qconfig.bits.qos_mask = 0x49; break;
337 case 4: qconfig.bits.qos_mask = 0x55; break;
338 case 5: qconfig.bits.qos_mask = 0x57; break;
339 case 6: qconfig.bits.qos_mask = 0x77; break;
340 case 7: qconfig.bits.qos_mask = 0x7f; break;
341 case 8: qconfig.bits.qos_mask = 0xff; break;
343 printf("\n%% Error: octeon_pko_config_port Invalid priority %llu",
344 (unsigned long long)priority[queue]);
345 qconfig.bits.qos_mask = 0xff;
346 result_code = OCTEON_PKO_INVALID_PRIORITY;
349 if (port != OCTEON_PKO_PORT_ILLEGAL) {
351 buf_ptr = octeon_fpa_alloc_phys(pko_output_cmdbuf_fpa_pool);
353 printf("\n%% Error: octeon_pko_config_port: Unable to allocate");
354 return (OCTEON_PKO_NO_MEMORY);
357 sw_queues[queue].xmit_command_state = (buf_ptr << OCTEON_PKO_INDEX_BITS);
358 octeon_spinlock_init(&(sw_queues[queue].lock));
363 printf(" PKO: port %u pool: %u base+queue %u %u %u buf_ptr: 0x%llX\n",
365 pko_output_cmdbuf_fpa_pool,
366 base_queue, queue, base_queue+queue,
370 qconfig.bits.buf_ptr = buf_ptr;
371 oct_write64(OCTEON_PKO_MEM_QUEUE_PTRS, qconfig.word64);
376 return (result_code);