root/usr/src/uts/common/io/bnxe/577xx/drivers/common/lm/device/lm_hw_attn.c
/*******************************************************************************
 * 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 2014 QLogic Corporation
 * The contents of this file are subject to the terms of the
 * QLogic End User License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the License at
 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
 * QLogic_End_User_Software_License.txt
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 *
 * Module Description:
 *      This file contains functions that handle HW and FW attention
 *
 ******************************************************************************/

#include "lm5710.h"
#include "general_atten_bits.h"
#include "aeu_inputs.h"
#include "command.h"

static INLINE void lm_inc_er_debug_idx(lm_device_t * pdev)
{
    pdev->debug_info.curr_er_debug_idx++;
    if (pdev->debug_info.curr_er_debug_idx == MAX_ER_DEBUG_ENTRIES)
    {
        pdev->debug_info.curr_er_debug_idx=0;
    }
}

/**
 * @description
 *      called from attention handling routines, checks if the
 *      attention received is an error which is recoverable via
 *      process kill. If error recovery is disabled this
 *      function always returns FALSE;
 *
 * @param pdev
 * @param attn_sig : values of the after_invert registers read
 *                 in the misc that indicate which attention
 *                 occured
 *
 *
 * @return u8_t TRUE: attention requires process_kill. FALSE o/w
 */
u8_t lm_recoverable_error(lm_device_t *pdev, u32_t * attn_sig, u32_t arr_size)
{
    lm_er_debug_info_t * debug_info = NULL;
    u32_t                i;

    if (!pdev->params.enable_error_recovery || CHIP_IS_E1x(pdev))
    {
        return FALSE;
    }

    ASSERT_STATIC(ARRSIZE(debug_info->attn_sig) >= MAX_ATTN_REGS);
    DbgBreakIf(arr_size < MAX_ATTN_REGS);

    if ((attn_sig[0] & HW_PRTY_ASSERT_SET_0) || (attn_sig[1] & HW_PRTY_ASSERT_SET_1) ||
        (attn_sig[2] & HW_PRTY_ASSERT_SET_2) || (attn_sig[3] & HW_PRTY_ASSERT_SET_3))
    {
        /* Parity Error... Assuming we only enable parities we can deal with
         * this is a recoverable error...
         */
        debug_info = &((pdev)->debug_info.er_debug_info[pdev->debug_info.curr_er_debug_idx]);
        for (i = 0; i < arr_size; i++)
        {
            debug_info->attn_sig[i] = attn_sig[i];
        }
        lm_inc_er_debug_idx(pdev);

        /* TODO: maybe get GRCDump here in the future... */
        DbgMessage(pdev, FATAL, "lm_recoverable_error: funcid:%d, 0:0x%x, 0:0x%x, 0:0x%x, 0:0x%x\n",
                   ABS_FUNC_ID(pdev), attn_sig[0], attn_sig[1], attn_sig[2], attn_sig[3]);

        return TRUE;
    }

    /* HW Attentions (other than parity ) */
    if (attn_sig[1] & HW_INTERRUT_ASSERT_SET_1)
    {
        /* QM Interrupt is recoverable */
        if (attn_sig[1] & AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT)
        {
            debug_info = &((pdev)->debug_info.er_debug_info[pdev->debug_info.curr_er_debug_idx]);
            for (i = 0; i < arr_size; i++)
            {
                debug_info->attn_sig[i] = attn_sig[i];
            }
            lm_inc_er_debug_idx(pdev);

            DbgMessage(pdev, FATAL, "lm_recoverable_error: funcid:%d, 0:0x%x, 0:0x%x, 0:0x%x, 0:0x%x\n",
                   ABS_FUNC_ID(pdev), attn_sig[0], attn_sig[1], attn_sig[2], attn_sig[3]);
            return TRUE;
        }

    }

    if (attn_sig[3] & EVEREST_GEN_ATTN_IN_USE_MASK)
    {
        if ( GENERAL_ATTEN_OFFSET(ERROR_RECOVERY_ATTENTION_BIT) & attn_sig[3])
        {
            debug_info = &((pdev)->debug_info.er_debug_info[pdev->debug_info.curr_er_debug_idx]);
            for (i = 0; i < arr_size; i++)
            {
                debug_info->attn_sig[i] = attn_sig[i];
            }
            lm_inc_er_debug_idx(pdev);

            DbgMessage(pdev, FATAL, "lm_recoverable_error: funcid:%d, 0:0x%x, 0:0x%x, 0:0x%x, 0:0x%x\n",
                   ABS_FUNC_ID(pdev), attn_sig[0], attn_sig[1], attn_sig[2], attn_sig[3]);
            return TRUE;
        }
    }

    return FALSE;
}

void enable_blocks_attention(struct _lm_device_t *pdev)
{
    u32_t val = 0;

    REG_WR(pdev,PXP_REG_PXP_INT_MASK_0,0);
    if (!CHIP_IS_E1x(pdev))
    {
        REG_WR(pdev,PXP_REG_PXP_INT_MASK_1, (PXP_PXP_INT_MASK_1_REG_HST_INCORRECT_ACCESS
                                             | PXP_PXP_INT_MASK_1_REG_HST_VF_DISABLED_ACCESS /*Temporary solution*/
                                             | PXP_PXP_INT_MASK_1_REG_HST_PERMISSION_VIOLATION) /*Win8 MMIO (security test)???*/);
    }
    REG_WR(pdev,DORQ_REG_DORQ_INT_MASK,0);
    /* CFC_REG_CFC_INT_MASK see in init_cfc_common */


    //mask read length error interrupts in brb for parser (parsing unit and 'checksum and crc' unit)
    //these errors are legal (PU reads fixe length and CAC can cause read length error on truncated packets)
    REG_WR(pdev,BRB1_REG_BRB1_INT_MASK ,0xFC00);

    REG_WR(pdev,QM_REG_QM_INT_MASK ,0);
    REG_WR(pdev,TM_REG_TM_INT_MASK ,0);
    REG_WR(pdev,XSDM_REG_XSDM_INT_MASK_0 ,0);
    REG_WR(pdev,XSDM_REG_XSDM_INT_MASK_1 ,0);
    REG_WR(pdev,XCM_REG_XCM_INT_MASK ,0);
    //REG_WR(pdev,XSEM_REG_XSEM_INT_MASK_0 ,0);
    //REG_WR(pdev,XSEM_REG_XSEM_INT_MASK_1 ,0);
    REG_WR(pdev,USDM_REG_USDM_INT_MASK_0 ,0);
    REG_WR(pdev,USDM_REG_USDM_INT_MASK_1 ,0);
    REG_WR(pdev,UCM_REG_UCM_INT_MASK ,0);
    //REG_WR(pdev,USEM_REG_USEM_INT_MASK_0 ,0);
    //REG_WR(pdev,USEM_REG_USEM_INT_MASK_1 ,0);
    REG_WR(pdev,GRCBASE_UPB+PB_REG_PB_INT_MASK ,0);
    REG_WR(pdev,CSDM_REG_CSDM_INT_MASK_0 ,0);
    REG_WR(pdev,CSDM_REG_CSDM_INT_MASK_1 ,0);
    REG_WR(pdev,CCM_REG_CCM_INT_MASK ,0);
    //REG_WR(pdev,CSEM_REG_CSEM_INT_MASK_0 ,0);
    //REG_WR(pdev,CSEM_REG_CSEM_INT_MASK_1 ,0);
    val = PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT  |
          PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF |
          PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN;
    if (!CHIP_IS_E1x(pdev))
    {
        val |= PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED |
               PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED;
    }
    REG_WR(pdev, PXP2_REG_PXP2_INT_MASK_0, val);

    REG_WR(pdev,TSDM_REG_TSDM_INT_MASK_0 ,0);
    REG_WR(pdev,TSDM_REG_TSDM_INT_MASK_1 ,0);
    REG_WR(pdev,TCM_REG_TCM_INT_MASK ,0);
    //REG_WR(pdev,TSEM_REG_TSEM_INT_MASK_0 ,0);
    //REG_WR(pdev,TSEM_REG_TSEM_INT_MASK_1 ,0);
    REG_WR(pdev,CDU_REG_CDU_INT_MASK ,0);
    REG_WR(pdev,DMAE_REG_DMAE_INT_MASK ,0);
    //REG_WR(pdev,GRCBASE_MISC+MISC_REGISTERS_MISC_INT_MASK ,0);
    //MASK BIT 3,4
    REG_WR(pdev,PBF_REG_PBF_INT_MASK ,0X18);

}

