summaryrefslogtreecommitdiffstats
path: root/sys/contrib/octeon-sdk/cvmx-helper-util.c
diff options
context:
space:
mode:
authorjmallett <jmallett@FreeBSD.org>2012-03-11 06:17:49 +0000
committerjmallett <jmallett@FreeBSD.org>2012-03-11 06:17:49 +0000
commit56248d9da883404c78cefac055d0e0e1ae17dbc3 (patch)
treeaf4d9dcf90392eaadc4a3c38e945d006122e33c9 /sys/contrib/octeon-sdk/cvmx-helper-util.c
parent8bd1c57ee7ce29a7f3647cdc3e0c0d52ce1e223f (diff)
parent74539243c8f2e35e30bcbed4f81f61738ba9a0e2 (diff)
downloadFreeBSD-src-56248d9da883404c78cefac055d0e0e1ae17dbc3.zip
FreeBSD-src-56248d9da883404c78cefac055d0e0e1ae17dbc3.tar.gz
Merge the Cavium Octeon SDK 2.3.0 Simple Executive code and update FreeBSD to
make use of it where possible. This primarily brings in support for newer hardware, and FreeBSD is not yet able to support the abundance of IRQs on new hardware and many features in the Ethernet driver. Because of the changes to IRQs in the Simple Executive, we have to maintain our own list of Octeon IRQs now, which probably can be pared-down and be specific to the CIU interrupt unit soon, and when other interrupt mechanisms are added they can maintain their own definitions. Remove unmasking of interrupts from within the UART device now that the function used is no longer present in the Simple Executive. The unmasking seems to have been gratuitous as this is more properly handled by the buses above the UART device, and seems to work on that basis.
Diffstat (limited to 'sys/contrib/octeon-sdk/cvmx-helper-util.c')
-rw-r--r--sys/contrib/octeon-sdk/cvmx-helper-util.c529
1 files changed, 447 insertions, 82 deletions
diff --git a/sys/contrib/octeon-sdk/cvmx-helper-util.c b/sys/contrib/octeon-sdk/cvmx-helper-util.c
index 47250df..0ac8365 100644
--- a/sys/contrib/octeon-sdk/cvmx-helper-util.c
+++ b/sys/contrib/octeon-sdk/cvmx-helper-util.c
@@ -1,5 +1,5 @@
/***********************license start***************
- * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
+ * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
@@ -15,7 +15,7 @@
* disclaimer in the documentation and/or other materials provided
* with the distribution.
- * * Neither the name of Cavium Networks nor the names of
+ * * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
@@ -26,7 +26,7 @@
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
+ * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
* THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
* DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
@@ -48,10 +48,11 @@
*
* Small helper utilities.
*
- * <hr>$Revision: 49448 $<hr>
+ * <hr>$Revision: 70030 $<hr>
*/
#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
#include <linux/module.h>
+#include <linux/slab.h> \
#include <asm/octeon/cvmx.h>
#include <asm/octeon/cvmx-config.h>
@@ -60,6 +61,10 @@
#include <asm/octeon/cvmx-helper.h>
#include <asm/octeon/cvmx-gmxx-defs.h>
#include <asm/octeon/cvmx-pko-defs.h>
+#include <asm/octeon/cvmx-pko.h>
+#include <asm/octeon/cvmx-sli-defs.h>
+#include <asm/octeon/cvmx-pexp-defs.h>
+#include <asm/octeon/cvmx-helper-cfg.h>
#else
#if !defined(__FreeBSD__) || !defined(_KERNEL)
#include "executive-config.h"
@@ -70,6 +75,7 @@
#include "cvmx-fpa.h"
#include "cvmx-pip.h"
#include "cvmx-pko.h"
+#include "cvmx-ilk.h"
#include "cvmx-ipd.h"
#include "cvmx-gmx.h"
#include "cvmx-spi.h"
@@ -77,10 +83,25 @@
#include "cvmx-helper.h"
#include "cvmx-helper-util.h"
#include "cvmx-version.h"
+#include "cvmx-helper-ilk.h"
+#include "cvmx-helper-cfg.h"
#endif
#ifdef CVMX_ENABLE_HELPER_FUNCTIONS
+struct cvmx_iface {
+ int cvif_ipd_nports;
+ int cvif_has_fcs; /* PKO fcs for this interface. */
+ enum cvmx_pko_padding cvif_padding;
+ cvmx_helper_link_info_t *cvif_ipd_port_link_info;
+};
+
+/*
+ * This has to be static as u-boot expects to probe an interface and
+ * gets the number of its ports.
+ */
+static CVMX_SHARED struct cvmx_iface cvmx_interfaces[CVMX_HELPER_MAX_IFACE];
+
#ifndef CVMX_BUILD_FOR_LINUX_KERNEL
/**
* Get the version of the CVMX libraries.
@@ -111,11 +132,13 @@ const char *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t mo
case CVMX_HELPER_INTERFACE_MODE_SPI: return "SPI";
case CVMX_HELPER_INTERFACE_MODE_PCIE: return "PCIE";
case CVMX_HELPER_INTERFACE_MODE_XAUI: return "XAUI";
+ case CVMX_HELPER_INTERFACE_MODE_RXAUI: return "RXAUI";
case CVMX_HELPER_INTERFACE_MODE_SGMII: return "SGMII";
case CVMX_HELPER_INTERFACE_MODE_PICMG: return "PICMG";
case CVMX_HELPER_INTERFACE_MODE_NPI: return "NPI";
case CVMX_HELPER_INTERFACE_MODE_LOOP: return "LOOP";
case CVMX_HELPER_INTERFACE_MODE_SRIO: return "SRIO";
+ case CVMX_HELPER_INTERFACE_MODE_ILK: return "ILK";
}
return "UNKNOWN";
}
@@ -136,9 +159,9 @@ int cvmx_helper_dump_packet(cvmx_wqe_t *work)
uint8_t * data_address;
uint8_t * end_of_data;
- cvmx_dprintf("Packet Length: %u\n", work->len);
- cvmx_dprintf(" Input Port: %u\n", work->ipprt);
- cvmx_dprintf(" QoS: %u\n", work->qos);
+ cvmx_dprintf("Packet Length: %u\n", cvmx_wqe_get_len(work));
+ cvmx_dprintf(" Input Port: %u\n", cvmx_wqe_get_port(work));
+ cvmx_dprintf(" QoS: %u\n", cvmx_wqe_get_qos(work));
cvmx_dprintf(" Buffers: %u\n", work->word2.s.bufs);
if (work->word2.s.bufs == 0)
@@ -168,7 +191,7 @@ int cvmx_helper_dump_packet(cvmx_wqe_t *work)
}
else
buffer_ptr = work->packet_ptr;
- remaining_bytes = work->len;
+ remaining_bytes = cvmx_wqe_get_len(work);
while (remaining_bytes)
{
@@ -258,45 +281,107 @@ int cvmx_helper_setup_red_queue(int queue, int pass_thresh, int drop_thresh)
*/
int cvmx_helper_setup_red(int pass_thresh, int drop_thresh)
{
- cvmx_ipd_portx_bp_page_cnt_t page_cnt;
- cvmx_ipd_bp_prt_red_end_t ipd_bp_prt_red_end;
- cvmx_ipd_red_port_enable_t red_port_enable;
int queue;
int interface;
int port;
- /* Disable backpressure based on queued buffers. It needs SW support */
- page_cnt.u64 = 0;
- page_cnt.s.bp_enb = 0;
- page_cnt.s.page_cnt = 100;
- for (interface=0; interface<2; interface++)
+ /*
+ * Disable backpressure based on queued buffers. It needs SW support
+ */
+ if (octeon_has_feature(OCTEON_FEATURE_PKND))
{
- for (port=cvmx_helper_get_first_ipd_port(interface); port<cvmx_helper_get_last_ipd_port(interface); port++)
- cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port), page_cnt.u64);
+ int bpid;
+ for (interface = 0; interface < CVMX_HELPER_MAX_GMX; interface++)
+ {
+ int num_ports;
+
+ num_ports = cvmx_helper_ports_on_interface(interface);
+ for (port = 0; port < num_ports; port++) {
+ bpid = cvmx_helper_get_bpid(interface, port);
+ if (bpid == CVMX_INVALID_BPID)
+ cvmx_dprintf(
+ "setup_red: cvmx_helper_get_bpid(%d, %d) = %d\n",
+ interface, port, cvmx_helper_get_bpid(interface, port));
+ else
+ cvmx_write_csr(CVMX_IPD_BPIDX_MBUF_TH(bpid), 0);
+ }
+ }
}
+ else
+ {
+ cvmx_ipd_portx_bp_page_cnt_t page_cnt;
- for (queue=0; queue<8; queue++)
- cvmx_helper_setup_red_queue(queue, pass_thresh, drop_thresh);
-
- /* Shutoff the dropping based on the per port page count. SW isn't
- decrementing it right now */
- ipd_bp_prt_red_end.u64 = 0;
- ipd_bp_prt_red_end.s.prt_enb = 0;
- cvmx_write_csr(CVMX_IPD_BP_PRT_RED_END, ipd_bp_prt_red_end.u64);
+ page_cnt.u64 = 0;
+ page_cnt.s.bp_enb = 0;
+ page_cnt.s.page_cnt = 100;
+ for (interface = 0; interface < CVMX_HELPER_MAX_GMX; interface++)
+ {
+ for (port = cvmx_helper_get_first_ipd_port(interface);
+ port < cvmx_helper_get_last_ipd_port(interface); port++)
+ cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port), page_cnt.u64);
+ }
+ }
- red_port_enable.u64 = 0;
- red_port_enable.s.prt_enb = 0xfffffffffull;
- red_port_enable.s.avg_dly = 10000;
- red_port_enable.s.prb_dly = 10000;
- cvmx_write_csr(CVMX_IPD_RED_PORT_ENABLE, red_port_enable.u64);
+ for (queue = 0; queue < 8; queue++)
+ cvmx_helper_setup_red_queue(queue, pass_thresh, drop_thresh);
- /* Shutoff the dropping of packets based on RED for SRIO ports */
- if (OCTEON_IS_MODEL(OCTEON_CN6XXX))
+ /*
+ * Shutoff the dropping based on the per port page count. SW isn't
+ * decrementing it right now
+ */
+ if (octeon_has_feature(OCTEON_FEATURE_PKND))
+ cvmx_write_csr(CVMX_IPD_ON_BP_DROP_PKTX(0), 0);
+ else
+ cvmx_write_csr(CVMX_IPD_BP_PRT_RED_END, 0);
+
+#define IPD_RED_AVG_DLY 1000
+#define IPD_RED_PRB_DLY 1000
+ /*
+ * Setting up avg_dly and prb_dly, enable bits
+ */
+ if (octeon_has_feature(OCTEON_FEATURE_PKND))
{
- cvmx_ipd_red_port_enable2_t red_port_enable2;
- red_port_enable2.u64 = 0;
- red_port_enable2.s.prt_enb = 0xf0;
- cvmx_write_csr(CVMX_IPD_RED_PORT_ENABLE2, red_port_enable2.u64);
+ cvmx_ipd_red_delay_t red_delay;
+ cvmx_ipd_red_bpid_enablex_t red_bpid_enable;
+
+ red_delay.u64 = 0;
+ red_delay.s.avg_dly = IPD_RED_AVG_DLY;
+ red_delay.s.prb_dly = IPD_RED_PRB_DLY;
+ cvmx_write_csr(CVMX_IPD_RED_DELAY, red_delay.u64);
+
+ /*
+ * Only enable the gmx ports
+ */
+ red_bpid_enable.u64 = 0;
+ for (interface = 0; interface < CVMX_HELPER_MAX_GMX; interface++)
+ {
+ int num_ports = cvmx_helper_ports_on_interface(interface);
+ for (port = 0; port < num_ports; port++)
+ red_bpid_enable.u64 |= (((uint64_t) 1) <<
+ cvmx_helper_get_bpid(interface, port));
+ }
+ cvmx_write_csr(CVMX_IPD_RED_BPID_ENABLEX(0), red_bpid_enable.u64);
+ }
+ else
+ {
+ cvmx_ipd_red_port_enable_t red_port_enable;
+
+ red_port_enable.u64 = 0;
+ red_port_enable.s.prt_enb = 0xfffffffffull;
+ red_port_enable.s.avg_dly = IPD_RED_AVG_DLY;
+ red_port_enable.s.prb_dly = IPD_RED_PRB_DLY;
+ cvmx_write_csr(CVMX_IPD_RED_PORT_ENABLE, red_port_enable.u64);
+
+ /*
+ * Shutoff the dropping of packets based on RED for SRIO ports
+ */
+ if (octeon_has_feature(OCTEON_FEATURE_SRIO))
+ {
+ cvmx_ipd_red_port_enable2_t red_port_enable2;
+ red_port_enable2.u64 = 0;
+ red_port_enable2.s.prt_enb = 0xf0;
+ cvmx_write_csr(CVMX_IPD_RED_PORT_ENABLE2, red_port_enable2.u64);
+ }
}
return 0;
@@ -325,13 +410,17 @@ int __cvmx_helper_setup_gmx(int interface, int num_ports)
cvmx_gmxx_txx_thresh_t gmx_tx_thresh;
int index;
- /* Tell GMX the number of TX ports on this interface */
+ /*
+ * Tell GMX the number of TX ports on this interface
+ */
gmx_tx_prts.u64 = cvmx_read_csr(CVMX_GMXX_TX_PRTS(interface));
gmx_tx_prts.s.prts = num_ports;
cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), gmx_tx_prts.u64);
- /* Tell GMX the number of RX ports on this interface. This only
- ** applies to *GMII and XAUI ports */
+ /*
+ * Tell GMX the number of RX ports on this interface. This only applies
+ * to GMII and XAUI ports
+ */
if (cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_RGMII
|| cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_SGMII
|| cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_GMII
@@ -348,8 +437,12 @@ int __cvmx_helper_setup_gmx(int interface, int num_ports)
cvmx_write_csr(CVMX_GMXX_RX_PRTS(interface), gmx_rx_prts.u64);
}
- /* Skip setting CVMX_PKO_REG_GMX_PORT_MODE on 30XX, 31XX, and 50XX */
- if (!OCTEON_IS_MODEL(OCTEON_CN30XX) && !OCTEON_IS_MODEL(OCTEON_CN31XX) && !OCTEON_IS_MODEL(OCTEON_CN50XX))
+ /*
+ * Skip setting CVMX_PKO_REG_GMX_PORT_MODE on 30XX, 31XX, 50XX,
+ * and 68XX.
+ */
+ if (!OCTEON_IS_MODEL(OCTEON_CN30XX) && !OCTEON_IS_MODEL(OCTEON_CN31XX) &&
+ !OCTEON_IS_MODEL(OCTEON_CN50XX) && !OCTEON_IS_MODEL(OCTEON_CN68XX))
{
/* Tell PKO the number of ports on this interface */
pko_mode.u64 = cvmx_read_csr(CVMX_PKO_REG_GMX_PORT_MODE);
@@ -382,48 +475,96 @@ int __cvmx_helper_setup_gmx(int interface, int num_ports)
cvmx_write_csr(CVMX_PKO_REG_GMX_PORT_MODE, pko_mode.u64);
}
- /* Set GMX to buffer as much data as possible before starting transmit.
- This reduces the chances that we have a TX under run due to memory
- contention. Any packet that fits entirely in the GMX FIFO can never
- have an under run regardless of memory load */
+ /*
+ * Set GMX to buffer as much data as possible before starting
+ * transmit. This reduces the chances that we have a TX under run
+ * due to memory contention. Any packet that fits entirely in the
+ * GMX FIFO can never have an under run regardless of memory load.
+ */
gmx_tx_thresh.u64 = cvmx_read_csr(CVMX_GMXX_TXX_THRESH(0, interface));
- if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
- {
+ if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN31XX) ||
+ OCTEON_IS_MODEL(OCTEON_CN50XX))
/* These chips have a fixed max threshold of 0x40 */
gmx_tx_thresh.s.cnt = 0x40;
- }
else
{
+ /* ccn - common cnt numberator */
+ int ccn = 0x100;
+
/* Choose the max value for the number of ports */
if (num_ports <= 1)
- gmx_tx_thresh.s.cnt = 0x100 / 1;
+ gmx_tx_thresh.s.cnt = ccn / 1;
else if (num_ports == 2)
- gmx_tx_thresh.s.cnt = 0x100 / 2;
+ gmx_tx_thresh.s.cnt = ccn / 2;
else
- gmx_tx_thresh.s.cnt = 0x100 / 4;
+ gmx_tx_thresh.s.cnt = ccn / 4;
}
- /* SPI and XAUI can have lots of ports but the GMX hardware only ever has
- a max of 4 */
+
+ /*
+ * SPI and XAUI can have lots of ports but the GMX hardware only ever has
+ * a max of 4
+ */
if (num_ports > 4)
num_ports = 4;
- for (index=0; index<num_ports; index++)
- cvmx_write_csr(CVMX_GMXX_TXX_THRESH(index, interface), gmx_tx_thresh.u64);
+ for (index = 0; index < num_ports; index++)
+ cvmx_write_csr(CVMX_GMXX_TXX_THRESH(index, interface),
+ gmx_tx_thresh.u64);
+
+ /*
+ * For o68, we need to setup the pipes
+ */
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX) && interface < CVMX_HELPER_MAX_GMX)
+ {
+ cvmx_gmxx_txx_pipe_t config;
+
+ for (index = 0; index < num_ports; index++)
+ {
+ config.u64 = 0;
+
+ if (__cvmx_helper_cfg_pko_port_base(interface, index) >= 0)
+ {
+ config.u64 = cvmx_read_csr(
+ CVMX_GMXX_TXX_PIPE(index, interface));
+ config.s.nump = __cvmx_helper_cfg_pko_port_num(interface, index);
+ config.s.base = __cvmx_helper_cfg_pko_port_base(interface, index);
+ cvmx_write_csr(CVMX_GMXX_TXX_PIPE(index, interface),
+ config.u64);
+ }
+ }
+ }
return 0;
}
+int cvmx_helper_get_pko_port(int interface, int port)
+{
+ return cvmx_pko_get_base_pko_port(interface, port);
+}
+#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
+EXPORT_SYMBOL(cvmx_helper_get_pko_port);
+#endif
-/**
- * Returns the IPD/PKO port number for a port on the given
- * interface.
- *
- * @param interface Interface to use
- * @param port Port on the interface
- *
- * @return IPD/PKO port number
- */
int cvmx_helper_get_ipd_port(int interface, int port)
{
+ if (octeon_has_feature(OCTEON_FEATURE_PKND))
+ {
+ if (interface >= 0 && interface <= 4)
+ {
+ cvmx_helper_interface_mode_t mode = cvmx_helper_interface_get_mode(interface);
+ if (mode == CVMX_HELPER_INTERFACE_MODE_XAUI || mode == CVMX_HELPER_INTERFACE_MODE_RXAUI)
+ return 0x840 + (interface * 0x100);
+ else
+ return 0x800 + (interface * 0x100) + (port * 16);
+ }
+ else if (interface == 5 || interface == 6)
+ return 0x400 + (interface - 5) * 0x100 + port;
+ else if (interface == 7)
+ return 0x100 + port;
+ else if (interface == 8)
+ return port;
+ else
+ return -1;
+ }
switch (interface)
{
case 0: return port;
@@ -432,6 +573,7 @@ int cvmx_helper_get_ipd_port(int interface, int port)
case 3: return port + 36;
case 4: return port + 40;
case 5: return port + 42;
+ case 6: return port + 44;
}
return -1;
}
@@ -439,8 +581,190 @@ int cvmx_helper_get_ipd_port(int interface, int port)
EXPORT_SYMBOL(cvmx_helper_get_ipd_port);
#endif
-#endif /* CVMX_ENABLE_HELPER_FUNCTIONS */
+int __cvmx_helper_get_num_ipd_ports(int interface)
+{
+ struct cvmx_iface *piface;
+
+ if (interface >= cvmx_helper_get_number_of_interfaces())
+ return -1;
+
+ piface = &cvmx_interfaces[interface];
+ return piface->cvif_ipd_nports;
+}
+
+enum cvmx_pko_padding __cvmx_helper_get_pko_padding(int interface)
+{
+ struct cvmx_iface *piface;
+
+ if (interface >= cvmx_helper_get_number_of_interfaces())
+ return CVMX_PKO_PADDING_NONE;
+
+ piface = &cvmx_interfaces[interface];
+ return piface->cvif_padding;
+}
+
+int __cvmx_helper_init_interface(int interface, int num_ipd_ports, int has_fcs, enum cvmx_pko_padding pad)
+{
+ struct cvmx_iface *piface;
+ int sz;
+
+ if (interface >= cvmx_helper_get_number_of_interfaces())
+ return -1;
+
+ piface = &cvmx_interfaces[interface];
+ piface->cvif_ipd_nports = num_ipd_ports;
+ piface->cvif_padding = pad;
+
+ piface->cvif_has_fcs = has_fcs;
+
+ /*
+ * allocate the per-ipd_port link_info structure
+ */
+ sz = piface->cvif_ipd_nports * sizeof(cvmx_helper_link_info_t);
+#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
+ if (sz == 0)
+ sz = sizeof(cvmx_helper_link_info_t);
+ piface->cvif_ipd_port_link_info = (cvmx_helper_link_info_t *)kmalloc(sz, GFP_KERNEL);
+ if (ZERO_OR_NULL_PTR(piface->cvif_ipd_port_link_info))
+ panic("Cannot allocate memory in __cvmx_helper_init_interface.");
+#else
+ piface->cvif_ipd_port_link_info = (cvmx_helper_link_info_t *)cvmx_bootmem_alloc(sz, sizeof(cvmx_helper_link_info_t));
+#endif
+ if (!piface->cvif_ipd_port_link_info)
+ return -1;
+
+ /* Initialize 'em */ {
+ int i;
+ cvmx_helper_link_info_t *p;
+ p = piface->cvif_ipd_port_link_info;
+
+ for (i = 0; i < piface->cvif_ipd_nports; i++)
+ {
+ (*p).u64 = 0;
+ p++;
+ }
+ }
+
+ return 0;
+}
+/*
+ * Shut down the interfaces; free the resources.
+ * @INTERNAL
+ */
+void __cvmx_helper_shutdown_interfaces(void)
+{
+ int i;
+ int nifaces; /* number of interfaces */
+ struct cvmx_iface *piface;
+
+ nifaces = cvmx_helper_get_number_of_interfaces();
+ for (i = 0; i < nifaces; i++)
+ {
+ piface = cvmx_interfaces + i;
+ if (piface->cvif_ipd_port_link_info)
+#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
+ kfree(piface->cvif_ipd_port_link_info);
+#else
+ /*
+ * For SE apps, bootmem was meant to be allocated and never
+ * freed.
+ */
+#endif
+ piface->cvif_ipd_port_link_info = 0;
+ }
+}
+
+int __cvmx_helper_set_link_info(int interface, int port,
+ cvmx_helper_link_info_t link_info)
+{
+ struct cvmx_iface *piface;
+
+ if (interface >= cvmx_helper_get_number_of_interfaces())
+ return -1;
+
+ piface = &cvmx_interfaces[interface];
+
+ if (piface->cvif_ipd_port_link_info)
+ {
+ piface->cvif_ipd_port_link_info[port] = link_info;
+ return 0;
+ }
+
+ return -1;
+}
+
+cvmx_helper_link_info_t __cvmx_helper_get_link_info(int interface, int port)
+{
+ struct cvmx_iface *piface;
+ cvmx_helper_link_info_t err;
+
+ err.u64 = 0;
+
+ if (interface >= cvmx_helper_get_number_of_interfaces())
+ return err;
+ piface = &cvmx_interfaces[interface];
+
+ if (piface->cvif_ipd_port_link_info)
+ return piface->cvif_ipd_port_link_info[port];
+
+ return err;
+}
+
+int __cvmx_helper_get_has_fcs(int interface)
+{
+ return cvmx_interfaces[interface].cvif_has_fcs;
+}
+
+int cvmx_helper_get_pknd(int interface, int port)
+{
+ if (octeon_has_feature(OCTEON_FEATURE_PKND))
+ return __cvmx_helper_cfg_pknd(interface, port);
+
+ return CVMX_INVALID_PKND;
+}
+#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
+EXPORT_SYMBOL(cvmx_helper_get_pknd);
+#endif
+
+int cvmx_helper_get_bpid(int interface, int port)
+{
+ if (octeon_has_feature(OCTEON_FEATURE_PKND))
+ return __cvmx_helper_cfg_bpid(interface, port);
+
+ return CVMX_INVALID_BPID;
+}
+#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
+EXPORT_SYMBOL(cvmx_helper_get_bpid);
+#endif
+
+/**
+ * Display interface statistics.
+ *
+ * @param port IPD/PKO port number
+ *
+ * @return none
+ */
+void cvmx_helper_show_stats(int port)
+{
+ cvmx_pip_port_status_t status;
+ cvmx_pko_port_status_t pko_status;
+
+ /* ILK stats */
+ if (octeon_has_feature(OCTEON_FEATURE_ILK))
+ __cvmx_helper_ilk_show_stats();
+
+ /* PIP stats */
+ cvmx_pip_get_port_status (port, 0, &status);
+ cvmx_dprintf ("port %d: the number of packets - ipd: %d\n", port, (int)status.packets);
+
+ /* PKO stats */
+ cvmx_pko_get_port_status (port, 0, &pko_status);
+ cvmx_dprintf ("port %d: the number of packets - pko: %d\n", port, (int)pko_status.packets);
+
+ /* TODO: other stats */
+}
+#endif /* CVMX_ENABLE_HELPER_FUNCTIONS */
/**
* Returns the interface number for an IPD/PKO port number.
@@ -451,21 +775,43 @@ EXPORT_SYMBOL(cvmx_helper_get_ipd_port);
*/
int cvmx_helper_get_interface_num(int ipd_port)
{
- if (ipd_port < 16)
- return 0;
- else if (ipd_port < 32)
- return 1;
- else if (ipd_port < 36)
- return 2;
- else if (ipd_port < 40)
- return 3;
- else if (ipd_port < 42)
- return 4;
- else if (ipd_port < 44)
- return 5;
- else
- cvmx_dprintf("cvmx_helper_get_interface_num: Illegal IPD port number\n");
-
+ if (octeon_has_feature(OCTEON_FEATURE_PKND))
+ {
+ if (ipd_port >= 0x800 && ipd_port < 0x900)
+ return 0;
+ else if (ipd_port >= 0x900 && ipd_port < 0xa00)
+ return 1;
+ else if (ipd_port >= 0xa00 && ipd_port < 0xb00)
+ return 2;
+ else if (ipd_port >= 0xb00 && ipd_port < 0xc00)
+ return 3;
+ else if (ipd_port >= 0xc00 && ipd_port < 0xd00)
+ return 4;
+ else if (ipd_port >= 0x400 && ipd_port < 0x500)
+ return 5;
+ else if (ipd_port >= 0x500 && ipd_port < 0x600)
+ return 6;
+ else if (ipd_port >= 0x100 && ipd_port < 0x120)
+ return 7;
+ else if (ipd_port < 8)
+ return 8;
+ } else {
+ if (ipd_port < 16)
+ return 0;
+ else if (ipd_port < 32)
+ return 1;
+ else if (ipd_port < 36)
+ return 2;
+ else if (ipd_port < 40)
+ return 3;
+ else if (ipd_port < 42)
+ return 4;
+ else if (ipd_port < 44)
+ return 5;
+ else if (ipd_port < 46)
+ return 6;
+ }
+ cvmx_dprintf("cvmx_helper_get_interface_num: Illegal IPD port number %d\n", ipd_port);
return -1;
}
#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
@@ -483,12 +829,31 @@ EXPORT_SYMBOL(cvmx_helper_get_interface_num);
*/
int cvmx_helper_get_interface_index_num(int ipd_port)
{
+ if (octeon_has_feature(OCTEON_FEATURE_PKND))
+ {
+ if (ipd_port >= 0x800 && ipd_port < 0xd00)
+ {
+ int port = ((ipd_port & 0xff) >> 6);
+ return ((port) ? (port - 1) : ((ipd_port & 0xff) >> 4));
+ }
+ else if (ipd_port >= 0x400 && ipd_port < 0x600)
+ return (ipd_port & 0xff);
+ else if (ipd_port >= 0x100 && ipd_port < 0x120)
+ return (ipd_port & 0xff);
+ else if (ipd_port < 8)
+ return ipd_port;
+ else
+ cvmx_dprintf("cvmx_helper_get_interface_index_num: Illegal IPD port number %d\n", ipd_port);
+ return -1;
+ }
if (ipd_port < 32)
return ipd_port & 15;
else if (ipd_port < 40)
return ipd_port & 3;
else if (ipd_port < 44)
- return ipd_port & 1;
+ return ipd_port & 1;
+ else if (ipd_port < 46)
+ return ipd_port & 1;
else
cvmx_dprintf("cvmx_helper_get_interface_index_num: Illegal IPD port number\n");
OpenPOWER on IntegriCloud