cvmx-helper.c revision 215990
1/***********************license start*************** 2 * Copyright (c) 2003-2010 Cavium Networks (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 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 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 NETWORKS 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 * Helper functions for common, but complicated tasks. 50 * 51 * <hr>$Revision: 52004 $<hr> 52 */ 53#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 54#include <linux/module.h> 55#include <asm/octeon/cvmx.h> 56#include <asm/octeon/cvmx-config.h> 57#include <asm/octeon/cvmx-bootmem.h> 58#include <asm/octeon/cvmx-sriox-defs.h> 59#include <asm/octeon/cvmx-npi-defs.h> 60#include <asm/octeon/cvmx-pexp-defs.h> 61#include <asm/octeon/cvmx-pip-defs.h> 62#include <asm/octeon/cvmx-asxx-defs.h> 63#include <asm/octeon/cvmx-gmxx-defs.h> 64#include <asm/octeon/cvmx-smix-defs.h> 65#include <asm/octeon/cvmx-dbg-defs.h> 66 67#include <asm/octeon/cvmx-gmx.h> 68#include <asm/octeon/cvmx-fpa.h> 69#include <asm/octeon/cvmx-pip.h> 70#include <asm/octeon/cvmx-pko.h> 71#include <asm/octeon/cvmx-ipd.h> 72#include <asm/octeon/cvmx-spi.h> 73#include <asm/octeon/cvmx-clock.h> 74#include <asm/octeon/cvmx-helper.h> 75#include <asm/octeon/cvmx-helper-board.h> 76#include <asm/octeon/cvmx-helper-errata.h> 77#else 78#if !defined(__FreeBSD__) || !defined(_KERNEL) 79#include "executive-config.h" 80#endif 81#include "cvmx.h" 82#include "cvmx-sysinfo.h" 83#include "cvmx-bootmem.h" 84#include "cvmx-version.h" 85#include "cvmx-helper-check-defines.h" 86#include "cvmx-gmx.h" 87#include "cvmx-error.h" 88#if !defined(__FreeBSD__) || !defined(_KERNEL) 89#include "cvmx-config.h" 90#endif 91 92#include "cvmx-fpa.h" 93#include "cvmx-pip.h" 94#include "cvmx-pko.h" 95#include "cvmx-ipd.h" 96#include "cvmx-spi.h" 97#include "cvmx-helper.h" 98#include "cvmx-helper-board.h" 99#include "cvmx-helper-errata.h" 100#endif 101 102 103 104#ifdef CVMX_ENABLE_PKO_FUNCTIONS 105 106/** 107 * cvmx_override_pko_queue_priority(int ipd_port, uint64_t 108 * priorities[16]) is a function pointer. It is meant to allow 109 * customization of the PKO queue priorities based on the port 110 * number. Users should set this pointer to a function before 111 * calling any cvmx-helper operations. 112 */ 113CVMX_SHARED void (*cvmx_override_pko_queue_priority)(int pko_port, uint64_t priorities[16]) = NULL; 114#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 115EXPORT_SYMBOL(cvmx_override_pko_queue_priority); 116#endif 117 118/** 119 * cvmx_override_ipd_port_setup(int ipd_port) is a function 120 * pointer. It is meant to allow customization of the IPD port 121 * setup before packet input/output comes online. It is called 122 * after cvmx-helper does the default IPD configuration, but 123 * before IPD is enabled. Users should set this pointer to a 124 * function before calling any cvmx-helper operations. 125 */ 126CVMX_SHARED void (*cvmx_override_ipd_port_setup)(int ipd_port) = NULL; 127 128/* Port count per interface */ 129static CVMX_SHARED int interface_port_count[6] = {0,}; 130/* Port last configured link info index by IPD/PKO port */ 131static CVMX_SHARED cvmx_helper_link_info_t port_link_info[CVMX_PIP_NUM_INPUT_PORTS]; 132 133 134/** 135 * Return the number of interfaces the chip has. Each interface 136 * may have multiple ports. Most chips support two interfaces, 137 * but the CNX0XX and CNX1XX are exceptions. These only support 138 * one interface. 139 * 140 * @return Number of interfaces on chip 141 */ 142int cvmx_helper_get_number_of_interfaces(void) 143{ 144 switch (cvmx_sysinfo_get()->board_type) { 145#if defined(OCTEON_VENDOR_LANNER) 146 case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 147 return 2; 148 case CVMX_BOARD_TYPE_CUST_LANNER_MR730: 149 return 1; 150#endif 151 default: 152 break; 153 } 154 155 if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 156 return 6; 157 else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) 158 return 4; 159 else 160 return 3; 161} 162#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 163EXPORT_SYMBOL(cvmx_helper_get_number_of_interfaces); 164#endif 165 166 167/** 168 * Return the number of ports on an interface. Depending on the 169 * chip and configuration, this can be 1-16. A value of 0 170 * specifies that the interface doesn't exist or isn't usable. 171 * 172 * @param interface Interface to get the port count for 173 * 174 * @return Number of ports on interface. Can be Zero. 175 */ 176int cvmx_helper_ports_on_interface(int interface) 177{ 178 return interface_port_count[interface]; 179} 180#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 181EXPORT_SYMBOL(cvmx_helper_ports_on_interface); 182#endif 183 184 185/** 186 * Get the operating mode of an interface. Depending on the Octeon 187 * chip and configuration, this function returns an enumeration 188 * of the type of packet I/O supported by an interface. 189 * 190 * @param interface Interface to probe 191 * 192 * @return Mode of the interface. Unknown or unsupported interfaces return 193 * DISABLED. 194 */ 195cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface) 196{ 197 cvmx_gmxx_inf_mode_t mode; 198 if (interface == 2) 199 return CVMX_HELPER_INTERFACE_MODE_NPI; 200 201 if (interface == 3) 202 { 203 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN6XXX)) 204 return CVMX_HELPER_INTERFACE_MODE_LOOP; 205 else 206 return CVMX_HELPER_INTERFACE_MODE_DISABLED; 207 } 208 209 if (OCTEON_IS_MODEL(OCTEON_CN6XXX) && (interface == 4 || interface == 5)) 210 { 211 cvmx_sriox_status_reg_t sriox_status_reg; 212 sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(interface-4)); 213 if (sriox_status_reg.s.srio) 214 return CVMX_HELPER_INTERFACE_MODE_SRIO; 215 else 216 return CVMX_HELPER_INTERFACE_MODE_DISABLED; 217 } 218 219 if (interface == 0 && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5 && cvmx_sysinfo_get()->board_rev_major == 1) 220 { 221 /* Lie about interface type of CN3005 board. This board has a switch on port 1 like 222 ** the other evaluation boards, but it is connected over RGMII instead of GMII. Report 223 ** GMII mode so that the speed is forced to 1 Gbit full duplex. Other than some initial configuration 224 ** (which does not use the output of this function) there is no difference in setup between GMII and RGMII modes. 225 */ 226 return CVMX_HELPER_INTERFACE_MODE_GMII; 227 } 228 229 /* Interface 1 is always disabled on CN31XX and CN30XX */ 230 if ((interface == 1) && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN50XX) || OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))) 231 return CVMX_HELPER_INTERFACE_MODE_DISABLED; 232 233 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); 234 235 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) 236 { 237 switch(mode.cn56xx.mode) 238 { 239 case 0: return CVMX_HELPER_INTERFACE_MODE_DISABLED; 240 case 1: return CVMX_HELPER_INTERFACE_MODE_XAUI; 241 case 2: return CVMX_HELPER_INTERFACE_MODE_SGMII; 242 case 3: return CVMX_HELPER_INTERFACE_MODE_PICMG; 243 default:return CVMX_HELPER_INTERFACE_MODE_DISABLED; 244 } 245 } 246 else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 247 { 248 switch(mode.cn63xx.mode) 249 { 250 case 0: return CVMX_HELPER_INTERFACE_MODE_SGMII; 251 case 1: return CVMX_HELPER_INTERFACE_MODE_XAUI; 252 default: return CVMX_HELPER_INTERFACE_MODE_DISABLED; 253 } 254 } 255 else 256 { 257 if (!mode.s.en) 258 return CVMX_HELPER_INTERFACE_MODE_DISABLED; 259 260 if (mode.s.type) 261 { 262 if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) 263 return CVMX_HELPER_INTERFACE_MODE_SPI; 264 else 265 return CVMX_HELPER_INTERFACE_MODE_GMII; 266 } 267 else 268 return CVMX_HELPER_INTERFACE_MODE_RGMII; 269 } 270} 271#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 272EXPORT_SYMBOL(cvmx_helper_interface_get_mode); 273#endif 274 275/** 276 * @INTERNAL 277 * Configure the IPD/PIP tagging and QoS options for a specific 278 * port. This function determines the POW work queue entry 279 * contents for a port. The setup performed here is controlled by 280 * the defines in executive-config.h. 281 * 282 * @param ipd_port Port to configure. This follows the IPD numbering, not the 283 * per interface numbering 284 * 285 * @return Zero on success, negative on failure 286 */ 287static int __cvmx_helper_port_setup_ipd(int ipd_port) 288{ 289 cvmx_pip_prt_cfgx_t port_config; 290 cvmx_pip_prt_tagx_t tag_config; 291 292 port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); 293 tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port)); 294 295 /* Have each port go to a different POW queue */ 296 port_config.s.qos = ipd_port & 0x7; 297 298 /* Process the headers and place the IP header in the work queue */ 299 port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE; 300 301 tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP; 302 tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP; 303 tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT; 304 tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT; 305 tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER; 306 tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP; 307 tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP; 308 tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT; 309 tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT; 310 tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL; 311 tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT; 312 tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 313 tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 314 tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 315 tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 316 tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 317 /* Put all packets in group 0. Other groups can be used by the app */ 318 tag_config.s.grp = 0; 319 320 cvmx_pip_config_port(ipd_port, port_config, tag_config); 321 322 /* Give the user a chance to override our setting for each port */ 323 if (cvmx_override_ipd_port_setup) 324 cvmx_override_ipd_port_setup(ipd_port); 325 326 return 0; 327} 328 329 330/** 331 * This function probes an interface to determine the actual 332 * number of hardware ports connected to it. It doesn't setup the 333 * ports or enable them. The main goal here is to set the global 334 * interface_port_count[interface] correctly. Hardware setup of the 335 * ports will be performed later. 336 * 337 * @param interface Interface to probe 338 * 339 * @return Zero on success, negative on failure 340 */ 341int cvmx_helper_interface_probe(int interface) 342{ 343 /* At this stage in the game we don't want packets to be moving yet. 344 The following probe calls should perform hardware setup 345 needed to determine port counts. Receive must still be disabled */ 346 switch (cvmx_helper_interface_get_mode(interface)) 347 { 348 /* These types don't support ports to IPD/PKO */ 349 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 350 case CVMX_HELPER_INTERFACE_MODE_PCIE: 351 interface_port_count[interface] = 0; 352 break; 353 /* XAUI is a single high speed port */ 354 case CVMX_HELPER_INTERFACE_MODE_XAUI: 355 interface_port_count[interface] = __cvmx_helper_xaui_probe(interface); 356 break; 357 /* RGMII/GMII/MII are all treated about the same. Most functions 358 refer to these ports as RGMII */ 359 case CVMX_HELPER_INTERFACE_MODE_RGMII: 360 case CVMX_HELPER_INTERFACE_MODE_GMII: 361 interface_port_count[interface] = __cvmx_helper_rgmii_probe(interface); 362 break; 363 /* SPI4 can have 1-16 ports depending on the device at the other end */ 364 case CVMX_HELPER_INTERFACE_MODE_SPI: 365 interface_port_count[interface] = __cvmx_helper_spi_probe(interface); 366 break; 367 /* SGMII can have 1-4 ports depending on how many are hooked up */ 368 case CVMX_HELPER_INTERFACE_MODE_SGMII: 369 case CVMX_HELPER_INTERFACE_MODE_PICMG: 370 interface_port_count[interface] = __cvmx_helper_sgmii_probe(interface); 371 break; 372 /* PCI target Network Packet Interface */ 373 case CVMX_HELPER_INTERFACE_MODE_NPI: 374 interface_port_count[interface] = __cvmx_helper_npi_probe(interface); 375 break; 376 /* Special loopback only ports. These are not the same as other ports 377 in loopback mode */ 378 case CVMX_HELPER_INTERFACE_MODE_LOOP: 379 interface_port_count[interface] = __cvmx_helper_loop_probe(interface); 380 break; 381 /* SRIO has 2^N ports, where N is number of interfaces */ 382 case CVMX_HELPER_INTERFACE_MODE_SRIO: 383 interface_port_count[interface] = __cvmx_helper_srio_probe(interface); 384 break; 385 } 386 387 interface_port_count[interface] = __cvmx_helper_board_interface_probe(interface, interface_port_count[interface]); 388 389 /* Make sure all global variables propagate to other cores */ 390 CVMX_SYNCWS; 391 392 return 0; 393} 394 395 396/** 397 * @INTERNAL 398 * Setup the IPD/PIP for the ports on an interface. Packet 399 * classification and tagging are set for every port on the 400 * interface. The number of ports on the interface must already 401 * have been probed. 402 * 403 * @param interface Interface to setup IPD/PIP for 404 * 405 * @return Zero on success, negative on failure 406 */ 407static int __cvmx_helper_interface_setup_ipd(int interface) 408{ 409 int ipd_port = cvmx_helper_get_ipd_port(interface, 0); 410 int num_ports = interface_port_count[interface]; 411 412 while (num_ports--) 413 { 414 __cvmx_helper_port_setup_ipd(ipd_port); 415 ipd_port++; 416 } 417 return 0; 418} 419 420 421/** 422 * @INTERNAL 423 * Setup global setting for IPD/PIP not related to a specific 424 * interface or port. This must be called before IPD is enabled. 425 * 426 * @return Zero on success, negative on failure. 427 */ 428static int __cvmx_helper_global_setup_ipd(void) 429{ 430#ifndef CVMX_HELPER_IPD_DRAM_MODE 431#define CVMX_HELPER_IPD_DRAM_MODE CVMX_IPD_OPC_MODE_STT 432#endif 433 /* Setup the global packet input options */ 434 cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE/8, 435 CVMX_HELPER_FIRST_MBUFF_SKIP/8, 436 CVMX_HELPER_NOT_FIRST_MBUFF_SKIP/8, 437 (CVMX_HELPER_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */ 438 (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */ 439 CVMX_FPA_WQE_POOL, 440 CVMX_HELPER_IPD_DRAM_MODE, 441 1); 442 return 0; 443} 444 445 446/** 447 * @INTERNAL 448 * Setup the PKO for the ports on an interface. The number of 449 * queues per port and the priority of each PKO output queue 450 * is set here. PKO must be disabled when this function is called. 451 * 452 * @param interface Interface to setup PKO for 453 * 454 * @return Zero on success, negative on failure 455 */ 456static int __cvmx_helper_interface_setup_pko(int interface) 457{ 458 /* Each packet output queue has an associated priority. The higher the 459 priority, the more often it can send a packet. A priority of 8 means 460 it can send in all 8 rounds of contention. We're going to make each 461 queue one less than the last. 462 The vector of priorities has been extended to support CN5xxx CPUs, 463 where up to 16 queues can be associated to a port. 464 To keep backward compatibility we don't change the initial 8 465 priorities and replicate them in the second half. 466 With per-core PKO queues (PKO lockless operation) all queues have 467 the same priority. */ 468 uint64_t priorities[16] = {8,7,6,5,4,3,2,1,8,7,6,5,4,3,2,1}; 469 470 /* Setup the IPD/PIP and PKO for the ports discovered above. Here packet 471 classification, tagging and output priorities are set */ 472 int ipd_port = cvmx_helper_get_ipd_port(interface, 0); 473 int num_ports = interface_port_count[interface]; 474 while (num_ports--) 475 { 476 /* Give the user a chance to override the per queue priorities */ 477 if (cvmx_override_pko_queue_priority) 478 cvmx_override_pko_queue_priority(ipd_port, priorities); 479 480 cvmx_pko_config_port(ipd_port, cvmx_pko_get_base_queue_per_core(ipd_port, 0), 481 cvmx_pko_get_num_queues(ipd_port), priorities); 482 ipd_port++; 483 } 484 return 0; 485} 486 487 488/** 489 * @INTERNAL 490 * Setup global setting for PKO not related to a specific 491 * interface or port. This must be called before PKO is enabled. 492 * 493 * @return Zero on success, negative on failure. 494 */ 495static int __cvmx_helper_global_setup_pko(void) 496{ 497 /* Disable tagwait FAU timeout. This needs to be done before anyone might 498 start packet output using tags */ 499 cvmx_iob_fau_timeout_t fau_to; 500 fau_to.u64 = 0; 501 fau_to.s.tout_val = 0xfff; 502 fau_to.s.tout_enb = 0; 503 cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64); 504 return 0; 505} 506 507 508/** 509 * @INTERNAL 510 * Setup global backpressure setting. 511 * 512 * @return Zero on success, negative on failure 513 */ 514static int __cvmx_helper_global_setup_backpressure(void) 515{ 516#if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE 517 /* Disable backpressure if configured to do so */ 518 /* Disable backpressure (pause frame) generation */ 519 int num_interfaces = cvmx_helper_get_number_of_interfaces(); 520 int interface; 521 for (interface=0; interface<num_interfaces; interface++) 522 { 523 switch (cvmx_helper_interface_get_mode(interface)) 524 { 525 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 526 case CVMX_HELPER_INTERFACE_MODE_PCIE: 527 case CVMX_HELPER_INTERFACE_MODE_SRIO: 528 case CVMX_HELPER_INTERFACE_MODE_NPI: 529 case CVMX_HELPER_INTERFACE_MODE_LOOP: 530 case CVMX_HELPER_INTERFACE_MODE_XAUI: 531 break; 532 case CVMX_HELPER_INTERFACE_MODE_RGMII: 533 case CVMX_HELPER_INTERFACE_MODE_GMII: 534 case CVMX_HELPER_INTERFACE_MODE_SPI: 535 case CVMX_HELPER_INTERFACE_MODE_SGMII: 536 case CVMX_HELPER_INTERFACE_MODE_PICMG: 537 cvmx_gmx_set_backpressure_override(interface, 0xf); 538 break; 539 } 540 } 541 //cvmx_dprintf("Disabling backpressure\n"); 542#endif 543 544 return 0; 545} 546 547/** 548 * @INTERNAL 549 * Verify the per port IPD backpressure is aligned properly. 550 * @return Zero if working, non zero if misaligned 551 */ 552static int __cvmx_helper_backpressure_is_misaligned(void) 553{ 554 uint64_t ipd_int_enb; 555 cvmx_ipd_ctl_status_t ipd_reg; 556 uint64_t bp_status0; 557 uint64_t bp_status1; 558 const int port0 = 0; 559 const int port1 = 16; 560 cvmx_helper_interface_mode_t mode0 = cvmx_helper_interface_get_mode(0); 561 cvmx_helper_interface_mode_t mode1 = cvmx_helper_interface_get_mode(1); 562 563 /* Disable error interrupts while we check backpressure */ 564 ipd_int_enb = cvmx_read_csr(CVMX_IPD_INT_ENB); 565 cvmx_write_csr(CVMX_IPD_INT_ENB, 0); 566 567 /* Enable per port backpressure */ 568 ipd_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); 569 ipd_reg.s.pbp_en = 1; 570 cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_reg.u64); 571 572 if (mode0 != CVMX_HELPER_INTERFACE_MODE_DISABLED) 573 { 574 /* Enable backpressure for port with a zero threshold */ 575 cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port0), 1<<17); 576 /* Add 1000 to the page count to simulate packets coming in */ 577 cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port0<<25) | 1000); 578 } 579 580 if (mode1 != CVMX_HELPER_INTERFACE_MODE_DISABLED) 581 { 582 /* Enable backpressure for port with a zero threshold */ 583 cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port1), 1<<17); 584 /* Add 1000 to the page count to simulate packets coming in */ 585 cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port1<<25) | 1000); 586 } 587 588 /* Wait 500 cycles for the BP to update */ 589 cvmx_wait(500); 590 591 /* Read the BP state from the debug select register */ 592 switch (mode0) 593 { 594 case CVMX_HELPER_INTERFACE_MODE_SPI: 595 cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x9004); 596 bp_status0 = cvmx_read_csr(CVMX_DBG_DATA); 597 bp_status0 = 0xffff & ~bp_status0; 598 break; 599 case CVMX_HELPER_INTERFACE_MODE_RGMII: 600 case CVMX_HELPER_INTERFACE_MODE_GMII: 601 cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x0e00); 602 bp_status0 = 0xffff & cvmx_read_csr(CVMX_DBG_DATA); 603 break; 604 case CVMX_HELPER_INTERFACE_MODE_XAUI: 605 case CVMX_HELPER_INTERFACE_MODE_SGMII: 606 case CVMX_HELPER_INTERFACE_MODE_PICMG: 607 cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, 0x0e00); 608 bp_status0 = 0xffff & cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 609 break; 610 default: 611 bp_status0 = 1<<port0; 612 break; 613 } 614 615 /* Read the BP state from the debug select register */ 616 switch (mode1) 617 { 618 case CVMX_HELPER_INTERFACE_MODE_SPI: 619 cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x9804); 620 bp_status1 = cvmx_read_csr(CVMX_DBG_DATA); 621 bp_status1 = 0xffff & ~bp_status1; 622 break; 623 case CVMX_HELPER_INTERFACE_MODE_RGMII: 624 case CVMX_HELPER_INTERFACE_MODE_GMII: 625 cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x1600); 626 bp_status1 = 0xffff & cvmx_read_csr(CVMX_DBG_DATA); 627 break; 628 case CVMX_HELPER_INTERFACE_MODE_XAUI: 629 case CVMX_HELPER_INTERFACE_MODE_SGMII: 630 case CVMX_HELPER_INTERFACE_MODE_PICMG: 631 cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, 0x1600); 632 bp_status1 = 0xffff & cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 633 break; 634 default: 635 bp_status1 = 1<<(port1-16); 636 break; 637 } 638 639 if (mode0 != CVMX_HELPER_INTERFACE_MODE_DISABLED) 640 { 641 /* Shutdown BP */ 642 cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port0<<25) | (0x1ffffff & -1000)); 643 cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port0), 0); 644 } 645 646 if (mode1 != CVMX_HELPER_INTERFACE_MODE_DISABLED) 647 { 648 /* Shutdown BP */ 649 cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port1<<25) | (0x1ffffff & -1000)); 650 cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port1), 0); 651 } 652 653 /* Clear any error interrupts that might have been set */ 654 cvmx_write_csr(CVMX_IPD_INT_SUM, 0x1f); 655 cvmx_write_csr(CVMX_IPD_INT_ENB, ipd_int_enb); 656 657 return ((bp_status0 != 1ull<<port0) || (bp_status1 != 1ull<<(port1-16))); 658} 659 660 661/** 662 * @INTERNAL 663 * Enable packet input/output from the hardware. This function is 664 * called after all internal setup is complete and IPD is enabled. 665 * After this function completes, packets will be accepted from the 666 * hardware ports. PKO should still be disabled to make sure packets 667 * aren't sent out partially setup hardware. 668 * 669 * @param interface Interface to enable 670 * 671 * @return Zero on success, negative on failure 672 */ 673static int __cvmx_helper_packet_hardware_enable(int interface) 674{ 675 int result = 0; 676 switch (cvmx_helper_interface_get_mode(interface)) 677 { 678 /* These types don't support ports to IPD/PKO */ 679 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 680 case CVMX_HELPER_INTERFACE_MODE_PCIE: 681 /* Nothing to do */ 682 break; 683 /* XAUI is a single high speed port */ 684 case CVMX_HELPER_INTERFACE_MODE_XAUI: 685 result = __cvmx_helper_xaui_enable(interface); 686 break; 687 /* RGMII/GMII/MII are all treated about the same. Most functions 688 refer to these ports as RGMII */ 689 case CVMX_HELPER_INTERFACE_MODE_RGMII: 690 case CVMX_HELPER_INTERFACE_MODE_GMII: 691 result = __cvmx_helper_rgmii_enable(interface); 692 break; 693 /* SPI4 can have 1-16 ports depending on the device at the other end */ 694 case CVMX_HELPER_INTERFACE_MODE_SPI: 695 result = __cvmx_helper_spi_enable(interface); 696 break; 697 /* SGMII can have 1-4 ports depending on how many are hooked up */ 698 case CVMX_HELPER_INTERFACE_MODE_SGMII: 699 case CVMX_HELPER_INTERFACE_MODE_PICMG: 700 result = __cvmx_helper_sgmii_enable(interface); 701 break; 702 /* PCI target Network Packet Interface */ 703 case CVMX_HELPER_INTERFACE_MODE_NPI: 704 result = __cvmx_helper_npi_enable(interface); 705 break; 706 /* Special loopback only ports. These are not the same as other ports 707 in loopback mode */ 708 case CVMX_HELPER_INTERFACE_MODE_LOOP: 709 result = __cvmx_helper_loop_enable(interface); 710 break; 711 /* SRIO has 2^N ports, where N is number of interfaces */ 712 case CVMX_HELPER_INTERFACE_MODE_SRIO: 713 result = __cvmx_helper_srio_enable(interface); 714 break; 715 } 716 result |= __cvmx_helper_board_hardware_enable(interface); 717 return result; 718} 719 720 721/** 722 * Called after all internal packet IO paths are setup. This 723 * function enables IPD/PIP and begins packet input and output. 724 * 725 * @return Zero on success, negative on failure 726 */ 727int cvmx_helper_ipd_and_packet_input_enable(void) 728{ 729 int num_interfaces; 730 int interface; 731 732 /* Enable IPD */ 733 cvmx_ipd_enable(); 734 735 /* Time to enable hardware ports packet input and output. Note that at this 736 point IPD/PIP must be fully functional and PKO must be disabled */ 737 num_interfaces = cvmx_helper_get_number_of_interfaces(); 738 for (interface=0; interface<num_interfaces; interface++) 739 { 740 if (cvmx_helper_ports_on_interface(interface) > 0) 741 { 742 //cvmx_dprintf("Enabling packet I/O on interface %d\n", interface); 743 __cvmx_helper_packet_hardware_enable(interface); 744 } 745 } 746 747 /* Finally enable PKO now that the entire path is up and running */ 748 cvmx_pko_enable(); 749 750 if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1) || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1)) && 751 (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)) 752 __cvmx_helper_errata_fix_ipd_ptr_alignment(); 753 return 0; 754} 755#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 756EXPORT_SYMBOL(cvmx_helper_ipd_and_packet_input_enable); 757#endif 758 759/** 760 * Initialize the PIP, IPD, and PKO hardware to support 761 * simple priority based queues for the ethernet ports. Each 762 * port is configured with a number of priority queues based 763 * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower 764 * priority than the previous. 765 * 766 * @return Zero on success, non-zero on failure 767 */ 768int cvmx_helper_initialize_packet_io_global(void) 769{ 770 int result = 0; 771 int interface; 772 cvmx_l2c_cfg_t l2c_cfg; 773 cvmx_smix_en_t smix_en; 774 const int num_interfaces = cvmx_helper_get_number_of_interfaces(); 775 776 /* CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to be disabled */ 777 if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) 778 __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1); 779 780 /* Tell L2 to give the IOB statically higher priority compared to the 781 cores. This avoids conditions where IO blocks might be starved under 782 very high L2 loads */ 783 if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 784 { 785 cvmx_l2c_ctl_t l2c_ctl; 786 l2c_ctl.u64 = cvmx_read_csr(CVMX_L2C_CTL); 787 l2c_ctl.s.rsp_arb_mode = 1; 788 l2c_ctl.s.xmc_arb_mode = 0; 789 cvmx_write_csr(CVMX_L2C_CTL, l2c_ctl.u64); 790 } 791 else 792 { 793 l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG); 794 l2c_cfg.s.lrf_arb_mode = 0; 795 l2c_cfg.s.rfb_arb_mode = 0; 796 cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64); 797 } 798 799 if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) 800 { 801 /* Make sure SMI/MDIO is enabled so we can query PHYs */ 802 smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0)); 803 if (!smix_en.s.en) 804 { 805 smix_en.s.en = 1; 806 cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64); 807 } 808 809 /* Newer chips actually have two SMI/MDIO interfaces */ 810 if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) && 811 !OCTEON_IS_MODEL(OCTEON_CN58XX) && 812 !OCTEON_IS_MODEL(OCTEON_CN50XX)) 813 { 814 smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1)); 815 if (!smix_en.s.en) 816 { 817 smix_en.s.en = 1; 818 cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64); 819 } 820 } 821 } 822 823 for (interface=0; interface<num_interfaces; interface++) 824 result |= cvmx_helper_interface_probe(interface); 825 826 cvmx_pko_initialize_global(); 827 for (interface=0; interface<num_interfaces; interface++) 828 { 829 if (cvmx_helper_ports_on_interface(interface) > 0) 830 cvmx_dprintf("Interface %d has %d ports (%s)\n", 831 interface, cvmx_helper_ports_on_interface(interface), 832 cvmx_helper_interface_mode_to_string(cvmx_helper_interface_get_mode(interface))); 833 result |= __cvmx_helper_interface_setup_ipd(interface); 834 result |= __cvmx_helper_interface_setup_pko(interface); 835 } 836 837 result |= __cvmx_helper_global_setup_ipd(); 838 result |= __cvmx_helper_global_setup_pko(); 839 840 /* Enable any flow control and backpressure */ 841 result |= __cvmx_helper_global_setup_backpressure(); 842 843#if CVMX_HELPER_ENABLE_IPD 844 result |= cvmx_helper_ipd_and_packet_input_enable(); 845#endif 846 return result; 847} 848#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 849EXPORT_SYMBOL(cvmx_helper_initialize_packet_io_global); 850#endif 851 852 853/** 854 * Does core local initialization for packet io 855 * 856 * @return Zero on success, non-zero on failure 857 */ 858int cvmx_helper_initialize_packet_io_local(void) 859{ 860 return cvmx_pko_initialize_local(); 861} 862 863 864/** 865 * Undo the initialization performed in 866 * cvmx_helper_initialize_packet_io_global(). After calling this routine and the 867 * local version on each core, packet IO for Octeon will be disabled and placed 868 * in the initial reset state. It will then be safe to call the initialize 869 * later on. Note that this routine does not empty the FPA pools. It frees all 870 * buffers used by the packet IO hardware to the FPA so a function emptying the 871 * FPA after shutdown should find all packet buffers in the FPA. 872 * 873 * @return Zero on success, negative on failure. 874 */ 875int cvmx_helper_shutdown_packet_io_global(void) 876{ 877 const int timeout = 5; /* Wait up to 5 seconds for timeouts */ 878 int result = 0; 879 int num_interfaces; 880 int interface; 881 int num_ports; 882 int index; 883 int pool0_count; 884 cvmx_wqe_t *work; 885 886 /* Step 1: Disable all backpressure */ 887 for (interface=0; interface<2; interface++) 888 if (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_DISABLED) 889 cvmx_gmx_set_backpressure_override(interface, 0xf); 890 891step2: 892 /* Step 2: Wait for the PKO queues to drain */ 893 num_interfaces = cvmx_helper_get_number_of_interfaces(); 894 for (interface=0; interface<num_interfaces; interface++) 895 { 896 num_ports = cvmx_helper_ports_on_interface(interface); 897 for (index=0; index<num_ports; index++) 898 { 899 int pko_port = cvmx_helper_get_ipd_port(interface, index); 900 int queue = cvmx_pko_get_base_queue(pko_port); 901 int max_queue = queue + cvmx_pko_get_num_queues(pko_port); 902 while (queue < max_queue) 903 { 904 int count = cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue)); 905 uint64_t start_cycle = cvmx_get_cycle(); 906 uint64_t stop_cycle = start_cycle + 907 cvmx_clock_get_rate(CVMX_CLOCK_CORE) * timeout; 908 while (count && (cvmx_get_cycle() < stop_cycle)) 909 { 910 cvmx_wait(10000); 911 count = cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue)); 912 } 913 if (count) 914 { 915 cvmx_dprintf("PKO port %d, queue %d, timeout waiting for idle\n", 916 pko_port, queue); 917 result = -1; 918 } 919 queue++; 920 } 921 } 922 } 923 924 /* Step 3: Disable TX and RX on all ports */ 925 for (interface=0; interface<2; interface++) 926 { 927 switch (cvmx_helper_interface_get_mode(interface)) 928 { 929 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 930 case CVMX_HELPER_INTERFACE_MODE_PCIE: 931 /* Not a packet interface */ 932 break; 933 case CVMX_HELPER_INTERFACE_MODE_NPI: 934 case CVMX_HELPER_INTERFACE_MODE_SRIO: 935 /* We don't handle the NPI/NPEI/SRIO packet engines. The caller 936 must know these are idle */ 937 break; 938 case CVMX_HELPER_INTERFACE_MODE_LOOP: 939 /* Nothing needed. Once PKO is idle, the loopback devices 940 must be idle */ 941 break; 942 case CVMX_HELPER_INTERFACE_MODE_SPI: 943 /* SPI cannot be disabled from Octeon. It is the responsibility 944 of the caller to make sure SPI is idle before doing 945 shutdown */ 946 /* Fall through and do the same processing as RGMII/GMII */ 947 case CVMX_HELPER_INTERFACE_MODE_GMII: 948 case CVMX_HELPER_INTERFACE_MODE_RGMII: 949 /* Disable outermost RX at the ASX block */ 950 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), 0); 951 num_ports = cvmx_helper_ports_on_interface(interface); 952 if (num_ports > 4) 953 num_ports = 4; 954 for (index=0; index<num_ports; index++) 955 { 956 cvmx_gmxx_prtx_cfg_t gmx_cfg; 957 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 958 gmx_cfg.s.en = 0; 959 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); 960 /* Poll the GMX state machine waiting for it to become idle */ 961 cvmx_write_csr(CVMX_NPI_DBG_SELECT, interface*0x800 + index*0x100 + 0x880); 962 if (CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, cvmx_dbg_data_t, data&7, ==, 0, timeout*1000000)) 963 { 964 cvmx_dprintf("GMX RX path timeout waiting for idle\n"); 965 result = -1; 966 } 967 if (CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, cvmx_dbg_data_t, data&0xf, ==, 0, timeout*1000000)) 968 { 969 cvmx_dprintf("GMX TX path timeout waiting for idle\n"); 970 result = -1; 971 } 972 } 973 /* Disable outermost TX at the ASX block */ 974 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), 0); 975 /* Disable interrupts for interface */ 976 cvmx_write_csr(CVMX_ASXX_INT_EN(interface), 0); 977 cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0); 978 break; 979 case CVMX_HELPER_INTERFACE_MODE_XAUI: 980 case CVMX_HELPER_INTERFACE_MODE_SGMII: 981 case CVMX_HELPER_INTERFACE_MODE_PICMG: 982 num_ports = cvmx_helper_ports_on_interface(interface); 983 if (num_ports > 4) 984 num_ports = 4; 985 for (index=0; index<num_ports; index++) 986 { 987 cvmx_gmxx_prtx_cfg_t gmx_cfg; 988 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 989 gmx_cfg.s.en = 0; 990 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); 991 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface), cvmx_gmxx_prtx_cfg_t, rx_idle, ==, 1, timeout*1000000)) 992 { 993 cvmx_dprintf("GMX RX path timeout waiting for idle\n"); 994 result = -1; 995 } 996 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface), cvmx_gmxx_prtx_cfg_t, tx_idle, ==, 1, timeout*1000000)) 997 { 998 cvmx_dprintf("GMX TX path timeout waiting for idle\n"); 999 result = -1; 1000 } 1001 } 1002 break; 1003 } 1004 } 1005 1006 /* Step 4: Retrieve all packets from the POW and free them */ 1007 while ((work = cvmx_pow_work_request_sync(CVMX_POW_WAIT))) 1008 { 1009 cvmx_helper_free_packet_data(work); 1010 cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 0); 1011 } 1012 1013 /* Step 4b: Special workaround for pass 2 errata */ 1014 if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) 1015 { 1016 cvmx_ipd_ptr_count_t ipd_cnt; 1017 int to_add; 1018 ipd_cnt.u64 = cvmx_read_csr(CVMX_IPD_PTR_COUNT); 1019 to_add = (ipd_cnt.s.wqev_cnt + ipd_cnt.s.wqe_pcnt) & 0x7; 1020 if (to_add) 1021 { 1022 int port = -1; 1023 cvmx_dprintf("Aligning CN38XX pass 2 IPD counters\n"); 1024 if (cvmx_helper_interface_get_mode(0) == CVMX_HELPER_INTERFACE_MODE_RGMII) 1025 port = 0; 1026 else if (cvmx_helper_interface_get_mode(1) == CVMX_HELPER_INTERFACE_MODE_RGMII) 1027 port = 16; 1028 1029 if (port != -1) 1030 { 1031 char *buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL); 1032 if (buffer) 1033 { 1034 int queue = cvmx_pko_get_base_queue(port); 1035 cvmx_pko_command_word0_t pko_command; 1036 cvmx_buf_ptr_t packet; 1037 uint64_t start_cycle; 1038 uint64_t stop_cycle; 1039 1040 /* Populate a minimal packet */ 1041 memset(buffer, 0xff, 6); 1042 memset(buffer+6, 0, 54); 1043 pko_command.u64 = 0; 1044 pko_command.s.dontfree = 1; 1045 pko_command.s.total_bytes = 60; 1046 pko_command.s.segs = 1; 1047 packet.u64 = 0; 1048 packet.s.addr = cvmx_ptr_to_phys(buffer); 1049 packet.s.size = CVMX_FPA_PACKET_POOL_SIZE; 1050 __cvmx_helper_rgmii_configure_loopback(port, 1, 0); 1051 while (to_add--) 1052 { 1053 cvmx_pko_send_packet_prepare(port, queue, CVMX_PKO_LOCK_CMD_QUEUE); 1054 if (cvmx_pko_send_packet_finish(port, queue, pko_command, packet, CVMX_PKO_LOCK_CMD_QUEUE)) 1055 { 1056 cvmx_dprintf("ERROR: Unable to align IPD counters (PKO failed)\n"); 1057 break; 1058 } 1059 } 1060 cvmx_fpa_free(buffer, CVMX_FPA_PACKET_POOL, 0); 1061 1062 /* Wait for the packets to loop back */ 1063 start_cycle = cvmx_get_cycle(); 1064 stop_cycle = start_cycle + cvmx_clock_get_rate(CVMX_CLOCK_CORE) * timeout; 1065 while (cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue)) && 1066 (cvmx_get_cycle() < stop_cycle)) 1067 { 1068 cvmx_wait(1000); 1069 } 1070 cvmx_wait(1000); 1071 __cvmx_helper_rgmii_configure_loopback(port, 0, 0); 1072 if (to_add == -1) 1073 goto step2; 1074 } 1075 else 1076 cvmx_dprintf("ERROR: Unable to align IPD counters (Packet pool empty)\n"); 1077 } 1078 else 1079 cvmx_dprintf("ERROR: Unable to align IPD counters\n"); 1080 } 1081 } 1082 1083 /* Step 5: Disable IPD and PKO. PIP is taken care of in the next step */ 1084 cvmx_ipd_disable(); 1085 cvmx_pko_disable(); 1086 1087 /* Step 6: Drain all prefetched buffers from IPD/PIP. Note that IPD/PIP 1088 have not been reset yet */ 1089 __cvmx_ipd_free_ptr(); 1090 1091 /* Step 7: Free the PKO command buffers and put PKO in reset */ 1092 cvmx_pko_shutdown(); 1093 1094 /* Step 8: Disable MAC address filtering */ 1095 for (interface=0; interface<2; interface++) 1096 { 1097 switch (cvmx_helper_interface_get_mode(interface)) 1098 { 1099 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1100 case CVMX_HELPER_INTERFACE_MODE_PCIE: 1101 case CVMX_HELPER_INTERFACE_MODE_SRIO: 1102 case CVMX_HELPER_INTERFACE_MODE_NPI: 1103 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1104 break; 1105 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1106 case CVMX_HELPER_INTERFACE_MODE_GMII: 1107 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1108 case CVMX_HELPER_INTERFACE_MODE_SPI: 1109 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1110 case CVMX_HELPER_INTERFACE_MODE_PICMG: 1111 num_ports = cvmx_helper_ports_on_interface(interface); 1112 if (num_ports > 4) 1113 num_ports = 4; 1114 for (index=0; index<num_ports; index++) 1115 { 1116 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), 1); 1117 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN(index, interface), 0); 1118 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), 0); 1119 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), 0); 1120 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), 0); 1121 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), 0); 1122 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), 0); 1123 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), 0); 1124 } 1125 break; 1126 } 1127 } 1128 1129 /* Step 9: Drain all FPA buffers out of pool 0 before we reset IPD/PIP. 1130 This is needed to keep IPD_QUE0_FREE_PAGE_CNT in sync. We use pool 1 1131 for temporary storage */ 1132 pool0_count = 0; 1133 while (1) 1134 { 1135 void *buffer = cvmx_fpa_alloc(0); 1136 if (buffer) 1137 { 1138 cvmx_fpa_free(buffer, 1, 0); 1139 pool0_count++; 1140 } 1141 else 1142 break; 1143 } 1144 1145 1146 /* Step 10: Reset IPD and PIP */ 1147 { 1148 cvmx_ipd_ctl_status_t ipd_ctl_status; 1149 ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); 1150 ipd_ctl_status.s.reset = 1; 1151 cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64); 1152 1153 if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) && 1154 (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))) 1155 { 1156 /* only try 1000 times. Normally if this works it will happen in 1157 ** the first 50 loops. */ 1158 int max_loops = 1000; 1159 int loop = 0; 1160 /* Per port backpressure counters can get misaligned after an 1161 IPD reset. This code realigns them by performing repeated 1162 resets. See IPD-13473 */ 1163 cvmx_wait(100); 1164 if (__cvmx_helper_backpressure_is_misaligned()) 1165 { 1166 cvmx_dprintf("Starting to align per port backpressure counters.\n"); 1167 while (__cvmx_helper_backpressure_is_misaligned() && (loop++ < max_loops)) 1168 { 1169 cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64); 1170 cvmx_wait(123); 1171 } 1172 if (loop < max_loops) 1173 cvmx_dprintf("Completed aligning per port backpressure counters (%d loops).\n", loop); 1174 else 1175 { 1176 cvmx_dprintf("ERROR: unable to align per port backpressure counters.\n"); 1177 /* For now, don't hang.... */ 1178 } 1179 } 1180 } 1181 1182 /* PIP_SFT_RST not present in CN38XXp{1,2} */ 1183 if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) 1184 { 1185 cvmx_pip_sft_rst_t pip_sft_rst; 1186 pip_sft_rst.u64 = cvmx_read_csr(CVMX_PIP_SFT_RST); 1187 pip_sft_rst.s.rst = 1; 1188 cvmx_write_csr(CVMX_PIP_SFT_RST, pip_sft_rst.u64); 1189 } 1190 } 1191 1192 /* Step 11: Restore the FPA buffers into pool 0 */ 1193 while (pool0_count--) 1194 cvmx_fpa_free(cvmx_fpa_alloc(1), 0, 0); 1195 1196 return result; 1197} 1198#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1199EXPORT_SYMBOL(cvmx_helper_shutdown_packet_io_global); 1200#endif 1201 1202 1203/** 1204 * Does core local shutdown of packet io 1205 * 1206 * @return Zero on success, non-zero on failure 1207 */ 1208int cvmx_helper_shutdown_packet_io_local(void) 1209{ 1210 /* Currently there is nothing to do per core. This may change in 1211 the future */ 1212 return 0; 1213} 1214 1215 1216 1217/** 1218 * Auto configure an IPD/PKO port link state and speed. This 1219 * function basically does the equivalent of: 1220 * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port)); 1221 * 1222 * @param ipd_port IPD/PKO port to auto configure 1223 * 1224 * @return Link state after configure 1225 */ 1226cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port) 1227{ 1228 cvmx_helper_link_info_t link_info; 1229 int interface = cvmx_helper_get_interface_num(ipd_port); 1230 int index = cvmx_helper_get_interface_index_num(ipd_port); 1231 1232 if (index >= cvmx_helper_ports_on_interface(interface)) 1233 { 1234 link_info.u64 = 0; 1235 return link_info; 1236 } 1237 1238 link_info = cvmx_helper_link_get(ipd_port); 1239 if (link_info.u64 == port_link_info[ipd_port].u64) 1240 return link_info; 1241 1242#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL) 1243 if (!link_info.s.link_up) 1244 cvmx_error_disable_group(CVMX_ERROR_GROUP_ETHERNET, ipd_port); 1245#endif 1246 1247 /* If we fail to set the link speed, port_link_info will not change */ 1248 cvmx_helper_link_set(ipd_port, link_info); 1249 1250#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL) 1251 if (link_info.s.link_up) 1252 cvmx_error_enable_group(CVMX_ERROR_GROUP_ETHERNET, ipd_port); 1253#endif 1254 1255 /* port_link_info should be the current value, which will be different 1256 than expect if cvmx_helper_link_set() failed */ 1257 return port_link_info[ipd_port]; 1258} 1259#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1260EXPORT_SYMBOL(cvmx_helper_link_autoconf); 1261#endif 1262 1263/** 1264 * Return the link state of an IPD/PKO port as returned by 1265 * auto negotiation. The result of this function may not match 1266 * Octeon's link config if auto negotiation has changed since 1267 * the last call to cvmx_helper_link_set(). 1268 * 1269 * @param ipd_port IPD/PKO port to query 1270 * 1271 * @return Link state 1272 */ 1273cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port) 1274{ 1275 cvmx_helper_link_info_t result; 1276 int interface = cvmx_helper_get_interface_num(ipd_port); 1277 int index = cvmx_helper_get_interface_index_num(ipd_port); 1278 1279 /* The default result will be a down link unless the code below 1280 changes it */ 1281 result.u64 = 0; 1282 1283 if (index >= cvmx_helper_ports_on_interface(interface)) 1284 return result; 1285 1286 switch (cvmx_helper_interface_get_mode(interface)) 1287 { 1288 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1289 case CVMX_HELPER_INTERFACE_MODE_PCIE: 1290 /* Network links are not supported */ 1291 break; 1292 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1293 result = __cvmx_helper_xaui_link_get(ipd_port); 1294 break; 1295 case CVMX_HELPER_INTERFACE_MODE_GMII: 1296 if (index == 0) 1297 result = __cvmx_helper_rgmii_link_get(ipd_port); 1298 else 1299 { 1300 result.s.full_duplex = 1; 1301 result.s.link_up = 1; 1302 result.s.speed = 1000; 1303 } 1304 break; 1305 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1306 result = __cvmx_helper_rgmii_link_get(ipd_port); 1307 break; 1308 case CVMX_HELPER_INTERFACE_MODE_SPI: 1309 result = __cvmx_helper_spi_link_get(ipd_port); 1310 break; 1311 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1312 case CVMX_HELPER_INTERFACE_MODE_PICMG: 1313 result = __cvmx_helper_sgmii_link_get(ipd_port); 1314 break; 1315 case CVMX_HELPER_INTERFACE_MODE_SRIO: 1316 result = __cvmx_helper_srio_link_get(ipd_port); 1317 break; 1318 case CVMX_HELPER_INTERFACE_MODE_NPI: 1319 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1320 /* Network links are not supported */ 1321 break; 1322 } 1323 return result; 1324} 1325#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1326EXPORT_SYMBOL(cvmx_helper_link_get); 1327#endif 1328 1329 1330/** 1331 * Configure an IPD/PKO port for the specified link state. This 1332 * function does not influence auto negotiation at the PHY level. 1333 * The passed link state must always match the link state returned 1334 * by cvmx_helper_link_get(). It is normally best to use 1335 * cvmx_helper_link_autoconf() instead. 1336 * 1337 * @param ipd_port IPD/PKO port to configure 1338 * @param link_info The new link state 1339 * 1340 * @return Zero on success, negative on failure 1341 */ 1342int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info) 1343{ 1344 int result = -1; 1345 int interface = cvmx_helper_get_interface_num(ipd_port); 1346 int index = cvmx_helper_get_interface_index_num(ipd_port); 1347 1348 if (index >= cvmx_helper_ports_on_interface(interface)) 1349 return -1; 1350 1351 switch (cvmx_helper_interface_get_mode(interface)) 1352 { 1353 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1354 case CVMX_HELPER_INTERFACE_MODE_PCIE: 1355 break; 1356 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1357 result = __cvmx_helper_xaui_link_set(ipd_port, link_info); 1358 break; 1359 /* RGMII/GMII/MII are all treated about the same. Most functions 1360 refer to these ports as RGMII */ 1361 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1362 case CVMX_HELPER_INTERFACE_MODE_GMII: 1363 result = __cvmx_helper_rgmii_link_set(ipd_port, link_info); 1364 break; 1365 case CVMX_HELPER_INTERFACE_MODE_SPI: 1366 result = __cvmx_helper_spi_link_set(ipd_port, link_info); 1367 break; 1368 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1369 case CVMX_HELPER_INTERFACE_MODE_PICMG: 1370 result = __cvmx_helper_sgmii_link_set(ipd_port, link_info); 1371 break; 1372 case CVMX_HELPER_INTERFACE_MODE_SRIO: 1373 result = __cvmx_helper_srio_link_set(ipd_port, link_info); 1374 break; 1375 case CVMX_HELPER_INTERFACE_MODE_NPI: 1376 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1377 break; 1378 } 1379 /* Set the port_link_info here so that the link status is updated 1380 no matter how cvmx_helper_link_set is called. We don't change 1381 the value if link_set failed */ 1382 if (result == 0) 1383 port_link_info[ipd_port].u64 = link_info.u64; 1384 return result; 1385} 1386#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1387EXPORT_SYMBOL(cvmx_helper_link_set); 1388#endif 1389 1390 1391/** 1392 * Configure a port for internal and/or external loopback. Internal loopback 1393 * causes packets sent by the port to be received by Octeon. External loopback 1394 * causes packets received from the wire to sent out again. 1395 * 1396 * @param ipd_port IPD/PKO port to loopback. 1397 * @param enable_internal 1398 * Non zero if you want internal loopback 1399 * @param enable_external 1400 * Non zero if you want external loopback 1401 * 1402 * @return Zero on success, negative on failure. 1403 */ 1404int cvmx_helper_configure_loopback(int ipd_port, int enable_internal, int enable_external) 1405{ 1406 int result = -1; 1407 int interface = cvmx_helper_get_interface_num(ipd_port); 1408 int index = cvmx_helper_get_interface_index_num(ipd_port); 1409 1410 if (index >= cvmx_helper_ports_on_interface(interface)) 1411 return -1; 1412 1413 switch (cvmx_helper_interface_get_mode(interface)) 1414 { 1415 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1416 case CVMX_HELPER_INTERFACE_MODE_PCIE: 1417 case CVMX_HELPER_INTERFACE_MODE_SRIO: 1418 case CVMX_HELPER_INTERFACE_MODE_SPI: 1419 case CVMX_HELPER_INTERFACE_MODE_NPI: 1420 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1421 break; 1422 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1423 result = __cvmx_helper_xaui_configure_loopback(ipd_port, enable_internal, enable_external); 1424 break; 1425 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1426 case CVMX_HELPER_INTERFACE_MODE_GMII: 1427 result = __cvmx_helper_rgmii_configure_loopback(ipd_port, enable_internal, enable_external); 1428 break; 1429 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1430 case CVMX_HELPER_INTERFACE_MODE_PICMG: 1431 result = __cvmx_helper_sgmii_configure_loopback(ipd_port, enable_internal, enable_external); 1432 break; 1433 } 1434 return result; 1435} 1436 1437#endif /* CVMX_ENABLE_PKO_FUNCTIONS */ 1438