void disable_blocks_attention(struct _lm_device_t *pdev)
{
#define MASK_VALUE_GENERATE(_val) ((u32_t)((((u64_t)0x1)<<_val)-1))
    typedef struct _block_mask_info_t
    {
        u32_t reg_offset;    /* the register offset */
        u32_t mask_value[3]; /* the mask value per hw (e1 =0 /e1.5 = 1/e2 = 2)*/
    } block_mask_info_t;

    u8_t  chip_idx   = 0;
    u32_t mask_idx   = 0;
    u32_t val        = 0;
    u32_t offset     = 0;
    u32_t mask_value = 0;

    static const block_mask_info_t init_mask_values_arr[] =
    {
        { ATC_REG_ATC_INT_MASK,           { 0,
                                            0,
                                            6 } },

        { BRB1_REG_BRB1_INT_MASK,         { 19,
                                            19,
                                            19} },

        { CCM_REG_CCM_INT_MASK,           { 11,
                                            11,
                                            11 } },

        { CDU_REG_CDU_INT_MASK,           { 7,
                                            7,
                                            7 } },

        { CFC_REG_CFC_INT_MASK,           { 2,
                                            2,
                                            2  } },

        { CSDM_REG_CSDM_INT_MASK_0,       { 32,
                                            32,
                                            32 } },

        { CSDM_REG_CSDM_INT_MASK_1,       { 10,
                                            10,
                                            11 } },

#if 0
        { CSEM_REG_CSEM_INT_MASK_0,       { 32,
                                            32,
                                            32 } },

        { CSEM_REG_CSEM_INT_MASK_1,       { 10,
                                            11,
                                            11} },

        { DBG_REG_DBG_INT_MASK,           { 2,
                                            2,
                                            2 } },
#endif //0

        { DMAE_REG_DMAE_INT_MASK,         { 2,
                                            2,
                                            2 } },

        { DORQ_REG_DORQ_INT_MASK,         { 5,
                                            5,
                                            6 } },
#if 0
        { HC_REG_HC_INT_MASK,             { 7,
                                            7,
                                            7 } },
#endif //0

        { IGU_REG_IGU_INT_MASK,           { 0,
                                            0,
                                            11 } },
#if 0
        { MISC_REGISTERS_MISC_INT_MASK,   { 4,
                                            4,
                                            8 } },

        { NIG_REGISTERS_NIG_INT_MASK_0,   { 32,
                                            32,
                                            32 } },

        { NIG_REGISTERS_NIG_INT_MASK_1,   { 2,
                                            4,
                                            14 } },

        { PB_REGISTERS_PB_INT_MASK,       { 2,
                                            2,
                                            2} },
#endif // 0

        { PBF_REG_PBF_INT_MASK,           { 5,
                                            5,
                                            7 } },

        { PGLUE_B_REG_PGLUE_B_INT_MASK,   { 0,
                                            0,
                                            9 } },
#if 0
        { PRS_REG_PRS_INT_MASK,           { 1,
                                            1,
                                            1 } },
#endif // 0

        { PXP2_REG_PXP2_INT_MASK_0,       { 25,
                                            32,
                                            32 } },

#if 0
        { PXP2_REG_PXP2_INT_MASK_1,       { 0,
                                            6,
                                            16} },
#endif //0

        { PXP_REG_PXP_INT_MASK_0,         { 32,
                                            32,
                                            32 } },

        { PXP_REG_PXP_INT_MASK_1,         { 5,
                                            5,
                                            8 } },

        { QM_REG_QM_INT_MASK,             { 2,
                                            2,
                                            14 } },
#if 0
        { SEM_FAST_REG_SEM_FAST_INT_MASK, { 1, // This offset is actually 4 different registers (per SEM)
                                            1,
                                            1} },

        { SRC_REG_SRC_INT_MASK,           { 1,
                                            3,
                                            3 } },
#endif //0

        { TCM_REG_TCM_INT_MASK,           { 11,
                                            11,
                                            11 } },

        { TM_REG_TM_INT_MASK,             { 1,
                                            1,
                                            1} },

        { TSDM_REG_TSDM_INT_MASK_0,       { 32,
                                            32,
                                            32 } },

        { TSDM_REG_TSDM_INT_MASK_1,       { 10,
                                            10,
                                            11 } },
#if 0
        { TSEM_REG_TSEM_INT_MASK_0,       { 32,
                                            32,
                                            32 } },

        { TSEM_REG_TSEM_INT_MASK_1,       { 10,
                                            11,
                                            13 } },
#endif // 0

        { UCM_REG_UCM_INT_MASK,           { 11,
                                            11,
                                            11} },

        { USDM_REG_USDM_INT_MASK_0,       { 32,
                                            32,
                                            32 } },

        { USDM_REG_USDM_INT_MASK_1,       { 10,
                                            10,
                                            11 } },
#if 0
        { USEM_REG_USEM_INT_MASK_0,       { 32,
                                            32,
                                            32 } },

        { USEM_REG_USEM_INT_MASK_1,       { 10,
                                            11,
                                            11 } },
#endif //0

        { VFC_REG_VFC_INT_MASK,           { 0,
                                            0,
                                            1 } },

        { XCM_REG_XCM_INT_MASK,           { 14,
                                            14,
                                            14 } },

        { XSDM_REG_XSDM_INT_MASK_0,       { 32,
                                            32,
                                            32 } },

        { XSDM_REG_XSDM_INT_MASK_1,       { 10,
                                            10,
                                            11} },
#if 0
        { XSEM_REG_XSEM_INT_MASK_0,      { 32,
                                           32,
                                           32 } },

        { XSEM_REG_XSEM_INT_MASK_1,      { 10,
                                           11,
                                           13 } } ,
#endif // 0
    }; // init_mask_values_arr

    if (IS_VFDEV(pdev)) 
    {
        return;
    }
    if CHIP_IS_E1( pdev )
    {
        chip_idx = 0; // E1.0
    }
    else if CHIP_IS_E1H(pdev)
    {
        chip_idx = 1; // E1.5
    }
    else if CHIP_IS_E2E3(pdev)
    {
        chip_idx = 2; // E2
    }
    else
    {
        // New chip!!!
        DbgBreakIf(1); // E??
    }

    DbgBreakIf( chip_idx >= ARRSIZE( init_mask_values_arr[0].mask_value ) );

    for( mask_idx = 0; mask_idx < ARRSIZE(init_mask_values_arr);  mask_idx++ )
    {
        mask_value = init_mask_values_arr[mask_idx].mask_value[chip_idx] ;

        if( mask_value )
        {
            val        = MASK_VALUE_GENERATE(mask_value);
            offset     = init_mask_values_arr[mask_idx].reg_offset;
            REG_WR(pdev, offset, val );
        }
    }
    /*

    REG_WR(pdev,PXP_REG_PXP_INT_MASK_0,0xffffffff);
    if (IS_E2(pdev)) {
        REG_WR(pdev,PXP_REG_PXP_INT_MASK_1,0xff);
    } else {
    REG_WR(pdev,PXP_REG_PXP_INT_MASK_1,0x1f);
    }
    REG_WR(pdev,DORQ_REG_DORQ_INT_MASK,0x1f);
    REG_WR(pdev,CFC_REG_CFC_INT_MASK ,0x3);
    REG_WR(pdev,QM_REG_QM_INT_MASK ,0x3);
    REG_WR(pdev,TM_REG_TM_INT_MASK ,0x1);
    REG_WR(pdev,XSDM_REG_XSDM_INT_MASK_0 ,0xffffffff);
    REG_WR(pdev,XSDM_REG_XSDM_INT_MASK_1 ,0x3ff);
    REG_WR(pdev,XCM_REG_XCM_INT_MASK,0x3fff);
    //REG_WR(pdev,XSEM_REG_XSEM_INT_MASK_0 ,0);
    //REG_WR(pdev,XSEM_REG_XSEM_INT_MASK_1 ,0);
    REG_WR(pdev,USDM_REG_USDM_INT_MASK_0 ,0xffffffff);
    REG_WR(pdev,USDM_REG_USDM_INT_MASK_1 ,0x3ff);
    REG_WR(pdev,UCM_REG_UCM_INT_MASK ,0x7ff);
    //REG_WR(pdev,USEM_REG_USEM_INT_MASK_0 ,0);
    //REG_WR(pdev,USEM_REG_USEM_INT_MASK_1 ,0);
    REG_WR(pdev,GRCBASE_UPB+PB_REG_PB_INT_MASK ,0x3);
    REG_WR(pdev,CSDM_REG_CSDM_INT_MASK_0 ,0xffffffff);
    REG_WR(pdev,CSDM_REG_CSDM_INT_MASK_1 ,0x3ff);
    REG_WR(pdev,CCM_REG_CCM_INT_MASK ,0x7ff);
    //REG_WR(pdev,CSEM_REG_CSEM_INT_MASK_0 ,0);
    //REG_WR(pdev,CSEM_REG_CSEM_INT_MASK_1 ,0);

    REG_WR(pdev,PXP2_REG_PXP2_INT_MASK_0,0xffffffff);

    REG_WR(pdev,TSDM_REG_TSDM_INT_MASK_0 ,0xffffffff);
    REG_WR(pdev,TSDM_REG_TSDM_INT_MASK_1 ,0x3ff);
    REG_WR(pdev,TCM_REG_TCM_INT_MASK ,0x7ff);
    //REG_WR(pdev,TSEM_REG_TSEM_INT_MASK_0 ,0);
    //REG_WR(pdev,TSEM_REG_TSEM_INT_MASK_1 ,0);
    REG_WR(pdev,CDU_REG_CDU_INT_MASK ,0x7f);
    REG_WR(pdev,DMAE_REG_DMAE_INT_MASK ,0x3);
    //REG_WR(pdev,GRCBASE_MISC+MISC_REGISTERS_MISC_INT_MASK ,0);
    //MASK BIT 3,4
    REG_WR(pdev,PBF_REG_PBF_INT_MASK ,0x1f);
    */

    // disable MCP's attentions
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_0_OUT_1,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_0_OUT_2,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_0_OUT_3,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_1_OUT_1,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_1_OUT_2,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_1_OUT_3,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_0_OUT_4,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_0_OUT_5,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_0_OUT_6,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_0_OUT_7,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_1_OUT_4,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_1_OUT_5,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_1_OUT_6,0);
    REG_WR(pdev,MISC_REG_AEU_ENABLE4_FUNC_1_OUT_7,0);
}

void lm_reset_mask_attn(struct _lm_device_t *pdev)
{
    // mask the pxp attentions
    REG_WR(pdev,PXP_REG_PXP_INT_MASK_0,0xffffffff); // 32 bits
    if (CHIP_IS_E1x(pdev))
    {
        REG_WR(pdev,PXP_REG_PXP_INT_MASK_1,0x1f); // 5 bits
    }
    else
    {
        REG_WR(pdev,PXP_REG_PXP_INT_MASK_1,0xff); // 8 bits
    }
    REG_WR(pdev,PXP2_REG_PXP2_INT_MASK_0,0xffffffff); // 32 bits

    /* We never unmask this register so no need to re-mask it*/
    //REG_WR(pdev,PXP2_REG_PXP2_INT_MASK_1,0x3f); // 32 bits
}

static void lm_latch_attn_everest_processing(lm_device_t *pdev, u32_t sig_word_aft_inv)
{
    u32_t latch_bit_to_clr = 0;
    u32_t val              = 0;
    u32_t offset           = 0;

    //pass over all latched attentions
    offset = GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCR);
    if ( offset & sig_word_aft_inv)
    {
        latch_bit_to_clr = 0x1;
        REG_WR(pdev, MISC_REG_AEU_CLR_LATCH_SIGNAL, latch_bit_to_clr);
        DbgMessage(pdev, FATAL, "lm_latch_attn_everest_processing: LATCHED_ATTN_RBCR received!!!\n");
        DbgBreakIfAll(1);
    }
    offset = GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCT);
    if ( offset & sig_word_aft_inv)
    {
        latch_bit_to_clr = 0x2;
        REG_WR(pdev, MISC_REG_AEU_CLR_LATCH_SIGNAL, latch_bit_to_clr);
        DbgMessage(pdev, FATAL, "lm_latch_attn_everest_processing: LATCHED_ATTN_RBCT received!!!\n");
        DbgBreakIfAll(1);
    }
    offset = GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCN);
    if ( offset & sig_word_aft_inv)
    {
        latch_bit_to_clr = 0x4;
        REG_WR(pdev, MISC_REG_AEU_CLR_LATCH_SIGNAL, latch_bit_to_clr);
        DbgMessage(pdev, FATAL, "lm_latch_attn_everest_processing: LATCHED_ATTN_RBCN received!!!\n");
        DbgBreakIfAll(1);
    }
    offset = GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCU);
    if ( offset & sig_word_aft_inv)
    {
        latch_bit_to_clr = 0x8;
        REG_WR(pdev, MISC_REG_AEU_CLR_LATCH_SIGNAL, latch_bit_to_clr);
        DbgMessage(pdev, FATAL, "lm_latch_attn_everest_processing: LATCHED_ATTN_RBCU received!!!\n");
        DbgBreakIfAll(1);
    }
    offset = GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCP);
    if ( offset & sig_word_aft_inv)
    {
        latch_bit_to_clr = 0x10;
        REG_WR(pdev, MISC_REG_AEU_CLR_LATCH_SIGNAL, latch_bit_to_clr);
        DbgMessage(pdev, FATAL, "lm_latch_attn_everest_processing: LATCHED_ATTN_RBCP received!!! \n");
        DbgBreakIfAll(1);
    }
    offset = GENERAL_ATTEN_OFFSET(LATCHED_ATTN_TIMEOUT_GRC);
    if ( offset & sig_word_aft_inv)
    {
#define GRC_TIMEOUT_MASK_ADDRESS(_val)  ( (_val)     & ((1<<19)-1)) // 0x000fffff
#define GRC_TIMEOUT_MASK_FUNCTION(_val) ( (_val>>20) & ((1<<3)-1))  // 0x00700000
#define GRC_TIMEOUT_MASK_MASTER(_val)   ( (_val>>24) & ((1<<4)-1))  // 0x0f000000

        u32_t       addr                            = 0;
        u32_t       func                            = 0;
        u32_t       master                          = 0;
        u32_t       grc_timeout_cnt                 = 0;
        u8_t        b_assert                        = TRUE;
        u8_t        b_nig_reset_called              = lm_is_nig_reset_called(pdev);
        const u32_t grc_timeout_max_ignore          = pdev->params.grc_timeout_max_ignore;

        latch_bit_to_clr = 0x20;

        // we check if nig reset was done
        if( b_nig_reset_called )
        {
            b_assert = FALSE;
        }

        if (!CHIP_IS_E1(pdev))
        {
            val    = REG_RD(pdev, MISC_REG_GRC_TIMEOUT_ATTN);
            addr   = GRC_TIMEOUT_MASK_ADDRESS(val);
            func   = GRC_TIMEOUT_MASK_FUNCTION(val);
            master = GRC_TIMEOUT_MASK_MASTER(val);

            // in non E1 we can verify it is mcp cause (due to nig probably)
            if( 2 != master ) // 2 is mcp cause
            {
                b_assert = TRUE;
            }
        }

        REG_WR(pdev, MISC_REG_AEU_CLR_LATCH_SIGNAL, latch_bit_to_clr);
        DbgMessage(pdev, FATAL, "lm_latch_attn_everest_processing: LATCHED_ATTN_TIMEOUT_GRC received!!! val=0x%08x master=0x%x func=0x%x addr=0x%xx4=0x%X)\n"
                               ,val, master, func, addr, addr*4 );

        // NOTE: we ignore b_nig_reset_called and ASSERT only according to grc_timeout_max_ignore value (default is 0x10)

        grc_timeout_cnt = lm_inc_cnt_grc_timeout_ignore(pdev, val);
        // if we are here it means we ignore the ASSERT inc counter
        if( grc_timeout_cnt >= grc_timeout_max_ignore )
        {
            b_assert = TRUE;
        }
        else
        {
            b_assert = FALSE;
        }

        if( b_assert )
        {
            DbgBreakIf(1);
        }

        if( b_nig_reset_called )
        {
            // we reset the flag (we "allow" one timeout after nig reset)
            lm_clear_nig_reset_called(pdev);
        }
    }
    offset = GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RSVD_GRC);
    if ( offset & sig_word_aft_inv)
    {
        latch_bit_to_clr = 0x40;
        REG_WR(pdev, MISC_REG_AEU_CLR_LATCH_SIGNAL, latch_bit_to_clr);
        DbgMessage(pdev, FATAL, "lm_latch_attn_everest_processing: LATCHED_ATTN_RSVD_GRC received!!!\n");
        DbgBreakIfAll(1);
    }
    offset = GENERAL_ATTEN_OFFSET(LATCHED_ATTN_ROM_PARITY_MCP);
    if ( offset & sig_word_aft_inv)
    {
        latch_bit_to_clr = 0x80;
        REG_WR(pdev, MISC_REG_AEU_CLR_LATCH_SIGNAL, latch_bit_to_clr);
        val = lm_mcp_check(pdev);
        DbgMessage(pdev, FATAL, "lm_latch_attn_everest_processing: LATCHED_ATTN_ROM_PARITY_MCP received!!!\n");
        /* For E2, at the time this code was written (e2-bringup ) the parity is (somehow) expected */
        if (CHIP_IS_E1x(pdev))
        {
            DbgBreakIfAll(1);
        }
        else
        {
            DbgBreakIf(1);
        }
    }
    offset = GENERAL_ATTEN_OFFSET(LATCHED_ATTN_UM_RX_PARITY_MCP);
    if ( offset & sig_word_aft_inv)
    {
        latch_bit_to_clr = 0x100;
        REG_WR(pdev, MISC_REG_AEU_CLR_LATCH_SIGNAL, latch_bit_to_clr);
        val = lm_mcp_check(pdev);
        DbgMessage(pdev, FATAL, "lm_latch_attn_everest_processing: LATCHED_ATTN_UM_RX_PARITY_MCP received!!!\n");
        DbgBreakIfAll(1);
    }
    offset = GENERAL_ATTEN_OFFSET(LATCHED_ATTN_UM_TX_PARITY_MCP);
    if ( offset & sig_word_aft_inv)
    {
        latch_bit_to_clr = 0x200;
        REG_WR(pdev, MISC_REG_AEU_CLR_LATCH_SIGNAL, latch_bit_to_clr);
        val = lm_mcp_check(pdev);
        DbgMessage(pdev, FATAL, "lm_latch_attn_everest_processing: LATCHED_ATTN_UM_TX_PARITY_MCP received!!!\n");
        DbgBreakIfAll(1);
    }
    offset = GENERAL_ATTEN_OFFSET(LATCHED_ATTN_SCPAD_PARITY_MCP);
    if ( offset & sig_word_aft_inv)
    {
        latch_bit_to_clr = 0x400;
        REG_WR(pdev, MISC_REG_AEU_CLR_LATCH_SIGNAL, latch_bit_to_clr);
        val = lm_mcp_check(pdev);
        DbgMessage(pdev, FATAL, "lm_latch_attn_everest_processing: LATCHED_ATTN_SCPAD_PARITY_MCP received!!!\n");
        DbgBreakIfAll(1);
    }
}

