diff options
Diffstat (limited to 'usr/src/uts/common/io/nxge/npi/npi_fflp.c')
-rw-r--r-- | usr/src/uts/common/io/nxge/npi/npi_fflp.c | 2720 |
1 files changed, 2720 insertions, 0 deletions
diff --git a/usr/src/uts/common/io/nxge/npi/npi_fflp.c b/usr/src/uts/common/io/nxge/npi/npi_fflp.c new file mode 100644 index 0000000000..5cce5f8d9b --- /dev/null +++ b/usr/src/uts/common/io/nxge/npi/npi_fflp.c @@ -0,0 +1,2720 @@ +/* + * 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 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#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_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_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_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); +} |