1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2018-2022 Marvell International Ltd. 4 * 5 * Support library for the hardware Packet Output unit. 6 */ 7 8#include <errno.h> 9#include <log.h> 10#include <time.h> 11#include <linux/delay.h> 12 13#include <mach/cvmx-regs.h> 14#include <mach/cvmx-csr.h> 15#include <mach/cvmx-bootmem.h> 16#include <mach/octeon-model.h> 17#include <mach/cvmx-fuse.h> 18#include <mach/octeon-feature.h> 19#include <mach/cvmx-qlm.h> 20#include <mach/octeon_qlm.h> 21#include <mach/cvmx-pcie.h> 22#include <mach/cvmx-coremask.h> 23 24#include <mach/cvmx-agl-defs.h> 25#include <mach/cvmx-bgxx-defs.h> 26#include <mach/cvmx-ciu-defs.h> 27#include <mach/cvmx-gmxx-defs.h> 28#include <mach/cvmx-gserx-defs.h> 29#include <mach/cvmx-ilk-defs.h> 30#include <mach/cvmx-iob-defs.h> 31#include <mach/cvmx-ipd-defs.h> 32#include <mach/cvmx-pcsx-defs.h> 33#include <mach/cvmx-pcsxx-defs.h> 34#include <mach/cvmx-pki-defs.h> 35#include <mach/cvmx-pko-defs.h> 36#include <mach/cvmx-xcv-defs.h> 37 38#include <mach/cvmx-hwpko.h> 39#include <mach/cvmx-ilk.h> 40#include <mach/cvmx-pki.h> 41#include <mach/cvmx-pko3.h> 42#include <mach/cvmx-pko3-queue.h> 43#include <mach/cvmx-pko3-resources.h> 44 45#include <mach/cvmx-helper.h> 46#include <mach/cvmx-helper-board.h> 47#include <mach/cvmx-helper-cfg.h> 48 49#include <mach/cvmx-helper-bgx.h> 50#include <mach/cvmx-helper-cfg.h> 51#include <mach/cvmx-helper-util.h> 52#include <mach/cvmx-helper-pki.h> 53#include <mach/cvmx-helper-pko.h> 54 55DECLARE_GLOBAL_DATA_PTR; 56 57#define CVMX_PKO_NQ_PER_PORT_MAX 32 58 59static cvmx_pko_return_value_t cvmx_pko2_config_port(short ipd_port, 60 int base_queue, 61 int num_queues, 62 const u8 priority[]); 63 64static const int debug; 65 66/** 67 * Internal state of packet output 68 */ 69 70/* 71 * PKO port iterator 72 * XXX this macro only works for 68XX 73 */ 74 75#define pko_for_each_port(__p) \ 76 for (__p = 0; __p < CVMX_HELPER_CFG_MAX_PKO_PORT; __p++) \ 77 if (__cvmx_helper_cfg_pko_queue_base(__p) != \ 78 CVMX_HELPER_CFG_INVALID_VALUE) 79 80/* 81 * @INTERNAL 82 * 83 * Get INT for a port 84 * 85 * @param interface 86 * @param index 87 * @return the INT value on success and -1 on error 88 * 89 * This function is only for CN68XX. 90 */ 91static int __cvmx_pko_int(int interface, int index) 92{ 93 cvmx_helper_cfg_assert(interface < CVMX_HELPER_MAX_IFACE); 94 cvmx_helper_cfg_assert(index >= 0); 95 96 switch (interface) { 97 case 0: 98 cvmx_helper_cfg_assert(index < 4); 99 return index; 100 case 1: 101 cvmx_helper_cfg_assert(index == 0); 102 return 4; 103 case 2: 104 cvmx_helper_cfg_assert(index < 4); 105 return index + 8; 106 case 3: 107 cvmx_helper_cfg_assert(index < 4); 108 return index + 0xC; 109 case 4: 110 cvmx_helper_cfg_assert(index < 4); 111 return index + 0x10; 112 case 5: 113 cvmx_helper_cfg_assert(index < 256); 114 return 0x1C; 115 case 6: 116 cvmx_helper_cfg_assert(index < 256); 117 return 0x1D; 118 case 7: 119 cvmx_helper_cfg_assert(index < 32); 120 return 0x1E; 121 case 8: 122 cvmx_helper_cfg_assert(index < 8); 123 return 0x1F; 124 } 125 126 return -1; 127} 128 129int cvmx_pko_get_base_pko_port(int interface, int index) 130{ 131 if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) 132 return cvmx_helper_get_ipd_port(interface, index); 133 else if (octeon_has_feature(OCTEON_FEATURE_PKND)) 134 return __cvmx_helper_cfg_pko_port_base(interface, index); 135 else 136 return cvmx_helper_get_ipd_port(interface, index); 137} 138 139int cvmx_pko_get_base_queue(int port) 140{ 141 if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) { 142 return cvmx_pko3_get_queue_base(port); 143 } else if (octeon_has_feature(OCTEON_FEATURE_PKND)) { 144 return __cvmx_helper_cfg_pko_queue_base( 145 cvmx_helper_cfg_ipd2pko_port_base(port)); 146 } else { 147 if (port < 48) 148 return cvmx_pko_queue_table[port].ccppp_queue_base; 149 else 150 return CVMX_PKO_ILLEGAL_QUEUE; 151 } 152} 153 154int cvmx_pko_get_num_queues(int port) 155{ 156 if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) { 157 return cvmx_pko3_get_queue_num(port); 158 } else if (octeon_has_feature(OCTEON_FEATURE_PKND)) { 159 return __cvmx_helper_cfg_pko_queue_num( 160 cvmx_helper_cfg_ipd2pko_port_base(port)); 161 } else { 162 if (port < 48) 163 return cvmx_pko_queue_table[port].ccppp_num_queues; 164 } 165 return 0; 166} 167 168/* 169 * Allocate memory for PKO engines. 170 * 171 * @param engine is the PKO engine ID. 172 * @return # of 2KB-chunks allocated to this PKO engine. 173 */ 174static int __cvmx_pko_memory_per_engine_o68(int engine) 175{ 176 /* CN68XX has 40KB to devide between the engines in 2KB chunks */ 177 int max_engine; 178 int size_per_engine; 179 int size; 180 181 max_engine = __cvmx_helper_cfg_pko_max_engine(); 182 size_per_engine = 40 / 2 / max_engine; 183 184 if (engine >= max_engine) 185 /* Unused engines get no space */ 186 size = 0; 187 else if (engine == max_engine - 1) 188 /* 189 * The last engine gets all the space lost by rounding. This means 190 * the ILK gets the most space 191 */ 192 size = 40 / 2 - engine * size_per_engine; 193 else 194 /* All other engines get the same space */ 195 size = size_per_engine; 196 197 return size; 198} 199 200/* 201 * Setup one-to-one mapping between PKO2 iport and eport. 202 * @INTERNAL 203 */ 204static void __cvmx_pko2_chip_init(void) 205{ 206 int i; 207 int interface, index, port; 208 cvmx_helper_interface_mode_t mode; 209 union cvmx_pko_mem_iport_ptrs config; 210 211 /* 212 * Initialize every iport with the invalid eid. 213 */ 214#define CVMX_O68_PKO2_INVALID_EID 31 215 config.u64 = 0; 216 config.s.eid = CVMX_O68_PKO2_INVALID_EID; 217 for (i = 0; i < CVMX_HELPER_CFG_MAX_PKO_PORT; i++) { 218 config.s.ipid = i; 219 csr_wr(CVMX_PKO_MEM_IPORT_PTRS, config.u64); 220 } 221 222 /* 223 * Set up PKO_MEM_IPORT_PTRS 224 */ 225 pko_for_each_port(port) { 226 interface = __cvmx_helper_cfg_pko_port_interface(port); 227 index = __cvmx_helper_cfg_pko_port_index(port); 228 mode = cvmx_helper_interface_get_mode(interface); 229 230 if (mode == CVMX_HELPER_INTERFACE_MODE_DISABLED) 231 continue; 232 233 config.s.ipid = port; 234 config.s.qos_mask = 0xff; 235 config.s.crc = __cvmx_helper_get_has_fcs(interface); 236 config.s.min_pkt = __cvmx_helper_get_pko_padding(interface); 237 config.s.intr = __cvmx_pko_int(interface, index); 238 config.s.eid = __cvmx_helper_cfg_pko_port_eid(port); 239 config.s.pipe = (mode == CVMX_HELPER_INTERFACE_MODE_LOOP) ? 240 index : 241 port; 242 csr_wr(CVMX_PKO_MEM_IPORT_PTRS, config.u64); 243 } 244} 245 246int __cvmx_pko_get_pipe(int interface, int index) 247{ 248 /* The loopback ports do not have pipes */ 249 if (cvmx_helper_interface_get_mode(interface) == 250 CVMX_HELPER_INTERFACE_MODE_LOOP) 251 return -1; 252 /* We use pko_port as the pipe. See __cvmx_pko_port_map_o68(). */ 253 return cvmx_helper_get_pko_port(interface, index); 254} 255 256static void __cvmx_pko1_chip_init(void) 257{ 258 int queue; 259 union cvmx_pko_mem_queue_ptrs config; 260 union cvmx_pko_reg_queue_ptrs1 config1; 261 const int port = CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID; 262 263 /* Initialize all queues to connect to port 63 (ILLEGAL_PID) */ 264 for (queue = 0; queue < CVMX_PKO_MAX_OUTPUT_QUEUES; queue++) { 265 config1.u64 = 0; 266 config1.s.idx3 = 0; 267 config1.s.qid7 = queue >> 7; 268 269 config.u64 = 0; 270 config.s.tail = 1; 271 config.s.index = 0; 272 config.s.port = port; 273 config.s.queue = queue; 274 config.s.buf_ptr = 0; 275 276 csr_wr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64); 277 csr_wr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64); 278 } 279} 280 281/** 282 * Call before any other calls to initialize the packet 283 * output system. This does chip global config, and should only be 284 * done by one core. 285 */ 286void cvmx_pko_hw_init(u8 pool, unsigned int bufsize) 287{ 288 union cvmx_pko_reg_cmd_buf config; 289 union cvmx_iob_fau_timeout fau_to; 290 int i; 291 292 if (debug) 293 debug("%s: pool=%u bufsz=%u\n", __func__, pool, bufsize); 294 295 /* chip-specific setup. */ 296 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 297 __cvmx_pko2_chip_init(); 298 else 299 __cvmx_pko1_chip_init(); 300 301 /* 302 * Set the size of the PKO command buffers to an odd number of 303 * 64bit words. This allows the normal two word send to stay 304 * aligned and never span a command word buffer. 305 */ 306 config.u64 = 0; 307 config.s.pool = pool; 308 config.s.size = bufsize / 8 - 1; 309 csr_wr(CVMX_PKO_REG_CMD_BUF, config.u64); 310 311 /* 312 * Disable tagwait FAU timeout. This needs to be done before 313 * anyone might start packet output using tags. 314 */ 315 fau_to.u64 = 0; 316 fau_to.s.tout_val = 0xfff; 317 fau_to.s.tout_enb = 0; 318 csr_wr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64); 319 320 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { 321 union cvmx_pko_reg_min_pkt min_pkt; 322 323 min_pkt.u64 = 0; 324 min_pkt.s.size1 = 59; 325 min_pkt.s.size2 = 59; 326 min_pkt.s.size3 = 59; 327 min_pkt.s.size4 = 59; 328 min_pkt.s.size5 = 59; 329 min_pkt.s.size6 = 59; 330 min_pkt.s.size7 = 59; 331 csr_wr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64); 332 } 333 334 /* 335 * If we aren't using all of the queues optimize PKO's 336 * internal memory. 337 */ 338 if (OCTEON_IS_OCTEON2() || OCTEON_IS_MODEL(OCTEON_CN70XX)) { 339 int max_queues = __cvmx_helper_cfg_pko_max_queue(); 340 341 if (OCTEON_IS_MODEL(OCTEON_CN68XX) && max_queues <= 32) 342 csr_wr(CVMX_PKO_REG_QUEUE_MODE, 3); 343 else if (max_queues <= 64) 344 csr_wr(CVMX_PKO_REG_QUEUE_MODE, 2); 345 else if (max_queues <= 128) 346 csr_wr(CVMX_PKO_REG_QUEUE_MODE, 1); 347 else 348 csr_wr(CVMX_PKO_REG_QUEUE_MODE, 0); 349 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { 350 for (i = 0; i < 2; i++) { 351 union cvmx_pko_reg_engine_storagex 352 engine_storage; 353 354#define PKO_ASSIGN_ENGINE_STORAGE(index) \ 355 engine_storage.s.engine##index = \ 356 __cvmx_pko_memory_per_engine_o68(16 * i + (index)) 357 358 engine_storage.u64 = 0; 359 PKO_ASSIGN_ENGINE_STORAGE(0); 360 PKO_ASSIGN_ENGINE_STORAGE(1); 361 PKO_ASSIGN_ENGINE_STORAGE(2); 362 PKO_ASSIGN_ENGINE_STORAGE(3); 363 PKO_ASSIGN_ENGINE_STORAGE(4); 364 PKO_ASSIGN_ENGINE_STORAGE(5); 365 PKO_ASSIGN_ENGINE_STORAGE(6); 366 PKO_ASSIGN_ENGINE_STORAGE(7); 367 PKO_ASSIGN_ENGINE_STORAGE(8); 368 PKO_ASSIGN_ENGINE_STORAGE(9); 369 PKO_ASSIGN_ENGINE_STORAGE(10); 370 PKO_ASSIGN_ENGINE_STORAGE(11); 371 PKO_ASSIGN_ENGINE_STORAGE(12); 372 PKO_ASSIGN_ENGINE_STORAGE(13); 373 PKO_ASSIGN_ENGINE_STORAGE(14); 374 PKO_ASSIGN_ENGINE_STORAGE(15); 375 csr_wr(CVMX_PKO_REG_ENGINE_STORAGEX(i), 376 engine_storage.u64); 377 } 378 } 379 } 380} 381 382/** 383 * Enables the packet output hardware. It must already be 384 * configured. 385 */ 386void cvmx_pko_enable(void) 387{ 388 union cvmx_pko_reg_flags flags; 389 390 flags.u64 = csr_rd(CVMX_PKO_REG_FLAGS); 391 if (flags.s.ena_pko) 392 debug("Warning: Enabling PKO when PKO already enabled.\n"); 393 394 flags.s.ena_dwb = cvmx_helper_cfg_opt_get(CVMX_HELPER_CFG_OPT_USE_DWB); 395 flags.s.ena_pko = 1; 396 /* 397 * always enable big endian for 3-word command. Does nothing 398 * for 2-word. 399 */ 400 flags.s.store_be = 1; 401 csr_wr(CVMX_PKO_REG_FLAGS, flags.u64); 402} 403 404/** 405 * Configure a output port and the associated queues for use. 406 * 407 * @param port Port to configure. 408 * @param base_queue First queue number to associate with this port. 409 * @param num_queues Number of queues to associate with this port 410 * @param priority Array of priority levels for each queue. Values are 411 * allowed to be 0-8. A value of 8 get 8 times the traffic 412 * of a value of 1. A value of 0 indicates that no rounds 413 * will be participated in. These priorities can be changed 414 * on the fly while the pko is enabled. A priority of 9 415 * indicates that static priority should be used. If static 416 * priority is used all queues with static priority must be 417 * contiguous starting at the base_queue, and lower numbered 418 * queues have higher priority than higher numbered queues. 419 * There must be num_queues elements in the array. 420 */ 421cvmx_pko_return_value_t cvmx_pko_config_port(int port, int base_queue, 422 int num_queues, 423 const u8 priority[]) 424{ 425 cvmx_pko_return_value_t result_code; 426 int queue; 427 union cvmx_pko_mem_queue_ptrs config; 428 union cvmx_pko_reg_queue_ptrs1 config1; 429 int static_priority_base = -1; 430 int static_priority_end = -1; 431 int outputbuffer_pool = (int)cvmx_fpa_get_pko_pool(); 432 u64 outputbuffer_pool_size = cvmx_fpa_get_pko_pool_block_size(); 433 434 /* This function is not used for CN68XX */ 435 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 436 return cvmx_pko2_config_port(port, base_queue, num_queues, 437 priority); 438 439 if (debug) 440 debug("%s: port=%d queue=%d-%d pri %#x %#x %#x %#x\n", __func__, 441 port, base_queue, (base_queue + num_queues - 1), 442 priority[0], priority[1], priority[2], priority[3]); 443 444 /* The need to handle ILLEGAL_PID port argument 445 * is obsolete now, the code here can be simplified. 446 */ 447 448 if (port >= CVMX_PKO_NUM_OUTPUT_PORTS && 449 port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) { 450 debug("ERROR: %s: Invalid port %llu\n", __func__, 451 (unsigned long long)port); 452 return CVMX_PKO_INVALID_PORT; 453 } 454 455 if (base_queue + num_queues > CVMX_PKO_MAX_OUTPUT_QUEUES) { 456 debug("ERROR: %s: Invalid queue range port = %lld base=%llu numques=%lld\n", 457 __func__, (unsigned long long)port, 458 (unsigned long long)base_queue, 459 (unsigned long long)num_queues); 460 return CVMX_PKO_INVALID_QUEUE; 461 } 462 463 if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) { 464 /* 465 * Validate the static queue priority setup and set 466 * static_priority_base and static_priority_end 467 * accordingly. 468 */ 469 for (queue = 0; queue < num_queues; queue++) { 470 /* Find first queue of static priority */ 471 int p_queue = queue % 16; 472 473 if (static_priority_base == -1 && 474 priority[p_queue] == CVMX_PKO_QUEUE_STATIC_PRIORITY) 475 static_priority_base = queue; 476 /* Find last queue of static priority */ 477 if (static_priority_base != -1 && 478 static_priority_end == -1 && 479 priority[p_queue] != 480 CVMX_PKO_QUEUE_STATIC_PRIORITY && 481 queue) 482 static_priority_end = queue - 1; 483 else if (static_priority_base != -1 && 484 static_priority_end == -1 && 485 queue == num_queues - 1) 486 /* all queues're static priority */ 487 static_priority_end = queue; 488 489 /* 490 * Check to make sure all static priority 491 * queues are contiguous. Also catches some 492 * cases of static priorites not starting at 493 * queue 0. 494 */ 495 if (static_priority_end != -1 && 496 (int)queue > static_priority_end && 497 priority[p_queue] == 498 CVMX_PKO_QUEUE_STATIC_PRIORITY) { 499 debug("ERROR: %s: Static priority queues aren't contiguous or don't start at base queue. q: %d, eq: %d\n", 500 __func__, (int)queue, static_priority_end); 501 return CVMX_PKO_INVALID_PRIORITY; 502 } 503 } 504 if (static_priority_base > 0) { 505 debug("ERROR: %s: Static priority queues don't start at base queue. sq: %d\n", 506 __func__, static_priority_base); 507 return CVMX_PKO_INVALID_PRIORITY; 508 } 509 } 510 511 /* 512 * At this point, static_priority_base and static_priority_end 513 * are either both -1, or are valid start/end queue numbers 514 */ 515 516 result_code = CVMX_PKO_SUCCESS; 517 518 for (queue = 0; queue < num_queues; queue++) { 519 u64 *buf_ptr = NULL; 520 int p_queue = queue % 16; 521 522 config1.u64 = 0; 523 config1.s.idx3 = queue >> 3; 524 config1.s.qid7 = (base_queue + queue) >> 7; 525 526 config.u64 = 0; 527 config.s.tail = queue == (num_queues - 1); 528 config.s.index = queue; 529 config.s.port = port; 530 config.s.queue = base_queue + queue; 531 532 config.s.static_p = static_priority_base >= 0; 533 config.s.static_q = (int)queue <= static_priority_end; 534 config.s.s_tail = (int)queue == static_priority_end; 535 /* 536 * Convert the priority into an enable bit field. Try 537 * to space the bits out evenly so the packet don't 538 * get grouped up. 539 */ 540 switch ((int)priority[p_queue]) { 541 case 0: 542 config.s.qos_mask = 0x00; 543 break; 544 case 1: 545 config.s.qos_mask = 0x01; 546 break; 547 case 2: 548 config.s.qos_mask = 0x11; 549 break; 550 case 3: 551 config.s.qos_mask = 0x49; 552 break; 553 case 4: 554 config.s.qos_mask = 0x55; 555 break; 556 case 5: 557 config.s.qos_mask = 0x57; 558 break; 559 case 6: 560 config.s.qos_mask = 0x77; 561 break; 562 case 7: 563 config.s.qos_mask = 0x7f; 564 break; 565 case 8: 566 config.s.qos_mask = 0xff; 567 break; 568 case CVMX_PKO_QUEUE_STATIC_PRIORITY: 569 config.s.qos_mask = 0xff; 570 break; 571 default: 572 debug("ERROR: %s: Invalid priority %llu\n", __func__, 573 (unsigned long long)priority[p_queue]); 574 config.s.qos_mask = 0xff; 575 result_code = CVMX_PKO_INVALID_PRIORITY; 576 break; 577 } 578 579 if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) { 580 cvmx_cmd_queue_result_t cmd_res; 581 582 cmd_res = cvmx_cmd_queue_initialize( 583 CVMX_CMD_QUEUE_PKO(base_queue + queue), 584 CVMX_PKO_MAX_QUEUE_DEPTH, outputbuffer_pool, 585 outputbuffer_pool_size - 586 CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST * 587 8); 588 if (cmd_res != CVMX_CMD_QUEUE_SUCCESS) { 589 switch (cmd_res) { 590 case CVMX_CMD_QUEUE_NO_MEMORY: 591 debug("ERROR: %s: Unable to allocate output buffer\n", 592 __func__); 593 return CVMX_PKO_NO_MEMORY; 594 case CVMX_CMD_QUEUE_ALREADY_SETUP: 595 debug("ERROR: %s: Port already setup. port=%d\n", 596 __func__, (int)port); 597 return CVMX_PKO_PORT_ALREADY_SETUP; 598 case CVMX_CMD_QUEUE_INVALID_PARAM: 599 default: 600 debug("ERROR: %s: Command queue initialization failed.\n", 601 __func__); 602 return CVMX_PKO_CMD_QUEUE_INIT_ERROR; 603 } 604 } 605 606 buf_ptr = (u64 *)cvmx_cmd_queue_buffer( 607 CVMX_CMD_QUEUE_PKO(base_queue + queue)); 608 config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr); 609 } else { 610 config.s.buf_ptr = 0; 611 } 612 613 CVMX_SYNCWS; 614 615 csr_wr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64); 616 csr_wr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64); 617 } 618 619 return result_code; 620} 621 622/* 623 * Configure queues for an internal port. 624 * @INTERNAL 625 * @param pko_port PKO internal port number 626 * @note this is the PKO2 equivalent to cvmx_pko_config_port() 627 */ 628static cvmx_pko_return_value_t cvmx_pko2_config_port(short ipd_port, 629 int base_queue, 630 int num_queues, 631 const u8 priority[]) 632{ 633 int queue, pko_port; 634 int static_priority_base; 635 int static_priority_end; 636 union cvmx_pko_mem_iqueue_ptrs config; 637 u64 *buf_ptr = NULL; 638 int outputbuffer_pool = (int)cvmx_fpa_get_pko_pool(); 639 u64 outputbuffer_pool_size = cvmx_fpa_get_pko_pool_block_size(); 640 641 pko_port = cvmx_helper_cfg_ipd2pko_port_base(ipd_port); 642 643 if (debug) 644 debug("%s: ipd_port %d pko_iport %d qbase %d qnum %d\n", 645 __func__, ipd_port, pko_port, base_queue, num_queues); 646 647 static_priority_base = -1; 648 static_priority_end = -1; 649 650 /* 651 * static queue priority validation 652 */ 653 for (queue = 0; queue < num_queues; queue++) { 654 int p_queue = queue % 16; 655 656 if (static_priority_base == -1 && 657 priority[p_queue] == CVMX_PKO_QUEUE_STATIC_PRIORITY) 658 static_priority_base = queue; 659 660 if (static_priority_base != -1 && static_priority_end == -1 && 661 priority[p_queue] != CVMX_PKO_QUEUE_STATIC_PRIORITY && 662 queue) 663 static_priority_end = queue - 1; 664 else if (static_priority_base != -1 && 665 static_priority_end == -1 && queue == num_queues - 1) 666 static_priority_end = 667 queue; /* all queues are static priority */ 668 669 /* 670 * Check to make sure all static priority queues are contiguous. 671 * Also catches some cases of static priorites not starting from 672 * queue 0. 673 */ 674 if (static_priority_end != -1 && 675 (int)queue > static_priority_end && 676 priority[p_queue] == CVMX_PKO_QUEUE_STATIC_PRIORITY) { 677 debug("ERROR: %s: Static priority queues aren't contiguous or don't start at base queue. q: %d, eq: %d\n", 678 __func__, (int)queue, static_priority_end); 679 } 680 if (static_priority_base > 0) { 681 debug("ERROR: %s: Static priority queues don't start at base queue. sq: %d\n", 682 __func__, static_priority_base); 683 } 684 } 685 686 /* 687 * main loop to set the fields of CVMX_PKO_MEM_IQUEUE_PTRS for 688 * each queue 689 */ 690 for (queue = 0; queue < num_queues; queue++) { 691 int p_queue = queue % 8; 692 693 config.u64 = 0; 694 config.s.index = queue; 695 config.s.qid = base_queue + queue; 696 config.s.ipid = pko_port; 697 config.s.tail = (queue == (num_queues - 1)); 698 config.s.s_tail = (queue == static_priority_end); 699 config.s.static_p = (static_priority_base >= 0); 700 config.s.static_q = (queue <= static_priority_end); 701 702 /* 703 * Convert the priority into an enable bit field. 704 * Try to space the bits out evenly so the packet 705 * don't get grouped up. 706 */ 707 switch ((int)priority[p_queue]) { 708 case 0: 709 config.s.qos_mask = 0x00; 710 break; 711 case 1: 712 config.s.qos_mask = 0x01; 713 break; 714 case 2: 715 config.s.qos_mask = 0x11; 716 break; 717 case 3: 718 config.s.qos_mask = 0x49; 719 break; 720 case 4: 721 config.s.qos_mask = 0x55; 722 break; 723 case 5: 724 config.s.qos_mask = 0x57; 725 break; 726 case 6: 727 config.s.qos_mask = 0x77; 728 break; 729 case 7: 730 config.s.qos_mask = 0x7f; 731 break; 732 case 8: 733 config.s.qos_mask = 0xff; 734 break; 735 case CVMX_PKO_QUEUE_STATIC_PRIORITY: 736 config.s.qos_mask = 0xff; 737 break; 738 default: 739 debug("ERROR: %s: Invalid priority %llu\n", __func__, 740 (unsigned long long)priority[p_queue]); 741 config.s.qos_mask = 0xff; 742 break; 743 } 744 745 /* 746 * The command queues 747 */ 748 { 749 cvmx_cmd_queue_result_t cmd_res; 750 751 cmd_res = cvmx_cmd_queue_initialize( 752 CVMX_CMD_QUEUE_PKO(base_queue + queue), 753 CVMX_PKO_MAX_QUEUE_DEPTH, outputbuffer_pool, 754 (outputbuffer_pool_size - 755 CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST * 8)); 756 757 if (cmd_res != CVMX_CMD_QUEUE_SUCCESS) { 758 switch (cmd_res) { 759 case CVMX_CMD_QUEUE_NO_MEMORY: 760 debug("ERROR: %s: Unable to allocate output buffer\n", 761 __func__); 762 break; 763 case CVMX_CMD_QUEUE_ALREADY_SETUP: 764 debug("ERROR: %s: Port already setup\n", 765 __func__); 766 break; 767 case CVMX_CMD_QUEUE_INVALID_PARAM: 768 default: 769 debug("ERROR: %s: Command queue initialization failed.", 770 __func__); 771 break; 772 } 773 debug(" pko_port%d base_queue%d num_queues%d queue%d.\n", 774 pko_port, base_queue, num_queues, queue); 775 } 776 777 buf_ptr = (u64 *)cvmx_cmd_queue_buffer( 778 CVMX_CMD_QUEUE_PKO(base_queue + queue)); 779 config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr) >> 7; 780 } 781 782 CVMX_SYNCWS; 783 csr_wr(CVMX_PKO_MEM_IQUEUE_PTRS, config.u64); 784 } 785 786 /* Error detection is resirable here */ 787 return 0; 788} 789