static void lm_hard_wired_processing(lm_device_t *pdev, u16_t assertion_proc_flgs)
{
    /* processing of highest 8-15 bits of 8 "hard-wired" attention signals toward IGU.
       Excluding NIG & PXP "close the gates"

       ! No need to lock here since this is an uncommon group whether there is a recovery procedure or not.

       Signal name         Bit position    SOURCE       Type        Required Destination
       -----------------------------------------------------------------------------
       NIG attention for port0  D8         NIG          Event       MCP/Driver0(PHY)
       SW timer#4 port0         D9         MISC         Event       MCP -> Ignore!
       GPIO#2 port0             D10        MISC         Event       MCP
       GPIO#3 port0             D11        MISC         Event       MCP
       GPIO#4 port0             D12        MISC         Event       MCP
       General attn1            D13        GRC mapped   Attention   MCP/Driver0/Driver1 -> ASSERT!
       General attn2            D14        GRC mapped   Attention   MCP/Driver0/Driver1 -> ASSERT!
       General attn3            D15        GRC mapped   Attention   MCP/Driver0/Driver1 -> ASSERT!
    */
    //TODO: for the required attn signals, need to "clean the hw block" (INT_STS_CLR..)
    if (PORT_ID(pdev) == 0)
    {
#if 0   // Timer 4 is being used by OCBB now
        if (assertion_proc_flgs & ATTN_SW_TIMER_4_FUNC)
        {
            //DbgMessage(pdev, FATAL, "lm_hard_wired_processing: ATTN_SW_TIMER_4_FUNC!\n");
            //to deal with this signal, add dispatch func call here
        }
#endif
        if (assertion_proc_flgs & GPIO_2_FUNC)
        {
            DbgMessage(pdev, WARN, "lm_hard_wired_processing: GPIO_1_FUNC!\n");
            //to deal with this signal, add dispatch func call here
        }
        if (assertion_proc_flgs & GPIO_3_FUNC)
        {
            DbgMessage(pdev, WARN, "lm_hard_wired_processing: GPIO_2_FUNC!\n");
            //to deal with this signal, add dispatch func call here
        }
        if (assertion_proc_flgs & GPIO_4_FUNC)
        {
        DbgMessage(pdev, WARN, "lm_hard_wired_processing: GPIO_3_FUNC0!\n");
        // Will be handled in deassertion
        }
        if (assertion_proc_flgs & ATTN_GENERAL_ATTN_1)
        {
            DbgMessage(pdev, FATAL, "lm_hard_wired_processing: ATTN_GENERAL_ATTN_1! and clean it!!!\n");
            REG_WR(pdev,MISC_REG_AEU_GENERAL_ATTN_1,0x0);
        }
        if (assertion_proc_flgs & ATTN_GENERAL_ATTN_2)
        {
            DbgMessage(pdev, FATAL, "lm_hard_wired_processing: ATTN_GENERAL_ATTN_2! and clean it!!!\n");
            REG_WR(pdev,MISC_REG_AEU_GENERAL_ATTN_2,0x0);
        }
        if (assertion_proc_flgs & ATTN_GENERAL_ATTN_3)
        {
            DbgMessage(pdev, FATAL, "lm_hard_wired_processing: ATTN_GENERAL_ATTN_3! and clean it!!!\n");
            REG_WR(pdev,MISC_REG_AEU_GENERAL_ATTN_3,0x0);
        }
    }
    else
    {
        DbgBreakIf(PORT_ID(pdev) != 1);

        if (assertion_proc_flgs & ATTN_SW_TIMER_4_FUNC1)
        {
            //DbgMessage(pdev, FATAL, "lm_hard_wired_processing: ATTN_SW_TIMER_4_FUNC1!\n");
            //to deal with this signal, add dispatch func call here
        }
        if (assertion_proc_flgs & GPIO_2_FUNC1)
        {
            DbgMessage(pdev, WARN, "lm_hard_wired_processing: GPIO_1_FUNC1!\n");
            //to deal with this signal, add dispatch func call here
        }
        if (assertion_proc_flgs & GPIO_3_FUNC1)
        {
            DbgMessage(pdev, WARN, "lm_hard_wired_processing: GPIO_2_FUNC1!\n");
            //to deal with this signal, add dispatch func call here
        }
        if (assertion_proc_flgs & GPIO_4_FUNC1)
        {
            DbgMessage(pdev, WARN, "lm_hard_wired_processing: GPIO_3_FUNC1!\n");
            // Will be handled in deassertion
        }
        if (assertion_proc_flgs & ATTN_GENERAL_ATTN_4)
        {
            DbgMessage(pdev, FATAL, "lm_hard_wired_processing: ATTN_GENERAL_ATTN_4! and clean it!!!\n");
            REG_WR(pdev,MISC_REG_AEU_GENERAL_ATTN_4,0x0);
        }
        if (assertion_proc_flgs & ATTN_GENERAL_ATTN_5)
        {
            DbgMessage(pdev, FATAL, "lm_hard_wired_processing: ATTN_GENERAL_ATTN_5! and clean it!!!\n");
            REG_WR(pdev,MISC_REG_AEU_GENERAL_ATTN_5,0x0);
        }
        if (assertion_proc_flgs & ATTN_GENERAL_ATTN_6)
        {
            DbgMessage(pdev, FATAL, "lm_hard_wired_processing: ATTN_GENERAL_ATTN_6! and clean it!!!\n");
            REG_WR(pdev,MISC_REG_AEU_GENERAL_ATTN_6,0x0);
        }
    }
}

