| /******************************************************************************* |
| Copyright (C) Marvell International Ltd. and its affiliates |
| |
| This software file (the "File") is owned and distributed by Marvell |
| International Ltd. and/or its affiliates ("Marvell") under the following |
| alternative licensing terms. Once you have made an election to distribute the |
| File under one of the following license alternatives, please (i) delete this |
| introductory statement regarding license alternatives, (ii) delete the two |
| license alternatives that you have not elected to use and (iii) preserve the |
| Marvell copyright notice above. |
| |
| ******************************************************************************** |
| Marvell Commercial License Option |
| |
| If you received this File from Marvell and you have entered into a commercial |
| license agreement (a "Commercial License") with Marvell, the File is licensed |
| to you under the terms of the applicable Commercial License. |
| |
| ******************************************************************************** |
| Marvell GPL License Option |
| |
| If you received this File from Marvell, you may opt to use, redistribute and/or |
| modify this File in accordance with the terms and conditions of the General |
| Public License Version 2, June 1991 (the "GPL License"), a copy of which is |
| available along with the File in the license.txt file or by writing to the Free |
| Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or |
| on the worldwide web at http://www.gnu.org/licenses/gpl.txt. |
| |
| THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED |
| WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY |
| DISCLAIMED. The GPL License provides additional details about this warranty |
| disclaimer. |
| ******************************************************************************** |
| Marvell BSD License Option |
| |
| If you received this File from Marvell, you may opt to use, redistribute and/or |
| modify this File under the following licensing terms. |
| Redistribution and use in source and binary forms, with or without modification, |
| are permitted provided that the following conditions are met: |
| |
| * Redistributions of source code must retain the above copyright notice, |
| this list of conditions and the following disclaimer. |
| |
| * Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| |
| * Neither the name of Marvell nor the names of its contributors may be |
| used to endorse or promote products derived from this software without |
| specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |
| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| *******************************************************************************/ |
| #include "mvPp2Cls3Hw.h" |
| |
| CLS3_SHADOW_HASH_ENTRY mvCls3ShadowTbl[MV_PP2_CLS_C3_HASH_TBL_SIZE]; |
| int mvCls3ShadowExtTbl[MV_PP2_CLS_C3_EXT_TBL_SIZE]; |
| static int mvPp2ClsC3SwActDump(MV_PP2_CLS_C3_ENTRY *c3); |
| |
| static int SwInitCntSet; |
| |
| /****************************************************************************** |
| * Common utilities |
| |
| ******************************************************************************/ |
| static void mvPp2ClsC3ShadowSet(int hekSize, int index, int ext_index) |
| { |
| mvCls3ShadowTbl[index].size = hekSize; |
| |
| if (hekSize > MV_PP2_CLS_C3_HEK_BYTES) { |
| mvCls3ShadowTbl[index].ext_ptr = ext_index; |
| mvCls3ShadowExtTbl[ext_index] = IN_USE; |
| } else |
| mvCls3ShadowTbl[index].ext_ptr = NOT_IN_USE; |
| } |
| |
| /*-----------------------------------------------------------------------------*/ |
| void mvPp2ClsC3ShadowInit(void) |
| { |
| /* clear hash shadow and extension shadow */ |
| int index; |
| |
| for (index = 0; index < MV_PP2_CLS_C3_HASH_TBL_SIZE; index++) { |
| mvCls3ShadowTbl[index].size = 0; |
| mvCls3ShadowTbl[index].ext_ptr = NOT_IN_USE; |
| } |
| |
| for (index = 0; index < MV_PP2_CLS_C3_EXT_TBL_SIZE; index++) |
| mvCls3ShadowExtTbl[index] = NOT_IN_USE; |
| } |
| |
| /*-----------------------------------------------------------------------------*/ |
| int mvPp2ClsC3ShadowFreeGet(void) |
| { |
| int index; |
| |
| /* Go through the all entires from first to last */ |
| for (index = 0; index < MV_PP2_CLS_C3_HASH_TBL_SIZE; index++) { |
| if (!mvCls3ShadowTbl[index].size) |
| break; |
| } |
| return index; |
| } |
| /*-----------------------------------------------------------------------------*/ |
| int mvPp2ClsC3ShadowExtFreeGet(void) |
| { |
| int index; |
| |
| /* Go through the all entires from first to last */ |
| for (index = 0; index < MV_PP2_CLS_C3_EXT_TBL_SIZE; index++) { |
| if (mvCls3ShadowExtTbl[index] == NOT_IN_USE) |
| break; |
| } |
| return index; |
| } |
| /*-----------------------------------------------------------------------------*/ |
| void mvPp2C3ShadowClear(int index) |
| { |
| int ext_ptr; |
| |
| mvCls3ShadowTbl[index].size = 0; |
| ext_ptr = mvCls3ShadowTbl[index].ext_ptr; |
| |
| if (ext_ptr != NOT_IN_USE) |
| mvCls3ShadowExtTbl[ext_ptr] = NOT_IN_USE; |
| |
| mvCls3ShadowTbl[index].ext_ptr = NOT_IN_USE; |
| } |
| /*------------------------------------------------------------------------------- |
| retun 1 scan procedure completed |
| -------------------------------------------------------------------------------*/ |
| static int mvPp2ClsC3ScanIsComplete(void) |
| { |
| unsigned int regVal; |
| |
| regVal = mvPp2RdReg(MV_PP2_CLS3_STATE_REG); |
| regVal &= MV_PP2_CLS3_STATE_SC_DONE_MASK; |
| regVal >>= MV_PP2_CLS3_STATE_SC_DONE; |
| |
| return regVal; |
| } |
| /*------------------------------------------------------------------------------- |
| return 1 if that the last CPU access (Query,Add or Delete) was completed |
| -------------------------------------------------------------------------------*/ |
| static int mvPp2ClsC3CpuIsDone(void) |
| { |
| unsigned int regVal; |
| |
| regVal = mvPp2RdReg(MV_PP2_CLS3_STATE_REG); |
| regVal &= MV_PP2_CLS3_STATE_CPU_DONE_MASK; |
| regVal >>= MV_PP2_CLS3_STATE_CPU_DONE; |
| return regVal; |
| } |
| |
| /*------------------------------------------------------------------------------- |
| 0x0 "ScanCompleted" scan completed and the scan results are ready in hardware |
| 0x1 "HitCountersClear" The engine is clearing the Hit Counters |
| 0x2 "ScanWait" The engine waits for the scan delay timer |
| 0x3 "ScanInProgress" The scan process is in progress |
| -------------------------------------------------------------------------------*/ |
| static int mvPp2ClsC3ScanStateGet(int *state) |
| { |
| unsigned int regVal; |
| |
| PTR_VALIDATE(state); |
| |
| regVal = mvPp2RdReg(MV_PP2_CLS3_STATE_REG); |
| regVal &= MV_PP2_CLS3_STATE_SC_STATE_MASK; |
| regVal >>= MV_PP2_CLS3_STATE_SC_STATE; |
| *state = regVal; |
| |
| return MV_OK; |
| } |
| /*------------------------------------------------------------------------------- |
| return 1 if counters clearing is completed |
| --------------------------------------------------------------------------------*/ |
| static int mvPp2ClsC3HitCntrClearDone(void) |
| { |
| unsigned int regVal; |
| |
| regVal = mvPp2RdReg(MV_PP2_CLS3_STATE_REG); |
| regVal &= MV_PP2_CLS3_STATE_CLEAR_CTR_DONE_MASK; |
| regVal >>= MV_PP2_CLS3_STATE_CLEAR_CTR_DONE; |
| return regVal; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| void mvPp2ClsC3SwClear(MV_PP2_CLS_C3_ENTRY *c3) |
| { |
| memset(c3, 0, sizeof(MV_PP2_CLS_C3_ENTRY)); |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3Init() |
| { |
| int rc; |
| |
| mvPp2ClsC3ShadowInit(); |
| rc = mvPp2ClsC3HitCntrsClearAll(); |
| return rc; |
| } |
| |
| /*------------------------------------------------------------------------------- |
| Add entry to hash table |
| ext_index used only if hek size < 12 |
| -------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3HwAdd(MV_PP2_CLS_C3_ENTRY *c3, int index, int ext_index) |
| { |
| int regStartInd, hekSize, iter = 0; |
| unsigned int regVal = 0; |
| |
| |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(index, MV_PP2_CLS3_HASH_OP_TBL_ADDR_MAX); |
| |
| c3->index = index; |
| |
| /* write key control */ |
| mvPp2WrReg(MV_PP2_CLS3_KEY_CTRL_REG, c3->key.key_ctrl); |
| |
| hekSize = ((c3->key.key_ctrl & KEY_CTRL_HEK_SIZE_MASK) >> KEY_CTRL_HEK_SIZE); |
| |
| if (hekSize > MV_PP2_CLS_C3_HEK_BYTES) { |
| /* Extension */ |
| POS_RANGE_VALIDATE(ext_index, MV_PP2_CLS3_HASH_OP_EXT_TBL_ADDR_MAX) |
| c3->ext_index = ext_index; |
| regVal |= (ext_index << MV_PP2_CLS3_HASH_OP_EXT_TBL_ADDR); |
| |
| /* write 9 hek refisters */ |
| regStartInd = 0; |
| } else |
| /* write 3 hek refisters */ |
| regStartInd = 6; |
| |
| for (; regStartInd < MV_PP2_CLS_C3_EXT_HEK_WORDS; regStartInd++) |
| mvPp2WrReg(MV_PP2_CLS3_KEY_HEK_REG(regStartInd), c3->key.hek.words[regStartInd]); |
| |
| |
| regVal |= (index << MV_PP2_CLS3_HASH_OP_TBL_ADDR); |
| regVal &= ~MV_PP2_CLS3_MISS_PTR_MASK; /*set miss bit to 0, ppv2.1 mas 3.16*/ |
| regVal |= (1 << MV_PP2_CLS3_HASH_OP_ADD); |
| |
| /* set hit counter init value */ |
| mvPp2WrReg(MV_PP2_CLS3_INIT_HIT_CNT_REG, SwInitCntSet << MV_PP2_CLS3_INIT_HIT_CNT_OFFS); |
| /*trigger ADD operation*/ |
| mvPp2WrReg(MV_PP2_CLS3_HASH_OP_REG, regVal); |
| |
| /* wait to cpu access done bit */ |
| while (!mvPp2ClsC3CpuIsDone()) |
| if (++iter >= RETRIES_EXCEEDED) { |
| mvOsPrintf("%s:Error - retries exceeded.\n", __func__); |
| return MV_CLS3_RETRIES_EXCEEDED; |
| } |
| |
| /* write action table registers */ |
| mvPp2WrReg(MV_PP2_CLS3_ACT_REG, c3->sram.regs.actions); |
| mvPp2WrReg(MV_PP2_CLS3_ACT_QOS_ATTR_REG, c3->sram.regs.qos_attr); |
| mvPp2WrReg(MV_PP2_CLS3_ACT_HWF_ATTR_REG, c3->sram.regs.hwf_attr); |
| mvPp2WrReg(MV_PP2_CLS3_ACT_DUP_ATTR_REG, c3->sram.regs.dup_attr); |
| mvPp2WrReg(MV_PP2_CLS3_ACT_SEQ_L_ATTR_REG, c3->sram.regs.seq_l_attr); |
| mvPp2WrReg(MV_PP2_CLS3_ACT_SEQ_H_ATTR_REG, c3->sram.regs.seq_h_attr); |
| /* set entry as valid, extesion pointer in use only if size > 12*/ |
| mvPp2ClsC3ShadowSet(hekSize, index, ext_index); |
| |
| |
| return MV_OK; |
| } |
| |
| /*------------------------------------------------------------------------------- |
| Add entry to miss hash table |
| ppv2.1 mas 3.16 relevant only for ppv2.1 |
| -------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3HwMissAdd(MV_PP2_CLS_C3_ENTRY *c3, int lkp_type) |
| { |
| unsigned int regVal = 0; |
| |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(lkp_type, MV_PP2_CLS_C3_MISS_TBL_SIZE - 1); |
| |
| c3->index = lkp_type; |
| |
| regVal |= (lkp_type << MV_PP2_CLS3_HASH_OP_TBL_ADDR); |
| regVal |= (1 << MV_PP2_CLS3_HASH_OP_ADD); |
| regVal |= MV_PP2_CLS3_MISS_PTR_MASK;/*set miss bit to 1, ppv2.1 mas 3.16*/ |
| |
| /*index to miss table */ |
| mvPp2WrReg(MV_PP2_CLS3_HASH_OP_REG, regVal); |
| |
| /* write action table registers */ |
| mvPp2WrReg(MV_PP2_CLS3_ACT_REG, c3->sram.regs.actions); |
| mvPp2WrReg(MV_PP2_CLS3_ACT_QOS_ATTR_REG, c3->sram.regs.qos_attr); |
| mvPp2WrReg(MV_PP2_CLS3_ACT_HWF_ATTR_REG, c3->sram.regs.hwf_attr); |
| mvPp2WrReg(MV_PP2_CLS3_ACT_DUP_ATTR_REG, c3->sram.regs.dup_attr); |
| mvPp2WrReg(MV_PP2_CLS3_ACT_SEQ_L_ATTR_REG, c3->sram.regs.seq_l_attr); |
| mvPp2WrReg(MV_PP2_CLS3_ACT_SEQ_H_ATTR_REG, c3->sram.regs.seq_h_attr); |
| /*clear hit counter, clear on read */ |
| mvPp2ClsC3HitCntrsMissRead(lkp_type, ®Val); |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3HwDel(int index) |
| { |
| |
| unsigned int regVal = 0; |
| int iter = 0; |
| |
| POS_RANGE_VALIDATE(index, MV_PP2_CLS3_HASH_OP_TBL_ADDR_MAX); |
| |
| regVal |= (index << MV_PP2_CLS3_HASH_OP_TBL_ADDR); |
| regVal |= (1 << MV_PP2_CLS3_HASH_OP_DEL); |
| regVal &= ~MV_PP2_CLS3_MISS_PTR_MASK;/*set miss bit to 1, ppv2.1 mas 3.16*/ |
| |
| |
| /*trigger del operation*/ |
| mvPp2WrReg(MV_PP2_CLS3_HASH_OP_REG, regVal); |
| |
| /* wait to cpu access done bit */ |
| while (!mvPp2ClsC3CpuIsDone()) |
| if (++iter >= RETRIES_EXCEEDED) { |
| mvOsPrintf("%s:Error - retries exceeded.\n", __func__); |
| return MV_CLS3_RETRIES_EXCEEDED; |
| } |
| |
| /* delete form shadow and extension shadow if exist */ |
| mvPp2C3ShadowClear(index); |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3HwDelAll() |
| { |
| int index, status; |
| |
| for (index = 0; index < MV_PP2_CLS_C3_HASH_TBL_SIZE; index++) { |
| status = mvPp2ClsC3HwDel(index); |
| if (status != MV_OK) |
| return status; |
| } |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| void mvPp2ClsC3HwInitCtrSet(int cntVal) |
| { |
| SwInitCntSet = cntVal; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| |
| static int mvPp2ClsC3HwQueryAddRelocate(int new_idx, int max_depth, int cur_depth, MV_PP2_CLS3_HASH_PAIR *hash_pair_arr) |
| { |
| int status, index_free, idx = 0; |
| unsigned char occupied_bmp; |
| MV_PP2_CLS_C3_ENTRY local_c3; |
| int usedIndex[MV_PP2_CLS3_HASH_BANKS_NUM] = {0}; |
| |
| if (cur_depth >= max_depth) |
| return MV_CLS3_RETRIES_EXCEEDED; |
| |
| |
| mvPp2ClsC3SwClear(&local_c3); |
| |
| if (mvPp2ClsC3HwRead(&local_c3, new_idx)) { |
| mvOsPrintf("%s could not get key for index [0x%x]\n", __func__, new_idx); |
| return MV_CLS3_RETRIES_EXCEEDED; |
| } |
| |
| if (mvPp2ClsC3HwQuery(&local_c3, &occupied_bmp, usedIndex)) { |
| mvOsPrintf("%s: mvPp2ClsC3HwQuery failed, depth = %d\n", __func__, cur_depth); |
| return MV_CLS3_ERR; |
| } |
| |
| /* fill in indices for this key */ |
| for (idx = 0; idx < MV_PP2_CLS3_HASH_BANKS_NUM; idx++) { |
| /* if new index is in the bank index, skip it */ |
| if (new_idx == usedIndex[idx]) { |
| usedIndex[idx] = 0; |
| continue; |
| } |
| |
| /* found a vacant index */ |
| if (!(occupied_bmp & (1 << idx))) { |
| index_free = usedIndex[idx]; |
| break; |
| } |
| } |
| |
| /* no free index, recurse and relocate another key */ |
| if (idx == MV_PP2_CLS3_HASH_BANKS_NUM) { |
| #ifdef MV_DEBUG |
| mvOsPrintf("new[0x%.3x]:%.1d ", new_idx, cur_depth); |
| for (idx = 0; idx < MV_PP2_CLS3_HASH_BANKS_NUM; idx++) |
| mvOsPrintf("0x%.3x ", usedIndex[idx]); |
| mvOsPrintf("\n"); |
| #endif |
| |
| /* recurse over all valid indices */ |
| for (idx = 0; idx < MV_PP2_CLS3_HASH_BANKS_NUM; idx++) { |
| if (usedIndex[idx] == 0) |
| continue; |
| |
| if (mvPp2ClsC3HwQueryAddRelocate(usedIndex[idx], max_depth, |
| cur_depth+1, hash_pair_arr) == MV_OK) |
| break; |
| } |
| |
| /* tried relocate, no valid entries found */ |
| if (idx == MV_PP2_CLS3_HASH_BANKS_NUM) |
| return MV_CLS3_RETRIES_EXCEEDED; |
| |
| } |
| |
| /* if we reached here, we found a valid free index */ |
| index_free = usedIndex[idx]; |
| |
| /* new_idx del is not necessary */ |
| |
| /*We do not chage extension tabe*/ |
| status = mvPp2ClsC3HwAdd(&local_c3, index_free, local_c3.ext_index); |
| |
| /* update the hash pair */ |
| if (hash_pair_arr != NULL) { |
| hash_pair_arr->old_idx[hash_pair_arr->pair_num] = new_idx; |
| hash_pair_arr->new_idx[hash_pair_arr->pair_num] = index_free; |
| hash_pair_arr->pair_num++; |
| } |
| |
| if (status != MV_OK) { |
| mvOsPrintf("%s:Error - mvPp2ClsC3HwAdd failed, depth = %d\\n", __func__, cur_depth); |
| return status; |
| } |
| |
| mvOsPrintf("key relocated 0x%.3x->0x%.3x\n", new_idx, index_free); |
| |
| return MV_OK; |
| } |
| |
| |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3HwQueryAdd(MV_PP2_CLS_C3_ENTRY *c3, int max_search_depth, MV_PP2_CLS3_HASH_PAIR *hash_pair_arr) |
| { |
| int usedIndex[MV_PP2_CLS3_HASH_BANKS_NUM] = {0}; |
| unsigned char occupied_bmp; |
| int idx, index_free, hekSize, status, ext_index = 0; |
| |
| status = mvPp2ClsC3HwQuery(c3, &occupied_bmp, usedIndex); |
| |
| if (status != MV_OK) { |
| mvOsPrintf("%s:Error - mvPp2ClsC3HwQuery failed\n", __func__); |
| return status; |
| } |
| |
| /* Select avaliable entry index */ |
| for (idx = 0; idx < MV_PP2_CLS3_HASH_BANKS_NUM; idx++) { |
| if (!(occupied_bmp & (1 << idx))) |
| break; |
| } |
| |
| /* Avaliable index did not found, try to relocate another key */ |
| |
| if (idx == MV_PP2_CLS3_HASH_BANKS_NUM) { |
| |
| for (idx = 0; idx < MV_PP2_CLS3_HASH_BANKS_NUM; idx++) { |
| if (mvPp2ClsC3HwQueryAddRelocate(usedIndex[idx], max_search_depth, |
| 0 /*curren depth*/, hash_pair_arr) == MV_OK) |
| break; |
| } |
| |
| if (idx == MV_PP2_CLS3_HASH_BANKS_NUM) { |
| /* Avaliable index did not found*/ |
| mvOsPrintf("%s:Error - HASH table is full.\n", __func__); |
| return MV_CLS3_ERR; |
| } |
| } |
| |
| index_free = usedIndex[idx]; |
| |
| hekSize = ((c3->key.key_ctrl & KEY_CTRL_HEK_SIZE_MASK) >> KEY_CTRL_HEK_SIZE); |
| |
| if (hekSize > MV_PP2_CLS_C3_HEK_BYTES) { |
| /* Get Free Extension Index */ |
| ext_index = mvPp2ClsC3ShadowExtFreeGet(); |
| |
| if (ext_index == MV_PP2_CLS_C3_EXT_TBL_SIZE) { |
| mvOsPrintf("%s:Error - Extension table is full.\n", __func__); |
| return MV_CLS3_ERR; |
| } |
| } |
| |
| status = mvPp2ClsC3HwAdd(c3, index_free, ext_index); |
| |
| if (status != MV_OK) { |
| mvOsPrintf("%s:Error - mvPp2ClsC3HwAdd failed\n", __func__); |
| return status; |
| } |
| |
| if (hekSize > MV_PP2_CLS_C3_HEK_BYTES) |
| mvOsPrintf("Added C3 entry @ index=0x%.3x ext=0x%.3x\n", index_free, ext_index); |
| else |
| mvOsPrintf("Added C3 entry @ index=0x%.3x\n", index_free); |
| |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| /*if index or occupied_bmp is NULL dump the data */ |
| /* index[] size must be 8 */ |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3HwQuery(MV_PP2_CLS_C3_ENTRY *c3, unsigned char *occupied_bmp, int index[]) |
| { |
| int idx = 0; |
| unsigned int regVal = 0; |
| |
| PTR_VALIDATE(c3); |
| |
| /* write key control */ |
| mvPp2WrReg(MV_PP2_CLS3_KEY_CTRL_REG, c3->key.key_ctrl); |
| |
| /* write hek */ |
| for (idx = 0; idx < MV_PP2_CLS_C3_EXT_HEK_WORDS; idx++) |
| mvPp2WrReg(MV_PP2_CLS3_KEY_HEK_REG(idx), c3->key.hek.words[idx]); |
| |
| /*trigger query operation*/ |
| mvPp2WrReg(MV_PP2_CLS3_QRY_ACT_REG, (1 << MV_PP2_CLS3_QRY_ACT)); |
| |
| idx = 0; |
| while (!mvPp2ClsC3CpuIsDone()) |
| if (++idx >= RETRIES_EXCEEDED) { |
| mvOsPrintf("%s:Error - retries exceeded.\n", __func__); |
| return MV_CLS3_RETRIES_EXCEEDED; |
| } |
| |
| regVal = mvPp2RdReg(MV_PP2_CLS3_STATE_REG) & MV_PP2_CLS3_STATE_OCCIPIED_MASK; |
| regVal = regVal >> MV_PP2_CLS3_STATE_OCCIPIED; |
| |
| if ((!occupied_bmp) || (!index)) { |
| /* print to screen - call from sysfs*/ |
| for (idx = 0; idx < MV_PP2_CLS3_HASH_BANKS_NUM; idx++) |
| mvOsPrintf("0x%8.8x %s\n", |
| mvPp2RdReg(MV_PP2_CLS3_QRY_RES_HASH_REG(idx)), |
| (regVal & (1 << idx)) ? "OCCUPIED" : "FREE"); |
| return MV_OK; |
| } |
| |
| *occupied_bmp = regVal; |
| for (idx = 0; idx < MV_PP2_CLS3_HASH_BANKS_NUM; idx++) |
| index[idx] = mvPp2RdReg(MV_PP2_CLS3_QRY_RES_HASH_REG(idx)); |
| |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3HwRead(MV_PP2_CLS_C3_ENTRY *c3, int index) |
| { |
| int i, isExt; |
| MV_U32 regVal = 0; |
| |
| unsigned int hashData[MV_PP2_CLS3_HASH_DATA_REG_NUM]; |
| unsigned int hashExtData[MV_PP2_CLS3_HASH_EXT_DATA_REG_NUM]; |
| |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(index, MV_PP2_CLS3_HASH_OP_TBL_ADDR_MAX); |
| |
| mvPp2ClsC3SwClear(c3); |
| |
| c3->index = index; |
| c3->ext_index = NOT_IN_USE; |
| |
| /* write index */ |
| mvPp2WrReg(MV_PP2_CLS3_DB_INDEX_REG, index); |
| |
| regVal |= (index << MV_PP2_CLS3_HASH_OP_TBL_ADDR); |
| mvPp2WrReg(MV_PP2_CLS3_HASH_OP_REG, regVal); |
| |
| /* read action table */ |
| c3->sram.regs.actions = mvPp2RdReg(MV_PP2_CLS3_ACT_REG); |
| c3->sram.regs.qos_attr = mvPp2RdReg(MV_PP2_CLS3_ACT_QOS_ATTR_REG); |
| c3->sram.regs.hwf_attr = mvPp2RdReg(MV_PP2_CLS3_ACT_HWF_ATTR_REG); |
| c3->sram.regs.dup_attr = mvPp2RdReg(MV_PP2_CLS3_ACT_DUP_ATTR_REG); |
| |
| c3->sram.regs.seq_l_attr = mvPp2RdReg(MV_PP2_CLS3_ACT_SEQ_L_ATTR_REG); |
| c3->sram.regs.seq_h_attr = mvPp2RdReg(MV_PP2_CLS3_ACT_SEQ_H_ATTR_REG); |
| |
| /* read hash data*/ |
| for (i = 0; i < MV_PP2_CLS3_HASH_DATA_REG_NUM; i++) |
| hashData[i] = mvPp2RdReg(MV_PP2_CLS3_HASH_DATA_REG(i)); |
| |
| if (mvCls3ShadowTbl[index].size == 0) { |
| /* entry not in use */ |
| return MV_OK; |
| } |
| |
| c3->key.key_ctrl = 0; |
| |
| if (mvCls3ShadowTbl[index].ext_ptr == NOT_IN_USE) { |
| isExt = 0; |
| /* TODO REMOVE NEXT LINES- ONLY FOR INTERNAL VALIDATION */ |
| if ((mvCls3ShadowTbl[index].size == 0) || |
| (mvCls3ShadowTbl[index].ext_ptr != NOT_IN_USE)) { |
| mvOsPrintf("%s: SW internal error.\n", __func__); |
| return MV_CLS3_SW_INTERNAL; |
| } |
| |
| /*read Multihash entry data*/ |
| c3->key.hek.words[6] = hashData[0]; /* hek 0*/ |
| c3->key.hek.words[7] = hashData[1]; /* hek 1*/ |
| c3->key.hek.words[8] = hashData[2]; /* hek 2*/ |
| |
| /* write key control data to SW */ |
| c3->key.key_ctrl |= (((hashData[3] & KEY_PRT_ID_MASK(isExt)) >> |
| (KEY_PRT_ID(isExt) % DWORD_BITS_LEN)) << KEY_CTRL_PRT_ID); |
| |
| c3->key.key_ctrl |= (((hashData[3] & KEY_PRT_ID_TYPE_MASK(isExt)) >> |
| (KEY_PRT_ID_TYPE(isExt) % DWORD_BITS_LEN)) << KEY_CTRL_PRT_ID_TYPE); |
| |
| c3->key.key_ctrl |= (((hashData[3] & KEY_LKP_TYPE_MASK(isExt)) >> |
| (KEY_LKP_TYPE(isExt) % DWORD_BITS_LEN)) << KEY_CTRL_LKP_TYPE); |
| |
| c3->key.key_ctrl |= (((hashData[3] & KEY_L4_INFO_MASK(isExt)) >> |
| (KEY_L4_INFO(isExt) % DWORD_BITS_LEN)) << KEY_CTRL_L4); |
| |
| } else { |
| isExt = 1; |
| /* TODO REMOVE NEXT LINES- ONLY FOR INTERNAL VALIDATION */ |
| if ((mvCls3ShadowTbl[index].size == 0) || |
| (mvCls3ShadowTbl[index].ext_ptr == NOT_IN_USE)) { |
| mvOsPrintf("%s: SW internal error.\n", __func__); |
| return MV_CLS3_SW_INTERNAL; |
| } |
| c3->ext_index = mvCls3ShadowTbl[index].ext_ptr; |
| |
| /* write extension index */ |
| mvPp2WrReg(MV_PP2_CLS3_DB_INDEX_REG, mvCls3ShadowTbl[index].ext_ptr); |
| |
| /* read hash extesion data*/ |
| for (i = 0; i < MV_PP2_CLS3_HASH_EXT_DATA_REG_NUM; i++) |
| hashExtData[i] = mvPp2RdReg(MV_PP2_CLS3_HASH_EXT_DATA_REG(i)); |
| |
| |
| /* heks bytes 35 - 32 */ |
| c3->key.hek.words[8] = ((hashData[2] & 0x00FFFFFF) << 8) | ((hashData[1] & 0xFF000000) >> 24); |
| |
| /* heks bytes 31 - 28 */ |
| c3->key.hek.words[7] = ((hashData[1] & 0x00FFFFFF) << 8) | ((hashData[0] & 0xFF000000) >> 24); |
| |
| /* heks bytes 27 - 24 */ |
| c3->key.hek.words[6] = ((hashData[0] & 0x00FFFFFF) << 8) | (hashExtData[6] & 0x000000FF); |
| |
| c3->key.hek.words[5] = hashExtData[5]; /* heks bytes 23 - 20 */ |
| c3->key.hek.words[4] = hashExtData[4]; /* heks bytes 19 - 16 */ |
| c3->key.hek.words[3] = hashExtData[3]; /* heks bytes 15 - 12 */ |
| c3->key.hek.words[2] = hashExtData[2]; /* heks bytes 11 - 8 */ |
| c3->key.hek.words[1] = hashExtData[1]; /* heks bytes 7 - 4 */ |
| c3->key.hek.words[0] = hashExtData[0]; /* heks bytes 3 - 0 */ |
| |
| /* write key control data to SW*/ |
| |
| c3->key.key_ctrl |= (((hashData[3] & KEY_PRT_ID_MASK(isExt)) >> |
| (KEY_PRT_ID(isExt) % DWORD_BITS_LEN)) << KEY_CTRL_PRT_ID); |
| |
| /* PPv2.1 (feature MAS 3.16) LKP_TYPE size and offset changed */ |
| |
| c3->key.key_ctrl |= (((hashData[3] & KEY_PRT_ID_TYPE_MASK(isExt)) >> |
| (KEY_PRT_ID_TYPE(isExt) % DWORD_BITS_LEN)) << KEY_CTRL_PRT_ID_TYPE); |
| |
| c3->key.key_ctrl |= ((((hashData[2] & 0xf8000000) >> 27) | |
| ((hashData[3] & 0x1) << 5)) << KEY_CTRL_LKP_TYPE); |
| |
| |
| c3->key.key_ctrl |= (((hashData[2] & KEY_L4_INFO_MASK(isExt)) >> |
| (KEY_L4_INFO(isExt) % DWORD_BITS_LEN)) << KEY_CTRL_L4); |
| } |
| |
| /* update hek size */ |
| c3->key.key_ctrl |= ((mvCls3ShadowTbl[index].size << KEY_CTRL_HEK_SIZE) & KEY_CTRL_HEK_SIZE_MASK); |
| |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| /* ppv2.1 MAS 3.12 */ |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3HwMissRead(MV_PP2_CLS_C3_ENTRY *c3, int lkp_type) |
| { |
| unsigned int regVal = 0; |
| |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(lkp_type, MV_PP2_CLS_C3_MISS_TBL_SIZE - 1); |
| |
| mvPp2ClsC3SwClear(c3); |
| |
| c3->index = lkp_type; |
| c3->ext_index = NOT_IN_USE; |
| |
| regVal = (lkp_type << MV_PP2_CLS3_HASH_OP_TBL_ADDR) | MV_PP2_CLS3_MISS_PTR_MASK; |
| mvPp2WrReg(MV_PP2_CLS3_HASH_OP_REG, regVal); |
| |
| /* read action table */ |
| c3->sram.regs.actions = mvPp2RdReg(MV_PP2_CLS3_ACT_REG); |
| c3->sram.regs.qos_attr = mvPp2RdReg(MV_PP2_CLS3_ACT_QOS_ATTR_REG); |
| c3->sram.regs.hwf_attr = mvPp2RdReg(MV_PP2_CLS3_ACT_HWF_ATTR_REG); |
| c3->sram.regs.dup_attr = mvPp2RdReg(MV_PP2_CLS3_ACT_DUP_ATTR_REG); |
| c3->sram.regs.seq_l_attr = mvPp2RdReg(MV_PP2_CLS3_ACT_SEQ_L_ATTR_REG); |
| c3->sram.regs.seq_h_attr = mvPp2RdReg(MV_PP2_CLS3_ACT_SEQ_H_ATTR_REG); |
| |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3SwDump(MV_PP2_CLS_C3_ENTRY *c3) |
| { |
| int hekSize; |
| |
| PTR_VALIDATE(c3); |
| |
| mvOsPrintf("\n"); |
| mvOsPrintf("INDEX[0x%3.3x] ", c3->index); |
| |
| hekSize = ((c3->key.key_ctrl & KEY_CTRL_HEK_SIZE_MASK) >> KEY_CTRL_HEK_SIZE); |
| |
| /* print extension index if exist*/ |
| if (hekSize > MV_PP2_CLS_C3_HEK_BYTES) |
| /* extension */ |
| mvOsPrintf("EXT_INDEX[0x%2.2x] ", c3->ext_index); |
| else |
| /* without extension */ |
| mvOsPrintf("EXT_INDEX[ NA ] "); |
| |
| mvOsPrintf("SIZE[0x%2.2x] ", hekSize); |
| mvOsPrintf("PRT[ID = 0x%2.2x,TYPE = 0x%1.1x] ", |
| ((c3->key.key_ctrl & KEY_CTRL_PRT_ID_MASK) >> KEY_CTRL_PRT_ID), |
| ((c3->key.key_ctrl & KEY_CTRL_PRT_ID_TYPE_MASK) >> KEY_CTRL_PRT_ID_TYPE)); |
| |
| mvOsPrintf("LKP_TYPE[0x%1.1x] ", |
| ((c3->key.key_ctrl & KEY_CTRL_LKP_TYPE_MASK) >> KEY_CTRL_LKP_TYPE)); |
| |
| mvOsPrintf("L4INFO[0x%1.1x] ", |
| ((c3->key.key_ctrl & KEY_CTRL_L4_MASK) >> KEY_CTRL_L4)); |
| |
| mvOsPrintf("\n\n"); |
| mvOsPrintf("HEK "); |
| if (hekSize > MV_PP2_CLS_C3_HEK_BYTES) |
| /* extension */ |
| mvOsPrintf(HEK_EXT_FMT, HEK_EXT_VAL(c3->key.hek.words)); |
| else |
| /* without extension */ |
| mvOsPrintf(HEK_FMT, HEK_VAL(c3->key.hek.words)); |
| mvOsPrintf("\n"); |
| return mvPp2ClsC3SwActDump(c3); |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| |
| static int mvPp2ClsC3SwActDump(MV_PP2_CLS_C3_ENTRY *c3) |
| { |
| PTR_VALIDATE(c3); |
| mvOsPrintf("\n"); |
| |
| /*------------------------------*/ |
| /* actions 0x1D40 */ |
| /*------------------------------*/ |
| |
| mvOsPrintf("ACT_TBL: COLOR LOW_Q HIGH_Q FWD POLICER FID\n"); |
| mvOsPrintf("CMD: [%1d] [%1d] [%1d] [%1d] [%1d] [%1d]\n", |
| ((c3->sram.regs.actions & (ACT_COLOR_MASK)) >> ACT_COLOR), |
| ((c3->sram.regs.actions & (ACT_LOW_Q_MASK)) >> ACT_LOW_Q), |
| ((c3->sram.regs.actions & (ACT_HIGH_Q_MASK)) >> ACT_HIGH_Q), |
| ((c3->sram.regs.actions & ACT_FWD_MASK) >> ACT_FWD), |
| ((c3->sram.regs.actions & (ACT_POLICER_SELECT_MASK)) >> ACT_POLICER_SELECT), |
| ((c3->sram.regs.actions & ACT_FLOW_ID_EN_MASK) >> ACT_FLOW_ID_EN)); |
| |
| mvOsPrintf("VAL: [%1d] [0x%x]\n", |
| ((c3->sram.regs.qos_attr & (ACT_QOS_ATTR_MDF_LOW_Q_MASK)) >> ACT_QOS_ATTR_MDF_LOW_Q), |
| ((c3->sram.regs.qos_attr & (ACT_QOS_ATTR_MDF_HIGH_Q_MASK)) >> ACT_QOS_ATTR_MDF_HIGH_Q)); |
| |
| mvOsPrintf("\n"); |
| /*------------------------------*/ |
| /* hwf_attr 0x1D48 */ |
| /*------------------------------*/ |
| |
| mvOsPrintf("HWF_ATTR: IPTR DPTR CHKSM MTU_IDX\n"); |
| mvOsPrintf(" 0x%1.1x 0x%4.4x %s 0x%1.1x\n", |
| |
| ((c3->sram.regs.hwf_attr & ACT_HWF_ATTR_IPTR_MASK) >> ACT_HWF_ATTR_IPTR), |
| ((c3->sram.regs.hwf_attr & ACT_HWF_ATTR_DPTR_MASK) >> ACT_HWF_ATTR_DPTR), |
| (((c3->sram.regs.hwf_attr & |
| ACT_HWF_ATTR_CHKSM_EN_MASK) >> ACT_HWF_ATTR_CHKSM_EN) ? "ENABLE" : "DISABLE"), |
| ((c3->sram.regs.hwf_attr & ACT_HWF_ATTR_MTU_INX_MASK) >> ACT_HWF_ATTR_MTU_INX)); |
| mvOsPrintf("\n"); |
| /*------------------------------*/ |
| /* dup_attr 0x1D4C */ |
| /*------------------------------*/ |
| mvOsPrintf("DUP_ATTR:FID COUNT POLICER [id bank]\n"); |
| mvOsPrintf(" 0x%2.2x\t0x%1.1x\t\t[0x%2.2x 0x%1.1x]\n", |
| ((c3->sram.regs.dup_attr & ACT_DUP_FID_MASK) >> ACT_DUP_FID), |
| ((c3->sram.regs.dup_attr & ACT_DUP_COUNT_MASK) >> ACT_DUP_COUNT), |
| ((c3->sram.regs.dup_attr & ACT_DUP_POLICER_MASK) >> ACT_DUP_POLICER_ID), |
| ((c3->sram.regs.dup_attr & ACT_DUP_POLICER_BANK_MASK) >> ACT_DUP_POLICER_BANK_BIT)); |
| mvOsPrintf("\n"); |
| mvOsPrintf("SEQ_ATTR: HIGH[32:37] LOW[0:31]\n"); |
| mvOsPrintf(" 0x%2.2x 0x%8.8x", c3->sram.regs.seq_h_attr, c3->sram.regs.seq_l_attr); |
| |
| |
| mvOsPrintf("\n\n"); |
| |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3HwDump() |
| { |
| int index; |
| MV_PP2_CLS_C3_ENTRY c3; |
| |
| mvPp2ClsC3SwClear(&c3); |
| |
| for (index = 0; index < MV_PP2_CLS_C3_HASH_TBL_SIZE; index++) { |
| if (mvCls3ShadowTbl[index].size > 0) { |
| mvPp2ClsC3HwRead(&c3, index); |
| mvPp2ClsC3SwDump(&c3); |
| mvOsPrintf("----------------------------------------------------------------------\n"); |
| } |
| } |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| /* |
| All miss entries are valid, |
| the key+heks in miss entries are hot in use and this is the |
| reason that we dump onlt action table fields |
| */ |
| int mvPp2ClsC3HwMissDump() |
| { |
| int index; |
| MV_PP2_CLS_C3_ENTRY c3; |
| |
| mvPp2ClsC3SwClear(&c3); |
| |
| for (index = 0; index < MV_PP2_CLS_C3_MISS_TBL_SIZE; index++) { |
| mvPp2ClsC3HwMissRead(&c3, index); |
| mvOsPrintf("INDEX[0x%3.3X]\n", index); |
| mvPp2ClsC3SwActDump(&c3); |
| mvOsPrintf("----------------------------------------------------------------------\n"); |
| } |
| |
| return MV_OK; |
| } |
| |
| |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3HwExtDump() |
| { |
| int index, i; |
| unsigned int hashExtData[MV_PP2_CLS3_HASH_EXT_DATA_REG_NUM]; |
| |
| mvOsPrintf("INDEX DATA\n"); |
| |
| for (index = 0; index < MV_PP2_CLS_C3_EXT_TBL_SIZE; index++) |
| if (mvCls3ShadowExtTbl[index] == IN_USE) { |
| /* write extension index */ |
| mvPp2WrReg(MV_PP2_CLS3_DB_INDEX_REG, index); |
| |
| /* read hash extesion data*/ |
| for (i = 0; i < MV_PP2_CLS3_HASH_EXT_DATA_REG_NUM; i++) |
| hashExtData[i] = mvPp2RdReg(MV_PP2_CLS3_HASH_EXT_DATA_REG(i)); |
| |
| mvOsPrintf("[0x%2.2x] %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x\n", |
| index, hashExtData[6], hashExtData[5], hashExtData[4], |
| hashExtData[3], hashExtData[2], hashExtData[1], hashExtData[0]); |
| } /* if */ |
| |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| /* APIs for Classification C3 key fields */ |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3SwL4infoSet(MV_PP2_CLS_C3_ENTRY *c3, int l4info) |
| { |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(l4info, KEY_CTRL_L4_MAX); |
| |
| c3->key.key_ctrl &= ~KEY_CTRL_L4_MASK; |
| c3->key.key_ctrl |= (l4info << KEY_CTRL_L4); |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3SwLkpTypeSet(MV_PP2_CLS_C3_ENTRY *c3, int lkp_type) |
| { |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(lkp_type, KEY_CTRL_LKP_TYPE_MAX); |
| |
| c3->key.key_ctrl &= ~KEY_CTRL_LKP_TYPE_MASK; |
| c3->key.key_ctrl |= (lkp_type << KEY_CTRL_LKP_TYPE); |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3SwPortIDSet(MV_PP2_CLS_C3_ENTRY *c3, int type, int portid) |
| { |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(portid, KEY_CTRL_PRT_ID_MAX); |
| POS_RANGE_VALIDATE(type, KEY_CTRL_PRT_ID_TYPE_MAX); |
| |
| c3->key.key_ctrl &= ~(KEY_CTRL_PRT_ID_MASK | KEY_CTRL_PRT_ID_TYPE_MASK); |
| c3->key.key_ctrl |= ((portid << KEY_CTRL_PRT_ID) | (type << KEY_CTRL_PRT_ID_TYPE)); |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3SwHekSizeSet(MV_PP2_CLS_C3_ENTRY *c3, int hekSize) |
| { |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(hekSize, KEY_CTRL_HEK_SIZE_MAX); |
| |
| c3->key.key_ctrl &= ~KEY_CTRL_HEK_SIZE_MASK; |
| c3->key.key_ctrl |= (hekSize << KEY_CTRL_HEK_SIZE); |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3SwHekByteSet(MV_PP2_CLS_C3_ENTRY *c3, unsigned int offs, unsigned char byte) |
| { |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(offs, ((MV_PP2_CLS_C3_EXT_HEK_WORDS*4) - 1)); |
| |
| c3->key.hek.bytes[HW_BYTE_OFFS(offs)] = byte; |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3SwHekWordSet(MV_PP2_CLS_C3_ENTRY *c3, unsigned int offs, unsigned int word) |
| { |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(offs, ((MV_PP2_CLS_C3_EXT_HEK_WORDS) - 1)); |
| |
| c3->key.hek.words[offs] = word; |
| |
| return MV_OK; |
| } |
| |
| |
| /*-------------------------------------------------------------------------------*/ |
| /* APIs for Classification C3 action table fields */ |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3ColorSet(MV_PP2_CLS_C3_ENTRY *c3, int cmd) |
| { |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(cmd, COLOR_RED_AND_LOCK); |
| |
| c3->sram.regs.actions &= ~ACT_COLOR_MASK; |
| c3->sram.regs.actions |= (cmd << ACT_COLOR); |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3QueueHighSet(MV_PP2_CLS_C3_ENTRY *c3, int cmd, int queue) |
| { |
| PTR_VALIDATE(c3); |
| |
| |
| POS_RANGE_VALIDATE(cmd, UPDATE_AND_LOCK); |
| POS_RANGE_VALIDATE(queue, ACT_QOS_ATTR_MDF_HIGH_Q_MAX); |
| |
| /*set command*/ |
| c3->sram.regs.actions &= ~ACT_HIGH_Q_MASK; |
| c3->sram.regs.actions |= (cmd << ACT_HIGH_Q); |
| |
| /*set modify High queue value*/ |
| c3->sram.regs.qos_attr &= ~ACT_QOS_ATTR_MDF_HIGH_Q_MASK; |
| c3->sram.regs.qos_attr |= (queue << ACT_QOS_ATTR_MDF_HIGH_Q); |
| |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3QueueLowSet(MV_PP2_CLS_C3_ENTRY *c3, int cmd, int queue) |
| { |
| PTR_VALIDATE(c3); |
| |
| POS_RANGE_VALIDATE(cmd, UPDATE_AND_LOCK); |
| POS_RANGE_VALIDATE(queue, ACT_QOS_ATTR_MDF_LOW_Q_MAX); |
| |
| /*set command*/ |
| c3->sram.regs.actions &= ~ACT_LOW_Q_MASK; |
| c3->sram.regs.actions |= (cmd << ACT_LOW_Q); |
| |
| /*set modify High queue value*/ |
| c3->sram.regs.qos_attr &= ~ACT_QOS_ATTR_MDF_LOW_Q_MASK; |
| c3->sram.regs.qos_attr |= (queue << ACT_QOS_ATTR_MDF_LOW_Q); |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3QueueSet(MV_PP2_CLS_C3_ENTRY *c3, int cmd, int queue) |
| { |
| int status = MV_OK; |
| int qHigh, qLow; |
| |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(queue, ACT_QOS_ATTR_Q_MAX); |
| |
| /* cmd validation in set functions */ |
| |
| qHigh = (queue & ACT_QOS_ATTR_MDF_HIGH_Q_MASK) >> ACT_QOS_ATTR_MDF_HIGH_Q; |
| qLow = (queue & ACT_QOS_ATTR_MDF_LOW_Q_MASK) >> ACT_QOS_ATTR_MDF_LOW_Q; |
| |
| status |= mvPp2ClsC3QueueLowSet(c3, cmd, qLow); |
| status |= mvPp2ClsC3QueueHighSet(c3, cmd, qHigh); |
| |
| return status; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3ForwardSet(MV_PP2_CLS_C3_ENTRY *c3, int cmd) |
| { |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(cmd, HWF_AND_LOW_LATENCY_AND_LOCK); |
| |
| c3->sram.regs.actions &= ~ACT_FWD_MASK; |
| c3->sram.regs.actions |= (cmd << ACT_FWD); |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3PolicerSet(MV_PP2_CLS_C3_ENTRY *c3, int cmd, int policerId, int bank) |
| { |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(cmd, UPDATE_AND_LOCK); |
| POS_RANGE_VALIDATE(policerId, ACT_DUP_POLICER_MAX); |
| BIT_RANGE_VALIDATE(bank); |
| |
| c3->sram.regs.actions &= ~ACT_POLICER_SELECT_MASK; |
| c3->sram.regs.actions |= (cmd << ACT_POLICER_SELECT); |
| |
| c3->sram.regs.dup_attr &= ~ACT_DUP_POLICER_MASK; |
| c3->sram.regs.dup_attr |= (policerId << ACT_DUP_POLICER_ID); |
| |
| if (bank) |
| c3->sram.regs.dup_attr |= ACT_DUP_POLICER_BANK_MASK; |
| else |
| c3->sram.regs.dup_attr &= ~ACT_DUP_POLICER_BANK_MASK; |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3FlowIdEn(MV_PP2_CLS_C3_ENTRY *c3, int flowid_en) |
| { |
| PTR_VALIDATE(c3); |
| |
| /*set Flow ID enable or disable*/ |
| if (flowid_en) |
| c3->sram.regs.actions |= (1 << ACT_FLOW_ID_EN); |
| else |
| c3->sram.regs.actions &= ~(1 << ACT_FLOW_ID_EN); |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| /* |
| PPv2.1 (feature MAS 3.7) function changed , get also MTU index as parameter |
| */ |
| int mvPp2ClsC3ModSet(MV_PP2_CLS_C3_ENTRY *c3, int data_ptr, int instr_offs, int l4_csum) |
| { |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(data_ptr, ACT_HWF_ATTR_DPTR_MAX); |
| POS_RANGE_VALIDATE(instr_offs, ACT_HWF_ATTR_IPTR_MAX); |
| POS_RANGE_VALIDATE(l4_csum, 1); |
| |
| c3->sram.regs.hwf_attr &= ~ACT_HWF_ATTR_DPTR_MASK; |
| c3->sram.regs.hwf_attr &= ~ACT_HWF_ATTR_IPTR_MASK; |
| c3->sram.regs.hwf_attr &= ~ACT_HWF_ATTR_CHKSM_EN_MASK; |
| |
| c3->sram.regs.hwf_attr |= (data_ptr << ACT_HWF_ATTR_DPTR); |
| c3->sram.regs.hwf_attr |= (instr_offs << ACT_HWF_ATTR_IPTR); |
| c3->sram.regs.hwf_attr |= (l4_csum << ACT_HWF_ATTR_CHKSM_EN); |
| |
| return MV_OK; |
| } |
| |
| |
| /*-------------------------------------------------------------------------------*/ |
| /* |
| PPv2.1 (feature MAS 3.7) mtu - new field at action table |
| */ |
| |
| int mvPp2ClsC3MtuSet(MV_PP2_CLS_C3_ENTRY *c3, int mtu_inx) |
| { |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(mtu_inx, ACT_HWF_ATTR_MTU_INX_MAX); |
| |
| c3->sram.regs.hwf_attr &= ~ACT_HWF_ATTR_MTU_INX_MASK; |
| c3->sram.regs.hwf_attr |= (mtu_inx << ACT_HWF_ATTR_MTU_INX); |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3DupSet(MV_PP2_CLS_C3_ENTRY *c3, int dupid, int count) |
| { |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(count, ACT_DUP_COUNT_MAX); |
| POS_RANGE_VALIDATE(dupid, ACT_DUP_FID_MAX); |
| |
| /*set flowid and count*/ |
| c3->sram.regs.dup_attr &= ~(ACT_DUP_FID_MASK | ACT_DUP_COUNT_MASK); |
| c3->sram.regs.dup_attr |= (dupid << ACT_DUP_FID); |
| c3->sram.regs.dup_attr |= (count << ACT_DUP_COUNT); |
| |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| /* PPv2.1 (feature MAS 3.14) cls sequence */ |
| int mvPp2ClsC3SeqSet(MV_PP2_CLS_C3_ENTRY *c3, int id, int bits_offs, int bits) |
| { |
| unsigned int low_bits, high_bits = 0; |
| |
| PTR_VALIDATE(c3); |
| POS_RANGE_VALIDATE(bits, MV_PP2_CLS_SEQ_SIZE_MAX); |
| POS_RANGE_VALIDATE(id, (1 << bits) - 1); |
| POS_RANGE_VALIDATE(bits_offs + bits, MV_PP2_CLS3_ACT_SEQ_SIZE); |
| |
| if (bits_offs >= DWORD_BITS_LEN) |
| high_bits = bits; |
| |
| else if (bits_offs + bits > DWORD_BITS_LEN) |
| high_bits = (bits_offs + bits) % DWORD_BITS_LEN; |
| |
| low_bits = bits - high_bits; |
| |
| /* |
| high_bits hold the num of bits that we need to write in seq_h_attr |
| low_bits hold the num of bits that we need to write in seq_l_attr |
| */ |
| |
| if (low_bits) { |
| /* mask and set new value in seq_l_attr*/ |
| c3->sram.regs.seq_l_attr &= ~(((1 << low_bits) - 1) << bits_offs); |
| c3->sram.regs.seq_l_attr |= (id << bits_offs); |
| } |
| |
| if (high_bits) { |
| int high_id = id >> low_bits; |
| int high_offs = (low_bits == 0) ? (bits_offs % DWORD_BITS_LEN) : 0; |
| |
| /* mask and set new value in seq_h_attr*/ |
| c3->sram.regs.seq_h_attr &= ~(((1 << high_bits) - 1) << high_offs); |
| c3->sram.regs.seq_h_attr |= (high_id << high_offs); |
| } |
| |
| return MV_OK; |
| |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| /* APIs for Classification C3 Hit counters management */ |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3HitCntrsClear(int lkpType) |
| { |
| /* clear all counters that entry lookup type corresponding to lkpType */ |
| int iter = 0; |
| |
| POS_RANGE_VALIDATE(lkpType, KEY_CTRL_LKP_TYPE_MAX); |
| |
| mvPp2WrReg(MV_PP2_CLS3_CLEAR_COUNTERS_REG, lkpType); |
| |
| /* wait to clear het counters done bit */ |
| while (!mvPp2ClsC3HitCntrClearDone()) |
| if (++iter >= RETRIES_EXCEEDED) { |
| mvOsPrintf("%s:Error - retries exceeded.\n", __func__); |
| return MV_CLS3_RETRIES_EXCEEDED; |
| } |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3HitCntrsClearAll(void) |
| { |
| int iter = 0; |
| /* |
| PPv2.1 (feature MAS 3.16) CLEAR_COUNTERS size changed, clear all code changed from 0x1f to 0x3f |
| */ |
| |
| mvPp2WrReg(MV_PP2_CLS3_CLEAR_COUNTERS_REG, MV_PP2_V1_CLS3_CLEAR_ALL); |
| /* wait to clear het counters done bit */ |
| while (!mvPp2ClsC3HitCntrClearDone()) |
| if (++iter >= RETRIES_EXCEEDED) { |
| mvOsPrintf("%s:Error - retries exceeded.\n", __func__); |
| return MV_CLS3_RETRIES_EXCEEDED; |
| } |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3HitCntrsRead(int index, MV_U32 *cntr) |
| { |
| unsigned int counter; |
| |
| POS_RANGE_VALIDATE(index, MV_PP2_CLS3_HASH_OP_TBL_ADDR_MAX); |
| |
| /*write entry index*/ |
| mvPp2WrReg(MV_PP2_CLS3_DB_INDEX_REG, index); |
| |
| /*counter read*/ |
| counter = mvPp2RdReg(MV_PP2_CLS3_HIT_COUNTER_REG) & MV_PP2_V1_CLS3_HIT_COUNTER_MASK; |
| |
| if (!cntr) |
| mvOsPrintf("ADDR:0x%3.3x COUNTER VAL:0x%6.6x\n", index, counter); |
| else |
| *cntr = counter; |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3HitCntrsMissRead(int lkp_type, MV_U32 *cntr) |
| { |
| unsigned int counter; |
| int index; |
| |
| POS_RANGE_VALIDATE(lkp_type, MV_PP2_CLS_C3_MISS_TBL_SIZE - 1); |
| |
| |
| /*set miss bit to 1, ppv2.1 mas 3.16*/ |
| index = (lkp_type | MV_PP2_CLS3_DB_MISS_MASK); |
| |
| /*write entry index*/ |
| mvPp2WrReg(MV_PP2_CLS3_DB_INDEX_REG, index); |
| |
| /*counter read*/ |
| counter = mvPp2RdReg(MV_PP2_CLS3_HIT_COUNTER_REG) & MV_PP2_V1_CLS3_HIT_COUNTER_MASK; |
| |
| if (!cntr) |
| mvOsPrintf("LKPT:0x%3.3x COUNTER VAL:0x%6.6x\n", lkp_type, counter); |
| else |
| *cntr = counter; |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3HitCntrsReadAll(void) |
| { |
| unsigned int counter, index; |
| |
| for (index = 0; index < MV_PP2_CLS_C3_HASH_TBL_SIZE; index++) { |
| mvPp2ClsC3HitCntrsRead(index, &counter); |
| |
| /* skip initial counter value */ |
| if (counter == 0) |
| continue; |
| |
| mvOsPrintf("ADDR:0x%3.3x COUNTER VAL:0x%6.6x\n", index, counter); |
| } |
| |
| for (index = 0; index < MV_PP2_CLS_C3_MISS_TBL_SIZE; index++) { |
| mvPp2ClsC3HitCntrsMissRead(index, &counter); |
| |
| /* skip initial counter value */ |
| if (counter == 0) |
| continue; |
| |
| mvOsPrintf("LKPT:0x%3.3x COUNTER VAL:0x%6.6x\n", index, counter); |
| } |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| /* APIs for Classification C3 hit counters scan fields operation */ |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3ScanStart() |
| { |
| int complete, iter = 0; |
| |
| /* trigger scan operation */ |
| mvPp2WrReg(MV_PP2_CLS3_SC_ACT_REG, (1 << MV_PP2_CLS3_SC_ACT)); |
| |
| do { |
| complete = mvPp2ClsC3ScanIsComplete(); |
| |
| } while ((!complete) && ((iter++) < RETRIES_EXCEEDED));/*scan compleated*/ |
| |
| if (iter >= RETRIES_EXCEEDED) { |
| return MV_CLS3_RETRIES_EXCEEDED; |
| } |
| |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3ScanRegs() |
| { |
| unsigned int prop, propVal; |
| unsigned int treshHold; |
| treshHold = mvPp2RdReg(MV_PP2_CLS3_SC_TH_REG); |
| |
| prop = mvPp2RdReg(MV_PP2_CLS3_SC_PROP_REG); |
| propVal = mvPp2RdReg(MV_PP2_CLS3_SC_PROP_VAL_REG); |
| |
| |
| mvOsPrintf("%-32s: 0x%x = 0x%08x\n", "MV_PP2_CLS3_SC_PROP_REG", MV_PP2_CLS3_SC_PROP_REG, prop); |
| mvOsPrintf("%-32s: 0x%x = 0x%08x\n", "MV_PP2_CLS3_SC_PROP_VAL_REG", MV_PP2_CLS3_SC_PROP_VAL_REG, propVal); |
| mvOsPrintf("\n"); |
| |
| mvOsPrintf("MODE = %s\n", ((MV_PP2_CLS3_SC_PROP_TH_MODE_MASK & prop) == 0) ? "Below" : "Above"); |
| mvOsPrintf("CLEAR = %s\n", ((MV_PP2_CLS3_SC_PROP_CLEAR_MASK & prop) == 0) ? "NoClear" : "Clear "); |
| |
| /* lookup type */ |
| ((MV_PP2_CLS3_SC_PROP_LKP_TYPE_EN_MASK & prop) == 0) ? |
| mvOsPrintf("LKP_TYPE = NA\n") : |
| mvOsPrintf("LKP_TYPE = 0x%x\n", ((MV_PP2_CLS3_SC_PROP_LKP_TYPE_MASK & prop) >> MV_PP2_CLS3_SC_PROP_LKP_TYPE)); |
| |
| /* start index */ |
| mvOsPrintf("START = 0x%x\n", (MV_PP2_CLS3_SC_PROP_START_ENTRY_MASK & prop) >> MV_PP2_CLS3_SC_PROP_START_ENTRY); |
| /* threshold */ |
| mvOsPrintf("THRESHOLD = 0x%x\n", (MV_PP2_CLS3_SC_TH_MASK & treshHold) >> MV_PP2_CLS3_SC_TH); |
| |
| /* delay value */ |
| mvOsPrintf("DELAY = 0x%x\n\n", |
| (MV_PP2_V1_CLS3_SC_PROP_VAL_DELAY_MASK & propVal) >> MV_PP2_V1_CLS3_SC_PROP_VAL_DELAY); |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| /*mod = 0 below th . mode = 1 above threshold*/ |
| int mvPp2ClsC3ScanThreshSet(int mode, int thresh) |
| { |
| unsigned int regVal; |
| |
| POS_RANGE_VALIDATE(mode, 1); /* one bit */ |
| POS_RANGE_VALIDATE(thresh, MV_PP2_CLS3_SC_TH_MAX); |
| |
| regVal = mvPp2RdReg(MV_PP2_CLS3_SC_PROP_REG); |
| regVal &= ~MV_PP2_CLS3_SC_PROP_TH_MODE_MASK; |
| regVal |= (mode << MV_PP2_CLS3_SC_PROP_TH_MODE); |
| mvPp2WrReg(MV_PP2_CLS3_SC_PROP_REG, regVal); |
| |
| regVal = mvPp2RdReg(MV_PP2_CLS3_SC_TH_REG); |
| regVal &= ~MV_PP2_CLS3_SC_TH_MASK; |
| regVal |= (thresh << MV_PP2_CLS3_SC_TH); |
| mvPp2WrReg(MV_PP2_CLS3_SC_TH_REG, regVal); |
| |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3ScanLkpTypeSet(int type) |
| { |
| unsigned int prop; |
| |
| RANGE_VALIDATE(type, -1, MV_PP2_CLS3_SC_PROP_LKP_TYPE_MAX); |
| prop = mvPp2RdReg(MV_PP2_CLS3_SC_PROP_REG); |
| |
| if (type == -1) |
| /* scan all entries */ |
| prop &= ~(1 << MV_PP2_CLS3_SC_PROP_LKP_TYPE_EN); |
| else { |
| /* scan according to lookup type */ |
| prop |= (1 << MV_PP2_CLS3_SC_PROP_LKP_TYPE_EN); |
| prop &= ~MV_PP2_CLS3_SC_PROP_LKP_TYPE_MASK; |
| prop |= (type << MV_PP2_CLS3_SC_PROP_LKP_TYPE); |
| } |
| |
| mvPp2WrReg(MV_PP2_CLS3_SC_PROP_REG, prop); |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3ScanClearBeforeEnSet(int en) |
| { |
| unsigned int prop; |
| |
| POS_RANGE_VALIDATE(en, 1); /* one bit */ |
| |
| prop = mvPp2RdReg(MV_PP2_CLS3_SC_PROP_REG); |
| |
| prop &= ~MV_PP2_CLS3_SC_PROP_CLEAR_MASK; |
| prop |= (en << MV_PP2_CLS3_SC_PROP_CLEAR); |
| |
| mvPp2WrReg(MV_PP2_CLS3_SC_PROP_REG, prop); |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3ScanStartIndexSet(int idx) |
| { |
| unsigned int prop; |
| |
| POS_RANGE_VALIDATE(idx, MV_PP2_CLS3_HASH_OP_TBL_ADDR_MAX); /* one bit */ |
| |
| prop = mvPp2RdReg(MV_PP2_CLS3_SC_PROP_REG); |
| |
| prop &= ~MV_PP2_CLS3_SC_PROP_START_ENTRY_MASK; |
| prop |= (idx << MV_PP2_CLS3_SC_PROP_START_ENTRY); |
| |
| mvPp2WrReg(MV_PP2_CLS3_SC_PROP_REG, prop); |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| |
| int mvPp2ClsC3ScanDelaySet(int time) |
| { |
| unsigned int propVal; |
| |
| POS_RANGE_VALIDATE(time, MV_PP2_CLS3_SC_PROP_VAL_DELAY_MAX); |
| |
| propVal = mvPp2RdReg(MV_PP2_CLS3_SC_PROP_VAL_REG); |
| propVal &= ~MV_PP2_V1_CLS3_SC_PROP_VAL_DELAY_MASK; |
| propVal |= (time << MV_PP2_V1_CLS3_SC_PROP_VAL_DELAY); |
| mvPp2WrReg(MV_PP2_CLS3_SC_PROP_VAL_REG, propVal); |
| |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3ScanResRead(int index, int *addr, int *cnt) |
| { |
| unsigned int regVal, scState, addres, counter; |
| int iter = 0; |
| |
| POS_RANGE_VALIDATE(index, MV_PP2_CLS_C3_SC_RES_TBL_SIZE-1); |
| |
| do { |
| mvPp2ClsC3ScanStateGet(&scState); |
| } while (scState != 0 && ((iter++) < RETRIES_EXCEEDED));/*scan compleated*/ |
| |
| if (iter >= RETRIES_EXCEEDED) { |
| mvOsPrintf("%s:Error - retries exceeded.\n", __func__); |
| return MV_CLS3_RETRIES_EXCEEDED; |
| } |
| |
| /*write index*/ |
| mvPp2WrReg(MV_PP2_CLS3_SC_INDEX_REG, index); |
| |
| /*read date*/ |
| regVal = mvPp2RdReg(MV_PP2_CLS3_SC_RES_REG); |
| addres = (regVal & MV_PP2_CLS3_SC_RES_ENTRY_MASK) >> MV_PP2_CLS3_SC_RES_ENTRY; |
| counter = (regVal & MV_PP2_V1_CLS3_SC_RES_CTR_MASK) >> MV_PP2_V1_CLS3_SC_RES_CTR; |
| /* if one of parameters is null - func call from sysfs*/ |
| if ((!addr) | (!cnt)) |
| mvOsPrintf("INDEX:0x%2.2x ADDR:0x%3.3x COUNTER VAL:0x%6.6x\n", index, addres, counter); |
| else { |
| *addr = addres; |
| *cnt = counter; |
| } |
| |
| return MV_OK; |
| } |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3ScanResDump() |
| { |
| int addr, cnt, resNum, index; |
| |
| mvPp2ClsC3ScanNumOfResGet(&resNum); |
| |
| mvOsPrintf("INDEX ADDRESS COUNTER\n"); |
| for (index = 0; index < resNum; index++) { |
| mvPp2ClsC3ScanResRead(index, &addr, &cnt); |
| mvOsPrintf("[0x%2.2x]\t[0x%3.3x]\t[0x%6.6x]\n", index, addr, cnt); |
| } |
| |
| return MV_OK; |
| } |
| |
| /*-------------------------------------------------------------------------------*/ |
| int mvPp2ClsC3ScanNumOfResGet(int *resNum) |
| { |
| unsigned int regVal, scState; |
| int iter = 0; |
| |
| do { |
| mvPp2ClsC3ScanStateGet(&scState); |
| } while (scState != 0 && ((iter++) < RETRIES_EXCEEDED));/*scan compleated*/ |
| |
| if (iter >= RETRIES_EXCEEDED) { |
| mvOsPrintf("%s:Error - retries exceeded.\n", __func__); |
| return MV_CLS3_RETRIES_EXCEEDED; |
| } |
| |
| regVal = mvPp2RdReg(MV_PP2_CLS3_STATE_REG); |
| regVal &= MV_PP2_CLS3_STATE_NO_OF_SC_RES_MASK; |
| regVal >>= MV_PP2_CLS3_STATE_NO_OF_SC_RES; |
| *resNum = regVal; |
| return MV_OK; |
| } |
| /*------------------------------------------------------------------------------- |
| |
| int mvPp2ClsC3ScanTimerGet(int *timer) |
| { |
| unsigned int regVal; |
| |
| if (timer == NULL) { |
| mvOsPrintf("mvCls3Hw %s: null pointer.\n", __func__); |
| return MV_CLS3_ERR; |
| } |
| |
| regVal = mvPp2RdReg(MV_PP2_CLS3_SC_TIMER_REG); |
| regVal &= MV_PP2_CLS3_SC_TIMER_MASK; |
| regVal >>= MV_PP2_CLS3_SC_TIMER; |
| *timer = regVal; |
| return MV_OK; |
| } |
| -------------------------------------------------------------------------------------*/ |