npi_fflp.c revision 4df55fde49134f9735f84011f23a767c75e393c7
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <npi_fflp.h>
#include <nxge_common.h>
/* macros to compute calss configuration register offset */
#define GET_TCAM_CLASS_OFFSET(cls) \
(FFLP_TCAM_CLS_BASE_OFFSET + (cls - 2) * 8)
#define GET_TCAM_KEY_OFFSET(cls) \
(FFLP_TCAM_KEY_BASE_OFFSET + (cls - 4) * 8)
#define GET_FLOW_KEY_OFFSET(cls) \
(FFLP_FLOW_KEY_BASE_OFFSET + (cls - 4) * 8)
#define HASHTBL_PART_REG_STEP 8192
#define HASHTBL_PART_REG_VIR_OFFSET 0x2100
#define HASHTBL_PART_REG_VIR_STEP 0x4000
#define GET_HASHTBL_PART_OFFSET_NVIR(partid, reg) \
((partid * HASHTBL_PART_REG_STEP) + reg)
#define GET_HASHTBL_PART_OFFSET(handle, partid, reg) \
(handle.is_vraddr ? \
(((partid & 0x1) * HASHTBL_PART_REG_VIR_STEP) + \
(reg & 0x8) + (HASHTBL_PART_REG_VIR_OFFSET)) : \
(partid * HASHTBL_PART_REG_STEP) + reg)
#define FFLP_PART_OFFSET(partid, reg) ((partid * 8) + reg)
#define FFLP_VLAN_OFFSET(vid, reg) ((vid * 8) + reg)
#define TCAM_COMPLETION_TRY_COUNT 10
#define BIT_ENABLE 0x1
#define BIT_DISABLE 0x0
#define FCRAM_PARTITION_VALID(partid) \
((partid < NXGE_MAX_RDC_GRPS))
#define FFLP_VLAN_VALID(vid) \
((vid > 0) && (vid < NXGE_MAX_VLANS))
#define FFLP_PORT_VALID(port) \
((port < MAX_PORTS_PER_NXGE))
#define FFLP_RDC_TABLE_VALID(table) \
((table < NXGE_MAX_RDC_GRPS))
#define TCAM_L3_USR_CLASS_VALID(class) \
((class >= TCAM_CLASS_IP_USER_4) && (class <= TCAM_CLASS_IP_USER_7))
#define TCAM_L2_USR_CLASS_VALID(class) \
((class == TCAM_CLASS_ETYPE_1) || (class == TCAM_CLASS_ETYPE_2))
#define TCAM_L3_CLASS_VALID(class) \
((class >= TCAM_CLASS_IP_USER_4) && (class <= TCAM_CLASS_SCTP_IPV6))
#define TCAM_L3_CLASS_VALID_RFNL(class) \
((TCAM_L3_CLASS_VALID(class)) || class == TCAM_CLASS_IPV6_FRAG)
#define TCAM_CLASS_VALID(class) \
((class >= TCAM_CLASS_ETYPE_1) && (class <= TCAM_CLASS_RARP))
uint64_t fflp_fzc_offset[] = {
FFLP_ENET_VLAN_TBL_REG, FFLP_L2_CLS_ENET1_REG, FFLP_L2_CLS_ENET2_REG,
FFLP_TCAM_KEY_IP_USR4_REG, FFLP_TCAM_KEY_IP_USR5_REG,
FFLP_TCAM_KEY_IP_USR6_REG, FFLP_TCAM_KEY_IP_USR7_REG,
FFLP_TCAM_KEY_IP4_TCP_REG, FFLP_TCAM_KEY_IP4_UDP_REG,
FFLP_TCAM_KEY_IP4_AH_ESP_REG, FFLP_TCAM_KEY_IP4_SCTP_REG,
FFLP_TCAM_KEY_IP6_TCP_REG, FFLP_TCAM_KEY_IP6_UDP_REG,
FFLP_TCAM_KEY_IP6_AH_ESP_REG, FFLP_TCAM_KEY_IP6_SCTP_REG,
FFLP_TCAM_KEY_0_REG, FFLP_TCAM_KEY_1_REG, FFLP_TCAM_KEY_2_REG,
FFLP_TCAM_KEY_3_REG, FFLP_TCAM_MASK_0_REG, FFLP_TCAM_MASK_1_REG,
FFLP_TCAM_MASK_2_REG, FFLP_TCAM_MASK_3_REG, FFLP_TCAM_CTL_REG,
FFLP_VLAN_PAR_ERR_REG, FFLP_TCAM_ERR_REG, HASH_LKUP_ERR_LOG1_REG,
HASH_LKUP_ERR_LOG2_REG, FFLP_FCRAM_ERR_TST0_REG,
FFLP_FCRAM_ERR_TST1_REG, FFLP_FCRAM_ERR_TST2_REG, FFLP_ERR_MSK_REG,
FFLP_CFG_1_REG, FFLP_DBG_TRAIN_VCT_REG, FFLP_TCP_CFLAG_MSK_REG,
FFLP_FCRAM_REF_TMR_REG, FFLP_FLOW_KEY_IP_USR4_REG,
FFLP_FLOW_KEY_IP_USR5_REG, FFLP_FLOW_KEY_IP_USR6_REG,
FFLP_FLOW_KEY_IP_USR7_REG, FFLP_FLOW_KEY_IP4_TCP_REG,
FFLP_FLOW_KEY_IP4_UDP_REG, FFLP_FLOW_KEY_IP4_AH_ESP_REG,
FFLP_FLOW_KEY_IP4_SCTP_REG, FFLP_FLOW_KEY_IP6_TCP_REG,
FFLP_FLOW_KEY_IP6_UDP_REG, FFLP_FLOW_KEY_IP6_AH_ESP_REG,
FFLP_FLOW_KEY_IP6_SCTP_REG, FFLP_H1POLY_REG, FFLP_H2POLY_REG,
FFLP_FLW_PRT_SEL_REG
};
const char *fflp_fzc_name[] = {
"FFLP_ENET_VLAN_TBL_REG", "FFLP_L2_CLS_ENET1_REG",
"FFLP_L2_CLS_ENET2_REG", "FFLP_TCAM_KEY_IP_USR4_REG",
"FFLP_TCAM_KEY_IP_USR5_REG", "FFLP_TCAM_KEY_IP_USR6_REG",
"FFLP_TCAM_KEY_IP_USR7_REG", "FFLP_TCAM_KEY_IP4_TCP_REG",
"FFLP_TCAM_KEY_IP4_UDP_REG", "FFLP_TCAM_KEY_IP4_AH_ESP_REG",
"FFLP_TCAM_KEY_IP4_SCTP_REG", "FFLP_TCAM_KEY_IP6_TCP_REG",
"FFLP_TCAM_KEY_IP6_UDP_REG", "FFLP_TCAM_KEY_IP6_AH_ESP_REG",
"FFLP_TCAM_KEY_IP6_SCTP_REG", "FFLP_TCAM_KEY_0_REG",
"FFLP_TCAM_KEY_1_REG", "FFLP_TCAM_KEY_2_REG", "FFLP_TCAM_KEY_3_REG",
"FFLP_TCAM_MASK_0_REG", "FFLP_TCAM_MASK_1_REG", "FFLP_TCAM_MASK_2_REG",
"FFLP_TCAM_MASK_3_REG", "FFLP_TCAM_CTL_REG", "FFLP_VLAN_PAR_ERR_REG",
"FFLP_TCAM_ERR_REG", "HASH_LKUP_ERR_LOG1_REG",
"HASH_LKUP_ERR_LOG2_REG", "FFLP_FCRAM_ERR_TST0_REG",
"FFLP_FCRAM_ERR_TST1_REG", "FFLP_FCRAM_ERR_TST2_REG",
"FFLP_ERR_MSK_REG", "FFLP_CFG_1_REG", "FFLP_DBG_TRAIN_VCT_REG",
"FFLP_TCP_CFLAG_MSK_REG", "FFLP_FCRAM_REF_TMR_REG",
"FFLP_FLOW_KEY_IP_USR4_REG", "FFLP_FLOW_KEY_IP_USR5_REG",
"FFLP_FLOW_KEY_IP_USR6_REG", "FFLP_FLOW_KEY_IP_USR7_REG",
"FFLP_FLOW_KEY_IP4_TCP_REG", "FFLP_FLOW_KEY_IP4_UDP_REG",
"FFLP_FLOW_KEY_IP4_AH_ESP_REG", "FFLP_FLOW_KEY_IP4_SCTP_REG",
"FFLP_FLOW_KEY_IP6_TCP_REG", "FFLP_FLOW_KEY_IP6_UDP_REG",
"FFLP_FLOW_KEY_IP6_AH_ESP_REG",
"FFLP_FLOW_KEY_IP6_SCTP_REG", "FFLP_H1POLY_REG", "FFLP_H2POLY_REG",
"FFLP_FLW_PRT_SEL_REG"
};
uint64_t fflp_reg_offset[] = {
FFLP_HASH_TBL_ADDR_REG, FFLP_HASH_TBL_DATA_REG,
FFLP_HASH_TBL_DATA_LOG_REG
};
const char *fflp_reg_name[] = {
"FFLP_HASH_TBL_ADDR_REG", "FFLP_HASH_TBL_DATA_REG",
"FFLP_HASH_TBL_DATA_LOG_REG"
};
npi_status_t
npi_fflp_dump_regs(npi_handle_t handle)
{
uint64_t value;
int num_regs, i;
num_regs = sizeof (fflp_fzc_offset) / sizeof (uint64_t);
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"\nFFLP_FZC Register Dump \n"));
for (i = 0; i < num_regs; i++) {
REG_PIO_READ64(handle, fflp_fzc_offset[i], &value);
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
" %8llx %s\t %8llx \n",
fflp_fzc_offset[i], fflp_fzc_name[i], value));
}
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"\nFFLP Register Dump\n"));
num_regs = sizeof (fflp_reg_offset) / sizeof (uint64_t);
for (i = 0; i < num_regs; i++) {
REG_PIO_READ64(handle, fflp_reg_offset[i], &value);
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
" %8llx %s\t %8llx \n",
fflp_reg_offset[i], fflp_reg_name[i], value));
}
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"\n FFLP Register Dump done\n"));
return (NPI_SUCCESS);
}
void
npi_fflp_vlan_tbl_dump(npi_handle_t handle)
{
uint64_t offset;
vlan_id_t vlan_id;
uint64_t value;
vlan_id_t start = 0, stop = NXGE_MAX_VLANS;
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"\nVlan Table Dump \n"));
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"VID\t Offset\t Value\n"));
for (vlan_id = start; vlan_id < stop; vlan_id++) {
offset = FFLP_VLAN_OFFSET(vlan_id, FFLP_ENET_VLAN_TBL_REG);
REG_PIO_READ64(handle, offset, &value);
NPI_REG_DUMP_MSG((handle.function, NPI_REG_CTL,
"%x\t %llx\t %llx\n", vlan_id, offset, value));
}
}
static uint64_t
npi_fflp_tcam_check_completion(npi_handle_t handle, tcam_op_t op_type);
/*
* npi_fflp_tcam_check_completion()
* Returns TCAM completion status.
*
* Input:
* op_type : Read, Write, Compare
* handle : OS specific handle
*
* Output:
* For Read and write operations:
* 0 Successful
* -1 Fail/timeout
*
* For Compare operations (debug only )
* TCAM_REG_CTL read value on success
* value contains match location
* NPI_TCAM_COMP_NO_MATCH no match
*
*/
static uint64_t
npi_fflp_tcam_check_completion(npi_handle_t handle, tcam_op_t op_type)
{
uint32_t try_counter, tcam_delay = 10;
tcam_ctl_t tctl;
try_counter = TCAM_COMPLETION_TRY_COUNT;
switch (op_type) {
case TCAM_RWC_STAT:
READ_TCAM_REG_CTL(handle, &tctl.value);
while ((try_counter) &&
(tctl.bits.ldw.stat != TCAM_CTL_RWC_RWC_STAT)) {
try_counter--;
NXGE_DELAY(tcam_delay);
READ_TCAM_REG_CTL(handle, &tctl.value);
}
if (!try_counter) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" TCAM RWC_STAT operation"
" failed to complete \n"));
return (NPI_FFLP_TCAM_HW_ERROR);
}
tctl.value = 0;
break;
case TCAM_RWC_MATCH:
READ_TCAM_REG_CTL(handle, &tctl.value);
while ((try_counter) &&
(tctl.bits.ldw.match != TCAM_CTL_RWC_RWC_MATCH)) {
try_counter--;
NXGE_DELAY(tcam_delay);
READ_TCAM_REG_CTL(handle, &tctl.value);
}
if (!try_counter) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" TCAM Match operation"
"failed to find match \n"));
tctl.value = NPI_TCAM_COMP_NO_MATCH;
}
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" Invalid TCAM completion Request \n"));
return (NPI_FFLP_ERROR |
NPI_TCAM_ERROR | OPCODE_INVALID);
}
return (tctl.value);
}
/*
* npi_fflp_tcam_entry_invalidate()
*
* invalidates entry at tcam location
*
* Input
* handle : OS specific handle
* location : TCAM location
*
* Return
* NPI_SUCCESS
* NPI_FFLP_TCAM_HW_ERROR
*
*/
npi_status_t
npi_fflp_tcam_entry_invalidate(npi_handle_t handle, tcam_location_t location)
{
tcam_ctl_t tctl, tctl_stat;
/*
* Need to write zero to class field.
* Class field is bits [195:191].
* This corresponds to TCAM key 0 register
*
*/
WRITE_TCAM_REG_MASK0(handle, 0xffULL);
WRITE_TCAM_REG_KEY0(handle, 0x0ULL);
tctl.value = 0;
tctl.bits.ldw.location = location;
tctl.bits.ldw.rwc = TCAM_CTL_RWC_TCAM_WR;
WRITE_TCAM_REG_CTL(handle, tctl.value);
tctl_stat.value = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
if (tctl_stat.value & NPI_FAILURE)
return (NPI_FFLP_TCAM_HW_ERROR);
return (NPI_SUCCESS);
}
/*
* npi_fflp_tcam_entry_match()
*
* lookup a tcam entry in the TCAM
*
* Input
* handle : OS specific handle
* tcam_ptr : TCAM entry ptr
*
* Return
*
* NPI_FAILURE | NPI_XX_ERROR: Operational Error (HW etc ...)
* NPI_TCAM_NO_MATCH: no match
* 0 - TCAM_SIZE: matching entry location (if match)
*/
int
npi_fflp_tcam_entry_match(npi_handle_t handle, tcam_entry_t *tcam_ptr)
{
uint64_t tcam_stat = 0;
tcam_ctl_t tctl, tctl_stat;
WRITE_TCAM_REG_MASK0(handle, tcam_ptr->mask0);
WRITE_TCAM_REG_MASK1(handle, tcam_ptr->mask1);
WRITE_TCAM_REG_MASK2(handle, tcam_ptr->mask2);
WRITE_TCAM_REG_MASK3(handle, tcam_ptr->mask3);
WRITE_TCAM_REG_KEY0(handle, tcam_ptr->key0);
WRITE_TCAM_REG_KEY1(handle, tcam_ptr->key1);
WRITE_TCAM_REG_KEY2(handle, tcam_ptr->key2);
WRITE_TCAM_REG_KEY3(handle, tcam_ptr->key3);
tctl.value = 0;
tctl.bits.ldw.rwc = TCAM_CTL_RWC_TCAM_CMP;
WRITE_TCAM_REG_CTL(handle, tctl.value);
tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
if (tcam_stat & NPI_FAILURE) {
return ((uint32_t)tcam_stat);
}
tctl_stat.value = npi_fflp_tcam_check_completion(handle,
TCAM_RWC_MATCH);
if (tctl_stat.bits.ldw.match == TCAM_CTL_RWC_RWC_MATCH) {
return (uint32_t)(tctl_stat.bits.ldw.location);
}
return ((uint32_t)tctl_stat.value);
}
/*
* npi_fflp_tcam_entry_read ()
*
* Reads a tcam entry from the TCAM location, location
*
* Input:
* handle : OS specific handle
* location : TCAM location
* tcam_ptr : TCAM entry pointer
*
* Return:
* NPI_SUCCESS
* NPI_FFLP_TCAM_RD_ERROR
*
*/
npi_status_t
npi_fflp_tcam_entry_read(npi_handle_t handle,
tcam_location_t location,
struct tcam_entry *tcam_ptr)
{
uint64_t tcam_stat;
tcam_ctl_t tctl;
tctl.value = 0;
tctl.bits.ldw.location = location;
tctl.bits.ldw.rwc = TCAM_CTL_RWC_TCAM_RD;
WRITE_TCAM_REG_CTL(handle, tctl.value);
tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
if (tcam_stat & NPI_FAILURE) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
"TCAM read failed loc %d \n", location));
return (NPI_FFLP_TCAM_RD_ERROR);
}
READ_TCAM_REG_MASK0(handle, &tcam_ptr->mask0);
READ_TCAM_REG_MASK1(handle, &tcam_ptr->mask1);
READ_TCAM_REG_MASK2(handle, &tcam_ptr->mask2);
READ_TCAM_REG_MASK3(handle, &tcam_ptr->mask3);
READ_TCAM_REG_KEY0(handle, &tcam_ptr->key0);
READ_TCAM_REG_KEY1(handle, &tcam_ptr->key1);
READ_TCAM_REG_KEY2(handle, &tcam_ptr->key2);
READ_TCAM_REG_KEY3(handle, &tcam_ptr->key3);
return (NPI_SUCCESS);
}
/*
* npi_fflp_tcam_entry_write()
*
* writes a tcam entry to the TCAM location, location
*
* Input:
* handle : OS specific handle
* location : TCAM location
* tcam_ptr : TCAM entry pointer
*
* Return:
* NPI_SUCCESS
* NPI_FFLP_TCAM_WR_ERROR
*
*/
npi_status_t
npi_fflp_tcam_entry_write(npi_handle_t handle,
tcam_location_t location,
tcam_entry_t *tcam_ptr)
{
uint64_t tcam_stat;
tcam_ctl_t tctl;
WRITE_TCAM_REG_MASK0(handle, tcam_ptr->mask0);
WRITE_TCAM_REG_MASK1(handle, tcam_ptr->mask1);
WRITE_TCAM_REG_MASK2(handle, tcam_ptr->mask2);
WRITE_TCAM_REG_MASK3(handle, tcam_ptr->mask3);
WRITE_TCAM_REG_KEY0(handle, tcam_ptr->key0);
WRITE_TCAM_REG_KEY1(handle, tcam_ptr->key1);
WRITE_TCAM_REG_KEY2(handle, tcam_ptr->key2);
WRITE_TCAM_REG_KEY3(handle, tcam_ptr->key3);
NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
" tcam write: location %x\n"
" key: %llx %llx %llx %llx \n"
" mask: %llx %llx %llx %llx \n",
location, tcam_ptr->key0, tcam_ptr->key1,
tcam_ptr->key2, tcam_ptr->key3,
tcam_ptr->mask0, tcam_ptr->mask1,
tcam_ptr->mask2, tcam_ptr->mask3));
tctl.value = 0;
tctl.bits.ldw.location = location;
tctl.bits.ldw.rwc = TCAM_CTL_RWC_TCAM_WR;
NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
" tcam write: ctl value %llx \n", tctl.value));
WRITE_TCAM_REG_CTL(handle, tctl.value);
tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
if (tcam_stat & NPI_FAILURE) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
"TCAM Write failed loc %d \n", location));
return (NPI_FFLP_TCAM_WR_ERROR);
}
return (NPI_SUCCESS);
}
/*
* npi_fflp_tcam_asc_ram_entry_write()
*
* writes a tcam associatedRAM at the TCAM location, location
*
* Input:
* handle : OS specific handle
* location : tcam associatedRAM location
* ram_data : Value to write
*
* Return:
* NPI_SUCCESS
* NPI_FFLP_ASC_RAM_WR_ERROR
*
*/
npi_status_t
npi_fflp_tcam_asc_ram_entry_write(npi_handle_t handle,
tcam_location_t location,
uint64_t ram_data)
{
uint64_t tcam_stat = 0;
tcam_ctl_t tctl;
WRITE_TCAM_REG_KEY1(handle, ram_data);
tctl.value = 0;
tctl.bits.ldw.location = location;
tctl.bits.ldw.rwc = TCAM_CTL_RWC_RAM_WR;
NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
" tcam ascr write: location %x data %llx ctl value %llx \n",
location, ram_data, tctl.value));
WRITE_TCAM_REG_CTL(handle, tctl.value);
tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
if (tcam_stat & NPI_FAILURE) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
"TCAM RAM write failed loc %d \n", location));
return (NPI_FFLP_ASC_RAM_WR_ERROR);
}
return (NPI_SUCCESS);
}
/*
* npi_fflp_tcam_asc_ram_entry_read()
*
* reads a tcam associatedRAM content at the TCAM location, location
*
* Input:
* handle : OS specific handle
* location : tcam associatedRAM location
* ram_data : ptr to return contents
*
* Return:
* NPI_SUCCESS
* NPI_FFLP_ASC_RAM_RD_ERROR
*
*/
npi_status_t
npi_fflp_tcam_asc_ram_entry_read(npi_handle_t handle,
tcam_location_t location,
uint64_t *ram_data)
{
uint64_t tcam_stat;
tcam_ctl_t tctl;
tctl.value = 0;
tctl.bits.ldw.location = location;
tctl.bits.ldw.rwc = TCAM_CTL_RWC_RAM_RD;
WRITE_TCAM_REG_CTL(handle, tctl.value);
tcam_stat = npi_fflp_tcam_check_completion(handle, TCAM_RWC_STAT);
if (tcam_stat & NPI_FAILURE) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
"TCAM RAM read failed loc %d \n", location));
return (NPI_FFLP_ASC_RAM_RD_ERROR);
}
READ_TCAM_REG_KEY1(handle, ram_data);
return (NPI_SUCCESS);
}
/* FFLP FCRAM Related functions */
/* The following are FCRAM datapath functions */
/*
* npi_fflp_fcram_entry_write ()
* Populates an FCRAM entry
* Inputs:
* handle: opaque handle interpreted by the underlying OS
* partid: Partition ID
* location: Index to the FCRAM.
* Corresponds to last 20 bits of H1 value
* fcram_ptr: Pointer to the FCRAM contents to be used for writing
* format: Entry Format. Determines the size of the write.
* FCRAM_ENTRY_OPTIM: 8 bytes (a 64 bit write)
* FCRAM_ENTRY_EX_IP4: 32 bytes (4 X 64 bit write)
* FCRAM_ENTRY_EX_IP6: 56 bytes (7 X 64 bit write)
*
* Outputs:
* NPI success/failure status code
*/
npi_status_t
npi_fflp_fcram_entry_write(npi_handle_t handle, part_id_t partid,
uint32_t location, fcram_entry_t *fcram_ptr,
fcram_entry_format_t format)
{
int num_subareas = 0;
uint64_t addr_reg, data_reg;
int subarea;
int autoinc;
hash_tbl_addr_t addr;
switch (format) {
case FCRAM_ENTRY_OPTIM:
if (location % 8) {
/* need to be 8 byte alligned */
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" FCRAM_ENTRY_OOPTIM Write:"
" unaligned location %llx \n",
location));
return (NPI_FFLP_FCRAM_LOC_INVALID);
}
num_subareas = 1;
autoinc = 0;
break;
case FCRAM_ENTRY_EX_IP4:
if (location % 32) {
/* need to be 32 byte alligned */
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" FCRAM_ENTRY_EX_IP4 Write:"
" unaligned location %llx \n",
location));
return (NPI_FFLP_FCRAM_LOC_INVALID);
}
num_subareas = 4;
autoinc = 1;
break;
case FCRAM_ENTRY_EX_IP6:
if (location % 64) {
/* need to be 64 byte alligned */
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" FCRAM_ENTRY_EX_IP6 Write:"
" unaligned location %llx \n",
location));
return (NPI_FFLP_FCRAM_LOC_INVALID);
}
num_subareas = 7;
autoinc = 1;
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" fcram_entry_write:"
" unknown format param location %llx\n",
location));
return (NPI_FFLP_ERROR | NPI_FCRAM_ERROR | OPCODE_INVALID);
}
addr.value = 0;
addr.bits.ldw.autoinc = autoinc;
addr.bits.ldw.addr = location;
addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
FFLP_HASH_TBL_ADDR_REG);
data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
FFLP_HASH_TBL_DATA_REG);
/* write to addr reg */
REG_PIO_WRITE64(handle, addr_reg, addr.value);
/* write data to the data register */
for (subarea = 0; subarea < num_subareas; subarea++) {
REG_PIO_WRITE64(handle, data_reg, fcram_ptr->value[subarea]);
}
return (NPI_SUCCESS);
}
/*
* npi_fflp_fcram_read_read ()
* Reads an FCRAM entry
* Inputs:
* handle: opaque handle interpreted by the underlying OS
* partid: Partition ID
* location: Index to the FCRAM.
* Corresponds to last 20 bits of H1 value
*
* fcram_ptr: Pointer to the FCRAM contents to be updated
* format: Entry Format. Determines the size of the read.
* FCRAM_ENTRY_OPTIM: 8 bytes (a 64 bit read)
* FCRAM_ENTRY_EX_IP4: 32 bytes (4 X 64 bit read )
* FCRAM_ENTRY_EX_IP6: 56 bytes (7 X 64 bit read )
* Return:
* NPI Success/Failure status code
*
*/
npi_status_t
npi_fflp_fcram_entry_read(npi_handle_t handle, part_id_t partid,
uint32_t location, fcram_entry_t *fcram_ptr,
fcram_entry_format_t format)
{
int num_subareas = 0;
uint64_t addr_reg, data_reg;
int subarea, autoinc;
hash_tbl_addr_t addr;
switch (format) {
case FCRAM_ENTRY_OPTIM:
if (location % 8) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" FCRAM_ENTRY_OOPTIM Read:"
" unaligned location %llx \n",
location));
/* need to be 8 byte alligned */
return (NPI_FFLP_FCRAM_LOC_INVALID);
}
num_subareas = 1;
autoinc = 0;
break;
case FCRAM_ENTRY_EX_IP4:
if (location % 32) {
/* need to be 32 byte alligned */
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" FCRAM_ENTRY_EX_IP4 READ:"
" unaligned location %llx \n",
location));
return (NPI_FFLP_FCRAM_LOC_INVALID);
}
num_subareas = 4;
autoinc = 1;
break;
case FCRAM_ENTRY_EX_IP6:
if (location % 64) {
/* need to be 64 byte alligned */
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" FCRAM_ENTRY_EX_IP6 READ:"
" unaligned location %llx \n",
location));
return (NPI_FFLP_FCRAM_LOC_INVALID);
}
num_subareas = 7;
autoinc = 1;
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" fcram_entry_read:"
" unknown format param location %llx\n",
location));
return (NPI_FFLP_SW_PARAM_ERROR);
}
addr.value = 0;
addr.bits.ldw.autoinc = autoinc;
addr.bits.ldw.addr = location;
addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
FFLP_HASH_TBL_ADDR_REG);
data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
FFLP_HASH_TBL_DATA_REG);
/* write to addr reg */
REG_PIO_WRITE64(handle, addr_reg, addr.value);
/* read data from the data register */
for (subarea = 0; subarea < num_subareas; subarea++) {
REG_PIO_READ64(handle, data_reg, &fcram_ptr->value[subarea]);
}
return (NPI_SUCCESS);
}
/*
* npi_fflp_fcram_entry_invalidate ()
* Invalidate FCRAM entry at the given location
* Inputs:
* handle: opaque handle interpreted by the underlying OS
* partid: Partition ID
* location: location of the FCRAM/hash entry.
*
* Return:
* NPI Success/Failure status code
*/
npi_status_t
npi_fflp_fcram_entry_invalidate(npi_handle_t handle, part_id_t partid,
uint32_t location)
{
hash_tbl_addr_t addr;
uint64_t addr_reg, data_reg;
hash_hdr_t hdr;
if (location % 8) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" FCRAM_ENTRY_Invalidate:"
" unaligned location %llx \n",
location));
/* need to be 8 byte aligned */
return (NPI_FFLP_FCRAM_LOC_INVALID);
}
addr.value = 0;
addr.bits.ldw.addr = location;
addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
FFLP_HASH_TBL_ADDR_REG);
data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
FFLP_HASH_TBL_DATA_REG);
/* write to addr reg */
REG_PIO_WRITE64(handle, addr_reg, addr.value);
REG_PIO_READ64(handle, data_reg, &hdr.value);
hdr.exact_hdr.valid = 0;
REG_PIO_WRITE64(handle, data_reg, hdr.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_fcram_write_subarea ()
* Writes to FCRAM entry subarea i.e the 8 bytes within the 64 bytes
* pointed by the last 20 bits of H1. Effectively, this accesses
* specific 8 bytes within the hash table bucket.
*
* H1--> |-----------------|
* | subarea 0 |
* |_________________|
* | Subarea 1 |
* |_________________|
* | ....... |
* |_________________|
* | Subarea 7 |
* |_________________|
*
* Inputs:
* handle: opaque handle interpreted by the underlying OS
* partid: Partition ID
* location: location of the subarea. It is derived from:
* Bucket = [19:15][14:0] (20 bits of H1)
* location = (Bucket << 3 ) + subarea * 8
* = [22:18][17:3] || subarea * 8
* data: Data
*
* Return:
* NPI Success/Failure status code
*/
npi_status_t
npi_fflp_fcram_subarea_write(npi_handle_t handle, part_id_t partid,
uint32_t location, uint64_t data)
{
hash_tbl_addr_t addr;
uint64_t addr_reg, data_reg;
if (location % 8) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" fcram_subarea_write:"
" unaligned location %llx \n",
location));
/* need to be 8 byte alligned */
return (NPI_FFLP_FCRAM_LOC_INVALID);
}
addr.value = 0;
addr.bits.ldw.addr = location;
addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
FFLP_HASH_TBL_ADDR_REG);
data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
FFLP_HASH_TBL_DATA_REG);
/* write to addr reg */
REG_PIO_WRITE64(handle, addr_reg, addr.value);
REG_PIO_WRITE64(handle, data_reg, data);
return (NPI_SUCCESS);
}
/*
* npi_fflp_fcram_subarea_read ()
* Reads an FCRAM entry subarea i.e the 8 bytes within the 64 bytes
* pointed by the last 20 bits of H1. Effectively, this accesses
* specific 8 bytes within the hash table bucket.
*
* H1--> |-----------------|
* | subarea 0 |
* |_________________|
* | Subarea 1 |
* |_________________|
* | ....... |
* |_________________|
* | Subarea 7 |
* |_________________|
*
* Inputs:
* handle: opaque handle interpreted by the underlying OS
* partid: Partition ID
* location: location of the subarea. It is derived from:
* Bucket = [19:15][14:0] (20 bits of H1)
* location = (Bucket << 3 ) + subarea * 8
* = [22:18][17:3] || subarea * 8
* data: ptr do write subarea contents to.
*
* Return:
* NPI Success/Failure status code
*/
npi_status_t
npi_fflp_fcram_subarea_read(npi_handle_t handle, part_id_t partid,
uint32_t location, uint64_t *data)
{
hash_tbl_addr_t addr;
uint64_t addr_reg, data_reg;
if (location % 8) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" fcram_subarea_read:"
" unaligned location %llx \n",
location));
/* need to be 8 byte alligned */
return (NPI_FFLP_FCRAM_LOC_INVALID);
}
addr.value = 0;
addr.bits.ldw.addr = location;
addr_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
FFLP_HASH_TBL_ADDR_REG);
data_reg = GET_HASHTBL_PART_OFFSET(handle, partid,
FFLP_HASH_TBL_DATA_REG);
/* write to addr reg */
REG_PIO_WRITE64(handle, addr_reg, addr.value);
REG_PIO_READ64(handle, data_reg, data);
return (NPI_SUCCESS);
}
/*
* The following are zero function fflp configuration functions.
*/
/*
* npi_fflp_fcram_config_partition()
* Partitions and configures the FCRAM
*/
npi_status_t
npi_fflp_cfg_fcram_partition(npi_handle_t handle, part_id_t partid,
uint8_t base_mask, uint8_t base_reloc)
{
/*
* assumes that the base mask and relocation are computed somewhere
* and kept in the state data structure. Alternativiely, one can pass
* a partition size and a starting address and this routine can compute
* the mask and reloc vlaues.
*/
flow_prt_sel_t sel;
uint64_t offset;
ASSERT(FCRAM_PARTITION_VALID(partid));
if (!FCRAM_PARTITION_VALID(partid)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_fcram_partition:"
" Invalid Partition %d \n",
partid));
return (NPI_FFLP_FCRAM_PART_INVALID);
}
offset = FFLP_PART_OFFSET(partid, FFLP_FLW_PRT_SEL_REG);
sel.value = 0;
sel.bits.ldw.mask = base_mask;
sel.bits.ldw.base = base_reloc;
sel.bits.ldw.ext = BIT_DISABLE; /* disable */
REG_PIO_WRITE64(handle, offset, sel.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_fcram_partition_enable
* Enable previously configured FCRAM partition
*
* Input
* handle: opaque handle interpreted by the underlying OS
* partid: partition ID, Corresponds to the RDC table
*
* Return
* 0 Successful
* Non zero error code Enable failed, and reason.
*
*/
npi_status_t
npi_fflp_cfg_fcram_partition_enable (npi_handle_t handle, part_id_t partid)
{
flow_prt_sel_t sel;
uint64_t offset;
ASSERT(FCRAM_PARTITION_VALID(partid));
if (!FCRAM_PARTITION_VALID(partid)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" fcram_partition enable:"
" Invalid Partition %d \n",
partid));
return (NPI_FFLP_FCRAM_PART_INVALID);
}
offset = FFLP_PART_OFFSET(partid, FFLP_FLW_PRT_SEL_REG);
REG_PIO_READ64(handle, offset, &sel.value);
sel.bits.ldw.ext = BIT_ENABLE; /* enable */
REG_PIO_WRITE64(handle, offset, sel.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_fcram_partition_disable
* Disable previously configured FCRAM partition
*
* Input
* handle: opaque handle interpreted by the underlying OS
* partid: partition ID, Corresponds to the RDC table
*
* Return:
* NPI Success/Failure status code
*/
npi_status_t
npi_fflp_cfg_fcram_partition_disable(npi_handle_t handle, part_id_t partid)
{
flow_prt_sel_t sel;
uint64_t offset;
ASSERT(FCRAM_PARTITION_VALID(partid));
if (!FCRAM_PARTITION_VALID(partid)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" fcram_partition disable:"
" Invalid Partition %d \n",
partid));
return (NPI_FFLP_FCRAM_PART_INVALID);
}
offset = FFLP_PART_OFFSET(partid, FFLP_FLW_PRT_SEL_REG);
REG_PIO_READ64(handle, offset, &sel.value);
sel.bits.ldw.ext = BIT_DISABLE; /* disable */
REG_PIO_WRITE64(handle, offset, sel.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cam_errorcheck_disable
* Disables FCRAM and TCAM error checking
*/
npi_status_t
npi_fflp_cfg_cam_errorcheck_disable(npi_handle_t handle)
{
fflp_cfg_1_t fflp_cfg;
uint64_t offset;
offset = FFLP_CFG_1_REG;
REG_PIO_READ64(handle, offset, &fflp_cfg.value);
fflp_cfg.bits.ldw.errordis = BIT_ENABLE;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cam_errorcheck_enable
* Enables FCRAM and TCAM error checking
*/
npi_status_t
npi_fflp_cfg_cam_errorcheck_enable(npi_handle_t handle)
{
fflp_cfg_1_t fflp_cfg;
uint64_t offset;
offset = FFLP_CFG_1_REG;
REG_PIO_READ64(handle, offset, &fflp_cfg.value);
fflp_cfg.bits.ldw.errordis = BIT_DISABLE;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cam_llcsnap_enable
* Enables input parser llcsnap recognition
*/
npi_status_t
npi_fflp_cfg_llcsnap_enable(npi_handle_t handle)
{
fflp_cfg_1_t fflp_cfg;
uint64_t offset;
offset = FFLP_CFG_1_REG;
REG_PIO_READ64(handle, offset, &fflp_cfg.value);
fflp_cfg.bits.ldw.llcsnap = BIT_ENABLE;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cam_llcsnap_disable
* Disables input parser llcsnap recognition
*/
npi_status_t
npi_fflp_cfg_llcsnap_disable(npi_handle_t handle)
{
fflp_cfg_1_t fflp_cfg;
uint64_t offset;
offset = FFLP_CFG_1_REG;
REG_PIO_READ64(handle, offset, &fflp_cfg.value);
fflp_cfg.bits.ldw.llcsnap = BIT_DISABLE;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_config_fcram_refresh
* Set FCRAM min and max refresh time.
*
* Input
* handle opaque handle interpreted by the underlying OS
* min_time Minimum Refresh time count
* max_time maximum Refresh Time count
* sys_time System Clock rate
*
* The counters are 16 bit counters. The maximum refresh time is
* 3.9us/clock cycle. The minimum is 400ns/clock cycle.
* Clock cycle is the FCRAM clock cycle?????
* If the cycle is FCRAM clock cycle, then sys_time parameter
* is not needed as there wont be configuration variation due to
* system clock cycle.
*
* Return:
* NPI Success/Failure status code
*/
npi_status_t
npi_fflp_cfg_fcram_refresh_time(npi_handle_t handle, uint32_t min_time,
uint32_t max_time, uint32_t sys_time)
{
uint64_t offset;
fcram_ref_tmr_t refresh_timer_reg;
uint16_t max, min;
offset = FFLP_FCRAM_REF_TMR_REG;
/* need to figure out how to dervive the numbers */
max = max_time * sys_time;
min = min_time * sys_time;
/* for now, just set with #def values */
max = FCRAM_REFRESH_DEFAULT_MAX_TIME;
min = FCRAM_REFRESH_DEFAULT_MIN_TIME;
REG_PIO_READ64(handle, offset, &refresh_timer_reg.value);
refresh_timer_reg.bits.ldw.min = min;
refresh_timer_reg.bits.ldw.max = max;
REG_PIO_WRITE64(handle, offset, refresh_timer_reg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_hash_lookup_err_report
* Reports hash table (fcram) lookup errors
*
* Input
* handle opaque handle interpreted by the underlying OS
* err_stat Pointer to return Error bits
*
*
* Return:
* NPI success/failure status code
*/
npi_status_t
npi_fflp_fcram_get_lookup_err_log(npi_handle_t handle,
hash_lookup_err_log_t *err_stat)
{
hash_lookup_err_log1_t err_log1;
hash_lookup_err_log2_t err_log2;
uint64_t err_log1_offset, err_log2_offset;
err_log1.value = 0;
err_log2.value = 0;
err_log1_offset = HASH_LKUP_ERR_LOG1_REG;
err_log2_offset = HASH_LKUP_ERR_LOG2_REG;
REG_PIO_READ64(handle, err_log1_offset, &err_log1.value);
REG_PIO_READ64(handle, err_log2_offset, &err_log2.value);
if (err_log1.value) {
/* nonzero means there are some errors */
err_stat->lookup_err = BIT_ENABLE;
err_stat->syndrome = err_log2.bits.ldw.syndrome;
err_stat->subarea = err_log2.bits.ldw.subarea;
err_stat->h1 = err_log2.bits.ldw.h1;
err_stat->multi_bit = err_log1.bits.ldw.mult_bit;
err_stat->multi_lkup = err_log1.bits.ldw.mult_lk;
err_stat->ecc_err = err_log1.bits.ldw.ecc_err;
err_stat->uncor_err = err_log1.bits.ldw.cu;
} else {
err_stat->lookup_err = BIT_DISABLE;
}
return (NPI_SUCCESS);
}
/*
* npi_fflp_fcram_get_pio_err_log
* Reports hash table PIO read errors for the given partition.
* by default, it clears the error bit which was set by the HW.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* partid: partition ID
* err_stat Pointer to return Error bits
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_fcram_get_pio_err_log(npi_handle_t handle, part_id_t partid,
hash_pio_err_log_t *err_stat)
{
hash_tbl_data_log_t err_log;
uint64_t offset;
ASSERT(FCRAM_PARTITION_VALID(partid));
if (!FCRAM_PARTITION_VALID(partid)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" fcram_get_pio_err_log:"
" Invalid Partition %d \n",
partid));
return (NPI_FFLP_FCRAM_PART_INVALID);
}
offset = GET_HASHTBL_PART_OFFSET_NVIR(partid,
FFLP_HASH_TBL_DATA_LOG_REG);
REG_PIO_READ64(handle, offset, &err_log.value);
if (err_log.bits.ldw.pio_err == BIT_ENABLE) {
/* nonzero means there are some errors */
err_stat->pio_err = BIT_ENABLE;
err_stat->syndrome = err_log.bits.ldw.syndrome;
err_stat->addr = err_log.bits.ldw.fcram_addr;
err_log.value = 0;
REG_PIO_WRITE64(handle, offset, err_log.value);
} else {
err_stat->pio_err = BIT_DISABLE;
}
return (NPI_SUCCESS);
}
/*
* npi_fflp_fcram_clr_pio_err_log
* Clears FCRAM PIO error status for the partition.
* If there are TCAM errors as indicated by err bit set by HW,
* then the SW will clear it by clearing the bit.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* partid: partition ID
*
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_fcram_clr_pio_err_log(npi_handle_t handle, part_id_t partid)
{
uint64_t offset;
hash_tbl_data_log_t err_log;
ASSERT(FCRAM_PARTITION_VALID(partid));
if (!FCRAM_PARTITION_VALID(partid)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" fcram_clr_pio_err_log:"
" Invalid Partition %d \n",
partid));
return (NPI_FFLP_FCRAM_PART_INVALID);
}
offset = GET_HASHTBL_PART_OFFSET_NVIR(partid,
FFLP_HASH_TBL_DATA_LOG_REG);
err_log.value = 0;
REG_PIO_WRITE64(handle, offset, err_log.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_tcam_get_err_log
* Reports TCAM PIO read and lookup errors.
* If there are TCAM errors as indicated by err bit set by HW,
* then the SW will clear it by clearing the bit.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* err_stat: structure to report various TCAM errors.
* will be updated if there are TCAM errors.
*
*
* Return
* NPI_SUCCESS Success
*
*
*/
npi_status_t
npi_fflp_tcam_get_err_log(npi_handle_t handle, tcam_err_log_t *err_stat)
{
tcam_err_t err_log;
uint64_t offset;
offset = FFLP_TCAM_ERR_REG;
err_log.value = 0;
REG_PIO_READ64(handle, offset, &err_log.value);
if (err_log.bits.ldw.err == BIT_ENABLE) {
/* non-zero means err */
err_stat->tcam_err = BIT_ENABLE;
if (err_log.bits.ldw.p_ecc) {
err_stat->parity_err = 0;
err_stat->ecc_err = 1;
} else {
err_stat->parity_err = 1;
err_stat->ecc_err = 0;
}
err_stat->syndrome = err_log.bits.ldw.syndrome;
err_stat->location = err_log.bits.ldw.addr;
err_stat->multi_lkup = err_log.bits.ldw.mult;
/* now clear the error */
err_log.value = 0;
REG_PIO_WRITE64(handle, offset, err_log.value);
} else {
err_stat->tcam_err = 0;
}
return (NPI_SUCCESS);
}
/*
* npi_fflp_tcam_clr_err_log
* Clears TCAM PIO read and lookup error status.
* If there are TCAM errors as indicated by err bit set by HW,
* then the SW will clear it by clearing the bit.
*
* Input
* handle: opaque handle interpreted by the underlying OS
*
*
* Return
* NPI_SUCCESS Success
*
*
*/
npi_status_t
npi_fflp_tcam_clr_err_log(npi_handle_t handle)
{
tcam_err_t err_log;
uint64_t offset;
offset = FFLP_TCAM_ERR_REG;
err_log.value = 0;
REG_PIO_WRITE64(handle, offset, err_log.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_fcram_err_synd_test
* Tests the FCRAM error detection logic.
* The error detection logic for the syndrome is tested.
* tst0->synd (8bits) are set to select the syndrome bits
* to be XOR'ed
*
* Input
* handle: opaque handle interpreted by the underlying OS
* syndrome_bits: Syndrome bits to select bits to be xor'ed
*
*
* Return
* NPI_SUCCESS Success
*
*
*/
npi_status_t
npi_fflp_fcram_err_synd_test(npi_handle_t handle, uint8_t syndrome_bits)
{
uint64_t t0_offset;
fcram_err_tst0_t tst0;
t0_offset = FFLP_FCRAM_ERR_TST0_REG;
tst0.value = 0;
tst0.bits.ldw.syndrome_mask = syndrome_bits;
REG_PIO_WRITE64(handle, t0_offset, tst0.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_fcram_err_data_test
* Tests the FCRAM error detection logic.
* The error detection logic for the datapath is tested.
* bits [63:0] are set to select the data bits to be xor'ed
*
* Input
* handle: opaque handle interpreted by the underlying OS
* data: data bits to select bits to be xor'ed
*
*
* Return
* NPI_SUCCESS Success
*
*
*/
npi_status_t
npi_fflp_fcram_err_data_test(npi_handle_t handle, fcram_err_data_t *data)
{
uint64_t t1_offset, t2_offset;
fcram_err_tst1_t tst1; /* for data bits [31:0] */
fcram_err_tst2_t tst2; /* for data bits [63:32] */
t1_offset = FFLP_FCRAM_ERR_TST1_REG;
t2_offset = FFLP_FCRAM_ERR_TST2_REG;
tst1.value = 0;
tst2.value = 0;
tst1.bits.ldw.dat = data->bits.ldw.dat;
tst2.bits.ldw.dat = data->bits.hdw.dat;
REG_PIO_WRITE64(handle, t1_offset, tst1.value);
REG_PIO_WRITE64(handle, t2_offset, tst2.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_enet_vlan_table_assoc
* associates port vlan id to rdc table.
*
* Input
* handle opaque handle interpreted by the underlying OS
* mac_portn port number
* vlan_id VLAN ID
* rdc_table RDC Table #
* priority priority
*
* Output
*
* NPI success/failure status code
*
*/
npi_status_t
npi_fflp_cfg_enet_vlan_table_assoc(npi_handle_t handle, uint8_t mac_portn,
vlan_id_t vlan_id, uint8_t rdc_table,
uint8_t priority)
{
fflp_enet_vlan_tbl_t cfg;
uint64_t offset;
uint8_t vlan_parity[8] = {0, 1, 1, 2, 1, 2, 2, 3};
uint8_t parity_bit;
ASSERT(FFLP_VLAN_VALID(vlan_id));
if (!FFLP_VLAN_VALID(vlan_id)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" fflp_cfg_enet_vlan_table:"
" Invalid vlan ID %d \n",
vlan_id));
return (NPI_FFLP_VLAN_INVALID);
}
ASSERT(FFLP_PORT_VALID(mac_portn));
if (!FFLP_PORT_VALID(mac_portn)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" fflp_cfg_enet_vlan_table:"
" Invalid port num %d \n",
mac_portn));
return (NPI_FFLP_PORT_INVALID);
}
ASSERT(FFLP_RDC_TABLE_VALID(rdc_table));
if (!FFLP_RDC_TABLE_VALID(rdc_table)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" fflp_cfg_enet_vlan_table:"
" Invalid RDC Table %d \n",
rdc_table));
return (NPI_FFLP_RDC_TABLE_INVALID);
}
offset = FFLP_VLAN_OFFSET(vlan_id, FFLP_ENET_VLAN_TBL_REG);
REG_PIO_READ64(handle, offset, &cfg.value);
switch (mac_portn) {
case 0:
cfg.bits.ldw.vlanrdctbln0 = rdc_table;
if (priority)
cfg.bits.ldw.vpr0 = BIT_ENABLE;
else
cfg.bits.ldw.vpr0 = BIT_DISABLE;
/* set the parity bits */
parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln0] +
vlan_parity[cfg.bits.ldw.vlanrdctbln1] +
cfg.bits.ldw.vpr0 + cfg.bits.ldw.vpr1;
cfg.bits.ldw.parity0 = parity_bit & 0x1;
break;
case 1:
cfg.bits.ldw.vlanrdctbln1 = rdc_table;
if (priority)
cfg.bits.ldw.vpr1 = BIT_ENABLE;
else
cfg.bits.ldw.vpr1 = BIT_DISABLE;
/* set the parity bits */
parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln0] +
vlan_parity[cfg.bits.ldw.vlanrdctbln1] +
cfg.bits.ldw.vpr0 + cfg.bits.ldw.vpr1;
cfg.bits.ldw.parity0 = parity_bit & 0x1;
break;
case 2:
cfg.bits.ldw.vlanrdctbln2 = rdc_table;
if (priority)
cfg.bits.ldw.vpr2 = BIT_ENABLE;
else
cfg.bits.ldw.vpr2 = BIT_DISABLE;
/* set the parity bits */
parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln2] +
vlan_parity[cfg.bits.ldw.vlanrdctbln3] +
cfg.bits.ldw.vpr2 + cfg.bits.ldw.vpr3;
cfg.bits.ldw.parity1 = parity_bit & 0x1;
break;
case 3:
cfg.bits.ldw.vlanrdctbln3 = rdc_table;
if (priority)
cfg.bits.ldw.vpr3 = BIT_ENABLE;
else
cfg.bits.ldw.vpr3 = BIT_DISABLE;
/* set the parity bits */
parity_bit = vlan_parity[cfg.bits.ldw.vlanrdctbln2] +
vlan_parity[cfg.bits.ldw.vlanrdctbln3] +
cfg.bits.ldw.vpr2 + cfg.bits.ldw.vpr3;
cfg.bits.ldw.parity1 = parity_bit & 0x1;
break;
default:
return (NPI_FFLP_SW_PARAM_ERROR);
}
REG_PIO_WRITE64(handle, offset, cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_enet_vlan_table_set_pri
* sets the vlan based classification priority in respect to L2DA
* classification.
*
* Input
* handle opaque handle interpreted by the underlying OS
* mac_portn port number
* vlan_id VLAN ID
* priority priority
* 1: vlan classification has higher priority
* 0: l2da classification has higher priority
*
* Output
*
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_enet_vlan_table_set_pri(npi_handle_t handle, uint8_t mac_portn,
vlan_id_t vlan_id, uint8_t priority)
{
fflp_enet_vlan_tbl_t cfg;
uint64_t offset;
uint64_t old_value;
ASSERT(FFLP_VLAN_VALID(vlan_id));
if (!FFLP_VLAN_VALID(vlan_id)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" enet_vlan_table set pri:"
" Invalid vlan ID %d \n",
vlan_id));
return (NPI_FFLP_VLAN_INVALID);
}
ASSERT(FFLP_PORT_VALID(mac_portn));
if (!FFLP_PORT_VALID(mac_portn)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" enet_vlan_table set pri:"
" Invalid port num %d \n",
mac_portn));
return (NPI_FFLP_PORT_INVALID);
}
offset = FFLP_ENET_VLAN_TBL_REG + (vlan_id << 3);
REG_PIO_READ64(handle, offset, &cfg.value);
old_value = cfg.value;
switch (mac_portn) {
case 0:
if (priority)
cfg.bits.ldw.vpr0 = BIT_ENABLE;
else
cfg.bits.ldw.vpr0 = BIT_DISABLE;
break;
case 1:
if (priority)
cfg.bits.ldw.vpr1 = BIT_ENABLE;
else
cfg.bits.ldw.vpr1 = BIT_DISABLE;
break;
case 2:
if (priority)
cfg.bits.ldw.vpr2 = BIT_ENABLE;
else
cfg.bits.ldw.vpr2 = BIT_DISABLE;
break;
case 3:
if (priority)
cfg.bits.ldw.vpr3 = BIT_ENABLE;
else
cfg.bits.ldw.vpr3 = BIT_DISABLE;
break;
default:
return (NPI_FFLP_SW_PARAM_ERROR);
}
if (old_value != cfg.value) {
if (mac_portn > 1)
cfg.bits.ldw.parity1++;
else
cfg.bits.ldw.parity0++;
REG_PIO_WRITE64(handle, offset, cfg.value);
}
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_vlan_table_clear
* Clears the vlan RDC table
*
* Input
* handle opaque handle interpreted by the underlying OS
* vlan_id VLAN ID
*
* Output
*
* NPI success/failure status code
*
*/
npi_status_t
npi_fflp_cfg_vlan_table_clear(npi_handle_t handle, vlan_id_t vlan_id)
{
uint64_t offset;
uint64_t clear = 0ULL;
vlan_id_t start_vlan = 0;
if ((vlan_id < start_vlan) || (vlan_id >= NXGE_MAX_VLANS)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" enet_vlan_table clear:"
" Invalid vlan ID %d \n",
vlan_id));
return (NPI_FFLP_VLAN_INVALID);
}
offset = FFLP_VLAN_OFFSET(vlan_id, FFLP_ENET_VLAN_TBL_REG);
REG_PIO_WRITE64(handle, offset, clear);
return (NPI_SUCCESS);
}
/*
* npi_fflp_vlan_tbl_get_err_log
* Reports VLAN Table errors.
* If there are VLAN Table errors as indicated by err bit set by HW,
* then the SW will clear it by clearing the bit.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* err_stat: structure to report various VLAN table errors.
* will be updated if there are errors.
*
*
* Return
* NPI_SUCCESS Success
*
*
*/
npi_status_t
npi_fflp_vlan_tbl_get_err_log(npi_handle_t handle, vlan_tbl_err_log_t *err_stat)
{
vlan_par_err_t err_log;
uint64_t offset;
offset = FFLP_VLAN_PAR_ERR_REG;
err_log.value = 0;
REG_PIO_READ64(handle, offset, &err_log.value);
if (err_log.bits.ldw.err == BIT_ENABLE) {
/* non-zero means err */
err_stat->err = BIT_ENABLE;
err_stat->multi = err_log.bits.ldw.m_err;
err_stat->addr = err_log.bits.ldw.addr;
err_stat->data = err_log.bits.ldw.data;
/* now clear the error */
err_log.value = 0;
REG_PIO_WRITE64(handle, offset, err_log.value);
} else {
err_stat->err = 0;
}
return (NPI_SUCCESS);
}
/*
* npi_fflp_vlan_tbl_clr_err_log
* Clears VLAN Table PIO error status.
* If there are VLAN Table errors as indicated by err bit set by HW,
* then the SW will clear it by clearing the bit.
*
* Input
* handle: opaque handle interpreted by the underlying OS
*
*
* Return
* NPI_SUCCESS Success
*
*
*/
npi_status_t
npi_fflp_vlan_tbl_clr_err_log(npi_handle_t handle)
{
vlan_par_err_t err_log;
uint64_t offset;
offset = FFLP_VLAN_PAR_ERR_REG;
err_log.value = 0;
REG_PIO_WRITE64(handle, offset, err_log.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_enet_usr_cls_set()
* Configures a user configurable ethernet class
*
* Input
* handle: opaque handle interpreted by the underlying OS
* class: Ethernet Class class
* (TCAM_CLASS_ETYPE or TCAM_CLASS_ETYPE_2)
* enet_type: 16 bit Ethernet Type value, corresponding ethernet bytes
* [13:14] in the frame.
*
* by default, the class will be disabled until explicitly enabled.
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_enet_usr_cls_set(npi_handle_t handle,
tcam_class_t class, uint16_t enet_type)
{
uint64_t offset;
tcam_class_prg_ether_t cls_cfg;
cls_cfg.value = 0x0;
/* check if etype is valid */
ASSERT(TCAM_L2_USR_CLASS_VALID(class));
if (!TCAM_L2_USR_CLASS_VALID(class)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_enet_usr_cls_set:"
" Invalid class %d \n",
class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
offset = GET_TCAM_CLASS_OFFSET(class);
/*
* etype check code
*
* if (check_fail)
* return (NPI_FAILURE | NPI_SW_ERROR);
*/
cls_cfg.bits.ldw.etype = enet_type;
cls_cfg.bits.ldw.valid = BIT_DISABLE;
REG_PIO_WRITE64(handle, offset, cls_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_enet_usr_cls_enable()
* Enable previously configured TCAM user configurable Ethernet classes.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* class: Ethernet Class class
* (TCAM_CLASS_ETYPE or TCAM_CLASS_ETYPE_2)
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_enet_usr_cls_enable(npi_handle_t handle, tcam_class_t class)
{
uint64_t offset;
tcam_class_prg_ether_t cls_cfg;
ASSERT(TCAM_L2_USR_CLASS_VALID(class));
if (!TCAM_L2_USR_CLASS_VALID(class)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_enet_usr_cls_enable:"
" Invalid class %d \n",
class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
offset = GET_TCAM_CLASS_OFFSET(class);
REG_PIO_READ64(handle, offset, &cls_cfg.value);
cls_cfg.bits.ldw.valid = BIT_ENABLE;
REG_PIO_WRITE64(handle, offset, cls_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_enet_usr_cls_disable()
* Disables previously configured TCAM user configurable Ethernet classes.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* class: Ethernet Class class
* (TCAM_CLASS_ETYPE or TCAM_CLASS_ETYPE_2)
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_enet_usr_cls_disable(npi_handle_t handle, tcam_class_t class)
{
uint64_t offset;
tcam_class_prg_ether_t cls_cfg;
ASSERT(TCAM_L2_USR_CLASS_VALID(class));
if (!TCAM_L2_USR_CLASS_VALID(class)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_enet_usr_cls_disable:"
" Invalid class %d \n",
class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
offset = GET_TCAM_CLASS_OFFSET(class);
REG_PIO_READ64(handle, offset, &cls_cfg.value);
cls_cfg.bits.ldw.valid = BIT_DISABLE;
REG_PIO_WRITE64(handle, offset, cls_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_ip_usr_cls_set()
* Configures the TCAM user configurable IP classes.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* class: IP Class class
* (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
* tos: IP TOS bits
* tos_mask: IP TOS bits mask. bits with mask bits set will be used
* proto: IP Proto
* ver: IP Version
* by default, will the class is disabled until explicitly enabled
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_ip_usr_cls_set(npi_handle_t handle, tcam_class_t class,
uint8_t tos, uint8_t tos_mask,
uint8_t proto, uint8_t ver)
{
uint64_t offset;
tcam_class_prg_ip_t ip_cls_cfg;
ASSERT(TCAM_L3_USR_CLASS_VALID(class));
if (!TCAM_L3_USR_CLASS_VALID(class)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_ip_usr_cls_set:"
" Invalid class %d \n",
class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
offset = GET_TCAM_CLASS_OFFSET(class);
ip_cls_cfg.bits.ldw.pid = proto;
ip_cls_cfg.bits.ldw.ipver = ver;
ip_cls_cfg.bits.ldw.tos = tos;
ip_cls_cfg.bits.ldw.tosmask = tos_mask;
ip_cls_cfg.bits.ldw.valid = 0;
REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_ip_usr_cls_set_iptun()
* Configures the TCAM user configurable IP classes. This function sets the
* new fields that were added for IP tunneling support
*
* Input
* handle: opaque handle interpreted by the underlying OS
* class: IP Class class
* (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
* l4b0_val value of the first L4 byte to be compared
* l4b0_msk mask to apply to compare byte 0 of L4
* l4b23_val values of L4 bytes 2 and 3 to compare
* l4b23_sel set to 1 to compare L4 bytes 2 and 3.
* by default, the class is disabled until explicitly enabled
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_ip_usr_cls_set_iptun(npi_handle_t handle, tcam_class_t class,
uint8_t l4b0_val, uint8_t l4b0_msk,
uint16_t l4b23_val, uint8_t l4b23_sel)
{
uint64_t offset, val;
tcam_class_prg_ip_t ip_cls_cfg;
ASSERT(TCAM_L3_USR_CLASS_VALID(class));
if (!TCAM_L3_USR_CLASS_VALID(class)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_ip_usr_cls_set:"
" Invalid class %d \n",
class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
offset = GET_TCAM_CLASS_OFFSET(class);
REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
val = 1;
ip_cls_cfg.value |= (val << L3_UCLS_L4_MODE_SH);
val = l4b0_val;
ip_cls_cfg.value |= (val << L3_UCLS_L4B0_VAL_SH);
val = l4b0_msk;
ip_cls_cfg.value |= (val << L3_UCLS_L4B0_MASK_SH);
val = l4b23_sel;
ip_cls_cfg.value |= (val << L3_UCLS_L4B23_SEL_SH);
val = l4b23_val;
ip_cls_cfg.value |= (val << L3_UCLS_L4B23_VAL_SH);
ip_cls_cfg.bits.ldw.valid = 0;
REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_ip_usr_cls_get_iptun()
* Retrieves the IP tunneling related settings for the given TCAM user
* configurable IP classe.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* class: IP Class class
* (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
* l4b0_val value of the first L4 byte to be compared
* l4b0_msk mask to apply to compare byte 0 of L4
* l4b23_val values of L4 bytes 2 and 3 to compare
* l4b23_sel set to 1 to compare L4 bytes 2 and 3.
* by default, the class is disabled until explicitly enabled
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_ip_usr_cls_get_iptun(npi_handle_t handle, tcam_class_t class,
uint8_t *l4b0_val, uint8_t *l4b0_msk,
uint16_t *l4b23_val, uint8_t *l4b23_sel)
{
uint64_t offset;
tcam_class_prg_ip_t ip_cls_cfg;
ASSERT(TCAM_L3_USR_CLASS_VALID(class));
if (!TCAM_L3_USR_CLASS_VALID(class)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_ip_usr_cls_set:"
" Invalid class %d \n",
class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
offset = GET_TCAM_CLASS_OFFSET(class);
REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
*l4b0_val = (ip_cls_cfg.value >> L3_UCLS_L4B0_VAL_SH) &
L3_UCLS_L4B0_VAL_MSK;
*l4b0_msk = (ip_cls_cfg.value >> L3_UCLS_L4B0_MASK_SH) &
L3_UCLS_L4B0_MASK_MSK;
*l4b23_sel = (ip_cls_cfg.value >> L3_UCLS_L4B23_SEL_SH) &
L3_UCLS_L4B23_SEL_MSK;
*l4b23_val = (ip_cls_cfg.value >> L3_UCLS_L4B23_VAL_SH) &
L3_UCLS_L4B23_VAL_MSK;
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_ip_usr_cls_enable()
* Enable previously configured TCAM user configurable IP classes.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* class: IP Class class
* (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_ip_usr_cls_enable(npi_handle_t handle, tcam_class_t class)
{
uint64_t offset;
tcam_class_prg_ip_t ip_cls_cfg;
ASSERT(TCAM_L3_USR_CLASS_VALID(class));
if (!TCAM_L3_USR_CLASS_VALID(class)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_ip_usr_cls_enable:"
" Invalid class %d \n",
class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
offset = GET_TCAM_CLASS_OFFSET(class);
REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
ip_cls_cfg.bits.ldw.valid = 1;
REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_ip_usr_cls_disable()
* Disables previously configured TCAM user configurable IP classes.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* class: IP Class class
* (TCAM_CLASS_IP_USER_4 <= class <= TCAM_CLASS_IP_USER_7)
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_ip_usr_cls_disable(npi_handle_t handle, tcam_class_t class)
{
uint64_t offset;
tcam_class_prg_ip_t ip_cls_cfg;
ASSERT(TCAM_L3_USR_CLASS_VALID(class));
if (!TCAM_L3_USR_CLASS_VALID(class)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_ip_usr_cls_disable:"
" Invalid class %d \n",
class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
offset = GET_TCAM_CLASS_OFFSET(class);
REG_PIO_READ64(handle, offset, &ip_cls_cfg.value);
ip_cls_cfg.bits.ldw.valid = 0;
REG_PIO_WRITE64(handle, offset, ip_cls_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_ip_cls_tcam_key ()
*
* Configures the TCAM key generation for the IP classes
*
* Input
* handle: opaque handle interpreted by the underlying OS
* l3_class: IP class to configure key generation
* cfg: Configuration bits:
* discard: Discard all frames of this class
* use_ip_saddr: use ip src address (for ipv6)
* use_ip_daddr: use ip dest address (for ipv6)
* lookup_enable: Enable Lookup
*
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_ip_cls_tcam_key(npi_handle_t handle,
tcam_class_t l3_class, tcam_key_cfg_t *cfg)
{
uint64_t offset;
tcam_class_key_ip_t tcam_cls_cfg;
ASSERT(TCAM_L3_CLASS_VALID(l3_class));
if (!(TCAM_L3_CLASS_VALID(l3_class))) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_ip_cls_tcam_key:"
" Invalid class %d \n",
l3_class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
if ((cfg->use_ip_daddr) &&
(cfg->use_ip_saddr == cfg->use_ip_daddr)) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_ip_cls_tcam_key:"
" Invalid configuration %x for class %d \n",
*cfg, l3_class));
return (NPI_FFLP_SW_PARAM_ERROR);
}
offset = GET_TCAM_KEY_OFFSET(l3_class);
tcam_cls_cfg.value = 0;
if (cfg->discard) {
tcam_cls_cfg.bits.ldw.discard = 1;
}
if (cfg->use_ip_saddr) {
tcam_cls_cfg.bits.ldw.ipaddr = 1;
}
if (cfg->use_ip_daddr) {
tcam_cls_cfg.bits.ldw.ipaddr = 0;
}
if (cfg->lookup_enable) {
tcam_cls_cfg.bits.ldw.tsel = 1;
}
REG_PIO_WRITE64(handle, offset, tcam_cls_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_ip_cls_flow_key ()
*
* Configures the flow key generation for the IP classes
* Flow key is used to generate the H1 hash function value
* The fields used for the generation are configured using this
* NPI function.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* l3_class: IP class to configure flow key generation
* cfg: Configuration bits:
* use_proto: Use IP proto field
* use_dport: use l4 destination port
* use_sport: use l4 source port
* ip_opts_exist: IP Options Present
* use_daddr: use ip dest address
* use_saddr: use ip source address
* use_vlan: use VLAN ID
* use_l2da: use L2 Dest MAC Address
* use_portnum: use L2 virtual port number
*
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_ip_cls_flow_key(npi_handle_t handle, tcam_class_t l3_class,
flow_key_cfg_t *cfg)
{
uint64_t offset;
flow_class_key_ip_t flow_cfg_reg;
ASSERT(TCAM_L3_CLASS_VALID(l3_class));
if (!(TCAM_L3_CLASS_VALID(l3_class))) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_ip_cls_flow_key:"
" Invalid class %d \n",
l3_class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
offset = GET_FLOW_KEY_OFFSET(l3_class);
flow_cfg_reg.value = 0; /* default */
if (cfg->use_proto) {
flow_cfg_reg.bits.ldw.proto = 1;
}
if (cfg->use_dport) {
flow_cfg_reg.bits.ldw.l4_1 = 2;
if (cfg->ip_opts_exist)
flow_cfg_reg.bits.ldw.l4_1 = 3;
}
if (cfg->use_sport) {
flow_cfg_reg.bits.ldw.l4_0 = 2;
if (cfg->ip_opts_exist)
flow_cfg_reg.bits.ldw.l4_0 = 3;
}
if (cfg->use_daddr) {
flow_cfg_reg.bits.ldw.ipda = BIT_ENABLE;
}
if (cfg->use_saddr) {
flow_cfg_reg.bits.ldw.ipsa = BIT_ENABLE;
}
if (cfg->use_vlan) {
flow_cfg_reg.bits.ldw.vlan = BIT_ENABLE;
}
if (cfg->use_l2da) {
flow_cfg_reg.bits.ldw.l2da = BIT_ENABLE;
}
if (cfg->use_portnum) {
flow_cfg_reg.bits.ldw.port = BIT_ENABLE;
}
REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
return (NPI_SUCCESS);
}
npi_status_t
npi_fflp_cfg_ip_cls_flow_key_get(npi_handle_t handle,
tcam_class_t l3_class,
flow_key_cfg_t *cfg)
{
uint64_t offset;
flow_class_key_ip_t flow_cfg_reg;
ASSERT(TCAM_L3_CLASS_VALID(l3_class));
if (!(TCAM_L3_CLASS_VALID(l3_class))) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_ip_cls_flow_key:"
" Invalid class %d \n",
l3_class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
offset = GET_FLOW_KEY_OFFSET(l3_class);
cfg->use_proto = 0;
cfg->use_dport = 0;
cfg->use_sport = 0;
cfg->ip_opts_exist = 0;
cfg->use_daddr = 0;
cfg->use_saddr = 0;
cfg->use_vlan = 0;
cfg->use_l2da = 0;
cfg->use_portnum = 0;
REG_PIO_READ64(handle, offset, &flow_cfg_reg.value);
if (flow_cfg_reg.bits.ldw.proto) {
cfg->use_proto = 1;
}
if (flow_cfg_reg.bits.ldw.l4_1 == 2) {
cfg->use_dport = 1;
}
if (flow_cfg_reg.bits.ldw.l4_1 == 3) {
cfg->use_dport = 1;
cfg->ip_opts_exist = 1;
}
if (flow_cfg_reg.bits.ldw.l4_0 == 2) {
cfg->use_sport = 1;
}
if (flow_cfg_reg.bits.ldw.l4_0 == 3) {
cfg->use_sport = 1;
cfg->ip_opts_exist = 1;
}
if (flow_cfg_reg.bits.ldw.ipda) {
cfg->use_daddr = 1;
}
if (flow_cfg_reg.bits.ldw.ipsa) {
cfg->use_saddr = 1;
}
if (flow_cfg_reg.bits.ldw.vlan) {
cfg->use_vlan = 1;
}
if (flow_cfg_reg.bits.ldw.l2da) {
cfg->use_l2da = 1;
}
if (flow_cfg_reg.bits.ldw.port) {
cfg->use_portnum = 1;
}
NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
" npi_fflp_cfg_ip_cls_flow_get %llx \n",
flow_cfg_reg.value));
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_ip_cls_flow_key_rfnl ()
*
* Configures the flow key generation for the IP classes
* Flow key is used to generate the H1 hash function value
* The fields used for the generation are configured using this
* NPI function.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* l3_class: IP class to configure flow key generation
* cfg: Configuration bits:
* l4_xor_sel: bit field to select the L4 payload
* bytes for X-OR to get hash key.
* use_l4_md: Set to 1 for enabling L4-mode.
* use_sym: Set to 1 to use symmetric mode.
* use_proto: Use IP proto field
* use_dport: use l4 destination port
* use_sport: use l4 source port
* ip_opts_exist: IP Options Present
* use_daddr: use ip dest address
* use_saddr: use ip source address
* use_vlan: use VLAN ID
* use_l2da: use L2 Dest MAC Address
* use_portnum: use L2 virtual port number
*
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_ip_cls_flow_key_rfnl(npi_handle_t handle, tcam_class_t l3_class,
flow_key_cfg_t *cfg)
{
uint64_t offset;
flow_class_key_ip_t flow_cfg_reg;
ASSERT(TCAM_L3_CLASS_VALID_RFNL(l3_class));
if (!(TCAM_L3_CLASS_VALID_RFNL(l3_class))) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_ip_cls_flow_key_rfnl:"
" Invalid class %d \n",
l3_class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
if (l3_class == TCAM_CLASS_IPV6_FRAG) {
offset = FFLP_FLOW_KEY_IP6_FRAG_REG;
} else {
offset = GET_FLOW_KEY_OFFSET(l3_class);
}
flow_cfg_reg.value = 0;
flow_cfg_reg.bits.ldw.l4_xor = cfg->l4_xor_sel;
if (cfg->use_l4_md)
flow_cfg_reg.bits.ldw.l4_mode = 1;
if (cfg->use_sym)
flow_cfg_reg.bits.ldw.sym = 1;
if (cfg->use_proto) {
flow_cfg_reg.bits.ldw.proto = 1;
}
if (cfg->use_dport) {
flow_cfg_reg.bits.ldw.l4_1 = 2;
if (cfg->ip_opts_exist)
flow_cfg_reg.bits.ldw.l4_1 = 3;
}
if (cfg->use_sport) {
flow_cfg_reg.bits.ldw.l4_0 = 2;
if (cfg->ip_opts_exist)
flow_cfg_reg.bits.ldw.l4_0 = 3;
}
if (cfg->use_daddr) {
flow_cfg_reg.bits.ldw.ipda = BIT_ENABLE;
}
if (cfg->use_saddr) {
flow_cfg_reg.bits.ldw.ipsa = BIT_ENABLE;
}
if (cfg->use_vlan) {
flow_cfg_reg.bits.ldw.vlan = BIT_ENABLE;
}
if (cfg->use_l2da) {
flow_cfg_reg.bits.ldw.l2da = BIT_ENABLE;
}
if (cfg->use_portnum) {
flow_cfg_reg.bits.ldw.port = BIT_ENABLE;
}
REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
return (NPI_SUCCESS);
}
npi_status_t
npi_fflp_cfg_sym_ip_cls_flow_key(npi_handle_t handle, tcam_class_t l3_class,
boolean_t enable)
{
uint64_t offset;
flow_class_key_ip_t flow_cfg_reg;
ASSERT(TCAM_L3_CLASS_VALID_RFNL(l3_class));
if (!(TCAM_L3_CLASS_VALID_RFNL(l3_class))) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_sym_ip_cls_flow_key:"
" Invalid class %d \n",
l3_class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
if (l3_class == TCAM_CLASS_IPV6_FRAG) {
offset = FFLP_FLOW_KEY_IP6_FRAG_REG;
} else {
offset = GET_FLOW_KEY_OFFSET(l3_class);
}
REG_PIO_READ64(handle, offset, &flow_cfg_reg.value);
if (enable && flow_cfg_reg.bits.ldw.sym == 0) {
flow_cfg_reg.bits.ldw.sym = 1;
REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
} else if (!enable && flow_cfg_reg.bits.ldw.sym == 1) {
flow_cfg_reg.bits.ldw.sym = 0;
REG_PIO_WRITE64(handle, offset, flow_cfg_reg.value);
}
return (NPI_SUCCESS);
}
npi_status_t
npi_fflp_cfg_ip_cls_flow_key_get_rfnl(npi_handle_t handle,
tcam_class_t l3_class,
flow_key_cfg_t *cfg)
{
uint64_t offset;
flow_class_key_ip_t flow_cfg_reg;
ASSERT(TCAM_L3_CLASS_VALID_RFNL(l3_class));
if (!(TCAM_L3_CLASS_VALID_RFNL(l3_class))) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_ip_cls_flow_key_get_rfnl:"
" Invalid class %d \n",
l3_class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
if (l3_class == TCAM_CLASS_IPV6_FRAG) {
offset = FFLP_FLOW_KEY_IP6_FRAG_REG;
} else {
offset = GET_FLOW_KEY_OFFSET(l3_class);
}
cfg->l4_xor_sel = 0;
cfg->use_l4_md = 0;
cfg->use_sym = 0;
cfg->use_proto = 0;
cfg->use_dport = 0;
cfg->use_sport = 0;
cfg->ip_opts_exist = 0;
cfg->use_daddr = 0;
cfg->use_saddr = 0;
cfg->use_vlan = 0;
cfg->use_l2da = 0;
cfg->use_portnum = 0;
REG_PIO_READ64(handle, offset, &flow_cfg_reg.value);
cfg->l4_xor_sel = flow_cfg_reg.bits.ldw.l4_xor;
if (flow_cfg_reg.bits.ldw.l4_mode)
cfg->use_l4_md = 1;
if (flow_cfg_reg.bits.ldw.sym)
cfg->use_sym = 1;
if (flow_cfg_reg.bits.ldw.proto) {
cfg->use_proto = 1;
}
if (flow_cfg_reg.bits.ldw.l4_1 == 2) {
cfg->use_dport = 1;
}
if (flow_cfg_reg.bits.ldw.l4_1 == 3) {
cfg->use_dport = 1;
cfg->ip_opts_exist = 1;
}
if (flow_cfg_reg.bits.ldw.l4_0 == 2) {
cfg->use_sport = 1;
}
if (flow_cfg_reg.bits.ldw.l4_0 == 3) {
cfg->use_sport = 1;
cfg->ip_opts_exist = 1;
}
if (flow_cfg_reg.bits.ldw.ipda) {
cfg->use_daddr = 1;
}
if (flow_cfg_reg.bits.ldw.ipsa) {
cfg->use_saddr = 1;
}
if (flow_cfg_reg.bits.ldw.vlan) {
cfg->use_vlan = 1;
}
if (flow_cfg_reg.bits.ldw.l2da) {
cfg->use_l2da = 1;
}
if (flow_cfg_reg.bits.ldw.port) {
cfg->use_portnum = 1;
}
NPI_DEBUG_MSG((handle.function, NPI_FFLP_CTL,
" npi_fflp_cfg_ip_cls_flow_get %llx \n",
flow_cfg_reg.value));
return (NPI_SUCCESS);
}
npi_status_t
npi_fflp_cfg_ip_cls_tcam_key_get(npi_handle_t handle,
tcam_class_t l3_class, tcam_key_cfg_t *cfg)
{
uint64_t offset;
tcam_class_key_ip_t tcam_cls_cfg;
ASSERT(TCAM_L3_CLASS_VALID(l3_class));
if (!(TCAM_L3_CLASS_VALID(l3_class))) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_ip_cls_tcam_key_get:"
" Invalid class %d \n",
l3_class));
return (NPI_FFLP_TCAM_CLASS_INVALID);
}
offset = GET_TCAM_KEY_OFFSET(l3_class);
REG_PIO_READ64(handle, offset, &tcam_cls_cfg.value);
cfg->discard = 0;
cfg->use_ip_saddr = 0;
cfg->use_ip_daddr = 1;
cfg->lookup_enable = 0;
if (tcam_cls_cfg.bits.ldw.discard)
cfg->discard = 1;
if (tcam_cls_cfg.bits.ldw.ipaddr) {
cfg->use_ip_saddr = 1;
cfg->use_ip_daddr = 0;
}
if (tcam_cls_cfg.bits.ldw.tsel) {
cfg->lookup_enable = 1;
}
NPI_DEBUG_MSG((handle.function, NPI_CTL,
" npi_fflp_cfg_ip_cls_tcam_key_get %llx \n",
tcam_cls_cfg.value));
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_fcram_access ()
*
* Sets the ratio between the FCRAM pio and lookup access
* Input:
* handle: opaque handle interpreted by the underlying OS
* access_ratio: 0 Lookup has the highest priority
* 15 PIO has maximum possible priority
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_fcram_access(npi_handle_t handle, uint8_t access_ratio)
{
fflp_cfg_1_t fflp_cfg;
uint64_t offset;
offset = FFLP_CFG_1_REG;
if (access_ratio > 0xf) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_fcram_access:"
" Invalid access ratio %d \n",
access_ratio));
return (NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR);
}
REG_PIO_READ64(handle, offset, &fflp_cfg.value);
fflp_cfg.bits.ldw.fflpinitdone = 0;
fflp_cfg.bits.ldw.fcramratio = access_ratio;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
REG_PIO_READ64(handle, offset, &fflp_cfg.value);
fflp_cfg.bits.ldw.fflpinitdone = 1;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_tcam_access ()
*
* Sets the ratio between the TCAM pio and lookup access
* Input:
* handle: opaque handle interpreted by the underlying OS
* access_ratio: 0 Lookup has the highest priority
* 15 PIO has maximum possible priority
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_tcam_access(npi_handle_t handle, uint8_t access_ratio)
{
fflp_cfg_1_t fflp_cfg;
uint64_t offset;
offset = FFLP_CFG_1_REG;
if (access_ratio > 0xf) {
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_cfg_tcram_access:"
" Invalid access ratio %d \n",
access_ratio));
return (NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR);
}
REG_PIO_READ64(handle, offset, &fflp_cfg.value);
fflp_cfg.bits.ldw.fflpinitdone = 0;
fflp_cfg.bits.ldw.camratio = access_ratio;
/* since the cam latency is fixed, we might set it here */
fflp_cfg.bits.ldw.camlatency = TCAM_DEFAULT_LATENCY;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
REG_PIO_READ64(handle, offset, &fflp_cfg.value);
fflp_cfg.bits.ldw.fflpinitdone = 1;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_hash_h1poly()
* Initializes the H1 hash generation logic.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* init_value: The initial value (seed)
*
* Return
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_hash_h1poly(npi_handle_t handle, uint32_t init_value)
{
hash_h1poly_t h1_cfg;
uint64_t offset;
offset = FFLP_H1POLY_REG;
h1_cfg.value = 0;
h1_cfg.bits.ldw.init_value = init_value;
REG_PIO_WRITE64(handle, offset, h1_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_hash_h2poly()
* Initializes the H2 hash generation logic.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* init_value: The initial value (seed)
*
* Return
* NPI_SUCCESS
*
*/
npi_status_t
npi_fflp_cfg_hash_h2poly(npi_handle_t handle, uint16_t init_value)
{
hash_h2poly_t h2_cfg;
uint64_t offset;
offset = FFLP_H2POLY_REG;
h2_cfg.value = 0;
h2_cfg.bits.ldw.init_value = init_value;
REG_PIO_WRITE64(handle, offset, h2_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_fflp_cfg_reset
* Initializes the FCRAM reset sequence.
*
* Input
* handle: opaque handle interpreted by the underlying OS
* strength: FCRAM Drive strength
* strong, weak or normal
* HW recommended value:
* qs: FCRAM QS mode selection
* qs mode or free running
* HW recommended value is:
*
* Return:
* NPI success/failure status code
*/
npi_status_t
npi_fflp_cfg_fcram_reset(npi_handle_t handle,
fflp_fcram_output_drive_t strength, fflp_fcram_qs_t qs)
{
fflp_cfg_1_t fflp_cfg;
uint64_t offset;
offset = FFLP_CFG_1_REG;
/* These bits have to be configured before FCRAM reset is issued */
fflp_cfg.value = 0;
fflp_cfg.bits.ldw.pio_fio_rst = 1;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
NXGE_DELAY(5); /* TODO: What is the correct delay? */
fflp_cfg.bits.ldw.pio_fio_rst = 0;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
fflp_cfg.bits.ldw.fcramqs = qs;
fflp_cfg.bits.ldw.fcramoutdr = strength;
fflp_cfg.bits.ldw.fflpinitdone = 1;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
return (NPI_SUCCESS);
}
npi_status_t
npi_fflp_cfg_init_done(npi_handle_t handle)
{
fflp_cfg_1_t fflp_cfg;
uint64_t offset;
offset = FFLP_CFG_1_REG;
REG_PIO_READ64(handle, offset, &fflp_cfg.value);
fflp_cfg.bits.ldw.fflpinitdone = 1;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
return (NPI_SUCCESS);
}
npi_status_t
npi_fflp_cfg_init_start(npi_handle_t handle)
{
fflp_cfg_1_t fflp_cfg;
uint64_t offset;
offset = FFLP_CFG_1_REG;
REG_PIO_READ64(handle, offset, &fflp_cfg.value);
fflp_cfg.bits.ldw.fflpinitdone = 0;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
return (NPI_SUCCESS);
}
/*
* Enables the TCAM search function.
*
*/
npi_status_t
npi_fflp_cfg_tcam_enable(npi_handle_t handle)
{
fflp_cfg_1_t fflp_cfg;
uint64_t offset;
offset = FFLP_CFG_1_REG;
REG_PIO_READ64(handle, offset, &fflp_cfg.value);
fflp_cfg.bits.ldw.tcam_disable = 0;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
return (NPI_SUCCESS);
}
/*
* Disables the TCAM search function.
* While the TCAM is in disabled state, all TCAM matches would return NO_MATCH
*
*/
npi_status_t
npi_fflp_cfg_tcam_disable(npi_handle_t handle)
{
fflp_cfg_1_t fflp_cfg;
uint64_t offset;
offset = FFLP_CFG_1_REG;
REG_PIO_READ64(handle, offset, &fflp_cfg.value);
fflp_cfg.bits.ldw.tcam_disable = 1;
REG_PIO_WRITE64(handle, offset, fflp_cfg.value);
return (NPI_SUCCESS);
}
/*
* npi_rxdma_event_mask_config():
* This function is called to operate on the event mask
* register which is used for generating interrupts
* and status register.
*/
npi_status_t
npi_fflp_event_mask_config(npi_handle_t handle, io_op_t op_mode,
fflp_event_mask_cfg_t *mask_cfgp)
{
int status = NPI_SUCCESS;
fflp_err_mask_t mask_reg;
switch (op_mode) {
case OP_GET:
REG_PIO_READ64(handle, FFLP_ERR_MSK_REG, &mask_reg.value);
*mask_cfgp = mask_reg.value & FFLP_ERR_MASK_ALL;
break;
case OP_SET:
mask_reg.value = (~(*mask_cfgp) & FFLP_ERR_MASK_ALL);
REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, mask_reg.value);
break;
case OP_UPDATE:
REG_PIO_READ64(handle, FFLP_ERR_MSK_REG, &mask_reg.value);
mask_reg.value |= (~(*mask_cfgp) & FFLP_ERR_MASK_ALL);
REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, mask_reg.value);
break;
case OP_CLEAR:
mask_reg.value = FFLP_ERR_MASK_ALL;
REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, mask_reg.value);
break;
default:
NPI_ERROR_MSG((handle.function, NPI_ERR_CTL,
" npi_fflp_event_mask_config",
" eventmask <0x%x>", op_mode));
return (NPI_FFLP_ERROR | NPI_FFLP_SW_PARAM_ERROR);
}
return (status);
}
/*
* Read vlan error bits
*/
void
npi_fflp_vlan_error_get(npi_handle_t handle, p_vlan_par_err_t p_err)
{
REG_PIO_READ64(handle, FFLP_VLAN_PAR_ERR_REG, &p_err->value);
}
/*
* clear vlan error bits
*/
void
npi_fflp_vlan_error_clear(npi_handle_t handle)
{
vlan_par_err_t p_err;
p_err.value = 0;
p_err.bits.ldw.m_err = 0;
p_err.bits.ldw.err = 0;
REG_PIO_WRITE64(handle, FFLP_ERR_MSK_REG, p_err.value);
}
/*
* Read TCAM error bits
*/
void
npi_fflp_tcam_error_get(npi_handle_t handle, p_tcam_err_t p_err)
{
REG_PIO_READ64(handle, FFLP_TCAM_ERR_REG, &p_err->value);
}
/*
* clear TCAM error bits
*/
void
npi_fflp_tcam_error_clear(npi_handle_t handle)
{
tcam_err_t p_err;
p_err.value = 0;
p_err.bits.ldw.p_ecc = 0;
p_err.bits.ldw.mult = 0;
p_err.bits.ldw.err = 0;
REG_PIO_WRITE64(handle, FFLP_TCAM_ERR_REG, p_err.value);
}
/*
* Read FCRAM error bits
*/
void
npi_fflp_fcram_error_get(npi_handle_t handle,
p_hash_tbl_data_log_t p_err, uint8_t partition)
{
uint64_t offset;
offset = FFLP_HASH_TBL_DATA_LOG_REG + partition * 8192;
REG_PIO_READ64(handle, offset, &p_err->value);
}
/*
* clear FCRAM error bits
*/
void
npi_fflp_fcram_error_clear(npi_handle_t handle, uint8_t partition)
{
hash_tbl_data_log_t p_err;
uint64_t offset;
p_err.value = 0;
p_err.bits.ldw.pio_err = 0;
offset = FFLP_HASH_TBL_DATA_LOG_REG + partition * 8192;
REG_PIO_WRITE64(handle, offset,
p_err.value);
}
/*
* Read FCRAM lookup error log1 bits
*/
void
npi_fflp_fcram_error_log1_get(npi_handle_t handle,
p_hash_lookup_err_log1_t log1)
{
REG_PIO_READ64(handle, HASH_LKUP_ERR_LOG1_REG,
&log1->value);
}
/*
* Read FCRAM lookup error log2 bits
*/
void
npi_fflp_fcram_error_log2_get(npi_handle_t handle,
p_hash_lookup_err_log2_t log2)
{
REG_PIO_READ64(handle, HASH_LKUP_ERR_LOG2_REG,
&log2->value);
}