static void lm_nig_processing(lm_device_t *pdev)
{
    u32_t nig_status_port          = 0;
    u32_t unicore_val              = 0;
    u32_t is_unicore_intr_asserted = 0;
    // save nig interrupt mask and set it back later
    lm_link_update(pdev);
    if (PORT_ID(pdev) == 0)
    {
        //read the status interrupt of the NIG for the appropriate port (will do read-modify-write)
        nig_status_port = REG_RD(pdev,  NIG_REG_STATUS_INTERRUPT_PORT0);

        //pass over each of the 24 NIG REG to find out why the NIG attention was asserted.
        //every unicore interrupt read, in case it differs from the corresponding bit in the
        //NIG_REG_STATUS_INTERRUPT_PORT0, then we need to assign the value read into the apporpriate bit
        // in NIG_REG_STATUS_INTERRUPT_PORT0 register.

        //HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_EMAC0_STATUS_MISC_MI_INT, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_EMAC0_STATUS_MISC_MI_COMPLETE, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_COMPLETE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_COMPLETE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_EMAC0_STATUS_MISC_CFG_CHANGE, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_CFG_CHANGE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_CFG_CHANGE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_EMAC0_STATUS_MISC_LINK_STATUS, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_LINK_STATUS, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_LINK_STATUS_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_EMAC0_STATUS_MISC_LINK_CHANGE, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_LINK_CHANGE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_LINK_CHANGE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_EMAC0_STATUS_MISC_ATTN, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_ATTN, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_ATTN_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES0_STATUS_MAC_CRS, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_MAC_CRS, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_MAC_CRS_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES0_STATUS_AUTONEG_COMPLETE, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_AUTONEG_COMPLETE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_AUTONEG_COMPLETE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES0_STATUS_FIBER_RXACT, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_FIBER_RXACT, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_FIBER_RXACT_SIZE);
        //HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES0_STATUS_LINK_STATUS, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES0_STATUS_MR_PAGE_RX, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_MR_PAGE_RX, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_MR_PAGE_RX_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES0_STATUS_CL73_AN_COMPLETE, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_CL73_AN_COMPLETE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_CL73_AN_COMPLETE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES0_STATUS_CL73_MR_PAGE_RX, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_CL73_MR_PAGE_RX, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_CL73_MR_PAGE_RX_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES0_STATUS_RX_SIGDET, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_RX_SIGDET, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_RX_SIGDET_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS0_STATUS_REMOTEMDIOREQ, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_REMOTEMDIOREQ, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_REMOTEMDIOREQ_SIZE);
        //HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS0_STATUS_LINK10G, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS0_STATUS_AUTONEG_COMPLETE, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_AUTONEG_COMPLETE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_AUTONEG_COMPLETE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS0_STATUS_FIBER_RXACT, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_FIBER_RXACT, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_FIBER_RXACT_SIZE);
        //HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS0_STATUS_LINK_STATUS, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS0_STATUS_MR_PAGE_RX, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_MR_PAGE_RX, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_MR_PAGE_RX_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS0_STATUS_CL73_AN_COMPLETE, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_CL73_AN_COMPLETE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_CL73_AN_COMPLETE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS0_STATUS_CL73_MR_PAGE_RX, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_CL73_MR_PAGE_RX, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_CL73_MR_PAGE_RX_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS0_STATUS_RX_SIGDET, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_RX_SIGDET, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_RX_SIGDET_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS0_STATUS_MAC_CRS, &unicore_val, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_MAC_CRS, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_MAC_CRS_SIZE);

        //write back the updated status interrupt of the NIG for the appropriate port.
        REG_WR(pdev,  NIG_REG_STATUS_INTERRUPT_PORT0, nig_status_port);
    }
    else
    {
        DbgBreakIf(PORT_ID(pdev) != 1);
        nig_status_port = REG_RD(pdev,  NIG_REG_STATUS_INTERRUPT_PORT1);

        //HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_EMAC1_STATUS_MISC_MI_INT, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_EMAC1_MISC_MI_INT, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_EMAC1_MISC_MI_INT_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_EMAC1_STATUS_MISC_MI_COMPLETE, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_EMAC1_MISC_MI_COMPLETE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_EMAC1_MISC_MI_COMPLETE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_EMAC1_STATUS_MISC_CFG_CHANGE, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_EMAC1_MISC_CFG_CHANGE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_EMAC1_MISC_CFG_CHANGE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_EMAC1_STATUS_MISC_LINK_STATUS, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_EMAC1_MISC_LINK_STATUS, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_EMAC1_MISC_LINK_STATUS_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_EMAC1_STATUS_MISC_LINK_CHANGE, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_EMAC1_MISC_LINK_CHANGE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_EMAC1_MISC_LINK_CHANGE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_EMAC1_STATUS_MISC_ATTN, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_EMAC1_MISC_ATTN, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_EMAC1_MISC_ATTN_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES1_STATUS_MAC_CRS, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_MAC_CRS, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_MAC_CRS_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES1_STATUS_AUTONEG_COMPLETE, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_AUTONEG_COMPLETE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_AUTONEG_COMPLETE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES1_STATUS_FIBER_RXACT, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_FIBER_RXACT, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_FIBER_RXACT_SIZE);
        //HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES1_STATUS_LINK_STATUS, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_LINK_STATUS, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_LINK_STATUS_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES1_STATUS_MR_PAGE_RX, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_MR_PAGE_RX, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_MR_PAGE_RX_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES1_STATUS_CL73_AN_COMPLETE, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_CL73_AN_COMPLETE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_CL73_AN_COMPLETE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES1_STATUS_CL73_MR_PAGE_RX, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_CL73_MR_PAGE_RX, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_CL73_MR_PAGE_RX_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_SERDES1_STATUS_RX_SIGDET, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_RX_SIGDET, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_SERDES1_RX_SIGDET_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS1_STATUS_REMOTEMDIOREQ, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_REMOTEMDIOREQ, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_REMOTEMDIOREQ_SIZE);
        //HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS1_STATUS_LINK10G, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_LINK10G, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_LINK10G_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS1_STATUS_AUTONEG_COMPLETE, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_AUTONEG_COMPLETE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_AUTONEG_COMPLETE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS1_STATUS_FIBER_RXACT, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_FIBER_RXACT, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_FIBER_RXACT_SIZE);
        //HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS1_STATUS_LINK_STATUS, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_LINK_STATUS, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_LINK_STATUS_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS1_STATUS_MR_PAGE_RX, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_MR_PAGE_RX, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_MR_PAGE_RX_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS1_STATUS_CL73_AN_COMPLETE, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_CL73_AN_COMPLETE, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_CL73_AN_COMPLETE_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS1_STATUS_CL73_MR_PAGE_RX, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_CL73_MR_PAGE_RX, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_CL73_MR_PAGE_RX_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS1_STATUS_RX_SIGDET, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_RX_SIGDET, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_RX_SIGDET_SIZE);
        HANDLE_UNICORE_INT_ASSERTED(pdev, NIG_REG_XGXS1_STATUS_MAC_CRS, &unicore_val, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_MAC_CRS, &nig_status_port, &is_unicore_intr_asserted, NIG_STATUS_INTERRUPT_PORT1_REG_STATUS_XGXS1_MAC_CRS_SIZE);

        REG_WR(pdev,  NIG_REG_STATUS_INTERRUPT_PORT1, nig_status_port);

    }
}

void lm_handle_assertion_processing(lm_device_t *pdev, u16_t assertion_proc_flgs)
{
    u32_t       val           = 0;
    u32_t       port_reg_name = 0;
    u32_t       mask_val      = 0;
    u32_t       nig_mask      = 0;

    DbgMessage(pdev, INFORM, "lm_handle_assertion_processing: assertion_proc_flgs:%d\n", assertion_proc_flgs);

    //mask only appropriate attention output signals from configured routing and unifier logic toward IGU.
    //This is for driver/chip sync to eventually return to '00' monitored state
    //in both leading & trailing latch.
    //mask non-hard-wired dynamic groups only

    DbgBreakIf(pdev->vars.attn_state & assertion_proc_flgs);

    //mask relevant AEU attn lines
    //             mask  assert_flgs  new mask
    //legal:        0       0       ->    0
    //              1       0       ->    1
    //              1       1       ->    0
    //ASSERT:       0       1 -> this won't change us thanks to & ~

    ASSERT_STATIC( HW_LOCK_RESOURCE_PORT0_ATT_MASK +1 == HW_LOCK_RESOURCE_PORT1_ATT_MASK );
    ASSERT_STATIC( NIG_REG_MASK_INTERRUPT_PORT0 + 4   == NIG_REG_MASK_INTERRUPT_PORT1 );

    lm_hw_lock(pdev, HW_LOCK_RESOURCE_PORT0_ATT_MASK + PORT_ID(pdev), TRUE);
    port_reg_name = PORT_ID(pdev) ? MISC_REG_AEU_MASK_ATTN_FUNC_1 : MISC_REG_AEU_MASK_ATTN_FUNC_0;
    // read the hw current mask value
    mask_val=REG_RD(pdev, port_reg_name);
    //changed rrom XOR to & ~
    pdev->vars.aeu_mask_attn_func = mask_val & 0xff;
    DbgMessage(pdev, INFORM, "lm_handle_assertion_processing: BEFORE: aeu_mask_attn_func:0x%x\n", pdev->vars.aeu_mask_attn_func);
    //changed rrom XOR to & ~
    pdev->vars.aeu_mask_attn_func &= ~(assertion_proc_flgs & 0xff);
    REG_WR(pdev, port_reg_name, pdev->vars.aeu_mask_attn_func);
    DbgMessage(pdev, INFORM, "lm_handle_assertion_processing: AFTER : aeu_mask_attn_func:0x%x\n", pdev->vars.aeu_mask_attn_func);
    lm_hw_unlock(pdev, HW_LOCK_RESOURCE_PORT0_ATT_MASK + PORT_ID(pdev));
    //update the bits states

    //        state  assert_flgs  new state
    //legal:    0       0         -> 0
    //          0       1         -> 1
    //          1       0         -> 1
    //error:    1       1 -> this won't change us thanks to |
    DbgMessage(pdev, INFORM, "lm_handle_assertion_processing: BEFORE: attn_state:0x%x\n", pdev->vars.attn_state);
    //changed from XOR to OR for safety
    pdev->vars.attn_state |= assertion_proc_flgs;

    DbgMessage(pdev, INFORM, "lm_handle_assertion_processing: AFTER : attn_state:0x%x\n", pdev->vars.attn_state);
    //process only hard-wired lines in case any got up
    if (assertion_proc_flgs & ATTN_HARD_WIRED_MASK)
    {
        lm_hard_wired_processing(pdev, assertion_proc_flgs);
    }

    // now handle nig
    if (assertion_proc_flgs & ATTN_NIG_FOR_FUNC)
    {
        MM_ACQUIRE_PHY_LOCK(pdev);
         // save nig interrupt mask and set it back later
        nig_mask = REG_RD(pdev,  NIG_REG_MASK_INTERRUPT_PORT0 + 4*PORT_ID(pdev));
        REG_WR(pdev,  NIG_REG_MASK_INTERRUPT_PORT0 + 4*PORT_ID(pdev), 0);

        // we'll handle the attention only if mask is not 0
        // if mask is 0, it means that "old" and irrelevant is sent
        // and we should not hnalde it (e.g. CQ48990 - got link down event after loopback mode was set).
        if( nig_mask )
        {
            lm_nig_processing(pdev);
        }
        else
        {
            DbgMessage(pdev, WARN, "lm_handle_deassertion_processing: got attention when nig_mask is 0\n" );
        }
    }

    //parallel write to IGU to set the attn_ack for _all asserted_ lines.
    val = assertion_proc_flgs;

    // attntion bits set
    if (INTR_BLK_TYPE(pdev) == INTR_BLK_HC)
    {
        REG_WR(pdev,  HC_REG_COMMAND_REG + PORT_ID(pdev)*32 + COMMAND_REG_ATTN_BITS_SET,val);
    }
    else
    {
        u32_t cmd_addr = IGU_CMD_ATTN_BIT_SET_UPPER;
        if (INTR_BLK_ACCESS(pdev) == INTR_BLK_ACCESS_IGUMEM)
        {
            REG_WR(pdev, BAR_IGU_INTMEM + cmd_addr*8, val);
        }
        else
        {
            struct igu_ctrl_reg cmd_ctrl;
            u8_t                igu_func_id = 0;
            /* GRC ACCESS: */
            /* Write the Data, then the control */
             /* [18:12] - FID (if VF - [18] = 0; [17:12] = VF number; if PF - [18] = 1; [17:14] = 0; [13:12] = PF number) */
            igu_func_id = IGU_FUNC_ID(pdev);
            cmd_ctrl.ctrl_data =
                ((cmd_addr << IGU_CTRL_REG_ADDRESS_SHIFT) |
                 (igu_func_id << IGU_CTRL_REG_FID_SHIFT) |
                 (IGU_CTRL_CMD_TYPE_WR << IGU_CTRL_REG_TYPE_SHIFT));

            REG_WR(pdev, IGU_REG_COMMAND_REG_32LSB_DATA, val);
            REG_WR(pdev, IGU_REG_COMMAND_REG_CTRL, cmd_ctrl.ctrl_data);
        }
    }

    // now set back the mask
    if (assertion_proc_flgs & ATTN_NIG_FOR_FUNC)
    {
        u8_t blk_type   = INTR_BLK_TYPE(pdev);
        u8_t blk_access = INTR_BLK_ACCESS(pdev);

        if ( ( blk_type != INTR_BLK_HC ) && ( blk_access == INTR_BLK_ACCESS_IGUMEM ))
        {
            u32 cnt = 0;
            // Verify that IGU ack through BAR was written before restoring NIG mask.
            // This loop should exit after 2-3 iterations max.
            do
            {
                val = REG_RD(pdev, IGU_REG_ATTENTION_ACK_BITS);
            }
            while (((val & ATTN_NIG_FOR_FUNC) == 0) && (++cnt < MAX_IGU_ATTN_ACK_TO));

            if (!val)
            {
                DbgMessage(pdev, FATAL, "Failed to verify IGU ack on time\n");
            }
        }
        REG_WR(pdev,  NIG_REG_MASK_INTERRUPT_PORT0 + 4*PORT_ID(pdev), nig_mask);
        MM_RELEASE_PHY_LOCK(pdev);
    }
}

