cvmx-pko.h revision 232812
1/***********************license start*************** 2 * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3 * reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 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. 17 18 * * Neither the name of Cavium Inc. nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 23 * This Software, including technical data, may be subject to U.S. export control 24 * laws, including the U.S. Export Administration Act and its associated 25 * regulations, and may be subject to export or import regulations in other 26 * countries. 27 28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38 ***********************license end**************************************/ 39 40 41/** 42 * @file 43 * 44 * Interface to the hardware Packet Output unit. 45 * 46 * Starting with SDK 1.7.0, the PKO output functions now support 47 * two types of locking. CVMX_PKO_LOCK_ATOMIC_TAG continues to 48 * function similarly to previous SDKs by using POW atomic tags 49 * to preserve ordering and exclusivity. As a new option, you 50 * can now pass CVMX_PKO_LOCK_CMD_QUEUE which uses a ll/sc 51 * memory based locking instead. This locking has the advantage 52 * of not affecting the tag state but doesn't preserve packet 53 * ordering. CVMX_PKO_LOCK_CMD_QUEUE is appropriate in most 54 * generic code while CVMX_PKO_LOCK_CMD_QUEUE should be used 55 * with hand tuned fast path code. 56 * 57 * Some of other SDK differences visible to the command command 58 * queuing: 59 * - PKO indexes are no longer stored in the FAU. A large 60 * percentage of the FAU register block used to be tied up 61 * maintaining PKO queue pointers. These are now stored in a 62 * global named block. 63 * - The PKO <b>use_locking</b> parameter can now have a global 64 * effect. Since all application use the same named block, 65 * queue locking correctly applies across all operating 66 * systems when using CVMX_PKO_LOCK_CMD_QUEUE. 67 * - PKO 3 word commands are now supported. Use 68 * cvmx_pko_send_packet_finish3(). 69 * 70 * <hr>$Revision: 70030 $<hr> 71 */ 72 73 74#ifndef __CVMX_PKO_H__ 75#define __CVMX_PKO_H__ 76 77#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 78#include "cvmx-config.h" 79#include "cvmx-pko-defs.h" 80#include <asm/octeon/cvmx-fau.h> 81#include <asm/octeon/cvmx-fpa.h> 82#include <asm/octeon/cvmx-pow.h> 83#include <asm/octeon/cvmx-cmd-queue.h> 84#include <asm/octeon/cvmx-helper.h> 85#include <asm/octeon/cvmx-helper-cfg.h> 86#else 87# ifndef CVMX_DONT_INCLUDE_CONFIG 88# include "executive-config.h" 89# ifdef CVMX_ENABLE_PKO_FUNCTIONS 90# include "cvmx-config.h" 91# endif 92# endif 93#include "cvmx-fau.h" 94#include "cvmx-fpa.h" 95#include "cvmx-pow.h" 96#include "cvmx-cmd-queue.h" 97#include "cvmx-helper.h" 98#include "cvmx-helper-util.h" 99#include "cvmx-helper-cfg.h" 100#endif 101 102/* Adjust the command buffer size by 1 word so that in the case of using only 103** two word PKO commands no command words stradle buffers. The useful values 104** for this are 0 and 1. */ 105#define CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST (1) 106 107#ifdef __cplusplus 108extern "C" { 109#endif 110 111#define CVMX_PKO_MAX_OUTPUT_QUEUES_STATIC 256 112#define CVMX_PKO_MAX_OUTPUT_QUEUES ((OCTEON_IS_MODEL(OCTEON_CN31XX) || \ 113 OCTEON_IS_MODEL(OCTEON_CN3010) || \ 114 OCTEON_IS_MODEL(OCTEON_CN3005) || \ 115 OCTEON_IS_MODEL(OCTEON_CN50XX)) ? \ 116 32 : \ 117 (OCTEON_IS_MODEL(OCTEON_CN58XX) || \ 118 OCTEON_IS_MODEL(OCTEON_CN56XX) || \ 119 OCTEON_IS_MODEL(OCTEON_CN52XX) || \ 120 OCTEON_IS_MODEL(OCTEON_CN6XXX) || \ 121 OCTEON_IS_MODEL(OCTEON_CNF7XXX)) ? \ 122 256 : 128) 123#define CVMX_PKO_NUM_OUTPUT_PORTS ((OCTEON_IS_MODEL(OCTEON_CN63XX)) ? 44 : (OCTEON_IS_MODEL(OCTEON_CN66XX) ? 46 : 40)) 124#define CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID 63 /* use this for queues that are not used */ 125#define CVMX_PKO_QUEUE_STATIC_PRIORITY 9 126#define CVMX_PKO_ILLEGAL_QUEUE 0xFFFF 127#define CVMX_PKO_MAX_QUEUE_DEPTH 0 128 129typedef enum 130{ 131 CVMX_PKO_SUCCESS, 132 CVMX_PKO_INVALID_PORT, 133 CVMX_PKO_INVALID_QUEUE, 134 CVMX_PKO_INVALID_PRIORITY, 135 CVMX_PKO_NO_MEMORY, 136 CVMX_PKO_PORT_ALREADY_SETUP, 137 CVMX_PKO_CMD_QUEUE_INIT_ERROR 138} cvmx_pko_status_t; 139 140/** 141 * This enumeration represents the differnet locking modes supported by PKO. 142 */ 143typedef enum 144{ 145 CVMX_PKO_LOCK_NONE = 0, /**< PKO doesn't do any locking. It is the responsibility 146 of the application to make sure that no other core is 147 accessing the same queue at the same time */ 148 CVMX_PKO_LOCK_ATOMIC_TAG = 1, /**< PKO performs an atomic tagswitch to insure exclusive 149 access to the output queue. This will maintain 150 packet ordering on output */ 151 CVMX_PKO_LOCK_CMD_QUEUE = 2, /**< PKO uses the common command queue locks to insure 152 exclusive access to the output queue. This is a memory 153 based ll/sc. This is the most portable locking 154 mechanism */ 155} cvmx_pko_lock_t; 156 157typedef struct 158{ 159 uint32_t packets; 160 uint64_t octets; 161 uint64_t doorbell; 162} cvmx_pko_port_status_t; 163 164/** 165 * This structure defines the address to use on a packet enqueue 166 */ 167typedef union 168{ 169 uint64_t u64; 170 struct 171 { 172 cvmx_mips_space_t mem_space : 2; /**< Must CVMX_IO_SEG */ 173 uint64_t reserved :13; /**< Must be zero */ 174 uint64_t is_io : 1; /**< Must be one */ 175 uint64_t did : 8; /**< The ID of the device on the non-coherent bus */ 176 uint64_t reserved2 : 4; /**< Must be zero */ 177 uint64_t reserved3 :15; /**< Must be zero */ 178 uint64_t port : 9; /**< The hardware must have the output port in addition to the output queue */ 179 uint64_t queue : 9; /**< The output queue to send the packet to (0-127 are legal) */ 180 uint64_t reserved4 : 3; /**< Must be zero */ 181 } s; 182} cvmx_pko_doorbell_address_t; 183 184/** 185 * Structure of the first packet output command word. 186 */ 187typedef union 188{ 189 uint64_t u64; 190 struct 191 { 192 cvmx_fau_op_size_t size1 : 2; /**< The size of the reg1 operation - could be 8, 16, 32, or 64 bits */ 193 cvmx_fau_op_size_t size0 : 2; /**< The size of the reg0 operation - could be 8, 16, 32, or 64 bits */ 194 uint64_t subone1 : 1; /**< If set, subtract 1, if clear, subtract packet size */ 195 uint64_t reg1 :11; /**< The register, subtract will be done if reg1 is non-zero */ 196 uint64_t subone0 : 1; /**< If set, subtract 1, if clear, subtract packet size */ 197 uint64_t reg0 :11; /**< The register, subtract will be done if reg0 is non-zero */ 198 uint64_t le : 1; /**< When set, interpret segment pointer and segment bytes in little endian order */ 199 uint64_t n2 : 1; /**< When set, packet data not allocated in L2 cache by PKO */ 200 uint64_t wqp : 1; /**< If set and rsp is set, word3 contains a pointer to a work queue entry */ 201 uint64_t rsp : 1; /**< If set, the hardware will send a response when done */ 202 uint64_t gather : 1; /**< If set, the supplied pkt_ptr is really a pointer to a list of pkt_ptr's */ 203 uint64_t ipoffp1 : 7; /**< If ipoffp1 is non zero, (ipoffp1-1) is the number of bytes to IP header, 204 and the hardware will calculate and insert the UDP/TCP checksum */ 205 uint64_t ignore_i : 1; /**< If set, ignore the I bit (force to zero) from all pointer structures */ 206 uint64_t dontfree : 1; /**< If clear, the hardware will attempt to free the buffers containing the packet */ 207 uint64_t segs : 6; /**< The total number of segs in the packet, if gather set, also gather list length */ 208 uint64_t total_bytes :16; /**< Including L2, but no trailing CRC */ 209 } s; 210} cvmx_pko_command_word0_t; 211 212/* CSR typedefs have been moved to cvmx-pko-defs.h */ 213 214/** 215 * Definition of internal state for Packet output processing 216 */ 217typedef struct 218{ 219 uint64_t * start_ptr; /**< ptr to start of buffer, offset kept in FAU reg */ 220} cvmx_pko_state_elem_t; 221 222 223#ifdef CVMX_ENABLE_PKO_FUNCTIONS 224/** 225 * Call before any other calls to initialize the packet 226 * output system. 227 */ 228extern void cvmx_pko_initialize_global(void); 229extern int cvmx_pko_initialize_local(void); 230 231#endif 232 233 234/** 235 * Enables the packet output hardware. It must already be 236 * configured. 237 */ 238extern void cvmx_pko_enable(void); 239 240 241/** 242 * Disables the packet output. Does not affect any configuration. 243 */ 244extern void cvmx_pko_disable(void); 245 246 247/** 248 * Shutdown and free resources required by packet output. 249 */ 250 251#ifdef CVMX_ENABLE_PKO_FUNCTIONS 252extern void cvmx_pko_shutdown(void); 253 254/** 255 * Configure a output port and the associated queues for use. 256 * 257 * @param port Port to configure. 258 * @param base_queue First queue number to associate with this port. 259 * @param num_queues Number of queues t oassociate with this port 260 * @param priority Array of priority levels for each queue. Values are 261 * allowed to be 1-8. A value of 8 get 8 times the traffic 262 * of a value of 1. There must be num_queues elements in the 263 * array. 264 */ 265extern cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue, uint64_t num_queues, const uint64_t priority[]); 266 267 268/** 269 * Ring the packet output doorbell. This tells the packet 270 * output hardware that "len" command words have been added 271 * to its pending list. This command includes the required 272 * CVMX_SYNCWS before the doorbell ring. 273 * 274 * WARNING: This function may have to look up the proper PKO port in 275 * the IPD port to PKO port map, and is thus slower than calling 276 * cvmx_pko_doorbell_pkoid() directly if the PKO port identifier is 277 * known. 278 * 279 * @param ipd_port The IPD port corresponding the to pko port the packet is for 280 * @param queue Queue the packet is for 281 * @param len Length of the command in 64 bit words 282 */ 283static inline void cvmx_pko_doorbell(uint64_t ipd_port, uint64_t queue, uint64_t len) 284{ 285 cvmx_pko_doorbell_address_t ptr; 286 uint64_t pko_port; 287 288 pko_port = ipd_port; 289 if (octeon_has_feature(OCTEON_FEATURE_PKND)) 290 pko_port = cvmx_helper_cfg_ipd2pko_port_base(ipd_port); 291 292 ptr.u64 = 0; 293 ptr.s.mem_space = CVMX_IO_SEG; 294 ptr.s.did = CVMX_OCT_DID_PKT_SEND; 295 ptr.s.is_io = 1; 296 ptr.s.port = pko_port; 297 ptr.s.queue = queue; 298 CVMX_SYNCWS; /* Need to make sure output queue data is in DRAM before doorbell write */ 299 cvmx_write_io(ptr.u64, len); 300} 301#endif 302 303 304/** 305 * Prepare to send a packet. This may initiate a tag switch to 306 * get exclusive access to the output queue structure, and 307 * performs other prep work for the packet send operation. 308 * 309 * cvmx_pko_send_packet_finish() MUST be called after this function is called, 310 * and must be called with the same port/queue/use_locking arguments. 311 * 312 * The use_locking parameter allows the caller to use three 313 * possible locking modes. 314 * - CVMX_PKO_LOCK_NONE 315 * - PKO doesn't do any locking. It is the responsibility 316 * of the application to make sure that no other core 317 * is accessing the same queue at the same time. 318 * - CVMX_PKO_LOCK_ATOMIC_TAG 319 * - PKO performs an atomic tagswitch to insure exclusive 320 * access to the output queue. This will maintain 321 * packet ordering on output. 322 * - CVMX_PKO_LOCK_CMD_QUEUE 323 * - PKO uses the common command queue locks to insure 324 * exclusive access to the output queue. This is a 325 * memory based ll/sc. This is the most portable 326 * locking mechanism. 327 * 328 * NOTE: If atomic locking is used, the POW entry CANNOT be 329 * descheduled, as it does not contain a valid WQE pointer. 330 * 331 * @param port Port to send it on, this can be either IPD port or PKO 332 * port. 333 * @param queue Queue to use 334 * @param use_locking 335 * CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or CVMX_PKO_LOCK_CMD_QUEUE 336 */ 337#ifdef CVMX_ENABLE_PKO_FUNCTIONS 338static inline void cvmx_pko_send_packet_prepare(uint64_t port, uint64_t queue, cvmx_pko_lock_t use_locking) 339{ 340 if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) 341 { 342 /* Must do a full switch here to handle all cases. We use a fake WQE pointer, as the POW does 343 ** not access this memory. The WQE pointer and group are only used if this work is descheduled, 344 ** which is not supported by the cvmx_pko_send_packet_prepare/cvmx_pko_send_packet_finish combination. 345 ** Note that this is a special case in which these fake values can be used - this is not a general technique. 346 */ 347 uint32_t tag = CVMX_TAG_SW_BITS_INTERNAL << CVMX_TAG_SW_SHIFT | CVMX_TAG_SUBGROUP_PKO << CVMX_TAG_SUBGROUP_SHIFT | (CVMX_TAG_SUBGROUP_MASK & queue); 348 cvmx_pow_tag_sw_full((cvmx_wqe_t *)cvmx_phys_to_ptr(0x80), tag, CVMX_POW_TAG_TYPE_ATOMIC, 0); 349 } 350} 351 352#define cvmx_pko_send_packet_prepare_pkoid cvmx_pko_send_packet_prepare 353 354/** 355 * Complete packet output. cvmx_pko_send_packet_prepare() must be called exactly once before this, 356 * and the same parameters must be passed to both cvmx_pko_send_packet_prepare() and 357 * cvmx_pko_send_packet_finish(). 358 * 359 * WARNING: This function may have to look up the proper PKO port in 360 * the IPD port to PKO port map, and is thus slower than calling 361 * cvmx_pko_send_packet_finish_pkoid() directly if the PKO port 362 * identifier is known. 363 * 364 * @param ipd_port The IPD port corresponding the to pko port the packet is for 365 * @param queue Queue to use 366 * @param pko_command 367 * PKO HW command word 368 * @param packet Packet to send 369 * @param use_locking 370 * CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or CVMX_PKO_LOCK_CMD_QUEUE 371 * 372 * @return returns CVMX_PKO_SUCCESS on success, or error code on failure of output 373 */ 374static inline cvmx_pko_status_t cvmx_pko_send_packet_finish(uint64_t ipd_port, uint64_t queue, 375 cvmx_pko_command_word0_t pko_command, 376 cvmx_buf_ptr_t packet, cvmx_pko_lock_t use_locking) 377{ 378 cvmx_cmd_queue_result_t result; 379 if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) 380 cvmx_pow_tag_sw_wait(); 381 result = cvmx_cmd_queue_write2(CVMX_CMD_QUEUE_PKO(queue), 382 (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), 383 pko_command.u64, 384 packet.u64); 385 if (cvmx_likely(result == CVMX_CMD_QUEUE_SUCCESS)) 386 { 387 cvmx_pko_doorbell(ipd_port, queue, 2); 388 return CVMX_PKO_SUCCESS; 389 } 390 else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) || (result == CVMX_CMD_QUEUE_FULL)) 391 { 392 return CVMX_PKO_NO_MEMORY; 393 } 394 else 395 { 396 return CVMX_PKO_INVALID_QUEUE; 397 } 398} 399 400 401/** 402 * Complete packet output. cvmx_pko_send_packet_prepare() must be called exactly once before this, 403 * and the same parameters must be passed to both cvmx_pko_send_packet_prepare() and 404 * cvmx_pko_send_packet_finish(). 405 * 406 * WARNING: This function may have to look up the proper PKO port in 407 * the IPD port to PKO port map, and is thus slower than calling 408 * cvmx_pko_send_packet_finish3_pkoid() directly if the PKO port 409 * identifier is known. 410 * 411 * @param ipd_port The IPD port corresponding the to pko port the packet is for 412 * @param queue Queue to use 413 * @param pko_command 414 * PKO HW command word 415 * @param packet Packet to send 416 * @param addr Plysical address of a work queue entry or physical address to zero on complete. 417 * @param use_locking 418 * CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or CVMX_PKO_LOCK_CMD_QUEUE 419 * 420 * @return returns CVMX_PKO_SUCCESS on success, or error code on failure of output 421 */ 422static inline cvmx_pko_status_t cvmx_pko_send_packet_finish3(uint64_t ipd_port, uint64_t queue, 423 cvmx_pko_command_word0_t pko_command, 424 cvmx_buf_ptr_t packet, uint64_t addr, cvmx_pko_lock_t use_locking) 425{ 426 cvmx_cmd_queue_result_t result; 427 if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) 428 cvmx_pow_tag_sw_wait(); 429 result = cvmx_cmd_queue_write3(CVMX_CMD_QUEUE_PKO(queue), 430 (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), 431 pko_command.u64, 432 packet.u64, 433 addr); 434 if (cvmx_likely(result == CVMX_CMD_QUEUE_SUCCESS)) 435 { 436 cvmx_pko_doorbell(ipd_port, queue, 3); 437 return CVMX_PKO_SUCCESS; 438 } 439 else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) || (result == CVMX_CMD_QUEUE_FULL)) 440 { 441 return CVMX_PKO_NO_MEMORY; 442 } 443 else 444 { 445 return CVMX_PKO_INVALID_QUEUE; 446 } 447} 448 449/** 450 * Get the first pko_port for the (interface, index) 451 * 452 * @param interface 453 * @param index 454 */ 455extern int cvmx_pko_get_base_pko_port(int interface, int index); 456 457/** 458 * Get the number of pko_ports for the (interface, index) 459 * 460 * @param interface 461 * @param index 462 */ 463extern int cvmx_pko_get_num_pko_ports(int interface, int index); 464 465/** 466 * Return the pko output queue associated with a port and a specific core. 467 * In normal mode (PKO lockless operation is disabled), the value returned 468 * is the base queue. 469 * 470 * @param port Port number 471 * @param core Core to get queue for 472 * 473 * @return Core-specific output queue and -1 on error. 474 * 475 * Note: This function is invalid for o68. 476 */ 477static inline int cvmx_pko_get_base_queue_per_core(int port, int core) 478{ 479 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 480 { 481 cvmx_dprintf("cvmx_pko_get_base_queue_per_core() not" 482 "supported starting from o68!\n"); 483 return -1; 484 } 485 486#ifndef CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 487 #define CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 16 488#endif 489#ifndef CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 490 #define CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 16 491#endif 492#ifndef CVMX_PKO_QUEUES_PER_PORT_SRIO0 493 /* We use two queues per port for SRIO0. Having two queues per 494 port with two ports gives us four queues, one for each mailbox */ 495 #define CVMX_PKO_QUEUES_PER_PORT_SRIO0 2 496#endif 497#ifndef CVMX_PKO_QUEUES_PER_PORT_SRIO1 498 /* We use two queues per port for SRIO1. Having two queues per 499 port with two ports gives us four queues, one for each mailbox */ 500 #define CVMX_PKO_QUEUES_PER_PORT_SRIO1 2 501#endif 502#ifndef CVMX_PKO_QUEUES_PER_PORT_SRIO2 503 /* We use two queues per port for SRIO2. Having two queues per 504 port with two ports gives us four queues, one for each mailbox */ 505 #define CVMX_PKO_QUEUES_PER_PORT_SRIO2 2 506#endif 507 if (port < CVMX_PKO_MAX_PORTS_INTERFACE0) 508 return port * CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + core; 509 else if (port >=16 && port < 16 + CVMX_PKO_MAX_PORTS_INTERFACE1) 510 return CVMX_PKO_MAX_PORTS_INTERFACE0 * CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + 511 (port-16) * CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + core; 512 else if ((port >= 32) && (port < 36)) 513 return CVMX_PKO_MAX_PORTS_INTERFACE0 * CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + 514 CVMX_PKO_MAX_PORTS_INTERFACE1 * CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + 515 (port-32) * CVMX_PKO_QUEUES_PER_PORT_PCI; 516 else if ((port >= 36) && (port < 40)) 517 return CVMX_PKO_MAX_PORTS_INTERFACE0 * CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + 518 CVMX_PKO_MAX_PORTS_INTERFACE1 * CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + 519 4 * CVMX_PKO_QUEUES_PER_PORT_PCI + 520 (port-36) * CVMX_PKO_QUEUES_PER_PORT_LOOP; 521 else if ((port >= 40) && (port < 42)) 522 return CVMX_PKO_MAX_PORTS_INTERFACE0 * CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + 523 CVMX_PKO_MAX_PORTS_INTERFACE1 * CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + 524 4 * CVMX_PKO_QUEUES_PER_PORT_PCI + 525 4 * CVMX_PKO_QUEUES_PER_PORT_LOOP + 526 (port-40) * CVMX_PKO_QUEUES_PER_PORT_SRIO0; 527 else if ((port >= 42) && (port < 44)) 528 return CVMX_PKO_MAX_PORTS_INTERFACE0 * CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + 529 CVMX_PKO_MAX_PORTS_INTERFACE1 * CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + 530 4 * CVMX_PKO_QUEUES_PER_PORT_PCI + 531 4 * CVMX_PKO_QUEUES_PER_PORT_LOOP + 532 2 * CVMX_PKO_QUEUES_PER_PORT_SRIO0 + 533 (port-42) * CVMX_PKO_QUEUES_PER_PORT_SRIO1; 534 else if ((port >= 44) && (port < 46)) 535 return CVMX_PKO_MAX_PORTS_INTERFACE0 * CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + 536 CVMX_PKO_MAX_PORTS_INTERFACE1 * CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + 537 4 * CVMX_PKO_QUEUES_PER_PORT_PCI + 538 4 * CVMX_PKO_QUEUES_PER_PORT_LOOP + 539 4 * CVMX_PKO_QUEUES_PER_PORT_SRIO0 + 540 (port-44) * CVMX_PKO_QUEUES_PER_PORT_SRIO2; 541 else 542 /* Given the limit on the number of ports we can map to 543 * CVMX_MAX_OUTPUT_QUEUES_STATIC queues (currently 256, 544 * divided among all cores), the remaining unmapped ports 545 * are assigned an illegal queue number */ 546 return CVMX_PKO_ILLEGAL_QUEUE; 547} 548 549/** 550 * For a given port number, return the base pko output queue 551 * for the port. 552 * 553 * @param port IPD port number 554 * @return Base output queue 555 */ 556extern int cvmx_pko_get_base_queue(int port); 557 558/** 559 * For a given port number, return the number of pko output queues. 560 * 561 * @param port IPD port number 562 * @return Number of output queues 563 */ 564extern int cvmx_pko_get_num_queues(int port); 565 566#ifdef CVMX_ENABLE_PKO_FUNCTIONS 567 568/** 569 * Get the status counters for a port. 570 * 571 * @param ipd_port Port number (ipd_port) to get statistics for. 572 * @param clear Set to 1 to clear the counters after they are read 573 * @param status Where to put the results. 574 * 575 * Note: 576 * - Only the doorbell for the base queue of the ipd_port is 577 * collected. 578 * - Retrieving the stats involves writing the index through 579 * CVMX_PKO_REG_READ_IDX and reading the stat CSRs, in that 580 * order. It is not MP-safe and caller should guarantee 581 * atomicity. 582 */ 583static inline void cvmx_pko_get_port_status(uint64_t ipd_port, uint64_t clear, 584 cvmx_pko_port_status_t *status) 585{ 586 cvmx_pko_reg_read_idx_t pko_reg_read_idx; 587 cvmx_pko_mem_count0_t pko_mem_count0; 588 cvmx_pko_mem_count1_t pko_mem_count1; 589 int pko_port, port_base, port_limit; 590 591 if (octeon_has_feature(OCTEON_FEATURE_PKND)) { 592 int interface = cvmx_helper_get_interface_num(ipd_port); 593 int index = cvmx_helper_get_interface_index_num(ipd_port); 594 port_base = cvmx_helper_get_pko_port(interface, index); 595 if (port_base == -1) 596 cvmx_dprintf("Warning: Invalid port_base\n"); 597 port_limit = port_base + cvmx_pko_get_num_pko_ports(interface, index); 598 } else { 599 port_base = ipd_port; 600 port_limit = port_base + 1; 601 } 602 603 /* 604 * status->packets and status->octets 605 */ 606 status->packets = 0; 607 status->octets = 0; 608 pko_reg_read_idx.u64 = 0; 609 610 for (pko_port = port_base; pko_port < port_limit; pko_port++) 611 { 612 613 /* 614 * In theory, one doesn't need to write the index csr every 615 * time as he can set pko_reg_read_idx.s.inc to increment 616 * the index automatically. Need to find out exactly how XXX. 617 */ 618 pko_reg_read_idx.s.index = pko_port; 619 cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); 620 621 pko_mem_count0.u64 = cvmx_read_csr(CVMX_PKO_MEM_COUNT0); 622 status->packets += pko_mem_count0.s.count; 623 if (clear) 624 { 625 pko_mem_count0.s.count = pko_port; 626 cvmx_write_csr(CVMX_PKO_MEM_COUNT0, pko_mem_count0.u64); 627 } 628 629 pko_mem_count1.u64 = cvmx_read_csr(CVMX_PKO_MEM_COUNT1); 630 status->octets += pko_mem_count1.s.count; 631 if (clear) 632 { 633 pko_mem_count1.s.count = pko_port; 634 cvmx_write_csr(CVMX_PKO_MEM_COUNT1, pko_mem_count1.u64); 635 } 636 } 637 638 /* 639 * status->doorbell 640 */ 641 if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) 642 { 643 cvmx_pko_mem_debug9_t debug9; 644 pko_reg_read_idx.s.index = cvmx_pko_get_base_queue(ipd_port); 645 cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); 646 debug9.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG9); 647 status->doorbell = debug9.cn38xx.doorbell; 648 } 649 else 650 { 651 cvmx_pko_mem_debug8_t debug8; 652 pko_reg_read_idx.s.index = cvmx_pko_get_base_queue(ipd_port); 653 cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); 654 debug8.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG8); 655 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 656 status->doorbell = debug8.cn68xx.doorbell; 657 else 658 status->doorbell = debug8.cn58xx.doorbell; 659 } 660} 661 662#endif /* CVMX_ENABLE_PKO_FUNCTION */ 663 664 665/** 666 * Rate limit a PKO port to a max packets/sec. This function is only 667 * supported on CN57XX, CN56XX, CN55XX, and CN54XX. 668 * 669 * @param port Port to rate limit 670 * @param packets_s Maximum packet/sec 671 * @param burst Maximum number of packets to burst in a row before rate 672 * limiting cuts in. 673 * 674 * @return Zero on success, negative on failure 675 */ 676extern int cvmx_pko_rate_limit_packets(int port, int packets_s, int burst); 677 678/** 679 * Rate limit a PKO port to a max bits/sec. This function is only 680 * supported on CN57XX, CN56XX, CN55XX, and CN54XX. 681 * 682 * @param port Port to rate limit 683 * @param bits_s PKO rate limit in bits/sec 684 * @param burst Maximum number of bits to burst before rate 685 * limiting cuts in. 686 * 687 * @return Zero on success, negative on failure 688 */ 689extern int cvmx_pko_rate_limit_bits(int port, uint64_t bits_s, int burst); 690 691/** 692 * @INTERNAL 693 * 694 * Retrieve the PKO pipe number for a port 695 * 696 * @param interface 697 * @param index 698 * 699 * @return negative on error. 700 * 701 * This applies only to the non-loopback interfaces. 702 * 703 */ 704extern int __cvmx_pko_get_pipe(int interface, int index); 705 706/** 707 * For a given PKO port number, return the base output queue 708 * for the port. 709 * 710 * @param pko_port PKO port number 711 * @return Base output queue 712 */ 713extern int cvmx_pko_get_base_queue_pkoid(int pko_port); 714 715/** 716 * For a given PKO port number, return the number of output queues 717 * for the port. 718 * 719 * @param pko_port PKO port number 720 * @return the number of output queues 721 */ 722extern int cvmx_pko_get_num_queues_pkoid(int pko_port); 723 724/** 725 * Ring the packet output doorbell. This tells the packet 726 * output hardware that "len" command words have been added 727 * to its pending list. This command includes the required 728 * CVMX_SYNCWS before the doorbell ring. 729 * 730 * @param pko_port Port the packet is for 731 * @param queue Queue the packet is for 732 * @param len Length of the command in 64 bit words 733 */ 734static inline void cvmx_pko_doorbell_pkoid(uint64_t pko_port, uint64_t queue, uint64_t len) 735{ 736 cvmx_pko_doorbell_address_t ptr; 737 738 ptr.u64 = 0; 739 ptr.s.mem_space = CVMX_IO_SEG; 740 ptr.s.did = CVMX_OCT_DID_PKT_SEND; 741 ptr.s.is_io = 1; 742 ptr.s.port = pko_port; 743 ptr.s.queue = queue; 744 CVMX_SYNCWS; /* Need to make sure output queue data is in DRAM before doorbell write */ 745 cvmx_write_io(ptr.u64, len); 746} 747 748/** 749 * Complete packet output. cvmx_pko_send_packet_prepare() must be called exactly once before this, 750 * and the same parameters must be passed to both cvmx_pko_send_packet_prepare() and 751 * cvmx_pko_send_packet_finish_pkoid(). 752 * 753 * @param pko_port Port to send it on 754 * @param queue Queue to use 755 * @param pko_command 756 * PKO HW command word 757 * @param packet Packet to send 758 * @param use_locking 759 * CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or CVMX_PKO_LOCK_CMD_QUEUE 760 * 761 * @return returns CVMX_PKO_SUCCESS on success, or error code on failure of output 762 */ 763static inline cvmx_pko_status_t cvmx_pko_send_packet_finish_pkoid(int pko_port, uint64_t queue, 764 cvmx_pko_command_word0_t pko_command, 765 cvmx_buf_ptr_t packet, cvmx_pko_lock_t use_locking) 766{ 767 cvmx_cmd_queue_result_t result; 768 if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) 769 cvmx_pow_tag_sw_wait(); 770 result = cvmx_cmd_queue_write2(CVMX_CMD_QUEUE_PKO(queue), 771 (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), 772 pko_command.u64, 773 packet.u64); 774 if (cvmx_likely(result == CVMX_CMD_QUEUE_SUCCESS)) 775 { 776 cvmx_pko_doorbell_pkoid(pko_port, queue, 2); 777 return CVMX_PKO_SUCCESS; 778 } 779 else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) || (result == CVMX_CMD_QUEUE_FULL)) 780 { 781 return CVMX_PKO_NO_MEMORY; 782 } 783 else 784 { 785 return CVMX_PKO_INVALID_QUEUE; 786 } 787} 788 789/** 790 * Complete packet output. cvmx_pko_send_packet_prepare() must be called exactly once before this, 791 * and the same parameters must be passed to both cvmx_pko_send_packet_prepare() and 792 * cvmx_pko_send_packet_finish_pkoid(). 793 * 794 * @param pko_port The PKO port the packet is for 795 * @param queue Queue to use 796 * @param pko_command 797 * PKO HW command word 798 * @param packet Packet to send 799 * @param addr Plysical address of a work queue entry or physical address to zero on complete. 800 * @param use_locking 801 * CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or CVMX_PKO_LOCK_CMD_QUEUE 802 * 803 * @return returns CVMX_PKO_SUCCESS on success, or error code on failure of output 804 */ 805static inline cvmx_pko_status_t cvmx_pko_send_packet_finish3_pkoid(uint64_t pko_port, uint64_t queue, 806 cvmx_pko_command_word0_t pko_command, 807 cvmx_buf_ptr_t packet, uint64_t addr, cvmx_pko_lock_t use_locking) 808{ 809 cvmx_cmd_queue_result_t result; 810 if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) 811 cvmx_pow_tag_sw_wait(); 812 result = cvmx_cmd_queue_write3(CVMX_CMD_QUEUE_PKO(queue), 813 (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), 814 pko_command.u64, 815 packet.u64, 816 addr); 817 if (cvmx_likely(result == CVMX_CMD_QUEUE_SUCCESS)) 818 { 819 cvmx_pko_doorbell_pkoid(pko_port, queue, 3); 820 return CVMX_PKO_SUCCESS; 821 } 822 else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) || (result == CVMX_CMD_QUEUE_FULL)) 823 { 824 return CVMX_PKO_NO_MEMORY; 825 } 826 else 827 { 828 return CVMX_PKO_INVALID_QUEUE; 829 } 830} 831 832#endif /* CVMX_ENABLE_PKO_FUNCTIONS */ 833 834#ifdef __cplusplus 835} 836#endif 837 838#endif /* __CVMX_PKO_H__ */ 839