diff options
Diffstat (limited to 'cvmx-helper-util.c')
-rw-r--r-- | cvmx-helper-util.c | 529 |
1 files changed, 447 insertions, 82 deletions
diff --git a/cvmx-helper-util.c b/cvmx-helper-util.c index 4b5c22047b838..ae69dafc0c5c4 100644 --- a/cvmx-helper-util.c +++ b/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 #include "executive-config.h" #include "cvmx-config.h" @@ -68,6 +73,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" @@ -75,10 +81,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. @@ -109,11 +130,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"; } @@ -134,9 +157,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) @@ -166,7 +189,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) { @@ -256,45 +279,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; @@ -323,13 +408,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 @@ -346,8 +435,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); @@ -380,48 +473,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; @@ -430,6 +571,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; } @@ -437,8 +579,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. @@ -449,21 +773,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 @@ -481,12 +827,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"); |