static u32_t lm_cfc_attn_everest_processing(lm_device_t *pdev)
{
    u32_t val, valc;
    val = REG_RD(pdev,CFC_REG_CFC_INT_STS);

    // TODO add defines here
    DbgMessage(pdev, FATAL, "CFC hw attention 0x%x\n",val);
    if (val) {
        pdev->vars.cfc_int_status_cnt++;
    // CFC error attention
    if (val & 0x2)
    {
                //DbgBreakIfAll(1);
    }
}
    valc = REG_RD(pdev,CFC_REG_CFC_INT_STS_CLR);
    return val;
}
static void lm_pxp_attn_everest_processing(lm_device_t *pdev)
{
    u32_t val = REG_RD(pdev,PXP_REG_PXP_INT_STS_0);

    // TODO add defines here
    DbgMessage(pdev, FATAL, "PXP hw attention 0x%x\n",val);
    // RQ_USDMDP_FIFO_OVERFLOW attention
    if (val & 0x18000)
    {
        DbgBreakIfAll(1);
    }

}
/*
 *Function Name:lm_spio5_attn_everest_processing
 *
 *Parameters:
 *
 *Description:
 *  Indicates fan failure on specific external_phy_config (PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101)
 *Returns:
 *
 */
static void lm_spio5_attn_everest_processing(lm_device_t *pdev)
{
    u32_t      val            = 0;
    u32_t      offset         = 0;
    u32_t      ext_phy_config = 0;
    const u8_t port_id        = PORT_ID(pdev);

   // Special fan failure handling for boards with external PHY SFX7101 (which include fan)
    PHY_HW_LOCK(pdev);
    elink_hw_reset_phy(&pdev->params.link);
    PHY_HW_UNLOCK(pdev);

    offset = ( 0 == port_id ) ? MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0 : MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 ;

    val = REG_RD(pdev, offset );

    DbgMessage(pdev, FATAL, "lm_spio5_attn_everest_processing: SPIO5 hw attention 0x%x\n",val);

    // mask flags so we won't get this attention anymore
    RESET_FLAGS(val, AEU_INPUTS_ATTN_BITS_SPIO5 ) ;
    REG_WR(pdev, offset, val ) ;

    // change phy_type to type failure (under phy lock)
    MM_ACQUIRE_PHY_LOCK(pdev);

    offset = OFFSETOF(shmem_region_t,dev_info.port_hw_config[port_id].external_phy_config);

    LM_SHMEM_READ(pdev, offset, &ext_phy_config);

    RESET_FLAGS(ext_phy_config, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK ) ;
    SET_FLAGS(ext_phy_config, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE ) ;

    // Set external phy type to failure for MCP to know about the failure
    LM_SHMEM_WRITE(pdev, offset, ext_phy_config);

    DbgMessage(pdev, WARN, "lm_spio5_attn_everest_processing: external_phy_type 0x%x\n",ext_phy_config);

    // Indicate "link-down". elink_hw_reset_phy takes care of the physical part, but part of the function
    // masks attentions, which means we won't get a link event from anywhere else. Therefore we need to
    // indicate link down at this point to OS... to supress traffic and upload toe connections...
    // we do this under lock since we change the link status...
    pdev->vars.link_status = LM_STATUS_LINK_DOWN;

    mm_indicate_link(pdev, pdev->vars.link_status, pdev->vars.medium);

    MM_RELEASE_PHY_LOCK(pdev);

    // write to the event log!
    mm_event_log_generic( pdev, LM_LOG_ID_FAN_FAILURE );

    mm_indicate_hw_failure(pdev);
}

// Check current fan failure state - report in case signaled.
void lm_check_fan_failure(struct _lm_device_t *pdev)
{
    u32_t val = 0;

    if (IS_VFDEV(pdev))
    {
        return;
    }

    val = REG_RD(pdev, MISC_REG_AEU_AFTER_INVERT_1_FUNC_0 + PORT_ID(pdev)*4);

    if( GET_FLAGS(val, AEU_INPUTS_ATTN_BITS_SPIO5))
    {
        lm_spio5_attn_everest_processing(pdev);
    }
}

// Change PMF or link change
// PMF sent link updates to all func (but himself) OR I become a PMF from MCP notification
// on some cases PMF sends link event to himself as well if errors occured in the mac.
static void lm_pmf_or_link_event(lm_device_t *pdev, u32_t drv_status)
{
    u32_t val = 0;


    DbgMessage(pdev, WARN, "lm_pmf_or_link_event: sync general attention received!!! for func%d\n",FUNC_ID(pdev));

    // sync with link
    MM_ACQUIRE_PHY_LOCK(pdev);
    elink_link_status_update(&pdev->params.link,&pdev->vars.link);
    lm_link_report(pdev);
    MM_RELEASE_PHY_LOCK(pdev);

    if (!IS_PMF(pdev) && GET_FLAGS(drv_status,DRV_STATUS_PMF))
    {
        //pmf migration
        pdev->vars.is_pmf = PMF_MIGRATION;
        // load stat from MCP
        MM_ACQUIRE_PHY_LOCK(pdev);
        lm_stats_on_pmf_update(pdev,TRUE);
        MM_RELEASE_PHY_LOCK(pdev);

        // Connect to NIG attentions
        val = (0xff0f | (1 << (VNIC_ID(pdev) + 4)));
        if (INTR_BLK_TYPE(pdev) == INTR_BLK_HC)
        {
            REG_WR(pdev,  (PORT_ID(pdev) ? HC_REG_TRAILING_EDGE_1 : HC_REG_TRAILING_EDGE_0), val);
            REG_WR(pdev,  (PORT_ID(pdev) ? HC_REG_LEADING_EDGE_1  : HC_REG_LEADING_EDGE_0) , val);
        }
        else
        {
            if (CHIP_IS_E3(pdev))
            {
                val &= ~ATTN_SW_TIMER_4_FUNC; // To prevent Timer4 expiration attention
            }
            REG_WR(pdev,  IGU_REG_TRAILING_EDGE_LATCH, val);
            REG_WR(pdev,  IGU_REG_LEADING_EDGE_LATCH, val);
        }

        if(TRUE == IS_DCB_ENABLED(pdev))
        {
            lm_dcbx_pmf_migration(pdev);
        }
    }
}

static void lm_dcc_event(lm_device_t *pdev, u32_t dcc_event)
{
    u32_t       val               = 0;
    u32_t       event_val_current = 0;
    u32_t       fw_resp           = 0 ;
    lm_status_t lm_status         = LM_STATUS_FAILURE ;

    DbgMessage(pdev, WARN, "lm_dcc_event: dcc_event=0x%x\n",dcc_event);

    if( !IS_MULTI_VNIC(pdev) )
    {
        DbgBreakIf(1);
        return;
    }

    // read shemem

    // Read new mf config from shemem
    LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].config), &val);

    pdev->hw_info.mf_info.func_mf_cfg = val ;

    // is it enable/disable
    event_val_current = DRV_STATUS_DCC_DISABLE_ENABLE_PF ;

    if GET_FLAGS( dcc_event, event_val_current )
    {
        if( GET_FLAGS( pdev->hw_info.mf_info.func_mf_cfg, FUNC_MF_CFG_FUNC_DISABLED ) )
        {
            DbgMessage(pdev, WARN, "lm_dcc_event: mf_cfg function disabled val=0x%x\n",val);

            // TODO - receive packets fronm another machine when link is down - expected - miniport drop packets
            // TBD - disable RX & TX
        }
        else
        {
            DbgMessage(pdev, WARN, "lm_dcc_event: mf_cfg function enabled val=0x%x\n",val);
            // TBD - enable RX & TX
        }
        lm_status = LM_STATUS_SUCCESS ;
        RESET_FLAGS( dcc_event, event_val_current );
    }

    event_val_current = DRV_STATUS_DCC_BANDWIDTH_ALLOCATION ;

    if GET_FLAGS(dcc_event, event_val_current)
    {
        if( !IS_PMF(pdev) )
        {
            DbgBreakIf(1);
            return;
        }
        lm_status = LM_STATUS_SUCCESS ;
        RESET_FLAGS( dcc_event, event_val_current );
    }

    /* Report results to MCP */
    if (dcc_event)
    {
        // unknown event
        lm_status = lm_mcp_cmd_send_recieve( pdev, lm_mcp_mb_header, DRV_MSG_CODE_DCC_FAILURE, 0, MCP_CMD_DEFAULT_TIMEOUT, &fw_resp ) ;
    }
    else
    {
        // we are done
        if( LM_STATUS_SUCCESS == lm_status )
        {
            // sync with link --> update min max/link for all function
            MM_ACQUIRE_PHY_LOCK(pdev);
            elink_link_status_update(&pdev->params.link,&pdev->vars.link);
            lm_link_report(pdev);
            MM_RELEASE_PHY_LOCK(pdev);
        }
        lm_status = lm_mcp_cmd_send_recieve( pdev, lm_mcp_mb_header, DRV_MSG_CODE_DCC_OK, 0, MCP_CMD_DEFAULT_TIMEOUT, &fw_resp ) ;
        //bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK);
    }
    DbgBreakIf( lm_status != LM_STATUS_SUCCESS );
}

static lm_status_t lm_set_bandwidth_event(lm_device_t *pdev)
{
    u32_t       mcp_resp    = 0;
    lm_status_t lm_status   = LM_STATUS_SUCCESS;

    DbgBreakIf(!IS_SD_UFP_MODE(pdev) && (!IS_MULTI_VNIC(pdev) || !pdev->vars.is_pmf));

    MM_ACQUIRE_PHY_LOCK(pdev);

    //update CMNG data from SHMEM
    lm_reload_link_and_cmng(pdev);

    //acknoledge the MCP event
    lm_mcp_cmd_send_recieve(pdev,lm_mcp_mb_header, DRV_MSG_CODE_SET_MF_BW_ACK, 0, MCP_CMD_DEFAULT_TIMEOUT, &mcp_resp);

    if ( mcp_resp != FW_MSG_CODE_SET_MF_BW_DONE)
    {
        DbgBreakIf(mcp_resp != FW_MSG_CODE_SET_MF_BW_DONE);
        lm_status = LM_STATUS_FAILURE;
        goto _exit;
    }

    //indicate link change to OS, since sync_link_status does not generate a link event for the PMF.
    mm_indicate_link(pdev, pdev->vars.link_status, pdev->vars.medium);

    //notify all functions
    sync_link_status(pdev);

_exit:
    MM_RELEASE_PHY_LOCK(pdev);
    return lm_status;
}

typedef enum drv_info_opcode drv_info_opcode_t;

lm_status_t lm_stats_drv_info_to_mfw_event( struct _lm_device_t* pdev )
{
    u32_t              val             = 0;
    u32_t              drv_msg         = 0;
    u32_t              ver             = 0;
    u32_t              fw_resp         = 0 ;
    lm_status_t        lm_status       = LM_STATUS_SUCCESS ;
    drv_info_opcode_t  drv_info_op     = -1;

    if( !LM_SHMEM2_HAS(pdev, drv_info_control) )
    {
        // We should never get here...
        DbgBreakIfAll(!LM_SHMEM2_HAS(pdev, drv_info_control));
        return LM_STATUS_FAILURE;
    }

    LM_SHMEM2_READ(pdev, OFFSETOF(shmem2_region_t, drv_info_control), &val );

    ver = ( GET_FLAGS( val, DRV_INFO_CONTROL_VER_MASK ) ) >> DRV_INFO_CONTROL_VER_SHIFT ;

    do
    {
        if( DRV_INFO_CUR_VER != ver )
        {
            // We don't support this interface verison
            drv_msg = DRV_MSG_CODE_DRV_INFO_NACK;
            break;
        }

        drv_info_op = ( GET_FLAGS( val, DRV_INFO_CONTROL_OP_CODE_MASK ) ) >> DRV_INFO_CONTROL_OP_CODE_SHIFT;

        lm_status = lm_stats_drv_info_to_mfw_assign(pdev, drv_info_op );

        if( LM_STATUS_SUCCESS != lm_status )
        {
            // We don't support this interface verison/opcode
            drv_msg = DRV_MSG_CODE_DRV_INFO_NACK;
            break;
        }

        LM_SHMEM2_WRITE(pdev, OFFSETOF(shmem2_region_t, drv_info_host_addr_lo), pdev->vars.stats.stats_collect.drv_info_to_mfw.drv_info_to_mfw_phys_addr.as_u32.low );
        LM_SHMEM2_WRITE(pdev, OFFSETOF(shmem2_region_t, drv_info_host_addr_hi), pdev->vars.stats.stats_collect.drv_info_to_mfw.drv_info_to_mfw_phys_addr.as_u32.high );

        drv_msg = DRV_MSG_CODE_DRV_INFO_ACK;

    } while(0);

    lm_status = lm_mcp_cmd_send_recieve( pdev, lm_mcp_mb_header, drv_msg, 0, MCP_CMD_DEFAULT_TIMEOUT, &fw_resp );

    return lm_status;
}

