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 43 44 45 46/** 47 * @file 48 * 49 * Small helper utilities. 50 * 51 * <hr>$Revision: 70030 $<hr> 52 */ 53#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 54#include <linux/module.h> 55#include <linux/slab.h> \ 56 57#include <asm/octeon/cvmx.h> 58#include <asm/octeon/cvmx-config.h> 59#include <asm/octeon/cvmx-pip.h> 60#include <asm/octeon/cvmx-ipd.h> 61#include <asm/octeon/cvmx-helper.h> 62#include <asm/octeon/cvmx-gmxx-defs.h> 63#include <asm/octeon/cvmx-pko-defs.h> 64#include <asm/octeon/cvmx-pko.h> 65#include <asm/octeon/cvmx-sli-defs.h> 66#include <asm/octeon/cvmx-pexp-defs.h> 67#include <asm/octeon/cvmx-helper-cfg.h> 68#else 69#if !defined(__FreeBSD__) || !defined(_KERNEL) 70#include "executive-config.h" 71#include "cvmx-config.h" 72#endif 73#include "cvmx.h" 74#include "cvmx-bootmem.h" 75#include "cvmx-fpa.h" 76#include "cvmx-pip.h" 77#include "cvmx-pko.h" 78#include "cvmx-ilk.h" 79#include "cvmx-ipd.h" 80#include "cvmx-gmx.h" 81#include "cvmx-spi.h" 82#include "cvmx-sysinfo.h" 83#include "cvmx-helper.h" 84#include "cvmx-helper-util.h" 85#include "cvmx-version.h" 86#include "cvmx-helper-ilk.h" 87#include "cvmx-helper-cfg.h" 88#endif 89 90#ifdef CVMX_ENABLE_HELPER_FUNCTIONS 91 92struct cvmx_iface { 93 int cvif_ipd_nports; 94 int cvif_has_fcs; /* PKO fcs for this interface. */ 95 enum cvmx_pko_padding cvif_padding; 96 cvmx_helper_link_info_t *cvif_ipd_port_link_info; 97}; 98 99/* 100 * This has to be static as u-boot expects to probe an interface and 101 * gets the number of its ports. 102 */ 103static CVMX_SHARED struct cvmx_iface cvmx_interfaces[CVMX_HELPER_MAX_IFACE]; 104 105#ifndef CVMX_BUILD_FOR_LINUX_KERNEL 106/** 107 * Get the version of the CVMX libraries. 108 * 109 * @return Version string. Note this buffer is allocated statically 110 * and will be shared by all callers. 111 */ 112const char *cvmx_helper_get_version(void) 113{ 114 return OCTEON_SDK_VERSION_STRING; 115} 116#endif 117 118/** 119 * Convert a interface mode into a human readable string 120 * 121 * @param mode Mode to convert 122 * 123 * @return String 124 */ 125const char *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t mode) 126{ 127 switch (mode) 128 { 129 case CVMX_HELPER_INTERFACE_MODE_DISABLED: return "DISABLED"; 130 case CVMX_HELPER_INTERFACE_MODE_RGMII: return "RGMII"; 131 case CVMX_HELPER_INTERFACE_MODE_GMII: return "GMII"; 132 case CVMX_HELPER_INTERFACE_MODE_SPI: return "SPI"; 133 case CVMX_HELPER_INTERFACE_MODE_PCIE: return "PCIE"; 134 case CVMX_HELPER_INTERFACE_MODE_XAUI: return "XAUI"; 135 case CVMX_HELPER_INTERFACE_MODE_RXAUI: return "RXAUI"; 136 case CVMX_HELPER_INTERFACE_MODE_SGMII: return "SGMII"; 137 case CVMX_HELPER_INTERFACE_MODE_PICMG: return "PICMG"; 138 case CVMX_HELPER_INTERFACE_MODE_NPI: return "NPI"; 139 case CVMX_HELPER_INTERFACE_MODE_LOOP: return "LOOP"; 140 case CVMX_HELPER_INTERFACE_MODE_SRIO: return "SRIO"; 141 case CVMX_HELPER_INTERFACE_MODE_ILK: return "ILK"; 142 } 143 return "UNKNOWN"; 144} 145 146 147/** 148 * Debug routine to dump the packet structure to the console 149 * 150 * @param work Work queue entry containing the packet to dump 151 * @return 152 */ 153int cvmx_helper_dump_packet(cvmx_wqe_t *work) 154{ 155 uint64_t count; 156 uint64_t remaining_bytes; 157 cvmx_buf_ptr_t buffer_ptr; 158 uint64_t start_of_buffer; 159 uint8_t * data_address; 160 uint8_t * end_of_data; 161 162 cvmx_dprintf("Packet Length: %u\n", cvmx_wqe_get_len(work)); 163 cvmx_dprintf(" Input Port: %u\n", cvmx_wqe_get_port(work)); 164 cvmx_dprintf(" QoS: %u\n", cvmx_wqe_get_qos(work)); 165 cvmx_dprintf(" Buffers: %u\n", work->word2.s.bufs); 166 167 if (work->word2.s.bufs == 0) 168 { 169 cvmx_ipd_wqe_fpa_queue_t wqe_pool; 170 wqe_pool.u64 = cvmx_read_csr(CVMX_IPD_WQE_FPA_QUEUE); 171 buffer_ptr.u64 = 0; 172 buffer_ptr.s.pool = wqe_pool.s.wqe_pool; 173 buffer_ptr.s.size = 128; 174 buffer_ptr.s.addr = cvmx_ptr_to_phys(work->packet_data); 175 if (cvmx_likely(!work->word2.s.not_IP)) 176 { 177 cvmx_pip_ip_offset_t pip_ip_offset; 178 pip_ip_offset.u64 = cvmx_read_csr(CVMX_PIP_IP_OFFSET); 179 buffer_ptr.s.addr += (pip_ip_offset.s.offset<<3) - work->word2.s.ip_offset; 180 buffer_ptr.s.addr += (work->word2.s.is_v6^1)<<2; 181 } 182 else 183 { 184 /* WARNING: This code assume that the packet is not RAW. If it was, 185 we would use PIP_GBL_CFG[RAW_SHF] instead of 186 PIP_GBL_CFG[NIP_SHF] */ 187 cvmx_pip_gbl_cfg_t pip_gbl_cfg; 188 pip_gbl_cfg.u64 = cvmx_read_csr(CVMX_PIP_GBL_CFG); 189 buffer_ptr.s.addr += pip_gbl_cfg.s.nip_shf; 190 } 191 } 192 else 193 buffer_ptr = work->packet_ptr; 194 remaining_bytes = cvmx_wqe_get_len(work); 195 196 while (remaining_bytes) 197 { 198 start_of_buffer = ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; 199 cvmx_dprintf(" Buffer Start:%llx\n", (unsigned long long)start_of_buffer); 200 cvmx_dprintf(" Buffer I : %u\n", buffer_ptr.s.i); 201 cvmx_dprintf(" Buffer Back: %u\n", buffer_ptr.s.back); 202 cvmx_dprintf(" Buffer Pool: %u\n", buffer_ptr.s.pool); 203 cvmx_dprintf(" Buffer Data: %llx\n", (unsigned long long)buffer_ptr.s.addr); 204 cvmx_dprintf(" Buffer Size: %u\n", buffer_ptr.s.size); 205 206 cvmx_dprintf("\t\t"); 207 data_address = (uint8_t *)cvmx_phys_to_ptr(buffer_ptr.s.addr); 208 end_of_data = data_address + buffer_ptr.s.size; 209 count = 0; 210 while (data_address < end_of_data) 211 { 212 if (remaining_bytes == 0) 213 break; 214 else 215 remaining_bytes--; 216 cvmx_dprintf("%02x", (unsigned int)*data_address); 217 data_address++; 218 if (remaining_bytes && (count == 7)) 219 { 220 cvmx_dprintf("\n\t\t"); 221 count = 0; 222 } 223 else 224 count++; 225 } 226 cvmx_dprintf("\n"); 227 228 if (remaining_bytes) 229 buffer_ptr = *(cvmx_buf_ptr_t*)cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); 230 } 231 return 0; 232} 233 234 235/** 236 * Setup Random Early Drop on a specific input queue 237 * 238 * @param queue Input queue to setup RED on (0-7) 239 * @param pass_thresh 240 * Packets will begin slowly dropping when there are less than 241 * this many packet buffers free in FPA 0. 242 * @param drop_thresh 243 * All incomming packets will be dropped when there are less 244 * than this many free packet buffers in FPA 0. 245 * @return Zero on success. Negative on failure 246 */ 247int cvmx_helper_setup_red_queue(int queue, int pass_thresh, int drop_thresh) 248{ 249 cvmx_ipd_qosx_red_marks_t red_marks; 250 cvmx_ipd_red_quex_param_t red_param; 251 252 /* Set RED to begin dropping packets when there are pass_thresh buffers 253 left. It will linearly drop more packets until reaching drop_thresh 254 buffers */ 255 red_marks.u64 = 0; 256 red_marks.s.drop = drop_thresh; 257 red_marks.s.pass = pass_thresh; 258 cvmx_write_csr(CVMX_IPD_QOSX_RED_MARKS(queue), red_marks.u64); 259 260 /* Use the actual queue 0 counter, not the average */ 261 red_param.u64 = 0; 262 red_param.s.prb_con = (255ul<<24) / (red_marks.s.pass - red_marks.s.drop); 263 red_param.s.avg_con = 1; 264 red_param.s.new_con = 255; 265 red_param.s.use_pcnt = 1; 266 cvmx_write_csr(CVMX_IPD_RED_QUEX_PARAM(queue), red_param.u64); 267 return 0; 268} 269 270 271/** 272 * Setup Random Early Drop to automatically begin dropping packets. 273 * 274 * @param pass_thresh 275 * Packets will begin slowly dropping when there are less than 276 * this many packet buffers free in FPA 0. 277 * @param drop_thresh 278 * All incomming packets will be dropped when there are less 279 * than this many free packet buffers in FPA 0. 280 * @return Zero on success. Negative on failure 281 */ 282int cvmx_helper_setup_red(int pass_thresh, int drop_thresh) 283{ 284 int queue; 285 int interface; 286 int port; 287 288 /* 289 * Disable backpressure based on queued buffers. It needs SW support 290 */ 291 if (octeon_has_feature(OCTEON_FEATURE_PKND)) 292 { 293 int bpid; 294 for (interface = 0; interface < CVMX_HELPER_MAX_GMX; interface++) 295 { 296 int num_ports; 297 298 num_ports = cvmx_helper_ports_on_interface(interface); 299 for (port = 0; port < num_ports; port++) { 300 bpid = cvmx_helper_get_bpid(interface, port); 301 if (bpid == CVMX_INVALID_BPID) 302 cvmx_dprintf( 303 "setup_red: cvmx_helper_get_bpid(%d, %d) = %d\n", 304 interface, port, cvmx_helper_get_bpid(interface, port)); 305 else 306 cvmx_write_csr(CVMX_IPD_BPIDX_MBUF_TH(bpid), 0); 307 } 308 } 309 } 310 else 311 { 312 cvmx_ipd_portx_bp_page_cnt_t page_cnt; 313 314 page_cnt.u64 = 0; 315 page_cnt.s.bp_enb = 0; 316 page_cnt.s.page_cnt = 100; 317 for (interface = 0; interface < CVMX_HELPER_MAX_GMX; interface++) 318 { 319 for (port = cvmx_helper_get_first_ipd_port(interface); 320 port < cvmx_helper_get_last_ipd_port(interface); port++) 321 cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port), page_cnt.u64); 322 } 323 } 324 325 for (queue = 0; queue < 8; queue++) 326 cvmx_helper_setup_red_queue(queue, pass_thresh, drop_thresh); 327 328 /* 329 * Shutoff the dropping based on the per port page count. SW isn't 330 * decrementing it right now 331 */ 332 if (octeon_has_feature(OCTEON_FEATURE_PKND)) 333 cvmx_write_csr(CVMX_IPD_ON_BP_DROP_PKTX(0), 0); 334 else 335 cvmx_write_csr(CVMX_IPD_BP_PRT_RED_END, 0); 336 337#define IPD_RED_AVG_DLY 1000 338#define IPD_RED_PRB_DLY 1000 339 /* 340 * Setting up avg_dly and prb_dly, enable bits 341 */ 342 if (octeon_has_feature(OCTEON_FEATURE_PKND)) 343 { 344 cvmx_ipd_red_delay_t red_delay; 345 cvmx_ipd_red_bpid_enablex_t red_bpid_enable; 346 347 red_delay.u64 = 0; 348 red_delay.s.avg_dly = IPD_RED_AVG_DLY; 349 red_delay.s.prb_dly = IPD_RED_PRB_DLY; 350 cvmx_write_csr(CVMX_IPD_RED_DELAY, red_delay.u64); 351 352 /* 353 * Only enable the gmx ports 354 */ 355 red_bpid_enable.u64 = 0; 356 for (interface = 0; interface < CVMX_HELPER_MAX_GMX; interface++) 357 { 358 int num_ports = cvmx_helper_ports_on_interface(interface); 359 for (port = 0; port < num_ports; port++) 360 red_bpid_enable.u64 |= (((uint64_t) 1) << 361 cvmx_helper_get_bpid(interface, port)); 362 } 363 cvmx_write_csr(CVMX_IPD_RED_BPID_ENABLEX(0), red_bpid_enable.u64); 364 } 365 else 366 { 367 cvmx_ipd_red_port_enable_t red_port_enable; 368 369 red_port_enable.u64 = 0; 370 red_port_enable.s.prt_enb = 0xfffffffffull; 371 red_port_enable.s.avg_dly = IPD_RED_AVG_DLY; 372 red_port_enable.s.prb_dly = IPD_RED_PRB_DLY; 373 cvmx_write_csr(CVMX_IPD_RED_PORT_ENABLE, red_port_enable.u64); 374 375 /* 376 * Shutoff the dropping of packets based on RED for SRIO ports 377 */ 378 if (octeon_has_feature(OCTEON_FEATURE_SRIO)) 379 { 380 cvmx_ipd_red_port_enable2_t red_port_enable2; 381 red_port_enable2.u64 = 0; 382 red_port_enable2.s.prt_enb = 0xf0; 383 cvmx_write_csr(CVMX_IPD_RED_PORT_ENABLE2, red_port_enable2.u64); 384 } 385 } 386 387 return 0; 388} 389#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 390EXPORT_SYMBOL(cvmx_helper_setup_red); 391#endif 392 393 394/** 395 * @INTERNAL 396 * Setup the common GMX settings that determine the number of 397 * ports. These setting apply to almost all configurations of all 398 * chips. 399 * 400 * @param interface Interface to configure 401 * @param num_ports Number of ports on the interface 402 * 403 * @return Zero on success, negative on failure 404 */ 405int __cvmx_helper_setup_gmx(int interface, int num_ports) 406{ 407 cvmx_gmxx_tx_prts_t gmx_tx_prts; 408 cvmx_gmxx_rx_prts_t gmx_rx_prts; 409 cvmx_pko_reg_gmx_port_mode_t pko_mode; 410 cvmx_gmxx_txx_thresh_t gmx_tx_thresh; 411 int index; 412 413 /* 414 * Tell GMX the number of TX ports on this interface 415 */ 416 gmx_tx_prts.u64 = cvmx_read_csr(CVMX_GMXX_TX_PRTS(interface)); 417 gmx_tx_prts.s.prts = num_ports; 418 cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), gmx_tx_prts.u64); 419 420 /* 421 * Tell GMX the number of RX ports on this interface. This only applies 422 * to GMII and XAUI ports 423 */ 424 if (cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_RGMII 425 || cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_SGMII 426 || cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_GMII 427 || cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_XAUI) 428 { 429 if (num_ports > 4) 430 { 431 cvmx_dprintf("__cvmx_helper_setup_gmx: Illegal num_ports\n"); 432 return(-1); 433 } 434 435 gmx_rx_prts.u64 = cvmx_read_csr(CVMX_GMXX_RX_PRTS(interface)); 436 gmx_rx_prts.s.prts = num_ports; 437 cvmx_write_csr(CVMX_GMXX_RX_PRTS(interface), gmx_rx_prts.u64); 438 } 439 440 /* 441 * Skip setting CVMX_PKO_REG_GMX_PORT_MODE on 30XX, 31XX, 50XX, 442 * and 68XX. 443 */ 444 if (!OCTEON_IS_MODEL(OCTEON_CN30XX) && !OCTEON_IS_MODEL(OCTEON_CN31XX) && 445 !OCTEON_IS_MODEL(OCTEON_CN50XX) && !OCTEON_IS_MODEL(OCTEON_CN68XX)) 446 { 447 /* Tell PKO the number of ports on this interface */ 448 pko_mode.u64 = cvmx_read_csr(CVMX_PKO_REG_GMX_PORT_MODE); 449 if (interface == 0) 450 { 451 if (num_ports == 1) 452 pko_mode.s.mode0 = 4; 453 else if (num_ports == 2) 454 pko_mode.s.mode0 = 3; 455 else if (num_ports <= 4) 456 pko_mode.s.mode0 = 2; 457 else if (num_ports <= 8) 458 pko_mode.s.mode0 = 1; 459 else 460 pko_mode.s.mode0 = 0; 461 } 462 else 463 { 464 if (num_ports == 1) 465 pko_mode.s.mode1 = 4; 466 else if (num_ports == 2) 467 pko_mode.s.mode1 = 3; 468 else if (num_ports <= 4) 469 pko_mode.s.mode1 = 2; 470 else if (num_ports <= 8) 471 pko_mode.s.mode1 = 1; 472 else 473 pko_mode.s.mode1 = 0; 474 } 475 cvmx_write_csr(CVMX_PKO_REG_GMX_PORT_MODE, pko_mode.u64); 476 } 477 478 /* 479 * Set GMX to buffer as much data as possible before starting 480 * transmit. This reduces the chances that we have a TX under run 481 * due to memory contention. Any packet that fits entirely in the 482 * GMX FIFO can never have an under run regardless of memory load. 483 */ 484 gmx_tx_thresh.u64 = cvmx_read_csr(CVMX_GMXX_TXX_THRESH(0, interface)); 485 if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN31XX) || 486 OCTEON_IS_MODEL(OCTEON_CN50XX)) 487 /* These chips have a fixed max threshold of 0x40 */ 488 gmx_tx_thresh.s.cnt = 0x40; 489 else 490 { 491 /* ccn - common cnt numberator */ 492 int ccn = 0x100; 493 494 /* Choose the max value for the number of ports */ 495 if (num_ports <= 1) 496 gmx_tx_thresh.s.cnt = ccn / 1; 497 else if (num_ports == 2) 498 gmx_tx_thresh.s.cnt = ccn / 2; 499 else 500 gmx_tx_thresh.s.cnt = ccn / 4; 501 } 502 503 /* 504 * SPI and XAUI can have lots of ports but the GMX hardware only ever has 505 * a max of 4 506 */ 507 if (num_ports > 4) 508 num_ports = 4; 509 for (index = 0; index < num_ports; index++) 510 cvmx_write_csr(CVMX_GMXX_TXX_THRESH(index, interface), 511 gmx_tx_thresh.u64); 512 513 /* 514 * For o68, we need to setup the pipes 515 */ 516 if (OCTEON_IS_MODEL(OCTEON_CN68XX) && interface < CVMX_HELPER_MAX_GMX) 517 { 518 cvmx_gmxx_txx_pipe_t config; 519 520 for (index = 0; index < num_ports; index++) 521 { 522 config.u64 = 0; 523 524 if (__cvmx_helper_cfg_pko_port_base(interface, index) >= 0) 525 { 526 config.u64 = cvmx_read_csr( 527 CVMX_GMXX_TXX_PIPE(index, interface)); 528 config.s.nump = __cvmx_helper_cfg_pko_port_num(interface, index); 529 config.s.base = __cvmx_helper_cfg_pko_port_base(interface, index); 530 cvmx_write_csr(CVMX_GMXX_TXX_PIPE(index, interface), 531 config.u64); 532 } 533 } 534 } 535 536 return 0; 537} 538 539int cvmx_helper_get_pko_port(int interface, int port) 540{ 541 return cvmx_pko_get_base_pko_port(interface, port); 542} 543#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 544EXPORT_SYMBOL(cvmx_helper_get_pko_port); 545#endif 546 547int cvmx_helper_get_ipd_port(int interface, int port) 548{ 549 if (octeon_has_feature(OCTEON_FEATURE_PKND)) 550 { 551 if (interface >= 0 && interface <= 4) 552 { 553 cvmx_helper_interface_mode_t mode = cvmx_helper_interface_get_mode(interface); 554 if (mode == CVMX_HELPER_INTERFACE_MODE_XAUI || mode == CVMX_HELPER_INTERFACE_MODE_RXAUI) 555 return 0x840 + (interface * 0x100); 556 else 557 return 0x800 + (interface * 0x100) + (port * 16); 558 } 559 else if (interface == 5 || interface == 6) 560 return 0x400 + (interface - 5) * 0x100 + port; 561 else if (interface == 7) 562 return 0x100 + port; 563 else if (interface == 8) 564 return port; 565 else 566 return -1; 567 } 568 switch (interface) 569 { 570 case 0: return port; 571 case 1: return port + 16; 572 case 2: return port + 32; 573 case 3: return port + 36; 574 case 4: return port + 40; 575 case 5: return port + 42; 576 case 6: return port + 44; 577 } 578 return -1; 579} 580#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 581EXPORT_SYMBOL(cvmx_helper_get_ipd_port); 582#endif 583 584int __cvmx_helper_get_num_ipd_ports(int interface) 585{ 586 struct cvmx_iface *piface; 587 588 if (interface >= cvmx_helper_get_number_of_interfaces()) 589 return -1; 590 591 piface = &cvmx_interfaces[interface]; 592 return piface->cvif_ipd_nports; 593} 594 595enum cvmx_pko_padding __cvmx_helper_get_pko_padding(int interface) 596{ 597 struct cvmx_iface *piface; 598 599 if (interface >= cvmx_helper_get_number_of_interfaces()) 600 return CVMX_PKO_PADDING_NONE; 601 602 piface = &cvmx_interfaces[interface]; 603 return piface->cvif_padding; 604} 605 606int __cvmx_helper_init_interface(int interface, int num_ipd_ports, int has_fcs, enum cvmx_pko_padding pad) 607{ 608 struct cvmx_iface *piface; 609 int sz; 610 611 if (interface >= cvmx_helper_get_number_of_interfaces()) 612 return -1; 613 614 piface = &cvmx_interfaces[interface]; 615 piface->cvif_ipd_nports = num_ipd_ports; 616 piface->cvif_padding = pad; 617 618 piface->cvif_has_fcs = has_fcs; 619 620 /* 621 * allocate the per-ipd_port link_info structure 622 */ 623 sz = piface->cvif_ipd_nports * sizeof(cvmx_helper_link_info_t); 624#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 625 if (sz == 0) 626 sz = sizeof(cvmx_helper_link_info_t); 627 piface->cvif_ipd_port_link_info = (cvmx_helper_link_info_t *)kmalloc(sz, GFP_KERNEL); 628 if (ZERO_OR_NULL_PTR(piface->cvif_ipd_port_link_info)) 629 panic("Cannot allocate memory in __cvmx_helper_init_interface."); 630#else 631 piface->cvif_ipd_port_link_info = (cvmx_helper_link_info_t *)cvmx_bootmem_alloc(sz, sizeof(cvmx_helper_link_info_t)); 632#endif 633 if (!piface->cvif_ipd_port_link_info) 634 return -1; 635 636 /* Initialize 'em */ { 637 int i; 638 cvmx_helper_link_info_t *p; 639 p = piface->cvif_ipd_port_link_info; 640 641 for (i = 0; i < piface->cvif_ipd_nports; i++) 642 { 643 (*p).u64 = 0; 644 p++; 645 } 646 } 647 648 return 0; 649} 650 651/* 652 * Shut down the interfaces; free the resources. 653 * @INTERNAL 654 */ 655void __cvmx_helper_shutdown_interfaces(void) 656{ 657 int i; 658 int nifaces; /* number of interfaces */ 659 struct cvmx_iface *piface; 660 661 nifaces = cvmx_helper_get_number_of_interfaces(); 662 for (i = 0; i < nifaces; i++) 663 { 664 piface = cvmx_interfaces + i; 665 if (piface->cvif_ipd_port_link_info) 666#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 667 kfree(piface->cvif_ipd_port_link_info); 668#else 669 /* 670 * For SE apps, bootmem was meant to be allocated and never 671 * freed. 672 */ 673#endif 674 piface->cvif_ipd_port_link_info = 0; 675 } 676} 677 678int __cvmx_helper_set_link_info(int interface, int port, 679 cvmx_helper_link_info_t link_info) 680{ 681 struct cvmx_iface *piface; 682 683 if (interface >= cvmx_helper_get_number_of_interfaces()) 684 return -1; 685 686 piface = &cvmx_interfaces[interface]; 687 688 if (piface->cvif_ipd_port_link_info) 689 { 690 piface->cvif_ipd_port_link_info[port] = link_info; 691 return 0; 692 } 693 694 return -1; 695} 696 697cvmx_helper_link_info_t __cvmx_helper_get_link_info(int interface, int port) 698{ 699 struct cvmx_iface *piface; 700 cvmx_helper_link_info_t err; 701 702 err.u64 = 0; 703 704 if (interface >= cvmx_helper_get_number_of_interfaces()) 705 return err; 706 piface = &cvmx_interfaces[interface]; 707 708 if (piface->cvif_ipd_port_link_info) 709 return piface->cvif_ipd_port_link_info[port]; 710 711 return err; 712} 713 714int __cvmx_helper_get_has_fcs(int interface) 715{ 716 return cvmx_interfaces[interface].cvif_has_fcs; 717} 718 719int cvmx_helper_get_pknd(int interface, int port) 720{ 721 if (octeon_has_feature(OCTEON_FEATURE_PKND)) 722 return __cvmx_helper_cfg_pknd(interface, port); 723 724 return CVMX_INVALID_PKND; 725} 726#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 727EXPORT_SYMBOL(cvmx_helper_get_pknd); 728#endif 729 730int cvmx_helper_get_bpid(int interface, int port) 731{ 732 if (octeon_has_feature(OCTEON_FEATURE_PKND)) 733 return __cvmx_helper_cfg_bpid(interface, port); 734 735 return CVMX_INVALID_BPID; 736} 737#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 738EXPORT_SYMBOL(cvmx_helper_get_bpid); 739#endif 740 741/** 742 * Display interface statistics. 743 * 744 * @param port IPD/PKO port number 745 * 746 * @return none 747 */ 748void cvmx_helper_show_stats(int port) 749{ 750 cvmx_pip_port_status_t status; 751 cvmx_pko_port_status_t pko_status; 752 753 /* ILK stats */ 754 if (octeon_has_feature(OCTEON_FEATURE_ILK)) 755 __cvmx_helper_ilk_show_stats(); 756 757 /* PIP stats */ 758 cvmx_pip_get_port_status (port, 0, &status); 759 cvmx_dprintf ("port %d: the number of packets - ipd: %d\n", port, (int)status.packets); 760 761 /* PKO stats */ 762 cvmx_pko_get_port_status (port, 0, &pko_status); 763 cvmx_dprintf ("port %d: the number of packets - pko: %d\n", port, (int)pko_status.packets); 764 765 /* TODO: other stats */ 766} 767#endif /* CVMX_ENABLE_HELPER_FUNCTIONS */ 768 769/** 770 * Returns the interface number for an IPD/PKO port number. 771 * 772 * @param ipd_port IPD/PKO port number 773 * 774 * @return Interface number 775 */ 776int cvmx_helper_get_interface_num(int ipd_port) 777{ 778 if (octeon_has_feature(OCTEON_FEATURE_PKND)) 779 { 780 if (ipd_port >= 0x800 && ipd_port < 0x900) 781 return 0; 782 else if (ipd_port >= 0x900 && ipd_port < 0xa00) 783 return 1; 784 else if (ipd_port >= 0xa00 && ipd_port < 0xb00) 785 return 2; 786 else if (ipd_port >= 0xb00 && ipd_port < 0xc00) 787 return 3; 788 else if (ipd_port >= 0xc00 && ipd_port < 0xd00) 789 return 4; 790 else if (ipd_port >= 0x400 && ipd_port < 0x500) 791 return 5; 792 else if (ipd_port >= 0x500 && ipd_port < 0x600) 793 return 6; 794 else if (ipd_port >= 0x100 && ipd_port < 0x120) 795 return 7; 796 else if (ipd_port < 8) 797 return 8; 798 } else { 799 if (ipd_port < 16) 800 return 0; 801 else if (ipd_port < 32) 802 return 1; 803 else if (ipd_port < 36) 804 return 2; 805 else if (ipd_port < 40) 806 return 3; 807 else if (ipd_port < 42) 808 return 4; 809 else if (ipd_port < 44) 810 return 5; 811 else if (ipd_port < 46) 812 return 6; 813 } 814 cvmx_dprintf("cvmx_helper_get_interface_num: Illegal IPD port number %d\n", ipd_port); 815 return -1; 816} 817#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 818EXPORT_SYMBOL(cvmx_helper_get_interface_num); 819#endif 820 821 822/** 823 * Returns the interface index number for an IPD/PKO port 824 * number. 825 * 826 * @param ipd_port IPD/PKO port number 827 * 828 * @return Interface index number 829 */ 830int cvmx_helper_get_interface_index_num(int ipd_port) 831{ 832 if (octeon_has_feature(OCTEON_FEATURE_PKND)) 833 { 834 if (ipd_port >= 0x800 && ipd_port < 0xd00) 835 { 836 int port = ((ipd_port & 0xff) >> 6); 837 return ((port) ? (port - 1) : ((ipd_port & 0xff) >> 4)); 838 } 839 else if (ipd_port >= 0x400 && ipd_port < 0x600) 840 return (ipd_port & 0xff); 841 else if (ipd_port >= 0x100 && ipd_port < 0x120) 842 return (ipd_port & 0xff); 843 else if (ipd_port < 8) 844 return ipd_port; 845 else 846 cvmx_dprintf("cvmx_helper_get_interface_index_num: Illegal IPD port number %d\n", ipd_port); 847 return -1; 848 } 849 if (ipd_port < 32) 850 return ipd_port & 15; 851 else if (ipd_port < 40) 852 return ipd_port & 3; 853 else if (ipd_port < 44) 854 return ipd_port & 1; 855 else if (ipd_port < 46) 856 return ipd_port & 1; 857 else 858 cvmx_dprintf("cvmx_helper_get_interface_index_num: Illegal IPD port number\n"); 859 860 return -1; 861} 862#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 863EXPORT_SYMBOL(cvmx_helper_get_interface_index_num); 864#endif 865