static lm_status_t lm_ufp_pf_disable(lm_device_t *pdev)
{
    lm_status_t status        = LM_STATUS_SUCCESS;
    u32_t       mcp_resp      = 0;

    /*TODO: Have to do some processing based on fi the pF is enabled or disabled*/
    ///indicate "link-down"
    MM_ACQUIRE_PHY_LOCK(pdev);

    pdev->vars.link_status = LM_STATUS_LINK_DOWN;
    mm_indicate_link(pdev, pdev->vars.link_status, pdev->vars.medium);

    MM_RELEASE_PHY_LOCK(pdev);

    /* Report results to MCP */
    ///ACK the MCP message
    if(status == LM_STATUS_SUCCESS)
        lm_mcp_cmd_send_recieve(pdev, lm_mcp_mb_header, DRV_MSG_CODE_OEM_OK, 0, MCP_CMD_DEFAULT_TIMEOUT, &mcp_resp);
    else
        lm_mcp_cmd_send_recieve(pdev, lm_mcp_mb_header, DRV_MSG_CODE_OEM_FAILURE, 0, MCP_CMD_DEFAULT_TIMEOUT, &mcp_resp);

    DbgBreakIf(mcp_resp != FW_MSG_CODE_OEM_ACK);
    return status;
}

static void lm_ufp_pf_enable(lm_device_t *pdev)
{
    lm_status_t                  status    = LM_STATUS_SUCCESS;
    u32_t                        mcp_resp  = 0;
    struct function_update_data  *data     = LM_SLOWPATH(pdev, ufp_function_update_data);
    const lm_address_t           data_phys = LM_SLOWPATH_PHYS(pdev, ufp_function_update_data);
    lm_hardware_mf_info_t        *mf_info  = &pdev->hw_info.mf_info;
    u32_t                        tag       = 0;

    //Reconfigure rate-limit
    MM_ACQUIRE_PHY_LOCK(pdev);
    lm_reload_link_and_cmng(pdev);
    MM_RELEASE_PHY_LOCK(pdev);

    /* Other than vlan tag what are other UFP specific data? 
     * Should we read the priority etc
     */

    /* get ovlan if we're in switch-dependent mode... */
    LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].e1hov_tag),&tag);
    mf_info->ext_id    = (u16_t)tag;
    pdev->params.ovlan = (u16_t)tag;

    /* modify the NIG LLH registers */
    init_nig_func(pdev);

    DbgBreakIf(pdev->slowpath_info.ufp_func_ramrod_state != UFP_RAMROD_NOT_POSTED);

    /* send function update ramrod to change the tag in the FW */
    data->sd_vlan_tag_change_flg = TRUE;
    data->sd_vlan_tag            = mm_cpu_to_le16((u16_t)tag);
    data->echo                   = FUNC_UPDATE_RAMROD_SOURCE_UFP;

    status = lm_eq_ramrod_post_sync(pdev,
                                    RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE,
                                    data_phys.as_u64,CMD_PRIORITY_NORMAL,
                                    &pdev->slowpath_info.ufp_func_ramrod_state,
                                    UFP_RAMROD_PF_LINK_UPDATE_POSTED,
                                    UFP_RAMROD_COMPLETED);

    /* Report results to MCP */
    ///ACK the MCP message
    if(status == LM_STATUS_SUCCESS)
        lm_mcp_cmd_send_recieve(pdev, lm_mcp_mb_header, DRV_MSG_CODE_OEM_OK, 0, MCP_CMD_DEFAULT_TIMEOUT, &mcp_resp);
    else
        lm_mcp_cmd_send_recieve(pdev, lm_mcp_mb_header, DRV_MSG_CODE_OEM_FAILURE, 0, MCP_CMD_DEFAULT_TIMEOUT, &mcp_resp);

    DbgBreakIf(mcp_resp != FW_MSG_CODE_OEM_ACK);

    pdev->slowpath_info.ufp_func_ramrod_state = UFP_RAMROD_NOT_POSTED;
}

static lm_status_t lm_oem_event(lm_device_t *pdev, u32_t event)
{
    lm_status_t lm_status = LM_STATUS_SUCCESS;
    const u32_t offset    = OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].config);
    u32_t       config    = 0;

    DbgMessage(pdev, INFORM, "oem_event 0x%x\n", event);

    ///read FUNC-DISABLED and FUNC-DELETED from func_mf_cfg
    LM_MFCFG_READ(pdev, offset, &config);
    pdev->hw_info.mf_info.func_mf_cfg = config ;

    if (event & DRV_STATUS_OEM_DISABLE_ENABLE_PF)
    {
        if((config & FUNC_MF_CFG_FUNC_DISABLED) || (config & FUNC_MF_CFG_FUNC_DELETED))
        {
            lm_status = lm_ufp_pf_disable(pdev);
            if (lm_status != LM_STATUS_SUCCESS)
            {
                DbgBreakIf(lm_status != LM_STATUS_SUCCESS);
                return lm_status;
            }
        }
        else
        {
#ifdef EDIAG
            lm_ufp_pf_enable(pdev);
#else
            lm_status = MM_REGISTER_LPME(pdev, lm_ufp_pf_enable, TRUE, TRUE);
#endif
            if (lm_status != LM_STATUS_SUCCESS)
            {
                DbgBreakIf(lm_status != LM_STATUS_SUCCESS);
                return lm_status;
            }
        }
    }
    else if (event & DRV_STATUS_OEM_BANDWIDTH_ALLOCATION)
    {
        //lm_hardware_mf_info_t *mf_info = &pdev->hw_info.mf_info;

        ///* get min/max bw */
        //mf_info->min_bw[vnic] = (GET_FLAGS(config, FUNC_MF_CFG_MIN_BW_MASK) >> FUNC_MF_CFG_MIN_BW_SHIFT);
        //mf_info->max_bw[vnic] = (GET_FLAGS(config, FUNC_MF_CFG_MAX_BW_MASK) >> FUNC_MF_CFG_MAX_BW_SHIFT);

        /* this function reads the bw configuration and does the necessary processing..
         * only drawback is it reads the configuration for all the functions?
         *. todo check if we should be using this or not...
         */
        lm_status = lm_set_bandwidth_event(pdev);
        if (lm_status != LM_STATUS_SUCCESS)
        {
            DbgBreakIf(lm_status != LM_STATUS_SUCCESS);
            return lm_status;
        }
    }

    return lm_status;
}

static void lm_update_svid(lm_device_t *pdev)
{
    lm_hardware_mf_info_t          *mf_info        = &pdev->hw_info.mf_info;
    u32_t                          tag             = 0;
    u32_t                          mcp_resp        = 0;
    lm_status_t                    lm_status       = LM_STATUS_SUCCESS;
    struct function_update_data    *data           = LM_SLOWPATH(pdev, ufp_function_update_data);
    const lm_address_t             data_phys       = LM_SLOWPATH_PHYS(pdev, ufp_function_update_data);

    /* get ovlan if we're in switch-dependent mode... */
    LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].e1hov_tag),&tag);
    mf_info->ext_id      = (u16_t)tag;
    pdev->params.ovlan   = (u16_t)tag;

    /* modify the NIG LLH registers */
    init_nig_func(pdev);

    DbgBreakIf(pdev->slowpath_info.ufp_func_ramrod_state != UFP_RAMROD_NOT_POSTED);

    /* send function update ramrod to change the tag in the FW */
    data->sd_vlan_tag_change_flg = TRUE;
    data->sd_vlan_tag            = mm_cpu_to_le16((u16_t)tag);
    data->echo                   = FUNC_UPDATE_RAMROD_SOURCE_UFP;

    lm_status = lm_eq_ramrod_post_sync(pdev,
                                       RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE,
                                       data_phys.as_u64,CMD_PRIORITY_NORMAL,
                                       &pdev->slowpath_info.ufp_func_ramrod_state,
                                       UFP_RAMROD_PF_UPDATE_POSTED,
                                       UFP_RAMROD_COMPLETED);

    /* Report results to MCP */
    if(lm_status == LM_STATUS_SUCCESS)
        lm_mcp_cmd_send_recieve(pdev, lm_mcp_mb_header, DRV_MSG_CODE_OEM_UPDATE_SVID_OK, 0, MCP_CMD_DEFAULT_TIMEOUT, &mcp_resp);
    else
        lm_mcp_cmd_send_recieve(pdev, lm_mcp_mb_header, DRV_MSG_CODE_OEM_UPDATE_SVID_FAILURE, 0, MCP_CMD_DEFAULT_TIMEOUT, &mcp_resp);

    DbgBreakIf(mcp_resp != DRV_MSG_CODE_OEM_UPDATE_SVID_ACK);
    pdev->slowpath_info.ufp_func_ramrod_state = UFP_RAMROD_NOT_POSTED;
}

#ifndef EDIAG
static void lm_ufp_update_priority(lm_device_t *pdev)
{
    lm_hardware_mf_info_t          *mf_info        = &pdev->hw_info.mf_info;
    u32_t                          new_priority    = 0;
    u32_t                          mcp_resp        = 0;
    lm_status_t                    lm_status       = LM_STATUS_SUCCESS;
    struct function_update_data    *data           = LM_SLOWPATH(pdev, ufp_function_update_data);
    const lm_address_t             data_phys       = LM_SLOWPATH_PHYS(pdev, ufp_function_update_data);

    DbgBreakIf(pdev->slowpath_info.ufp_func_ramrod_state != UFP_RAMROD_NOT_POSTED);

    /* Todo get the priority from somewhere */

    /* send function update ramrod to change the tag in the FW */
    data->sd_vlan_force_pri_change_flg = TRUE;
    data->sd_vlan_force_pri_flg        = TRUE;
    //data->sd_vlan_force_pri_val        = mm_cpu_to_le16((u16_t)new_priority);

    data->echo                         = FUNC_UPDATE_RAMROD_SOURCE_UFP;

    lm_status = lm_eq_ramrod_post_sync(pdev,
                                       RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE,
                                       data_phys.as_u64,CMD_PRIORITY_NORMAL,
                                       &pdev->slowpath_info.ufp_func_ramrod_state,
                                       UFP_RAMROD_PF_UPDATE_POSTED,
                                       UFP_RAMROD_COMPLETED);
    /*Todo Report results to mcp?*/
    pdev->slowpath_info.ufp_func_ramrod_state = UFP_RAMROD_NOT_POSTED;
}
#endif

static lm_status_t lm_svid_event(lm_device_t *pdev)
{
    lm_status_t lm_status = LM_STATUS_SUCCESS;
#ifdef EDIAG
    lm_update_svid(pdev);
#else
    lm_status = MM_REGISTER_LPME(pdev, lm_update_svid, TRUE, TRUE);
#endif
    if (lm_status != LM_STATUS_SUCCESS)
    {
            DbgBreakIf(lm_status != LM_STATUS_SUCCESS);
            return lm_status;
    }

    return lm_status;
}

static void lm_generic_event(lm_device_t *pdev)
{
    u32_t      val              = 0;
    u32_t      offset           = 0; // for debugging convenient
    u8_t       call_pmf_or_link = FALSE;
    const u8_t func_id          = FUNC_ID(pdev);


    offset = MISC_REG_AEU_GENERAL_ATTN_12 + 4*func_id;

    // reset attention
    REG_WR(pdev, offset ,0x0);

    offset = OFFSETOF(shmem_region_t, func_mb[FUNC_MAILBOX_ID(pdev)].drv_status) ;

    // drv_status
    LM_SHMEM_READ(pdev,
                  offset,
                  &val);

    // E1H NIG status sync attention mapped to group 4-7

    if (GET_FLAGS( val, DRV_STATUS_VF_DISABLED))
    {
        u32_t mcp_vf_disabled[E2_VF_MAX / 32] = {0};
        u32_t i, fw_resp = 0;

        // Read VFs
        for (i = 0; i < ARRSIZE(mcp_vf_disabled); i++)
        {
            LM_SHMEM2_READ(pdev, OFFSETOF(shmem2_region_t,mcp_vf_disabled[i]), &mcp_vf_disabled[i]);
        }
        DbgMessage(pdev, FATAL, "lm_generic_event: DRV_STATUS_VF_DISABLED received for vfs bitmap %x %x!!!\n", mcp_vf_disabled[0], mcp_vf_disabled[1]);

        // SHMULIK, PLACE YOUR CODE HERE ( Handle only VFs of this PF )

        // Acknoledge the VFs you handled ( This array is per PF driver on path )
        for (i = 0; i < ARRSIZE(mcp_vf_disabled) ; i++)
        {
            LM_SHMEM2_WRITE(pdev, OFFSETOF(shmem2_region_t,drv_ack_vf_disabled[FUNC_MAILBOX_ID(pdev)][i]), mcp_vf_disabled[i]);
        }
        lm_mcp_cmd_send_recieve( pdev,
                                 lm_mcp_mb_header,
                                 DRV_MSG_CODE_VF_DISABLED_DONE,
                                 0,
                                 MCP_CMD_DEFAULT_TIMEOUT,
                                 &fw_resp);
        return; // YANIV - DEBUG @@@!!!
    }
    if(IS_MULTI_VNIC(pdev))
    {
        if( GET_FLAGS( val, DRV_STATUS_DCC_EVENT_MASK ) )
        {
            lm_dcc_event(pdev, (DRV_STATUS_DCC_EVENT_MASK & val) );
        }

        if (GET_FLAGS(val, DRV_STATUS_SET_MF_BW ))
        {
            lm_set_bandwidth_event(pdev);
        }

        //if val has any NIV event flags, call lm_niv_event
        if ( GET_FLAGS(val, DRV_STATUS_AFEX_EVENT_MASK) )
        {
            lm_niv_event(pdev, GET_FLAGS(val, DRV_STATUS_AFEX_EVENT_MASK) );
        }
    }

    if GET_FLAGS(val, DRV_STATUS_DRV_INFO_REQ)
    {
        lm_stats_drv_info_to_mfw_event(pdev);
    }

    // NOTE:
    // once we have events such as DCC and NIV, this condition doesn't stand anymore
    // we might get here TRUE although we are in MULTI_VNIC AND we are not PMF
    // and this is not for link change or pmf migration
    // the potential problem (redundant link report to OS CQ60223)
    // is resolved in "lm_link_report" function that check current link
    // with previous reported link

    /* Check if pmf or link event function should be called: */
    call_pmf_or_link = IS_MULTI_VNIC(pdev) && !pdev->vars.is_pmf;


    /* PMF or link event */
    if (GET_FLAGS(pdev->vars.link.periodic_flags, ELINK_PERIODIC_FLAGS_LINK_EVENT))
    {
        DbgMessage(pdev, WARN, "lm_generic_event: ELINK_PERIODIC_FLAGS_LINK_EVENT func_id=%d!!!\n", func_id );

        /*  sync with link */
        MM_ACQUIRE_PHY_LOCK_DPC(pdev);
        RESET_FLAGS(pdev->vars.link.periodic_flags, ELINK_PERIODIC_FLAGS_LINK_EVENT);
        MM_RELEASE_PHY_LOCK_DPC(pdev);

        call_pmf_or_link = TRUE;
    }

    if(call_pmf_or_link)
    {
        lm_pmf_or_link_event(pdev, val);
    }

    if GET_FLAGS(val, DRV_STATUS_OEM_EVENT_MASK)
    {
        lm_oem_event(pdev, val);
    }

    if GET_FLAGS(val, DRV_STATUS_OEM_UPDATE_SVID)
    {
        lm_svid_event(pdev);
    }

    lm_dcbx_event(pdev,val);
}

static void lm_gen_attn_everest_processing(lm_device_t *pdev, u32_t sig_word_aft_inv)
{
    u32_t offset = 0; // for debugging convenient
    u32_t val    = 0;

    //pass over all attention generals which are wired to a dynamic group of the lower 8 bits
    offset = GENERAL_ATTEN_OFFSET(TSTORM_FATAL_ASSERT_ATTENTION_BIT) ;
    if ( offset & sig_word_aft_inv)
    {
        REG_WR(pdev,MISC_REG_AEU_GENERAL_ATTN_7,0x0);
        DbgMessage(pdev, FATAL, "lm_gen_attn_everest_processing: TSTORM_FATAL_ASSERT_ATTENTION_BIT received!!!\n");
        DbgBreakIfAll(1);
    }
    offset = GENERAL_ATTEN_OFFSET(USTORM_FATAL_ASSERT_ATTENTION_BIT);
    if ( offset & sig_word_aft_inv)
    {
        REG_WR(pdev,MISC_REG_AEU_GENERAL_ATTN_8,0x0);
        DbgMessage(pdev, FATAL, "lm_gen_attn_everest_processing: USTORM_FATAL_ASSERT_ATTENTION_BIT received!!!\n");
        DbgBreakIfAll(1);
    }
    offset = GENERAL_ATTEN_OFFSET(CSTORM_FATAL_ASSERT_ATTENTION_BIT);
    if ( offset & sig_word_aft_inv)
    {
        REG_WR(pdev,MISC_REG_AEU_GENERAL_ATTN_9,0x0);
        DbgMessage(pdev, FATAL, "lm_gen_attn_everest_processing: CSTORM_FATAL_ASSERT_ATTENTION_BIT received!!!\n");
        DbgBreakIfAll(1);
    }
    offset = GENERAL_ATTEN_OFFSET(XSTORM_FATAL_ASSERT_ATTENTION_BIT);
    if ( offset & sig_word_aft_inv)
    {
        REG_WR(pdev,MISC_REG_AEU_GENERAL_ATTN_10,0x0);
        DbgMessage(pdev, FATAL, "lm_gen_attn_everest_processing: XSTORM_FATAL_ASSERT_ATTENTION_BIT received!!!\n");
        DbgBreakIfAll(1);
    }
    offset = GENERAL_ATTEN_OFFSET(MCP_FATAL_ASSERT_ATTENTION_BIT);
    if ( offset & sig_word_aft_inv)
    {
        REG_WR(pdev,MISC_REG_AEU_GENERAL_ATTN_11,0x0);
        val = lm_mcp_check(pdev);
        DbgMessage(pdev, FATAL, "lm_gen_attn_everest_processing: MCP_FATAL_ASSERT_ATTENTION_BIT received mcp_check=0x%x!!!\n" , val);
        DbgBreakIfAll(1);
    }
     // E1H NIG status sync attention mapped to group 4-7
    if (!CHIP_IS_E1(pdev))
    {
        // PMF change or link update
        offset = GENERAL_ATTEN_OFFSET(LINK_SYNC_ATTENTION_BIT_FUNC_0 + FUNC_ID(pdev));

        if ( offset & sig_word_aft_inv)
        {
           lm_generic_event(pdev);
        }
    }
}

void lm_read_attn_regs(lm_device_t *pdev, u32_t * attn_sig_af_inv_arr, u32_t arr_size)
{
    u8_t i;
    DbgBreakIf( pdev->vars.num_attn_sig_regs > arr_size );
    DbgBreakIf( pdev->vars.num_attn_sig_regs > ARRSIZE(pdev->vars.attn_sig_af_inv_reg_addr) );

    //Read the 128 attn signals bits after inverter
    for (i = 0; i < pdev->vars.num_attn_sig_regs; i++)
    {
        attn_sig_af_inv_arr[i] = REG_RD(pdev, pdev->vars.attn_sig_af_inv_reg_addr[i]);
    }

    DbgMessage(pdev, INFORM, "lm_handle_deassertion_processing: attn_sig_aft_invert_1:0x%x; attn_sig_aft_invert_2:0x%x; attn_sig_aft_invert_3:0x%x; attn_sig_aft_invert_4:0x%x,attn_sig_aft_invert_5:0x%x\n",
                attn_sig_af_inv_arr[0],
                attn_sig_af_inv_arr[1],
                attn_sig_af_inv_arr[2],
                attn_sig_af_inv_arr[3],
                attn_sig_af_inv_arr[4]);
}



void lm_get_attn_info(lm_device_t *pdev, u16_t *attn_bits, u16_t *attn_ack)
{
    volatile struct atten_sp_status_block *       attention_sb = NULL;
    u16_t                                   lcl_attn_sb_index = 0;

    DbgBreakIf(!(pdev && attn_bits && attn_ack));

    attention_sb = lm_get_attention_status_block(pdev);

    //guard against dynamic change of attn lines - 15 interations max
    //the main idea here is to assure that we work on synchronized snapshots of the attn_bits and
    //attn_ack and avoid a faulty scenario where attn_ack we read in sanpshot #2 corresponds to attn_bits
    //of snapshot #1 which occured on different time frames.
    do
    {
        lcl_attn_sb_index = mm_le16_to_cpu(attention_sb->attn_bits_index);
        *attn_bits = (u16_t)mm_le32_to_cpu(attention_sb->attn_bits);
        *attn_ack  = (u16_t)mm_le32_to_cpu(attention_sb->attn_bits_ack);

    } while (lcl_attn_sb_index != mm_le16_to_cpu(attention_sb->attn_bits_index));
    //the lcl_attn_sb_index differs from the real local attn_index in the pdev since in this while loop it could
    //have been changed, we don't save it locally, and thus we will definitely receive an interrupt in case the
    //while condition is met.

    DbgMessage(pdev,
               INFORMi,
               "lm_get_attn_info: def_sb->attn_bits:0x%x, def_sb->attn_ack:0x%x, attn_bits:0x%x, attn_ack:0x%x\n",
               mm_le32_to_cpu(attention_sb->attn_bits),
               mm_le32_to_cpu(attention_sb->attn_bits_ack),
               *attn_bits,
               *attn_ack);
}


static u32_t lm_dq_attn_everest_processing(lm_device_t *pdev)
{
    u32_t val,valc;
    val=REG_RD(pdev,DORQ_REG_DORQ_INT_STS);
    // TODO add defines here
    DbgMessage(pdev, FATAL, "DB hw attention 0x%x\n",val);
    if (val) {
        pdev->vars.dq_int_status_cnt++;
        if (val & DORQ_DORQ_INT_STS_REG_DB_DISCARD)
        {
    // DORQ discard attention
            pdev->vars.dq_int_status_discard_cnt++;//DbgBreakIfAll(1);
        }
        if (val & DORQ_DORQ_INT_STS_REG_TYPE_VAL_ERR)
    {
            // DORQ discard attention
            pdev->vars.dq_int_status_vf_val_err_cnt++;//DbgBreakIfAll(1);
            pdev->vars.dq_vf_type_val_err_fid = REG_RD(pdev,DORQ_REG_VF_TYPE_VAL_ERR_FID); 
            pdev->vars.dq_vf_type_val_err_mcid = REG_RD(pdev,DORQ_REG_VF_TYPE_VAL_ERR_MCID); 
    }
    }
    valc = REG_RD(pdev,DORQ_REG_DORQ_INT_STS_CLR);
    return val;
}

void lm_handle_deassertion_processing(lm_device_t *pdev, u16_t deassertion_proc_flgs)
{
    lm_status_t lm_status                     = LM_STATUS_SUCCESS;
    u32_t  val                                = 0;
    u32_t  port_reg_name                      = 0;
    u8_t   index                              = 0;
    u8_t   i                                  = 0;
    u32_t  mask_val                           = 0;
    u32_t  attn_sig_af_inv_arr[MAX_ATTN_REGS] = {0};
    u32_t  group_mask_arr[MAX_ATTN_REGS]      = {0};
    u32_t  mask_arr_val[MAX_ATTN_REGS]        = {0};
    u32_t  dq_int_sts, cfc_int_sts;

    DbgBreakIf(!pdev);
    DbgMessage(pdev, INFORM, "lm_handle_deassertion_processing: deassertion_proc_flgs:%d\n", deassertion_proc_flgs);


    //acquire split lock for attention signals handling
    acquire_split_alr(pdev);

    lm_read_attn_regs(pdev, attn_sig_af_inv_arr, ARRSIZE(attn_sig_af_inv_arr));

    if (lm_recoverable_error(pdev, attn_sig_af_inv_arr,ARRSIZE(attn_sig_af_inv_arr)))
    {
        DbgMessage(pdev, WARNer, "Starting lm recover flow ");
        lm_status = mm_er_initiate_recovery(pdev);
        if (lm_status == LM_STATUS_SUCCESS)
        {
            /* Continue only on success... */
            /* Disable HW interrupts */
            lm_disable_int(pdev);

            release_split_alr(pdev);
            /* In case of recoverable error don't handle attention so that
            * other functions get this parity as well.
            */
            return;
        }
        DbgMessage(pdev, WARNer, "mm_er_initiate_recovery returned status %d ", lm_status);

        /* Recovery failed... we'll keep going, and eventually hit
         * the attnetion and assert...
         */
    }

    //For all deasserted groups, pass over entire attn_bits after inverter and if they
    // are members of that particular gruop, treat each one of them accordingly.
    for (index = 0; index < ARRSIZE(pdev->vars.attn_groups_output); index++)
    {
        if (deassertion_proc_flgs & (1 << index))
        {
            for (i = 0; i < ARRSIZE(group_mask_arr); i++)
            {
                group_mask_arr[i] = pdev->vars.attn_groups_output[index].attn_sig_dword[i];
            }

            DbgMessage(pdev, WARN, "lm_handle_deassertion_processing: group #%d got attention on it!\n", index);
            DbgMessage(pdev, WARN, "lm_handle_deassertion_processing: mask1:0x%x, mask2:0x%x, mask3:0x%x, mask4:0x%x,mask5:0x%x\n",
                       group_mask_arr[0],
                       group_mask_arr[1],
                       group_mask_arr[2],
                       group_mask_arr[3],
                       group_mask_arr[4]);
            DbgMessage(pdev, WARN, "lm_handle_deassertion_processing: attn1:0x%x, attn2:0x%x, attn3:0x%x, attn4:0x%x,attn5:0x%x\n",
                       attn_sig_af_inv_arr[0],
                       attn_sig_af_inv_arr[1],
                       attn_sig_af_inv_arr[2],
                       attn_sig_af_inv_arr[3],
                       attn_sig_af_inv_arr[4]);

            if (attn_sig_af_inv_arr[3] & EVEREST_GEN_ATTN_IN_USE_MASK & group_mask_arr[3])
            {
                lm_gen_attn_everest_processing(pdev, attn_sig_af_inv_arr[3]);
            }

            // DQ attn
            if (attn_sig_af_inv_arr[1] & AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT & group_mask_arr[1])
            {
                dq_int_sts = lm_dq_attn_everest_processing(pdev);
            }
            // CFC attn
            if (attn_sig_af_inv_arr[2] & AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT & group_mask_arr[2])
            {
                cfc_int_sts = lm_cfc_attn_everest_processing(pdev);
            }
            // PXP attn
            if (attn_sig_af_inv_arr[2] & AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT & group_mask_arr[2])
            {
                lm_pxp_attn_everest_processing(pdev);
            }
            // SPIO 5 bit in register 0
            if (attn_sig_af_inv_arr[0] & AEU_INPUTS_ATTN_BITS_SPIO5 & group_mask_arr[0])
            {
                lm_spio5_attn_everest_processing(pdev);
            }

            // GPIO3 bits in register 0
            if (attn_sig_af_inv_arr[0] & pdev->vars.link.aeu_int_mask & group_mask_arr[0])
            {
                // Handle it only for PMF
                if (IS_PMF(pdev))
                {
                    MM_ACQUIRE_PHY_LOCK(pdev);
                    PHY_HW_LOCK(pdev);
                    elink_handle_module_detect_int(&pdev->params.link);
                    PHY_HW_UNLOCK(pdev);
                    MM_RELEASE_PHY_LOCK(pdev);
                }
            }

            //TODO: attribute each attention signal arrived and which is a member of a group and give it its own
            // specific treatment. later, for each attn, do "clean the hw block" via the INT_STS_CLR.

            //Check for lattched attn signals
            if (attn_sig_af_inv_arr[3] & EVEREST_LATCHED_ATTN_IN_USE_MASK & group_mask_arr[3])
            {
                lm_latch_attn_everest_processing(pdev, attn_sig_af_inv_arr[3]);
            }

            // general hw block attention
            i = 0;
            mask_arr_val[i] = attn_sig_af_inv_arr[i] & HW_INTERRUT_ASSERT_SET_0 & group_mask_arr[i];
            i = 1;
            mask_arr_val[i] = attn_sig_af_inv_arr[i] & HW_INTERRUT_ASSERT_SET_1 & group_mask_arr[i];
            i = 2;
            mask_arr_val[i] = attn_sig_af_inv_arr[i] & HW_INTERRUT_ASSERT_SET_2 & group_mask_arr[i];
            i = 4;
            mask_arr_val[i] = attn_sig_af_inv_arr[i] & HW_INTERRUT_ASSERT_SET_4 & group_mask_arr[i];

            if (mask_arr_val[2] & AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) {
                pdev->vars.pxp_hw_interrupts_cnt++;
            }

            if ( (mask_arr_val[0]) ||
                 (mask_arr_val[1] & ~AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT) ||
                 (mask_arr_val[2] & ~(AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT | AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT)) ||
                 (mask_arr_val[4]) )
            {
                DbgMessage(pdev, FATAL, "hw block attention:\n");
                DbgMessage(pdev, FATAL, "0: 0x%08x\n", mask_arr_val[0]);
                DbgMessage(pdev, FATAL, "1: 0x%08x\n", mask_arr_val[1]);
                DbgMessage(pdev, FATAL, "2: 0x%08x\n", mask_arr_val[2]);
                DbgMessage(pdev, FATAL, "4: 0x%08x\n", mask_arr_val[4]);
                DbgBreakIfAll(1);
            }
            // general hw block mem prty
            i = 0;
            mask_arr_val[i] = attn_sig_af_inv_arr[i] & HW_PRTY_ASSERT_SET_0 & group_mask_arr[i];
            i = 1;
            mask_arr_val[i] = attn_sig_af_inv_arr[i] & HW_PRTY_ASSERT_SET_1 & group_mask_arr[i];
            i = 2;
            mask_arr_val[i] = attn_sig_af_inv_arr[i] & HW_PRTY_ASSERT_SET_2 & group_mask_arr[i];
            i = 4;
            mask_arr_val[i] = attn_sig_af_inv_arr[i] & HW_PRTY_ASSERT_SET_4 & group_mask_arr[i];

            if ( (mask_arr_val[0]) ||
                 (mask_arr_val[1]) ||
                 (mask_arr_val[2]) ||
                 (mask_arr_val[4]) )
            {
                DbgMessage(pdev, FATAL, "hw block parity attention\n");
                DbgMessage(pdev, FATAL, "0: 0x%08x\n", mask_arr_val[0]);
                DbgMessage(pdev, FATAL, "1: 0x%08x\n", mask_arr_val[1]);
                DbgMessage(pdev, FATAL, "2: 0x%08x\n", mask_arr_val[2]);
                DbgMessage(pdev, FATAL, "4: 0x%08x\n", mask_arr_val[4]);
                DbgBreakIfAll(1);
            }
        }
    }

    //release split lock
    release_split_alr(pdev);

    //TODO: the attn_ack bits to clear must be passed with '0'
    //val = deassertion_proc_flgs;
    val = ~deassertion_proc_flgs;
    // attntion bits clear
    if (INTR_BLK_TYPE(pdev) == INTR_BLK_HC)
    {
        REG_WR(pdev,  HC_REG_COMMAND_REG + PORT_ID(pdev)*32 + COMMAND_REG_ATTN_BITS_CLR,val);
    }
    else
    {
        u32_t cmd_addr = IGU_CMD_ATTN_BIT_CLR_UPPER;

        if (INTR_BLK_ACCESS(pdev) == INTR_BLK_ACCESS_IGUMEM)
        {
            REG_WR(pdev, BAR_IGU_INTMEM + cmd_addr*8, val);
        }
        else
        {
            struct igu_ctrl_reg cmd_ctrl;
            u8_t                igu_func_id = 0;

            /* GRC ACCESS: */
            /* Write the Data, then the control */
             /* [18:12] - FID (if VF - [18] = 0; [17:12] = VF number; if PF - [18] = 1; [17:14] = 0; [13:12] = PF number) */
            igu_func_id = IGU_FUNC_ID(pdev);
            cmd_ctrl.ctrl_data =
                ((cmd_addr << IGU_CTRL_REG_ADDRESS_SHIFT) |
                 (igu_func_id << IGU_CTRL_REG_FID_SHIFT) |
                 (IGU_CTRL_CMD_TYPE_WR << IGU_CTRL_REG_TYPE_SHIFT));

            REG_WR(pdev, IGU_REG_COMMAND_REG_32LSB_DATA, val);
            REG_WR(pdev, IGU_REG_COMMAND_REG_CTRL, cmd_ctrl.ctrl_data);
        }
    }

    //unmask only appropriate attention output signals from configured routing and unifier logic toward IGU.
    //This is for driver/chip sync to eventually return to '00' monitored state
    //in both leading & trailing latch.
    //unmask non-hard-wired dynamic groups only

    DbgBreakIf(~pdev->vars.attn_state & deassertion_proc_flgs);

    //unmask relevant AEU attn lines
    //             mask  deassert_flgs  new mask
    //legal:        0       0       ->    0
    //              0       1       ->    1
    //              1       0       ->    1
    //ASSERT:       1       1 -> this won't change us thanks to the |

    port_reg_name = PORT_ID(pdev) ? MISC_REG_AEU_MASK_ATTN_FUNC_1 : MISC_REG_AEU_MASK_ATTN_FUNC_0;

    lm_hw_lock(pdev, HW_LOCK_RESOURCE_PORT0_ATT_MASK + PORT_ID(pdev), TRUE);

    mask_val = REG_RD(pdev, port_reg_name);

    pdev->vars.aeu_mask_attn_func = mask_val & 0xff;

    DbgMessage(pdev, INFORM, "lm_handle_deassertion_processing: BEFORE: aeu_mask_attn_func:0x%x\n", pdev->vars.aeu_mask_attn_func);
    //changed from XOR to OR for safely
    pdev->vars.aeu_mask_attn_func |= (deassertion_proc_flgs & 0xff);

    DbgMessage(pdev, INFORM, "lm_handle_deassertion_processing: AFTER : aeu_mask_attn_func:0x%x\n", pdev->vars.aeu_mask_attn_func);

    REG_WR(pdev, port_reg_name, pdev->vars.aeu_mask_attn_func);
    lm_hw_unlock(pdev, HW_LOCK_RESOURCE_PORT0_ATT_MASK + PORT_ID(pdev));
    //update the attn bits states
    //            state  deassert_flgs  new state
    //legal:        0       0       ->    0
    //              1       0       ->    1
    //              1       1       ->    0
    //ASSERT:       0       1 -> this won't change our state thanks to & ~ !
    DbgMessage(pdev, INFORM, "lm_handle_deassertion_processing: BEFORE: attn_state:0x%x\n", pdev->vars.attn_state);

    //changed from XOR to : AND ~ for safety
    pdev->vars.attn_state &= ~deassertion_proc_flgs;

    DbgMessage(pdev, INFORM, "lm_handle_deassertion_processing: AFTER : attn_state:0x%x\n", pdev->vars.attn_state);
}