hurricane2.c (256043B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: hurricane2.c 8 * Purpose: 9 * Requires: 10 */ 11 12 13 #include <shared/bsl.h> 14 15 #include <sal/core/boot.h> 16 #include <shared/bsl.h> 17 #include <soc/firebolt.h> 18 #include <soc/bradley.h> 19 #include <soc/hurricane2.h> 20 #include <soc/drv.h> 21 #include <soc/mem.h> 22 #include <soc/hash.h> 23 #include <soc/lpm.h> 24 #include <soc/error.h> 25 #include <soc/debug.h> 26 #include <soc/er_tcam.h> 27 #include <soc/memtune.h> 28 #include <soc/devids.h> 29 #include <soc/mspi.h> 30 31 #include <shared/util.h> 32 #include <shared/l3.h> 33 #include <soc/soc_ser_log.h> 34 35 36 #ifdef BCM_HURRICANE2_SUPPORT 37 38 #define SOC_MAX_PHY_PORTS 34 39 40 /* 41 * Enduro chip driver functions. 42 */ 43 soc_functions_t soc_hurricane2_drv_funs = { 44 soc_hurricane2_misc_init, 45 soc_hurricane2_mmu_init, 46 soc_hurricane2_age_timer_get, 47 soc_hurricane2_age_timer_max_get, 48 soc_hurricane2_age_timer_set, 49 }; 50 51 typedef enum { 52 _SOC_PARITY_INFO_TYPE_GENERIC, 53 _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 54 _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 55 _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 56 _SOC_PARITY_INFO_TYPE_MMU_PARITY, 57 _SOC_PARITY_INFO_TYPE_MMU_IPMC, 58 _SOC_PARITY_INFO_TYPE_MMU_E2EFC, 59 _SOC_PARITY_INFO_TYPE_OAM, /* Not parity, but same interrupt */ 60 _SOC_PARITY_INFO_TYPE_NUM 61 } _soc_parity_info_type_t; 62 63 typedef struct _soc_parity_info_s { 64 soc_field_t enable_field; 65 soc_field_t error_field; 66 char *msg; 67 soc_mem_t mem; 68 _soc_parity_info_type_t type; 69 soc_reg_t control_reg; 70 soc_reg_t intr_status0_reg; 71 soc_reg_t intr_status1_reg; /* Also SBE force for ECC */ 72 soc_reg_t nack_status0_reg; 73 soc_reg_t nack_status1_reg; /* Also DBE force for ECC */ 74 } _soc_parity_info_t; 75 76 /* 77 * _SOC_PARITY_INFO_TYPE_SINGLE_PARITY 78 * PARITY_EN 79 * ENTRY_IDX, MULTIPLE_ERR, PARITY_ERR 80 * 81 * _SOC_PARITY_INFO_TYPE_SINGLE_ECC 82 * ECC_EN 83 * ENTRY_IDX, DOUBLE_BIT_ERR, MULTIPLE_ERR, ECC_ERR 84 * 85 * _SOC_PARITY_INFO_TYPE_SINGLE_COUNTER 86 * PARITY_EN 87 * PORT_IDX, COUNTER_IDX, MULTIPLE_ERR, PARITY_ERR 88 * 89 * _SOC_PARITY_INFO_TYPE_DUAL_PARITY 90 * PARITY_EN 91 * BUCKET_IDX, MULTIPLE_ERR, PARITY_ERR_BM 92 */ 93 94 STATIC _soc_parity_info_t _soc_hu2_ip0_parity_info[] = { 95 { PARITY_ENf, VXLT_PAR_ERRf,"VLAN_XLATE table parity error", 96 VLAN_XLATEm, _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 97 VLAN_XLATE_PARITY_CONTROLr, 98 VLAN_XLATE_PARITY_STATUS_0r, VLAN_XLATE_PARITY_STATUS_1r, 99 INVALIDr, INVALIDr }, 100 /* { PPA_CMD_COMPLETEf }, */ 101 /* { MEM_RESET_COMPLETEf }, */ 102 /* { AGE_CMD_COMPLETEf }, */ 103 { PARITY_ENf, VLAN_SUBNET_DATA_PARITY_ERRf, "VLAN_SUBNET_DATA table parity error", 104 VLAN_SUBNET_DATA_ONLYm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 105 VLAN_SUBNET_DATA_PARITY_CONTROLr, 106 VLAN_SUBNET_DATA_PARITY_STATUSr, INVALIDr, 107 INVALIDr, INVALIDr }, 108 { PARITY_ENf, VLAN_PROTOCOL_DATA_PARITY_ERRf, "VLAN_PROTOCOL_DATA table parity error", 109 VLAN_PROTOCOL_DATAm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 110 VLAN_PROTOCOL_DATA_PARITY_CONTROLr, 111 VLAN_PROTOCOL_DATA_PARITY_STATUSr, INVALIDr, 112 INVALIDr, INVALIDr }, 113 { PARITY_ENf, VLAN_PARITY_ERRf, "VLAN table parity error", 114 VLAN_TABm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 115 VLAN_PARITY_CONTROLr, 116 VLAN_PARITY_STATUSr, INVALIDr, 117 INVALIDr, INVALIDr }, 118 { PARITY_ENf, VLAN_STG_PARITY_ERRf, "VLAN_STG table parity error", 119 STG_TABm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 120 VLAN_STG_PARITY_CONTROLr, 121 VLAN_STG_PARITY_STATUSr, INVALIDr, 122 INVALIDr, INVALIDr }, 123 /* { PARITY_ENf, L3_TUNNEL_RAM_PARITY_ERRf, "L3_TUNNEL_RAM table parity error", 124 L3_TUNNELm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 125 L3_TUNNEL_DATA_ONLY_PARITY_CONTROLr, 126 L3_TUNNEL_DATA_ONLY_PARITY_STATUSr, INVALIDr, 127 INVALIDr, INVALIDr }, */ 128 { PARITY_ENf, SOURCE_TRUNK_MAP_PARITY_ERRf, "SOURCE_TRUNK_MAP table parity error", 129 SOURCE_TRUNK_MAP_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 130 SOURCE_TRUNK_MAP_PARITY_CONTROLr, 131 SOURCE_TRUNK_MAP_PARITY_STATUSr, INVALIDr, 132 INVALIDr, INVALIDr }, 133 { PARITY_ENf, VFP_POLICY_PAR_ERRf, "VFP_POLICY table parity error", 134 VFP_POLICY_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 135 VFP_POLICY_PARITY_CONTROLr, 136 VFP_POLICY_PARITY_STATUS_INTRr, INVALIDr, 137 INVALIDr, INVALIDr }, 138 { PARITY_ENf, LMEP_PAR_ERRf, "LMEP table parity error", 139 LMEPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 140 LMEP_PARITY_CONTROLr, 141 LMEP_PARITY_STATUSr, INVALIDr, 142 INVALIDr, INVALIDr }, 143 { ECC_ENf, IARB_PKT_ECC_INTRf, "Iarb packet ecc error", 144 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 145 IARB_PKT_ECC_CONTROLr, 146 IARB_PKT_ECC_STATUS_INTRr, INVALIDr, 147 INVALIDr, INVALIDr }, 148 /* IARB_HDR_ECC_INTR, no control/status regiters */ 149 { INVALIDf, INVALIDf }, /* table terminator */ 150 }; 151 152 STATIC _soc_parity_info_t _soc_wf_ip0_parity_info[] = { 153 { PARITY_ENf, VXLT_PAR_ERRf,"VLAN_XLATE table parity error", 154 VLAN_XLATEm, _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 155 VLAN_XLATE_PARITY_CONTROLr, 156 VLAN_XLATE_PARITY_STATUS_0r, VLAN_XLATE_PARITY_STATUS_1r, 157 INVALIDr, INVALIDr }, 158 /* { PPA_CMD_COMPLETEf }, */ 159 /* { MEM_RESET_COMPLETEf }, */ 160 /* { AGE_CMD_COMPLETEf }, */ 161 { PARITY_ENf, VLAN_SUBNET_DATA_PARITY_ERRf, "VLAN_SUBNET_DATA table parity error", 162 VLAN_SUBNET_DATA_ONLYm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 163 VLAN_SUBNET_DATA_PARITY_CONTROLr, 164 VLAN_SUBNET_DATA_PARITY_STATUSr, INVALIDr, 165 INVALIDr, INVALIDr }, 166 { PARITY_ENf, VLAN_PROTOCOL_DATA_PARITY_ERRf, "VLAN_PROTOCOL_DATA table parity error", 167 VLAN_PROTOCOL_DATAm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 168 VLAN_PROTOCOL_DATA_PARITY_CONTROLr, 169 VLAN_PROTOCOL_DATA_PARITY_STATUSr, INVALIDr, 170 INVALIDr, INVALIDr }, 171 { PARITY_ENf, VLAN_PARITY_ERRf, "VLAN table parity error", 172 VLAN_TABm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 173 VLAN_PARITY_CONTROLr, 174 VLAN_PARITY_STATUSr, INVALIDr, 175 INVALIDr, INVALIDr }, 176 { PARITY_ENf, VLAN_STG_PARITY_ERRf, "VLAN_STG table parity error", 177 STG_TABm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 178 VLAN_STG_PARITY_CONTROLr, 179 VLAN_STG_PARITY_STATUSr, INVALIDr, 180 INVALIDr, INVALIDr }, 181 /* { PARITY_ENf, L3_TUNNEL_RAM_PARITY_ERRf, "L3_TUNNEL_RAM table parity error", 182 L3_TUNNELm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 183 L3_TUNNEL_DATA_ONLY_PARITY_CONTROLr, 184 L3_TUNNEL_DATA_ONLY_PARITY_STATUSr, INVALIDr, 185 INVALIDr, INVALIDr }, */ 186 { PARITY_ENf, SOURCE_TRUNK_MAP_PARITY_ERRf, "SOURCE_TRUNK_MAP table parity error", 187 SOURCE_TRUNK_MAP_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 188 SOURCE_TRUNK_MAP_PARITY_CONTROLr, 189 SOURCE_TRUNK_MAP_PARITY_STATUSr, INVALIDr, 190 INVALIDr, INVALIDr }, 191 { PARITY_ENf, LMEP_PAR_ERRf, "LMEP table parity error", 192 LMEPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 193 LMEP_PARITY_CONTROLr, 194 LMEP_PARITY_STATUSr, INVALIDr, 195 INVALIDr, INVALIDr }, 196 { ECC_ENf, IARB_PKT_ECC_INTRf, "Iarb packet ecc error", 197 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 198 IARB_PKT_ECC_CONTROLr, 199 IARB_PKT_ECC_STATUS_INTRr, INVALIDr, 200 INVALIDr, INVALIDr }, 201 /* IARB_HDR_ECC_INTR, no control/status regiters */ 202 { INVALIDf, INVALIDf }, /* table terminator */ 203 }; 204 205 206 STATIC _soc_parity_info_t _soc_hu2_ip1_parity_info[] = { 207 /* { PARITY_ENf, VFI_PAR_ERRf, "VFI table parity error.", 208 VFIm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 209 VFI_PARITY_CONTROLr, 210 VFI_PARITY_STATUS_INTRr, INVALIDr, 211 VFI_PARITY_STATUS_NACKr, INVALIDr }, */ 212 /* { PARITY_ENf, SVP_PAR_ERRf, "SOURCE_VP table parity error", 213 SOURCE_VPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 214 SOURCE_VP_PARITY_CONTROLr, 215 SOURCE_VP_PARITY_STATUSr, INVALIDr, 216 SOURCE_VP_PARITY_STATUS_NACKr, INVALIDr }, */ 217 /* { PARITY_ENf, L3_IIF_PAR_ERRf, "L3_IIF table parity error", 218 L3_IIFm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 219 L3_IIF_PARITY_CONTROLr, 220 L3_IIF_PARITY_STATUSr, INVALIDr, 221 L3_IIF_PARITY_STATUS_NACKr, INVALIDr }, */ 222 /* { PARITY_ENf, MPLS_ENTRY_PAR_ERRf, "MPLS_ENTRY table parity error", 223 MPLS_ENTRYm, _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 224 MPLS_ENTRY_PARITY_CONTROLr, 225 MPLS_ENTRY_PARITY_STATUS_INTR_0r, MPLS_ENTRY_PARITY_STATUS_INTR_1r, 226 MPLS_ENTRY_PARITY_STATUS_NACK_0r, MPLS_ENTRY_PARITY_STATUS_NACK_1r }, */ 227 { PARITY_ENf, L2_ENTRY_PAR_ERRf, "L2_ENTRY table parity error", 228 L2Xm, _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 229 L2_ENTRY_PARITY_CONTROLr, 230 L2_ENTRY_PARITY_STATUS_0r, L2_ENTRY_PARITY_STATUS_1r, 231 INVALIDr, INVALIDr }, 232 { PARITY_ENf, L2MC_PAR_ERRf, "L2MC table parity error", 233 L2MCm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 234 L2MC_PARITY_CONTROLr, 235 L2MC_PARITY_STATUSr, INVALIDr, 236 INVALIDr, INVALIDr }, 237 { PARITY_ENf, L3_ENTRY_PAR_ERRf, "L3_ENTRY table parity error", 238 L3_ENTRY_ONLYm, _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 239 L3_ENTRY_PARITY_CONTROLr, 240 L3_ENTRY_PARITY_STATUS_0r, L3_ENTRY_PARITY_STATUS_1r, 241 INVALIDr, INVALIDr }, 242 { PARITY_ENf, L3_DEFIP_DATA_PAR_ERRf, "L3_DEFIP_DATA_ONLY table parity error", 243 L3_DEFIP_DATA_ONLYm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 244 L3_DEFIP_PARITY_CONTROLr, 245 L3_DEFIP_PARITY_STATUSr, INVALIDr 246 INVALIDr, INVALIDr }, 247 { PARITY_ENf, L3MC_PAR_ERRf, "L3MC table parity error", 248 L3_IPMCm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 249 L3MC_PARITY_CONTROLr, 250 L3MC_PARITY_STATUSr, INVALIDr, 251 INVALIDr, INVALIDr }, 252 { PARITY_ENf, MA_STATE_PAR_ERRf, "MA_STATE table parity error", 253 MA_STATEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 254 MA_STATE_PARITY_CONTROLr, 255 MA_STATE_PARITY_STATUSr, INVALIDr, 256 INVALIDr, INVALIDr }, 257 { PARITY_ENf, RMEP_PAR_ERRf, "RMEP table parity error", 258 RMEPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 259 RMEP_PARITY_CONTROLr, 260 RMEP_PARITY_STATUSr, INVALIDr, 261 INVALIDr, INVALIDr }, 262 { PARITY_ENf, MAID_REDUCTION_PAR_ERRf, "MAID_REDUCTION table parity error", 263 MAID_REDUCTIONm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 264 MAID_REDUCTION_PARITY_CONTROLr, 265 MAID_REDUCTION_PARITY_STATUSr, INVALIDr, 266 INVALIDr, INVALIDr }, 267 { PARITY_ENf, MA_INDEX_PAR_ERRf, "MA_INDEX table parity error", 268 MA_INDEXm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 269 MA_INDEX_PARITY_CONTROLr, 270 MA_INDEX_PARITY_STATUSr, INVALIDr, 271 INVALIDr, INVALIDr }, 272 /* { PARITY_ENf, PORT_CBL_TABLE_PAR_ERRf, "PORT_CBL_TABLE table parity error", 273 PORT_CBL_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 274 PORT_CBL_TABLE_PARITY_CONTROLr, 275 PORT_CBL_TABLE_PARITY_STATUSr, INVALIDr, 276 INVALIDr, INVALIDr }, unsupported */ 277 { PARITY_ENf, INITIAL_NHOP_PAR_ERRf, "INITIAL_NHOP table parity error", 278 INITIAL_ING_L3_NEXT_HOPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 279 INITIAL_NHOP_PARITY_CONTROLr, 280 INITIAL_NHOP_PARITY_STATUSr, INVALIDr, 281 INVALIDr, INVALIDr }, 282 /* Start of parity-unrelated OAM faults */ 283 284 { ANY_RMEP_TLV_PORT_DOWN_INTRf, ANY_RMEP_TLV_PORT_DOWN_INTRf, NULL, 285 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 286 INVALIDr, 287 INVALIDr, INVALIDr, 288 INVALIDr, INVALIDr }, 289 290 { ANY_RMEP_TLV_PORT_UP_INTRf, ANY_RMEP_TLV_PORT_UP_INTRf, NULL, 291 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 292 INVALIDr, 293 INVALIDr, INVALIDr, 294 INVALIDr, INVALIDr }, 295 296 { ANY_RMEP_TLV_INTERFACE_DOWN_INTRf, ANY_RMEP_TLV_INTERFACE_DOWN_INTRf, NULL, 297 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 298 INVALIDr, 299 INVALIDr, INVALIDr, 300 INVALIDr, INVALIDr }, 301 302 { ANY_RMEP_TLV_INTERFACE_UP_INTRf, ANY_RMEP_TLV_INTERFACE_UP_INTRf, NULL, 303 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 304 INVALIDr, 305 INVALIDr, INVALIDr, 306 INVALIDr, INVALIDr }, 307 308 { XCON_CCM_DEFECT_INTRf, XCON_CCM_DEFECT_INTRf, NULL, 309 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 310 INVALIDr, 311 INVALIDr, INVALIDr, 312 INVALIDr, INVALIDr }, 313 314 { ERROR_CCM_DEFECT_INTRf, ERROR_CCM_DEFECT_INTRf, NULL, 315 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 316 INVALIDr, 317 INVALIDr, INVALIDr, 318 INVALIDr, INVALIDr }, 319 320 { SOME_RDI_DEFECT_INTRf, SOME_RDI_DEFECT_INTRf, NULL, 321 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 322 INVALIDr, 323 INVALIDr, INVALIDr, 324 INVALIDr, INVALIDr }, 325 326 { SOME_RMEP_CCM_DEFECT_INTRf, SOME_RMEP_CCM_DEFECT_INTRf, NULL, 327 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 328 INVALIDr, 329 INVALIDr, INVALIDr, 330 INVALIDr, INVALIDr }, 331 332 /* End of parity-unrelated OAM faults */ 333 /* { PARITY_ENf, VFI_1_PAR_INTRf, "VFI_1 parity interrupt", 334 VFI_1m, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 335 VFI_1_PARITY_CONTROLr, 336 VFI_1_PARITY_STATUS_INTRr, INVALIDr, 337 VFI_1_PARITY_STATUS_NACKr, INVALIDr }, */ 338 { INVALIDf, INVALIDf }, /* table terminator */ 339 }; 340 341 STATIC _soc_parity_info_t _soc_hu2_ip2_parity_info[] = { 342 { PARITY_ENf, ING_NHOP_PAR_ERRf, "ING_L3_NEXT_HOP table parity error", 343 ING_L3_NEXT_HOPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 344 ING_L3_NEXT_HOP_PARITY_CONTROLr, 345 ING_L3_NEXT_HOP_PARITY_STATUSr, INVALIDr, 346 INVALIDr, INVALIDr }, 347 { PARITY_ENf, IFP_METER_PAR_ERRf, "FP_METER_TABLE table parity error", 348 FP_METER_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 349 IFP_METER_PARITY_CONTROLr, 350 IFP_METER_PARITY_STATUSr, INVALIDr, 351 INVALIDr, INVALIDr }, 352 { PARITY_ENf, IFP_COUNTER_PAR_ERRf, "FP_COUNTER_TABLE table parity error", 353 FP_COUNTER_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 354 IFP_COUNTER_PARITY_CONTROLr, 355 IFP_COUNTER_PARITY_STATUSr, INVALIDr, 356 INVALIDr, INVALIDr }, 357 { PARITY_ENf, IFP_POLICY_PAR_ERRf, "FP_POLICY_TABLE table parity error", 358 FP_POLICY_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 359 IFP_POLICY_PARITY_CONTROLr, 360 IFP_POLICY_PARITY_STATUSr, INVALIDr, 361 INVALIDr, INVALIDr }, 362 { PARITY_ENf, IFP_STORM_CONTROL_PAR_ERRf, "FP_STORM_CONTROL_METERS table parity error", 363 FP_STORM_CONTROL_METERSm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 364 IFP_STORM_CONTROL_PARITY_CONTROLr, 365 IFP_STORM_CONTROL_PARITY_STATUSr, INVALIDr, 366 INVALIDr, INVALIDr }, 367 { PARITY_ENf, L3_MTU_VALUES_PAR_ERRf, "L3_MTU_VALUES table parity error", 368 L3_MTU_VALUESm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 369 L3_MTU_VALUES_PARITY_CONTROLr, 370 L3_MTU_VALUES_PARITY_STATUSr, INVALIDr, 371 INVALIDr, INVALIDr }, 372 { PARITY_ENf, EGR_MASK_PAR_ERRf, "EGR_MASK table parity error", 373 EGR_MASKm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 374 EGR_MASK_PARITY_CONTROLr, 375 EGR_MASK_PARITY_STATUSr, INVALIDr, 376 INVALIDr, INVALIDr }, 377 { PARITY_ENf, MODPORT_MAP_SW_PAR_ERRf, "MODPORT_MAP table parity error", 378 MODPORT_MAP_SWm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 379 MODPORT_MAP_SW_PARITY_CONTROLr, 380 MODPORT_MAP_SW_PARITY_STATUSr, INVALIDr, 381 INVALIDr, INVALIDr }, 382 { PARITY_ENf, MODPORT_MAP_IM_PAR_ERRf, "MODPORT_MAP_IM table parity error", 383 MODPORT_MAP_IMm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 384 MODPORT_MAP_IM_PARITY_CONTROLr, 385 MODPORT_MAP_IM_PARITY_STATUSr, INVALIDr, 386 INVALIDr, INVALIDr }, 387 { PARITY_ENf, MODPORT_MAP_EM_PAR_ERRf, "MODPORT_MAP_EM table parity error", 388 MODPORT_MAP_EMm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 389 MODPORT_MAP_EM_PARITY_CONTROLr, 390 MODPORT_MAP_EM_PARITY_STATUSr, INVALIDr, 391 INVALIDr, INVALIDr }, 392 { PARITY_ENf, OAM_LM_COUNTERS_PAR_ERRf, "OAM_LM_COUNTERS table parity error.", 393 OAM_LM_COUNTERSm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 394 OAM_LM_COUNTERS_PARITY_CONTROLr, 395 OAM_LM_COUNTERS_PARITY_STATUSr, INVALIDr, 396 INVALIDr, INVALIDr }, 397 { INVALIDf, INVALIDf }, /* table terminator */ 398 }; 399 400 STATIC _soc_parity_info_t _soc_hu2_ep_parity_info[] = { 401 { PARITY_ENf, EGR_NHOP_PAR_ERRf, NULL, 402 EGR_L3_NEXT_HOPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 403 EGR_L3_NEXT_HOP_PARITY_CONTROLr, 404 EGR_L3_NEXT_HOP_PARITY_STATUSr, INVALIDr, 405 INVALIDr, INVALIDr }, 406 { PARITY_ENf, EGR_L3_INTF_PAR_ERRf, NULL, 407 EGR_L3_INTFm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 408 EGR_L3_INTF_PARITY_CONTROLr, 409 EGR_L3_INTF_PARITY_STATUSr, INVALIDr, 410 INVALIDr, INVALIDr }, 411 { PARITY_ENf, EGR_VLAN_PAR_ERRf, NULL, 412 EGR_VLANm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 413 EGR_VLAN_PARITY_CONTROLr, 414 EGR_VLAN_PARITY_STATUSr, INVALIDr, 415 INVALIDr, INVALIDr }, 416 { PARITY_ENf, EGR_VLAN_STG_PAR_ERRf, NULL, 417 EGR_VLAN_STGm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 418 EGR_VLAN_STG_PARITY_CONTROLr, 419 EGR_VLAN_STG_PARITY_STATUSr, INVALIDr, 420 INVALIDr, INVALIDr }, 421 { PARITY_ENf, EGR_VXLT_PAR_ERRf, NULL, 422 EGR_VLAN_XLATEm, _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 423 EGR_VLAN_XLATE_PARITY_CONTROLr, 424 EGR_VLAN_XLATE_PARITY_STATUS_0r, EGR_VLAN_XLATE_PARITY_STATUS_1r, 425 INVALIDr, INVALIDr }, 426 { STATS_PAR_ENf, EGR_STATS_COUNTER_TABLE_PAR_ERRf, "Parity enable for egress stats counter memory", 427 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 428 EGR_EDATABUF_PARITY_CONTROLr, 429 EGR_STATS_COUNTER_TABLE_PARITY_STATUSr, INVALIDr, 430 INVALIDr, INVALIDr }, 431 { ECC_ENf, EP_INITBUF_DBEf, "EP_INITBUF double-bit ECC error", 432 INVALIDm,_SOC_PARITY_INFO_TYPE_SINGLE_ECC, 433 EGR_INITBUF_ECC_CONTROLr, 434 EGR_INITBUF_ECC_STATUS_DBEr, INVALIDr, 435 INVALIDr, INVALIDr }, 436 { ECC_ENf, EP_INITBUF_SBEf, "EP_INITBUF single-bit ECC error (corrected)", 437 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 438 EGR_INITBUF_ECC_CONTROLr, 439 EGR_INITBUF_ECC_STATUS_SBEr, INVALIDr, 440 INVALIDr, INVALIDr }, 441 { PERQ_PAR_ENf, EGR_PERQ_COUNTERf, "Parity enable for egress perq xmt counter memory", 442 EGR_PERQ_XMT_COUNTERSm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 443 EGR_EDATABUF_PARITY_CONTROLr, 444 EGR_PERQ_COUNTER_PARITY_STATUSr, INVALIDr, 445 INVALIDr, INVALIDr }, 446 { EFPCTR_PAR_ENf, EGR_FP_COUNTERf, "Parity enable for efp counter memory", 447 EFP_COUNTER_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 448 EGR_EDATABUF_PARITY_CONTROLr, 449 EGR_FP_COUNTER_PARITY_STATUSr, INVALIDr, 450 INVALIDr, INVALIDr }, 451 { GP0_ECC_ENf, EGR_GP0_DBUFf, "ECC enable for gp0 interaface buffer", 452 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 453 EGR_EDATABUF_PARITY_CONTROLr, 454 EGR_GP0_DBITS_PARITY_STATUSr, INVALIDr, 455 INVALIDr, INVALIDr }, 456 { GP1_ECC_ENf, EGR_GP1_DBUFf, "ECC enable for gp1 interaface buffer", 457 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 458 EGR_EDATABUF_PARITY_CONTROLr, 459 EGR_GP1_DBITS_PARITY_STATUSr, INVALIDr, 460 INVALIDr, INVALIDr }, 461 { GP2_ECC_ENf, EGR_GP2_DBUFf, "ECC enable for gp2 interaface buffer", 462 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 463 EGR_EDATABUF_PARITY_CONTROLr, 464 EGR_GP2_DBITS_PARITY_STATUSr, INVALIDr, 465 INVALIDr, INVALIDr }, 466 { XP0_ECC_ENf, EGR_XP0_DBUFf, "ECC enable for xp0 interaface buffer", 467 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 468 EGR_EDATABUF_PARITY_CONTROLr, 469 EGR_XP0_DBITS_PARITY_STATUSr, INVALIDr, 470 INVALIDr, INVALIDr }, 471 { XP1_ECC_ENf, EGR_XP1_DBUFf, "ECC enable for xp1 interaface buffer", 472 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 473 EGR_EDATABUF_PARITY_CONTROLr, 474 EGR_XP1_DBITS_PARITY_STATUSr, INVALIDr, 475 INVALIDr, INVALIDr }, 476 { XP2_ECC_ENf, EGR_XP2_DBUFf, "ECC enable for xp2 interaface buffer", 477 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 478 EGR_EDATABUF_PARITY_CONTROLr, 479 EGR_XP2_DBITS_PARITY_STATUSr, INVALIDr, 480 INVALIDr, INVALIDr }, 481 { XP3_ECC_ENf, EGR_XP3_DBUFf, "ECC enable for xp3 interaface buffer", 482 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 483 EGR_EDATABUF_PARITY_CONTROLr, 484 EGR_XP3_DBITS_PARITY_STATUSr, INVALIDr, 485 INVALIDr, INVALIDr }, 486 { XP4_ECC_ENf, EGR_XP4_DBUFf, "ECC enable for xp4 interaface buffer", 487 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 488 EGR_EDATABUF_PARITY_CONTROLr, 489 EGR_XP4_DBITS_PARITY_STATUSr, INVALIDr, 490 INVALIDr, INVALIDr }, 491 { XP5_ECC_ENf, EGR_XP5_DBUFf, "ECC enable for xp5 interaface buffer", 492 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 493 EGR_EDATABUF_PARITY_CONTROLr, 494 EGR_XP5_DBITS_PARITY_STATUSr, INVALIDr, 495 INVALIDr, INVALIDr }, 496 { XP6_ECC_ENf, EGR_XP6_DBUFf, "ECC enable for xp6 interaface buffer", 497 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 498 EGR_EDATABUF_PARITY_CONTROLr, 499 EGR_XP6_DBITS_PARITY_STATUSr, INVALIDr, 500 INVALIDr, INVALIDr }, 501 { XP7_ECC_ENf, EGR_XP7_DBUFf, "ECC enable for xp7 interaface buffer", 502 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 503 EGR_EDATABUF_PARITY_CONTROLr, 504 EGR_XP7_DBITS_PARITY_STATUSr, INVALIDr, 505 INVALIDr, INVALIDr }, 506 /* { GP_RESI_ECC_ENf, EGR_GP_RESI_DBUFf, "ECC enable for gp residue buffer", 507 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 508 EGR_EDATABUF_PARITY_CONTROLr, 509 EGR_GP_RESI_DBITS_PARITY_STATUSr, INVALIDr, 510 INVALIDr, INVALIDr }, */ 511 { CM_ECC_ENf, EGR_CM_DBUFf, "ECC enable for cm interaface buffer", 512 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 513 EGR_EDATABUF_PARITY_CONTROLr, 514 EGR_CM_DBITS_PARITY_STATUSr, INVALIDr, 515 INVALIDr, INVALIDr }, 516 { INVALIDf, INVALIDf }, /* table terminator */ 517 }; 518 519 STATIC _soc_parity_info_t _soc_hu2_xlp_parity_info[] = { 520 { TXFIFO_ECC_ENf, TXFIFO0_ERRf, "TXFIFO 0", 521 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 522 XLPORT_ECC_CONTROLr, 523 XLPORT_TXFIFO0_ECC_STATUSr, INVALIDr, 524 INVALIDr, INVALIDr }, 525 { TXFIFO_ECC_ENf, TXFIFO1_ERRf, "TXFIFO 1", 526 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 527 XLPORT_ECC_CONTROLr, 528 XLPORT_TXFIFO1_ECC_STATUSr, INVALIDr, 529 INVALIDr, INVALIDr }, 530 { TXFIFO_ECC_ENf, TXFIFO2_ERRf, "TXFIFO 2", 531 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 532 XLPORT_ECC_CONTROLr, 533 XLPORT_TXFIFO2_ECC_STATUSr, INVALIDr, 534 INVALIDr, INVALIDr }, 535 { TXFIFO_ECC_ENf, TXFIFO3_ERRf, "TXFIFO 3", 536 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 537 XLPORT_ECC_CONTROLr, 538 XLPORT_TXFIFO3_ECC_STATUSr, INVALIDr, 539 INVALIDr, INVALIDr }, 540 { BOD_ECC_ENABLEf, BOD_XLP0_ERRf, "Cell Assembly FIFO", 541 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 542 XLPORT_ECC_CONTROLr, 543 XLPORT_BOD_XLP0_ECC_STATUSr, INVALIDr, 544 INVALIDr, INVALIDr }, 545 { MIB_RSC_MEM_ENf, MIB_RSC1_MEM_ERRf, 546 "MIB RX Statistic counter memory instance 1", 547 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 548 XLPORT_ECC_CONTROLr, 549 XLPORT_MIB_RSC1_ECC_STATUSr, INVALIDr, 550 INVALIDr, INVALIDr }, 551 { MIB_RSC_MEM_ENf, MIB_RSC0_MEM_ERRf, 552 "MIB RX Statistic counter memory instance 0", 553 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 554 XLPORT_ECC_CONTROLr, 555 XLPORT_MIB_RSC0_ECC_STATUSr, INVALIDr, 556 INVALIDr, INVALIDr }, 557 { MIB_TSC_MEM_ENf, MIB_TSC1_MEM_ERRf, 558 "MIB TX Statistic counter memory instance 1", 559 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 560 XLPORT_ECC_CONTROLr, 561 XLPORT_MIB_TSC1_ECC_STATUSr, INVALIDr, 562 INVALIDr, INVALIDr }, 563 { MIB_TSC_MEM_ENf, MIB_TSC0_MEM_ERRf, 564 "MIB TX Statistic counter memory instance 0", 565 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 566 XLPORT_ECC_CONTROLr, 567 XLPORT_MIB_TSC0_ECC_STATUSr, INVALIDr, 568 INVALIDr, INVALIDr }, 569 { INVALIDf, INVALIDf }, /* table terminator */ 570 }; 571 572 STATIC _soc_parity_info_t _soc_hu2_mmu_parity_info[] = { 573 { CELLECCERRORINTMASKf, CELLECCERRORf, "MMU CBP cell data", 574 INVALIDm, _SOC_PARITY_INFO_TYPE_GENERIC, 575 INVALIDr, 576 INVALIDr, INVALIDr, 577 INVALIDr, INVALIDr}, 578 { CBPPKTHDRPARITYERRORINTMASKf, CBPPKTHDRPARITYERRORf, 579 "MMU CBP packet header memory", 580 INVALIDm, _SOC_PARITY_INFO_TYPE_GENERIC, 581 INVALIDr, 582 INVALIDr, INVALIDr, 583 INVALIDr, INVALIDr}, 584 { CBPCELLHDRPARITYERRORINTMASKf, CBPCELLHDRPARITYERRORf, 585 "MMU CBP cell header memory", 586 INVALIDm, _SOC_PARITY_INFO_TYPE_GENERIC, 587 INVALIDr, 588 INVALIDr, INVALIDr, 589 INVALIDr, INVALIDr}, 590 { XQPARITYERRORINTMASKf, XQPARITYERRORf, 591 "MMU XQ memory", 592 INVALIDm, _SOC_PARITY_INFO_TYPE_GENERIC, 593 INVALIDr, 594 INVALIDr, INVALIDr, 595 INVALIDr, INVALIDr }, 596 { CFAPPARITYERRORINTMASKf, CFAPPARITYERRORf, 597 "MMU CFP memory", 598 INVALIDm, _SOC_PARITY_INFO_TYPE_GENERIC, 599 INVALIDr, 600 INVALIDr, INVALIDr, 601 INVALIDr, INVALIDr}, 602 { CCPPARITYERRORINTMASKf, CCPPARITYERRORf, 603 "MMU CCP memory", 604 INVALIDm, _SOC_PARITY_INFO_TYPE_GENERIC, 605 INVALIDr, 606 INVALIDr, INVALIDr, 607 INVALIDr, INVALIDr}, 608 { IPMCREPOVERLIMITERRORINTMASKf, IPMCREPOVERLIMITERRORf, 609 "IPMC replication over limit error", 610 INVALIDm, _SOC_PARITY_INFO_TYPE_GENERIC, 611 INVALIDr, 612 INVALIDr, INVALIDr, 613 INVALIDr, INVALIDr}, 614 { XQFLLPARITYERRORINTMASKf, XQFLLPARITYERRORf, 615 "MMU XQ FLL memory", 616 INVALIDm, _SOC_PARITY_INFO_TYPE_GENERIC, 617 INVALIDr, 618 INVALIDr, INVALIDr, 619 INVALIDr, INVALIDr}, 620 { E2EFCPARITYERRORINTMASKf, E2EFCPARITYERRORf, 621 "MMU E2EFC memory", 622 INVALIDm, _SOC_PARITY_INFO_TYPE_MMU_E2EFC, 623 INVALIDr, 624 E2EFC_PARITYERRORPTRr, INVALIDr, 625 INVALIDr, INVALIDr}, 626 { IPMCVALNXPORTPARITYERRORINTMASKf, IPMCVLANXPORTPARITYERRORf, 627 "MMU IPMC VLAN XPORT memory", 628 MMU_IPMC_VLAN_TBLm, _SOC_PARITY_INFO_TYPE_MMU_IPMC, 629 MEMFAILINTMASKr, 630 IPMCPARITYERRORPTRr, INVALIDr, 631 INVALIDr, INVALIDr}, 632 /* { IPMCVALNGPORTPARITYERRORINTMASKf, IPMCVLANGPORTPARITYERRORf, 633 "MMU IPMC VLAN GPORT memory", 634 MMU_IPMC_VLAN_TBLm, _SOC_PARITY_INFO_TYPE_MMU_IPMC, 635 MEMFAILINTMASKr, 636 IPMCPARITYERRORPTRr, INVALIDr, 637 INVALIDr, INVALIDr}, */ 638 { IPMCGROUP0PARITYERRORINTMASKf, IPMCGROUP0PARITYERRORf, 639 "MMU IPMC GORUP0 memory", 640 MMU_IPMC_GROUP_TBL0m, _SOC_PARITY_INFO_TYPE_MMU_IPMC, 641 INVALIDr, 642 IPMCPARITYERRORPTRr, INVALIDr, 643 INVALIDr, INVALIDr}, 644 { IPMCGROUP1PARITYERRORINTMASKf, IPMCGROUP1PARITYERRORf, 645 "MMU IPMC GORUP1 memory", 646 MMU_IPMC_GROUP_TBL1m, _SOC_PARITY_INFO_TYPE_MMU_IPMC, 647 INVALIDr, 648 IPMCPARITYERRORPTRr, INVALIDr, 649 INVALIDr, INVALIDr}, 650 { INVALIDf, INVALIDf }, /* table terminator */ 651 }; 652 653 654 typedef struct { 655 uint32 cpi_bit; 656 soc_block_t blocktype; 657 soc_reg_t enable_reg; 658 soc_reg_t status_reg; 659 _soc_parity_info_t *info; 660 } _soc_hu2_parity_group_info_t; 661 662 static _soc_hu2_parity_group_info_t _soc_hu2_parity_group_info_template[] = { 663 { 0x00001, SOC_BLK_MMU, MEMFAILINTMASKr, MEMFAILINTSTATUSr, _soc_hu2_mmu_parity_info }, 664 { 0x00002, SOC_BLK_EPIPE, EGR_INTR_ENABLEr, EGR_INTR_STATUSr, _soc_hu2_ep_parity_info }, 665 { 0x00004, SOC_BLK_IPIPE, IP0_INTR_ENABLEr, IP0_INTR_STATUSr, _soc_hu2_ip0_parity_info }, 666 { 0x00008, SOC_BLK_IPIPE, IP1_INTR_ENABLEr, IP1_INTR_STATUSr, _soc_hu2_ip1_parity_info }, 667 { 0x00010, SOC_BLK_IPIPE, IP2_INTR_ENABLEr, IP2_INTR_STATUSr, _soc_hu2_ip2_parity_info }, 668 /* { 0x00020, PCIE_REPLAY_PERR, }, */ 669 { 0x00040, SOC_BLK_XLPORT, XLPORT_INTR_ENABLEr, XLPORT_INTR_STATUSr, _soc_hu2_xlp_parity_info }, /* x4 */ 670 { 0 }, /* table terminator */ 671 }; 672 static _soc_hu2_parity_group_info_t _soc_wf_parity_group_info_template[] = { 673 { 0x00001, SOC_BLK_MMU, MEMFAILINTMASKr, MEMFAILINTSTATUSr, _soc_hu2_mmu_parity_info }, 674 { 0x00002, SOC_BLK_EPIPE, EGR_INTR_ENABLEr, EGR_INTR_STATUSr, _soc_hu2_ep_parity_info }, 675 { 0x00004, SOC_BLK_IPIPE, IP0_INTR_ENABLEr, IP0_INTR_STATUSr, _soc_wf_ip0_parity_info }, 676 { 0x00008, SOC_BLK_IPIPE, IP1_INTR_ENABLEr, IP1_INTR_STATUSr, _soc_hu2_ip1_parity_info }, 677 { 0x00010, SOC_BLK_IPIPE, IP2_INTR_ENABLEr, IP2_INTR_STATUSr, _soc_hu2_ip2_parity_info }, 678 /* { 0x00020, PCIE_REPLAY_PERR, }, */ 679 { 0x00040, SOC_BLK_XLPORT, XLPORT_INTR_ENABLEr, XLPORT_INTR_STATUSr, _soc_hu2_xlp_parity_info }, /* x4 */ 680 { 0 }, /* table terminator */ 681 }; 682 683 684 STATIC _soc_generic_ser_info_t *_soc_hu2_tcam_ser_info = NULL; 685 STATIC _soc_hu2_parity_group_info_t *_soc_hu2_parity_group_info = NULL; 686 STATIC soc_hurricane2_oam_handler_t hu2_oam_handler[SOC_MAX_NUM_DEVICES] = {NULL}; 687 static soc_hurricane2_oam_ser_handler_t hu2_oam_ser_handler[SOC_MAX_NUM_DEVICES] = {NULL}; 688 689 690 static soc_ser_functions_t _hu2_ser_functions; 691 692 #define _SOC_HURRICANE2_SER_REG 1 693 #define _SOC_HURRICANE2_SER_MEM 0 694 695 typedef union _hurricane2_ser_nack_reg_mem_u { 696 soc_reg_t reg; 697 soc_mem_t mem; 698 } _hurricane2_ser_nack_reg_mem_t; 699 700 701 STATIC int 702 _soc_hurricane2_parity_block_port(int unit, soc_block_t block, soc_port_t *port) 703 { 704 *port = SOC_BLOCK_PORT(unit, block); 705 if ((*port != REG_PORT_ANY) && !SOC_PORT_VALID(unit, *port)) { 706 return SOC_E_PORT; 707 } 708 709 return SOC_E_NONE; 710 } 711 712 soc_field_t _soc_hu2_oam_interrupt_fields[] = { 713 SOME_RDI_DEFECT_INTRf, 714 SOME_RMEP_CCM_DEFECT_INTRf, 715 ERROR_CCM_DEFECT_INTRf, 716 ANY_RMEP_TLV_PORT_DOWN_INTRf, 717 ANY_RMEP_TLV_PORT_UP_INTRf, 718 ANY_RMEP_TLV_INTERFACE_DOWN_INTRf, 719 ANY_RMEP_TLV_INTERFACE_UP_INTRf, 720 XCON_CCM_DEFECT_INTRf, 721 INVALIDf 722 }; 723 724 STATIC int 725 _soc_hu2_process_oam_interrupt(int unit) 726 { 727 uint32 rval; 728 int found = 0, fidx = 0; 729 soc_hurricane2_oam_handler_t oam_handler_snapshot = hu2_oam_handler[unit]; 730 731 732 SOC_IF_ERROR_RETURN(READ_IP1_INTR_STATUSr(unit, &rval)); 733 734 while (_soc_hu2_oam_interrupt_fields[fidx] != INVALIDf) { 735 if (soc_reg_field_get(unit, IP1_INTR_STATUSr, rval, 736 _soc_hu2_oam_interrupt_fields[fidx])) { 737 738 if (oam_handler_snapshot != NULL) 739 { 740 (void)(oam_handler_snapshot(unit, 741 _soc_hu2_oam_interrupt_fields[fidx])); 742 } 743 found++; 744 } 745 fidx++; 746 } 747 if (!found) { 748 LOG_ERROR(BSL_LS_SOC_COMMON, 749 (BSL_META_U(unit, 750 "Unexpected interrupt received for OAM !!\n"))); 751 } 752 return SOC_E_NONE; 753 } 754 755 void 756 soc_hurricane2_oam_ser_handler_register(int unit, 757 soc_hurricane2_oam_ser_handler_t handler) 758 { 759 hu2_oam_ser_handler[unit] = handler; 760 } 761 762 int 763 soc_hurricane2_oam_ser_process(int unit, soc_mem_t mem, int index) 764 { 765 if (hu2_oam_ser_handler[unit]) { 766 return hu2_oam_ser_handler[unit](unit, mem, index); 767 } else { 768 return SOC_E_UNAVAIL; 769 } 770 } 771 772 773 STATIC int 774 _soc_hurricane2_parity_enable(int unit, int enable) 775 { 776 int group, table; 777 uint32 group_enable, regval, cmic_enable = 0, cpi_blk_bit; 778 _soc_parity_info_t *info; 779 soc_reg_t group_reg, reg; 780 soc_port_t block_port; 781 soc_field_t enable_field; 782 soc_block_t blk; 783 784 /* loop through each group */ 785 for (group = 0; _soc_hu2_parity_group_info[group].cpi_bit; group++) { 786 info = _soc_hu2_parity_group_info[group].info; 787 group_reg = _soc_hu2_parity_group_info[group].enable_reg; 788 group_enable = 0; 789 790 cpi_blk_bit = _soc_hu2_parity_group_info[group].cpi_bit; 791 792 SOC_BLOCK_ITER(unit, blk, 793 _soc_hu2_parity_group_info[group].blocktype) { 794 if (_soc_hurricane2_parity_block_port(unit, blk, &block_port) < 0) { 795 cpi_blk_bit <<= 1; 796 continue; 797 } 798 /* loop through each table in the group */ 799 for (table = 0; info[table].enable_field != INVALIDf; table++) { 800 /* handle different parity error reporting style */ 801 switch (info[table].type) { 802 case _SOC_PARITY_INFO_TYPE_GENERIC: 803 case _SOC_PARITY_INFO_TYPE_MMU_PARITY: 804 case _SOC_PARITY_INFO_TYPE_MMU_IPMC: 805 case _SOC_PARITY_INFO_TYPE_MMU_E2EFC: 806 case _SOC_PARITY_INFO_TYPE_OAM: 807 enable_field = info[table].enable_field; 808 break; 809 case _SOC_PARITY_INFO_TYPE_SINGLE_PARITY: 810 case _SOC_PARITY_INFO_TYPE_SINGLE_ECC: 811 case _SOC_PARITY_INFO_TYPE_DUAL_PARITY: 812 reg = info[table].control_reg; 813 if (!SOC_REG_IS_VALID(unit, reg)) { 814 continue; 815 } 816 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, block_port, 0, ®val)); 817 soc_reg_field_set(unit, reg, ®val, 818 info[table].enable_field, 819 enable ? 1 : 0); 820 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, block_port, 0, regval)); 821 enable_field = info[table].error_field; 822 break; 823 default: 824 enable_field = INVALIDf; 825 break; 826 } /* handle different parity error reporting style */ 827 if (enable_field != INVALIDf) { 828 soc_reg_field_set(unit, group_reg, &group_enable, 829 enable_field, enable ? 1 : 0); 830 } 831 } /* loop through each table in the group */ 832 833 if (!SOC_REG_IS_VALID(unit, group_reg)) { 834 cpi_blk_bit <<= 1; 835 continue; 836 } 837 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, group_reg, block_port, 0, group_enable)); 838 cmic_enable |= cpi_blk_bit; 839 cpi_blk_bit <<= 1; 840 } 841 } /* loop through each group */ 842 843 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, ®val)); 844 soc_reg_field_set(unit, MISCCONFIGr, ®val, E2EFC_PARITY_STAT_CLEARf, 1); 845 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, regval)); 846 if (enable) { 847 /* MMU enables */ 848 soc_reg_field_set(unit, MISCCONFIGr, ®val, PARITY_CHECK_ENf, 1); 849 soc_reg_field_set(unit, MISCCONFIGr, ®val, E2EFC_PARITY_GEN_ENf, 1); 850 soc_reg_field_set(unit, MISCCONFIGr, ®val, E2EFC_PARITY_STAT_CLEARf, 0); 851 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, regval)); 852 /* Write CMIC enable register */ 853 (void)soc_cmicm_intr2_enable(unit, cmic_enable); 854 } else { 855 /* MMU disables */ 856 soc_reg_field_set(unit, MISCCONFIGr, ®val, PARITY_CHECK_ENf, 0); 857 soc_reg_field_set(unit, MISCCONFIGr, ®val, E2EFC_PARITY_GEN_ENf, 0); 858 soc_reg_field_set(unit, MISCCONFIGr, ®val, E2EFC_PARITY_STAT_CLEARf, 0); 859 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, regval)); 860 /* Write CMIC disable register */ 861 (void)soc_cmicm_intr2_disable(unit, cmic_enable); 862 } 863 return SOC_E_NONE; 864 } 865 866 /* SER processing for TCAMs */ 867 STATIC _soc_generic_ser_info_t _soc_hu2_tcam_ser_info_template[] = { 868 { VFP_TCAMm, INVALIDm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_4BITS, 869 _SOC_SER_INTERLEAVE_MOD2, 870 { {0, 235}, {1, 235}, {236, 469}, {237, 469} }, 0, 0, 0, 0, 0 }, 871 { L2_USER_ENTRYm, INVALIDm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_4BITS, 872 _SOC_SER_INTERLEAVE_MOD2, 873 { {0, 69}, {1, 69}, {70, 138}, {71, 138} }, 0, 0, 0, 0, 0 }, 874 { FP_GLOBAL_MASK_TCAMm, INVALIDm, _SOC_SER_TYPE_PARITY, 875 _SOC_SER_PARITY_4BITS, _SOC_SER_INTERLEAVE_MOD2, 876 { {0, 37}, {1, 37}, {38, 74}, {39, 74} }, 0, 0, 0, 0, 0 }, 877 { VLAN_SUBNETm, INVALIDm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_4BITS, 878 _SOC_SER_INTERLEAVE_MOD2, 879 { {0, 64}, {1, 64}, {65, 128}, {66, 128} }, 0, 0, 0, 0, 0 }, 880 { VLAN_SUBNET_ONLYm, VLAN_SUBNETm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_4BITS, 881 _SOC_SER_INTERLEAVE_MOD2, 882 { {0, 64}, {1, 64}, {65, 128}, {66, 128} }, 0, 0, 0, 0, 0 }, 883 { L3_DEFIPm, INVALIDm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_4BITS, 884 _SOC_SER_INTERLEAVE_MOD2, 885 { {0, 69}, {1, 69}, {70, 138}, {71, 138} }, 0, 0, 0, 0, 0 }, 886 { CPU_COS_MAPm, INVALIDm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_4BITS, 887 _SOC_SER_INTERLEAVE_MOD2, 888 { {0, 69}, {1, 69}, {70, 138}, {71, 138} }, 0, 0, 0, 0, 0 }, 889 { EFP_TCAMm, INVALIDm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_4BITS, 890 _SOC_SER_INTERLEAVE_MOD2, 891 { {0, 235}, {1, 235}, {236, 469}, {237, 469} }, 0, 0, 0, 0, 0 }, 892 { FP_TCAMm, INVALIDm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_1BIT, 893 _SOC_SER_INTERLEAVE_MOD2, 894 { {0, 235}, {1, 235}, {236, 469}, {237, 469} }, 0, 0, 0, 0, 0 }, 895 { INVALIDm }, 896 }; 897 898 /* Remove the VFP_TCAM and EFP_TCAM for Wolfhound */ 899 STATIC _soc_generic_ser_info_t _soc_wf_tcam_ser_info_template[] = { 900 { L2_USER_ENTRYm, INVALIDm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_4BITS, 901 _SOC_SER_INTERLEAVE_MOD2, 902 { {0, 69}, {1, 69}, {70, 138}, {71, 138} }, 0, 0, 0, 0, 0 }, 903 { FP_GLOBAL_MASK_TCAMm, INVALIDm, _SOC_SER_TYPE_PARITY, 904 _SOC_SER_PARITY_4BITS, _SOC_SER_INTERLEAVE_MOD2, 905 { {0, 37}, {1, 37}, {38, 74}, {39, 74} }, 0, 0, 0, 0, 0 }, 906 { VLAN_SUBNETm, INVALIDm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_4BITS, 907 _SOC_SER_INTERLEAVE_MOD2, 908 { {0, 64}, {1, 64}, {65, 128}, {66, 128} }, 0, 0, 0, 0, 0 }, 909 { VLAN_SUBNET_ONLYm, VLAN_SUBNETm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_4BITS, 910 _SOC_SER_INTERLEAVE_MOD2, 911 { {0, 64}, {1, 64}, {65, 128}, {66, 128} }, 0, 0, 0, 0, 0 }, 912 { L3_DEFIPm, INVALIDm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_4BITS, 913 _SOC_SER_INTERLEAVE_MOD2, 914 { {0, 69}, {1, 69}, {70, 138}, {71, 138} }, 0, 0, 0, 0, 0 }, 915 { CPU_COS_MAPm, INVALIDm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_4BITS, 916 _SOC_SER_INTERLEAVE_MOD2, 917 { {0, 69}, {1, 69}, {70, 138}, {71, 138} }, 0, 0, 0, 0, 0 }, 918 { FP_TCAMm, INVALIDm, _SOC_SER_TYPE_PARITY, _SOC_SER_PARITY_1BIT, 919 _SOC_SER_INTERLEAVE_MOD2, 920 { {0, 235}, {1, 235}, {236, 469}, {237, 469} }, 0, 0, 0, 0, 0 }, 921 { INVALIDm }, 922 }; 923 924 925 926 STATIC int 927 _soc_hurricane2_tcam_ser_init(int unit) 928 { 929 if (soc_feature(unit, soc_feature_field_multi_stage)) { 930 _soc_hu2_tcam_ser_info = _soc_hu2_tcam_ser_info_template; 931 } else { 932 _soc_hu2_tcam_ser_info = _soc_wf_tcam_ser_info_template; 933 } 934 return soc_generic_ser_init(unit, _soc_hu2_tcam_ser_info); 935 } 936 937 void 938 soc_hurricane2_ser_fail(int unit) 939 940 { 941 soc_generic_ser_process_error(unit, _soc_hu2_tcam_ser_info, 0); 942 } 943 944 int 945 soc_hurricane2_ser_mem_clear(int unit, soc_mem_t mem) 946 { 947 uint32 range_enable; 948 int info_ix, i; 949 _soc_generic_ser_info_t *cur_spi; 950 ser_memory_entry_t ser_mem; 951 952 /* Check if enable */ 953 SOC_IF_ERROR_RETURN 954 (READ_SER_RANGE_ENABLEr(unit, &range_enable)); 955 956 if (!range_enable) { 957 return SOC_E_NONE; 958 } 959 960 info_ix = 0; 961 962 while (_soc_hu2_tcam_ser_info[info_ix].mem != INVALIDm) { 963 if (_soc_hu2_tcam_ser_info[info_ix].mem == mem) { 964 break; 965 } 966 info_ix++; 967 } 968 969 if ((_soc_hu2_tcam_ser_info[info_ix].mem != INVALIDm) && 970 (range_enable & (1 << info_ix))) { 971 cur_spi = &(_soc_hu2_tcam_ser_info[info_ix]); 972 973 range_enable &= ~(1 << info_ix); 974 /* Disable SER protection on this memory */ 975 SOC_IF_ERROR_RETURN 976 (WRITE_SER_RANGE_ENABLEr(unit, range_enable)); 977 978 979 /* Flush SER memory segment for the table */ 980 sal_memset(&ser_mem, 0, sizeof(ser_mem)); 981 for (i = cur_spi->ser_section_start; 982 i <= cur_spi->ser_section_end; 983 i++) { 984 SOC_IF_ERROR_RETURN 985 (WRITE_SER_MEMORYm(unit, MEM_BLOCK_ALL, i, &ser_mem)); 986 } 987 988 range_enable |= (1 << info_ix); 989 /* Enable SER protection on this memory */ 990 SOC_IF_ERROR_RETURN 991 (WRITE_SER_RANGE_ENABLEr(unit, range_enable)); 992 993 LOG_VERBOSE(BSL_LS_SOC_COMMON, 994 (BSL_META_U(unit, 995 "\t%s: SER[%d-%d]\n"), 996 SOC_MEM_NAME(unit, cur_spi->mem), 997 cur_spi->ser_section_start, cur_spi->ser_section_end)); 998 } 999 1000 return SOC_E_NONE; 1001 1002 } 1003 1004 1005 STATIC void 1006 _soc_hu2_mem_parity_info(int unit, int block_info_idx, int pipe, 1007 soc_field_t field_enum, uint32 *minfo) 1008 { 1009 *minfo = (SOC_BLOCK2SCH(unit, block_info_idx) << SOC_ERROR_BLK_BP) 1010 | ((pipe & 0xff) << SOC_ERROR_PIPE_BP) 1011 | (field_enum & SOC_ERROR_FIELD_ENUM_MASK); 1012 } 1013 1014 1015 1016 int 1017 _soc_hurricane2_mem_parity_control(int unit, soc_mem_t mem, 1018 int copyno, int enable) 1019 { 1020 int group, table; 1021 uint32 cpi_blk_bit, regval; 1022 _soc_parity_info_t *info; 1023 soc_reg_t group_reg, reg; 1024 soc_port_t block_port; 1025 soc_field_t enable_field; 1026 soc_block_t blk; 1027 1028 /* Convert component/aggregate memories to the table for which 1029 * the parity registers correspond. */ 1030 switch(mem) { 1031 case VLAN_SUBNETm: 1032 mem = VLAN_SUBNET_DATA_ONLYm; /* Should be VLAN_SUBNET? */ 1033 break; 1034 case L2_ENTRY_ONLYm: 1035 mem = L2Xm; 1036 break; 1037 case L2_USER_ENTRY_ONLYm: 1038 case L2_USER_ENTRY_DATA_ONLYm: 1039 mem = L2_USER_ENTRYm; 1040 break; 1041 case L3_DEFIPm: 1042 mem = L3_DEFIP_DATA_ONLYm; 1043 break; 1044 case L3_DEFIP_128m: 1045 mem = L3_DEFIP_128_DATA_ONLYm; 1046 break; 1047 case EGR_IP_TUNNEL_IPV6m: 1048 case EGR_IP_TUNNEL_MPLSm: 1049 mem = EGR_IP_TUNNELm; 1050 break; 1051 case L3_ENTRY_IPV4_UNICASTm: 1052 case L3_ENTRY_IPV6_UNICASTm: 1053 case L3_ENTRY_IPV4_MULTICASTm: 1054 case L3_ENTRY_IPV6_MULTICASTm: 1055 mem = L3_ENTRY_ONLYm; 1056 break; 1057 case VLAN_MACm: 1058 mem = VLAN_XLATEm; 1059 break; 1060 default: 1061 /* Do nothing, keep memory as provided */ 1062 break; 1063 } 1064 1065 1066 /* loop through each group */ 1067 for (group = 0; _soc_hu2_parity_group_info[group].cpi_bit; group++) { 1068 info = _soc_hu2_parity_group_info[group].info; 1069 group_reg = _soc_hu2_parity_group_info[group].enable_reg; 1070 cpi_blk_bit = _soc_hu2_parity_group_info[group].cpi_bit; 1071 1072 SOC_BLOCK_ITER(unit, blk, 1073 _soc_hu2_parity_group_info[group].blocktype) { 1074 if (_soc_hurricane2_parity_block_port(unit, blk, &block_port) < 0) { 1075 cpi_blk_bit <<= 1; 1076 continue; 1077 } 1078 if ((copyno != MEM_BLOCK_ANY) && (blk != copyno)) { 1079 cpi_blk_bit <<= 1; 1080 continue; 1081 } 1082 1083 /* loop through each table in the group */ 1084 for (table = 0; info[table].enable_field != INVALIDf; table++) { 1085 if (mem != info[table].mem) { 1086 continue; 1087 } 1088 1089 /* handle different parity error reporting style */ 1090 switch (info[table].type) { 1091 case _SOC_PARITY_INFO_TYPE_GENERIC: 1092 case _SOC_PARITY_INFO_TYPE_MMU_PARITY: 1093 case _SOC_PARITY_INFO_TYPE_MMU_IPMC: 1094 case _SOC_PARITY_INFO_TYPE_MMU_E2EFC: 1095 enable_field = info[table].enable_field; 1096 SOC_IF_ERROR_RETURN 1097 (soc_reg_field32_modify(unit, group_reg, block_port, 1098 enable_field, 1099 enable ? 1 : 0)); 1100 break; 1101 case _SOC_PARITY_INFO_TYPE_SINGLE_PARITY: 1102 case _SOC_PARITY_INFO_TYPE_SINGLE_ECC: 1103 case _SOC_PARITY_INFO_TYPE_DUAL_PARITY: 1104 reg = info[table].control_reg; 1105 if (!SOC_REG_IS_VALID(unit, reg)) { 1106 return SOC_E_NONE; 1107 } 1108 SOC_IF_ERROR_RETURN 1109 (soc_reg_field32_modify(unit, reg, block_port, 1110 info[table].enable_field, 1111 enable ? 1 : 0)); 1112 break; 1113 default: 1114 break; 1115 } /* handle different parity error reporting style */ 1116 } /* loop through each table in the group */ 1117 cpi_blk_bit <<= 1; 1118 } 1119 } /* loop through each group */ 1120 1121 /* MMU controls */ 1122 if (enable) { 1123 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, ®val)); 1124 soc_reg_field_set(unit, MISCCONFIGr, ®val, E2EFC_PARITY_STAT_CLEARf, 1); 1125 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, regval)); 1126 1127 soc_reg_field_set(unit, MISCCONFIGr, ®val, PARITY_CHECK_ENf, 1); 1128 soc_reg_field_set(unit, MISCCONFIGr, ®val, E2EFC_PARITY_GEN_ENf, 1); 1129 soc_reg_field_set(unit, MISCCONFIGr, ®val, E2EFC_PARITY_STAT_CLEARf, 0); 1130 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, regval)); 1131 } else { 1132 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, ®val)); 1133 soc_reg_field_set(unit, MISCCONFIGr, ®val, PARITY_CHECK_ENf, 0); 1134 soc_reg_field_set(unit, MISCCONFIGr, ®val, E2EFC_PARITY_GEN_ENf, 0); 1135 soc_reg_field_set(unit, MISCCONFIGr, ®val, E2EFC_PARITY_STAT_CLEARf, 0); 1136 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, regval)); 1137 } 1138 1139 return SOC_E_NONE; 1140 } 1141 1142 STATIC int 1143 _soc_hurricane2_process_single_parity_error(int unit, int group, 1144 soc_port_t block_port, int table, 1145 int schan, char *msg, soc_block_t block) 1146 { 1147 _soc_parity_info_t *info; 1148 soc_reg_t status_reg; 1149 uint32 reg_val; 1150 int index, multiple, error; 1151 uint32 minfo; 1152 _soc_ser_correct_info_t spci; 1153 1154 info = _soc_hu2_parity_group_info[group].info; 1155 1156 status_reg = schan ? info[table].nack_status0_reg : 1157 info[table].intr_status0_reg; 1158 if (status_reg == INVALIDr) { 1159 return SOC_E_INTERNAL; 1160 } 1161 SOC_IF_ERROR_RETURN(soc_reg32_get(unit,status_reg, block_port, 0, ®_val)); 1162 index = soc_reg_field_get(unit, status_reg, reg_val, ENTRY_IDXf); 1163 multiple = soc_reg_field_get(unit, status_reg, reg_val, MULTIPLE_ERRf); 1164 error = soc_reg_field_get(unit, status_reg, reg_val, PARITY_ERRf); 1165 1166 if (error) { 1167 _soc_hu2_mem_parity_info(unit, block, 0, 1168 info[table].error_field, &minfo); 1169 soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 1170 SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 1171 index, minfo); 1172 1173 LOG_ERROR(BSL_LS_SOC_COMMON, 1174 (BSL_META_U(unit, 1175 "unit %d %s entry %d parity error\n"), 1176 unit, msg, index)); 1177 if (multiple) { 1178 LOG_ERROR(BSL_LS_SOC_COMMON, 1179 (BSL_META_U(unit, 1180 "unit %d %s has multiple parity errors\n"), 1181 unit, msg)); 1182 } 1183 1184 if (info[table].mem != INVALIDm) { 1185 sal_memset(&spci, 0, sizeof(spci)); 1186 spci.flags = SOC_SER_SRC_MEM | SOC_SER_REG_MEM_KNOWN; 1187 spci.reg = INVALIDr; 1188 spci.mem = info[table].mem; 1189 spci.blk_type = -1; 1190 spci.index = index; 1191 (void)soc_ser_correction(unit, &spci); 1192 } 1193 } else { 1194 LOG_ERROR(BSL_LS_SOC_COMMON, 1195 (BSL_META_U(unit, 1196 "unit %d %s: parity hardware inconsistency\n"), 1197 unit, msg)); 1198 } 1199 1200 /* Clear parity status */ 1201 SOC_IF_ERROR_RETURN(soc_reg32_set(unit,status_reg, block_port, 0, 0)); 1202 return SOC_E_NONE; 1203 } 1204 1205 STATIC int 1206 _soc_hurricane2_process_single_ecc_error(int unit, int group, 1207 soc_port_t block_port, int table, 1208 int schan, char *msg, soc_block_t block) 1209 { 1210 _soc_parity_info_t *info; 1211 soc_reg_t status_reg; 1212 uint32 reg_val; 1213 int index, double_bit, multiple, error; 1214 uint32 minfo; 1215 _soc_ser_correct_info_t spci; 1216 1217 info = _soc_hu2_parity_group_info[group].info; 1218 1219 status_reg = schan ? info[table].nack_status0_reg : 1220 info[table].intr_status0_reg; 1221 if (status_reg == INVALIDr) { 1222 return SOC_E_INTERNAL; 1223 } 1224 SOC_IF_ERROR_RETURN(soc_reg32_get(unit,status_reg, block_port, 0, ®_val)); 1225 index = soc_reg_field_get(unit, status_reg, reg_val, ENTRY_IDXf); 1226 double_bit = soc_reg_field_get(unit, status_reg, 1227 reg_val, DOUBLE_BIT_ERRf); 1228 multiple = soc_reg_field_get(unit, status_reg, reg_val, MULTIPLE_ERRf); 1229 error = soc_reg_field_get(unit, status_reg, reg_val, ECC_ERRf); 1230 1231 if (error) { 1232 _soc_hu2_mem_parity_info(unit, block, 0, 1233 info[table].error_field, &minfo); 1234 soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 1235 SOC_SWITCH_EVENT_DATA_ERROR_ECC, 1236 index, minfo); 1237 LOG_ERROR(BSL_LS_SOC_COMMON, 1238 (BSL_META_U(unit, 1239 "unit %d %s entry %d %s ECC error\n"), 1240 unit, msg, index, double_bit ? "double-bit" : "")); 1241 if (multiple) { 1242 LOG_ERROR(BSL_LS_SOC_COMMON, 1243 (BSL_META_U(unit, 1244 "unit %d %s has multiple ECC errors\n"), 1245 unit, msg)); 1246 } 1247 sal_memset(&spci, 0, sizeof(spci)); 1248 if (double_bit) { 1249 spci.double_bit = 1; 1250 } 1251 if (info[table].mem != INVALIDm) { 1252 spci.flags = SOC_SER_SRC_MEM | SOC_SER_REG_MEM_KNOWN; 1253 spci.reg = INVALIDr; 1254 spci.mem = info[table].mem; 1255 spci.blk_type = -1; 1256 spci.index = index; 1257 spci.parity_type = SOC_PARITY_TYPE_ECC; 1258 (void)soc_ser_correction(unit, &spci); 1259 } 1260 } else { 1261 LOG_ERROR(BSL_LS_SOC_COMMON, 1262 (BSL_META_U(unit, 1263 "unit %d %s: parity hardware inconsistency\n"), 1264 unit, msg)); 1265 } 1266 1267 /* Clear parity status */ 1268 SOC_IF_ERROR_RETURN(soc_reg32_set(unit,status_reg, block_port, 0, 0)); 1269 return SOC_E_NONE; 1270 } 1271 1272 STATIC int 1273 _soc_hurricane2_process_dual_parity_error(int unit, int group, 1274 soc_port_t block_port, int table, 1275 int schan, char *msg, soc_block_t block) 1276 { 1277 _soc_parity_info_t *info; 1278 soc_reg_t status_reg; 1279 uint32 reg_val, bitmap = 0; 1280 int index, bucket_index = 0, multiple = 0, ix, bits, size = 0; 1281 _soc_ser_correct_info_t spci; 1282 uint32 minfo; 1283 1284 info = _soc_hu2_parity_group_info[group].info; 1285 1286 for (ix = 0; ix < 2; ix ++) { 1287 if (ix == 1) { 1288 status_reg = schan ? info[table].nack_status1_reg : 1289 info[table].intr_status1_reg; 1290 } else { 1291 status_reg = schan ? info[table].nack_status0_reg : 1292 info[table].intr_status0_reg; 1293 } 1294 1295 if (status_reg == INVALIDr) { 1296 continue; 1297 } 1298 1299 SOC_IF_ERROR_RETURN(soc_reg32_get(unit,status_reg, 1300 block_port, 0, ®_val)); 1301 if (soc_reg_field_valid(unit, status_reg, BUCKET_IDXf)) { 1302 bucket_index = 1303 soc_reg_field_get(unit, status_reg, reg_val, BUCKET_IDXf); 1304 multiple = 1305 soc_reg_field_get(unit, status_reg, reg_val, MULTIPLE_ERRf); 1306 bitmap = 1307 soc_reg_field_get(unit, status_reg, reg_val, PARITY_ERR_BMf); 1308 size = soc_reg_field_length(unit, status_reg, PARITY_ERR_BMf); 1309 } else if (soc_reg_field_valid(unit, status_reg, BUCKET_IDX_0f)) { 1310 bucket_index = 1311 soc_reg_field_get(unit, status_reg, reg_val, BUCKET_IDX_0f); 1312 multiple = 1313 soc_reg_field_get(unit, status_reg, reg_val, MULTIPLE_ERR_0f); 1314 bitmap = 1315 soc_reg_field_get(unit, status_reg, reg_val, PARITY_ERR_BM_0f); 1316 size = soc_reg_field_length(unit, status_reg, PARITY_ERR_BM_0f); 1317 } else if (soc_reg_field_valid(unit, status_reg, BUCKET_IDX_1f)) { 1318 bucket_index = 1319 soc_reg_field_get(unit, status_reg, reg_val, BUCKET_IDX_1f); 1320 multiple = 1321 soc_reg_field_get(unit, status_reg, reg_val, MULTIPLE_ERR_1f); 1322 bitmap = 1323 soc_reg_field_get(unit, status_reg, reg_val, PARITY_ERR_BM_1f); 1324 size = soc_reg_field_length(unit, status_reg, PARITY_ERR_BM_1f); 1325 } 1326 1327 if (bitmap != 0) { 1328 for (bits = 0; bits < size; bits++) { 1329 if (bitmap & (1 << bits)) { 1330 index = 1331 bucket_index * size * 2 + bits + (ix * size); 1332 _soc_hu2_mem_parity_info(unit, block, 0, 1333 info[table].error_field, &minfo); 1334 soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 1335 SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 1336 index, minfo); 1337 LOG_ERROR(BSL_LS_SOC_COMMON, 1338 (BSL_META_U(unit, 1339 "unit %d %s entry %d parity error\n"), 1340 unit, msg, index)); 1341 if (info[table].mem != INVALIDm) { 1342 sal_memset(&spci, 0, sizeof(_soc_ser_correct_info_t)); 1343 spci.flags = SOC_SER_SRC_MEM | SOC_SER_REG_MEM_KNOWN; 1344 spci.reg = INVALIDr; 1345 spci.mem = info[table].mem; 1346 spci.blk_type = block; 1347 spci.index = index; 1348 (void)soc_ser_correction(unit, &spci); 1349 } 1350 } 1351 } 1352 } 1353 1354 if (multiple) { 1355 LOG_ERROR(BSL_LS_SOC_COMMON, 1356 (BSL_META_U(unit, 1357 "unit %d %s has multiple parity errors\n"), 1358 unit, msg)); 1359 } 1360 1361 /* Clear parity status */ 1362 SOC_IF_ERROR_RETURN(soc_reg32_set(unit,status_reg, block_port, 0, 0)); 1363 } 1364 1365 return SOC_E_NONE; 1366 } 1367 1368 STATIC int 1369 _soc_hurricane2_process_mmu_e2efc_error(int unit, int group, 1370 soc_port_t block_port, int table, 1371 char *msg, soc_block_t block) 1372 { 1373 #define _SOC_HU2_MMU_E2EFC_MAX 4 1374 static soc_reg_t e2efc_regs[_SOC_HU2_MMU_E2EFC_MAX] = { 1375 INVALIDr, 1376 E2EFC_CNT_SET_LIMITr, 1377 E2EFC_CNT_RESET_LIMITr, 1378 E2EFC_CNT_DISC_LIMITr 1379 }; 1380 1381 1382 _soc_parity_info_t *info; 1383 soc_reg_t err_reg; 1384 uint32 reg_val, entry_index, mem_id; 1385 uint32 minfo; 1386 _soc_ser_correct_info_t spci; 1387 1388 info = _soc_hu2_parity_group_info[group].info; 1389 1390 err_reg = E2EFC_PARITYERRORPTRr; 1391 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, err_reg, 1392 block_port, 0, ®_val)); 1393 mem_id = 1394 soc_reg_field_get(unit, err_reg, reg_val, INSTf); 1395 /* CHECK if the error is valid */ 1396 if (mem_id == 0) { 1397 LOG_ERROR(BSL_LS_SOC_COMMON, 1398 (BSL_META_U(unit, 1399 "unit %d %s: parity hardware inconsistency\n"), 1400 unit, msg)); 1401 return SOC_E_NONE; 1402 } 1403 entry_index = 1404 soc_reg_field_get(unit, err_reg, reg_val, PTRf); 1405 1406 _soc_hu2_mem_parity_info(unit, block, 0, 1407 info[table].error_field, &minfo); 1408 soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 1409 SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 1410 entry_index, minfo); 1411 LOG_ERROR(BSL_LS_SOC_COMMON, 1412 (BSL_META_U(unit, 1413 "unit %d MMU E2EFC entry %d parity error\n"), 1414 unit, entry_index)); 1415 sal_memset(&spci, 0, sizeof(_soc_ser_correct_info_t)); 1416 spci.flags = SOC_SER_SRC_REG | SOC_SER_REG_MEM_KNOWN; 1417 spci.reg = e2efc_regs[mem_id]; 1418 spci.mem = INVALIDm; 1419 spci.blk_type = SOC_BLK_MMU; 1420 spci.index = entry_index; 1421 (void)soc_ser_correction(unit, &spci); 1422 1423 return SOC_E_NONE; 1424 } 1425 1426 STATIC int 1427 _soc_hurricane2_process_mmu_ipmc_error(int unit, int group, 1428 soc_port_t block_port, int table, 1429 char *msg, soc_block_t block) 1430 { 1431 1432 _soc_parity_info_t *info; 1433 soc_reg_t err_reg; 1434 uint32 reg_val, entry_index; 1435 uint32 minfo; 1436 _soc_ser_correct_info_t spci; 1437 soc_field_t index_fld; 1438 soc_mem_t target_mem; 1439 1440 1441 info = _soc_hu2_parity_group_info[group].info; 1442 1443 err_reg = IPMCPARITYERRORPTRr; 1444 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, err_reg, 1445 block_port, 0, ®_val)); 1446 switch (info[table].error_field) { 1447 case IPMCVLANXPORTPARITYERRORf: 1448 index_fld = IPMC_VLAN_XPORT_PARITYERRORPTRf; 1449 target_mem = MMU_IPMC_VLAN_TBLm; 1450 break; 1451 case IPMCVLANGPORTPARITYERRORf: 1452 index_fld = IPMC_VLAN_GPORT_PARITYERRORPTRf; 1453 target_mem = MMU_IPMC_VLAN_TBLm; 1454 break; 1455 case IPMCGROUP0PARITYERRORf: 1456 index_fld = IPMC_GROUP0_PARITYERRORPTRf; 1457 target_mem = MMU_IPMC_GROUP_TBL0m; 1458 break; 1459 case IPMCGROUP1PARITYERRORf: 1460 index_fld = IPMC_GROUP1_PARITYERRORPTRf; 1461 target_mem = MMU_IPMC_GROUP_TBL1m; 1462 break; 1463 default: 1464 return SOC_E_INTERNAL; 1465 } 1466 entry_index = 1467 soc_reg_field_get(unit, err_reg, reg_val, index_fld); 1468 1469 _soc_hu2_mem_parity_info(unit, block, 0, 1470 info[table].error_field, &minfo); 1471 soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 1472 SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 1473 entry_index, minfo); 1474 LOG_ERROR(BSL_LS_SOC_COMMON, 1475 (BSL_META_U(unit, 1476 "unit %d MMU_%s entry %d parity error\n"), 1477 unit, SOC_MEM_NAME(unit, target_mem), entry_index)); 1478 sal_memset(&spci, 0, sizeof(_soc_ser_correct_info_t)); 1479 spci.flags = SOC_SER_SRC_MEM | SOC_SER_REG_MEM_KNOWN; 1480 spci.reg = INVALIDr; 1481 spci.mem = target_mem; 1482 spci.blk_type = SOC_BLK_MMU; 1483 spci.index = entry_index; 1484 (void)soc_ser_correction(unit, &spci); 1485 1486 return SOC_E_NONE; 1487 } 1488 1489 1490 STATIC int 1491 _soc_hurricane2_process_parity_error(int unit) 1492 { 1493 int group, table; 1494 uint32 cmic_rval, group_status, 1495 group_enable, cpi_blk_bit; 1496 _soc_parity_info_t *info; 1497 soc_reg_t group_reg, reg; 1498 soc_port_t block_port; 1499 soc_block_t blk; 1500 char *msg; 1501 uint32 minfo; 1502 1503 /* Read CMIC parity status register */ 1504 /* coverity[result_independent_of_operands] */ 1505 SOC_IF_ERROR_RETURN 1506 (READ_CMIC_CMC0_IRQ_STAT2r(unit, &cmic_rval)); 1507 if (cmic_rval == 0) { 1508 return SOC_E_NONE; 1509 } 1510 1511 /* loop through each group */ 1512 for (group = 0; _soc_hu2_parity_group_info[group].cpi_bit; group++) { 1513 info = _soc_hu2_parity_group_info[group].info; 1514 group_reg = _soc_hu2_parity_group_info[group].status_reg; 1515 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1516 (BSL_META_U(unit, 1517 "unit %d %s parity processing\n"), 1518 unit, SOC_REG_NAME(unit, group_reg))); 1519 cpi_blk_bit = _soc_hu2_parity_group_info[group].cpi_bit; 1520 1521 SOC_BLOCK_ITER(unit, blk, 1522 _soc_hu2_parity_group_info[group].blocktype) { 1523 if (_soc_hurricane2_parity_block_port(unit, blk, &block_port) < 0) { 1524 cpi_blk_bit <<= 1; 1525 continue; 1526 } 1527 if (!(cmic_rval & cpi_blk_bit)) { 1528 cpi_blk_bit <<= 1; 1529 continue; 1530 } 1531 1532 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, group_reg, 1533 block_port, 0, &group_status)); 1534 1535 /* loop through each table in the group */ 1536 for (table = 0; info[table].error_field != INVALIDf; table++) { 1537 if (!soc_reg_field_valid(unit, group_reg, 1538 info[table].error_field)) { 1539 if (info[table].mem != INVALIDm) { 1540 LOG_ERROR(BSL_LS_SOC_COMMON, 1541 (BSL_META_U(unit, 1542 "unit %d %s has bad error field\n"), 1543 unit, SOC_MEM_NAME(unit, info[table].mem))); 1544 } 1545 continue; 1546 } 1547 1548 if (!soc_reg_field_get(unit, group_reg, group_status, 1549 info[table].error_field)) { 1550 continue; 1551 } 1552 if (info[table].msg) { 1553 msg = info[table].msg; 1554 } else if (info[table].mem != INVALIDm) { 1555 msg = SOC_MEM_NAME(unit, info[table].mem); 1556 } else { 1557 msg = SOC_FIELD_NAME(unit, info[table].error_field); 1558 } 1559 1560 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1561 (BSL_META_U(unit, 1562 "unit %d %s analysis\n"), 1563 unit, msg)); 1564 1565 /* handle different parity error reporting style */ 1566 switch (info[table].type) { 1567 case _SOC_PARITY_INFO_TYPE_GENERIC: 1568 _soc_hu2_mem_parity_info(unit, blk, 0, 1569 info[table].error_field, &minfo); 1570 soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 1571 SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 0, 1572 minfo); 1573 LOG_ERROR(BSL_LS_SOC_COMMON, 1574 (BSL_META_U(unit, 1575 "unit %d %s asserted\n"), 1576 unit, msg)); 1577 break; 1578 case _SOC_PARITY_INFO_TYPE_SINGLE_PARITY: 1579 SOC_IF_ERROR_RETURN 1580 (_soc_hurricane2_process_single_parity_error(unit, 1581 group, block_port, table, FALSE, msg, blk)); 1582 break; 1583 case _SOC_PARITY_INFO_TYPE_SINGLE_ECC: 1584 SOC_IF_ERROR_RETURN 1585 (_soc_hurricane2_process_single_ecc_error(unit, 1586 group, block_port, table, FALSE, msg, blk)); 1587 break; 1588 case _SOC_PARITY_INFO_TYPE_DUAL_PARITY: 1589 SOC_IF_ERROR_RETURN 1590 (_soc_hurricane2_process_dual_parity_error(unit, 1591 group, block_port, table, FALSE, msg, blk)); 1592 break; 1593 case _SOC_PARITY_INFO_TYPE_MMU_E2EFC: 1594 SOC_IF_ERROR_RETURN 1595 (_soc_hurricane2_process_mmu_e2efc_error(unit, 1596 group, block_port, table, msg, blk)); 1597 break; 1598 case _SOC_PARITY_INFO_TYPE_MMU_IPMC: 1599 SOC_IF_ERROR_RETURN 1600 (_soc_hurricane2_process_mmu_ipmc_error(unit, 1601 group, block_port, table, msg, blk)); 1602 break; 1603 1604 case _SOC_PARITY_INFO_TYPE_OAM: 1605 SOC_IF_ERROR_RETURN 1606 (_soc_hu2_process_oam_interrupt(unit)); 1607 break; 1608 1609 default: 1610 break; 1611 } /* handle different parity error reporting style */ 1612 } /* loop through each table in the group */ 1613 1614 /* clear MMU int status */ 1615 if (SOC_BLK_MMU == _soc_hu2_parity_group_info[group].blocktype) { 1616 SOC_IF_ERROR_RETURN(soc_reg32_set 1617 (unit, group_reg, block_port, 0, 0)); 1618 } 1619 reg = _soc_hu2_parity_group_info[group].enable_reg; 1620 SOC_IF_ERROR_RETURN(soc_reg32_get 1621 (unit, reg, block_port, 0, &group_enable)); 1622 group_enable &= ~group_status; 1623 SOC_IF_ERROR_RETURN(soc_reg32_set 1624 (unit, reg, block_port, 0, group_enable)); 1625 group_enable |= group_status; 1626 SOC_IF_ERROR_RETURN(soc_reg32_set 1627 (unit, reg, block_port, 0, group_enable)); 1628 } /* loop through each block for the group */ 1629 } /* loop through each group */ 1630 1631 return SOC_E_NONE; 1632 } 1633 1634 void 1635 soc_hurricane2_parity_error(void *unit_vp, void *d1, void *d2, void *d3, void *d4) 1636 { 1637 int unit = PTR_TO_INT(unit_vp); 1638 1639 (void)_soc_hurricane2_process_parity_error(unit); 1640 sal_usleep(SAL_BOOT_QUICKTURN ? 100000 : 1000); /* Don't reenable too soon */ 1641 if (d2 != NULL) { 1642 (void)soc_cmicm_intr2_enable(unit, PTR_TO_INT(d2)); 1643 } 1644 } 1645 1646 STATIC int 1647 _soc_hurricane2_mem_nack_error_process(int unit, 1648 _hurricane2_ser_nack_reg_mem_t nack_reg_mem, 1649 soc_block_t block, int reg_mem) 1650 { 1651 int group, table; 1652 _soc_parity_info_t *info; 1653 soc_port_t block_port; 1654 soc_block_t blk; 1655 char *msg; 1656 1657 if (nack_reg_mem.mem == INVALIDm) { 1658 return SOC_E_PARAM; 1659 } 1660 1661 /* loop through each group */ 1662 for (group = 0; _soc_hu2_parity_group_info[group].cpi_bit; group++) { 1663 info = _soc_hu2_parity_group_info[group].info; 1664 1665 SOC_BLOCK_ITER(unit, blk, 1666 _soc_hu2_parity_group_info[group].blocktype) { 1667 if (block != SOC_BLOCK_INFO(unit, blk).schan) { 1668 continue; 1669 } 1670 if (_soc_hurricane2_parity_block_port(unit, blk, &block_port) < 0) { 1671 continue; 1672 } 1673 /* loop through each table in the group */ 1674 for (table = 0; info[table].error_field != INVALIDf; table++) { 1675 if (info[table].mem != nack_reg_mem.mem) { 1676 continue; 1677 } 1678 if (info[table].msg) { 1679 msg = info[table].msg; 1680 } else { /* mem must be valid to get her */ 1681 msg = SOC_MEM_NAME(unit, info[table].mem); 1682 } 1683 1684 /* handle different parity error reporting style */ 1685 switch (info[table].type) { 1686 case _SOC_PARITY_INFO_TYPE_SINGLE_PARITY: 1687 SOC_IF_ERROR_RETURN 1688 (_soc_hurricane2_process_single_parity_error(unit, 1689 group, block_port, table, FALSE, msg, block)); 1690 break; 1691 case _SOC_PARITY_INFO_TYPE_SINGLE_ECC: 1692 SOC_IF_ERROR_RETURN 1693 (_soc_hurricane2_process_single_ecc_error(unit, 1694 group, block_port, table, FALSE, msg, blk)); 1695 break; 1696 case _SOC_PARITY_INFO_TYPE_DUAL_PARITY: 1697 SOC_IF_ERROR_RETURN 1698 (_soc_hurricane2_process_dual_parity_error(unit, 1699 group, block_port, table, FALSE, msg, blk)); 1700 break; 1701 default: 1702 break; 1703 } /* handle different parity error reporting style */ 1704 } /* loop through each table in the group */ 1705 } /* loop through each block of the group */ 1706 } /* loop through each group */ 1707 1708 return SOC_E_NONE; 1709 } 1710 1711 void 1712 soc_hurricane2_mem_nack(void *unit_vp, void *addr_vp, void *blk_vp, 1713 void *d3, void *d4) 1714 { 1715 soc_mem_t mem = INVALIDm; 1716 int reg_mem = PTR_TO_INT(d3); 1717 int rv, unit = PTR_TO_INT(unit_vp); 1718 uint32 address = PTR_TO_INT(addr_vp); 1719 uint32 block = PTR_TO_INT(blk_vp); 1720 uint32 offset = 0, min_addr = 0; 1721 soc_regaddrinfo_t ainfo; 1722 _hurricane2_ser_nack_reg_mem_t nack_reg_mem; 1723 soc_field_t error_fld = INVALIDf; 1724 uint32 minfo; 1725 _soc_ser_correct_info_t spci; 1726 char *msg; 1727 1728 if (reg_mem == _SOC_HURRICANE2_SER_REG) { 1729 nack_reg_mem.reg = INVALIDr; 1730 if (address) { 1731 soc_regaddrinfo_get(unit, &ainfo, address); 1732 nack_reg_mem.reg = ainfo.reg; 1733 } 1734 } else { 1735 offset = address; 1736 mem = soc_addr_to_mem_extended(unit, block, 0, address); 1737 if (mem == INVALIDm) { 1738 LOG_ERROR(BSL_LS_SOC_COMMON, 1739 (BSL_META_U(unit, 1740 "unit %d mem decode failed, " 1741 "SCHAN NACK analysis failure\n"), unit)); 1742 return; 1743 } 1744 1745 nack_reg_mem.mem = mem; 1746 1747 min_addr = SOC_MEM_INFO(unit, mem).base; 1748 min_addr += SOC_MEM_INFO(unit, mem).index_min; 1749 } 1750 1751 if ((mem == EGR_L3_NEXT_HOPm) || (mem == EGR_L3_INTFm) || 1752 (mem == EGR_VLANm) || (mem == EGR_VLAN_STGm) || 1753 (mem == EFP_COUNTER_TABLEm) || 1754 (mem == EGR_PERQ_XMT_COUNTERSm)) { 1755 /* 1756 * The inetrupt of parity error for these memories will not be triggered. 1757 * And the parity error status register will noT be updated. 1758 * Use the offset value of S-channel msg to instead of. 1759 */ 1760 switch (mem) { 1761 case EGR_L3_NEXT_HOPm: 1762 error_fld = EGR_NHOP_PAR_ERRf; 1763 break; 1764 case EGR_L3_INTFm: 1765 error_fld = EGR_L3_INTF_PAR_ERRf; 1766 break; 1767 case EGR_VLANm: 1768 error_fld = EGR_VLAN_PAR_ERRf; 1769 break; 1770 case EGR_VLAN_STGm: 1771 error_fld = EGR_VLAN_STG_PAR_ERRf; 1772 break; 1773 case EFP_COUNTER_TABLEm: 1774 error_fld = EGR_FP_COUNTERf; 1775 break; 1776 default: 1777 /* EGR_PERQ_XMT_COUNTERSm */ 1778 error_fld = EGR_PERQ_COUNTERf; 1779 break; 1780 } 1781 _soc_hu2_mem_parity_info(unit, block, 0, 1782 error_fld, &minfo); 1783 soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 1784 SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 1785 (offset - min_addr), minfo); 1786 msg = SOC_MEM_NAME(unit, mem); 1787 LOG_ERROR(BSL_LS_SOC_COMMON, 1788 (BSL_META_U(unit, 1789 "unit %d %s entry %d parity error\n"), 1790 unit, msg, (offset - min_addr))); 1791 sal_memset(&spci, 0, sizeof(spci)); 1792 spci.flags = SOC_SER_SRC_MEM | SOC_SER_REG_MEM_KNOWN; 1793 spci.reg = INVALIDr; 1794 spci.mem = mem; 1795 spci.blk_type = -1; 1796 spci.index = (offset - min_addr); 1797 (void)soc_ser_correction(unit, &spci); 1798 } else { 1799 1800 if ((rv = _soc_hurricane2_mem_nack_error_process(unit, nack_reg_mem, 1801 (soc_block_t)block, reg_mem)) < 0) { 1802 if (reg_mem == _SOC_HURRICANE2_SER_REG) { 1803 LOG_ERROR(BSL_LS_SOC_COMMON, 1804 (BSL_META_U(unit, 1805 "unit %d REG SCHAN NACK analysis failure\n"), 1806 unit)); 1807 } else { 1808 LOG_ERROR(BSL_LS_SOC_COMMON, 1809 (BSL_META_U(unit, 1810 "unit %d %s entry %d SCHAN NACK analysis failure\n"), 1811 unit, SOC_MEM_NAME(unit, mem), 1812 offset - min_addr)); 1813 } 1814 } 1815 } 1816 if (reg_mem == _SOC_HURRICANE2_SER_REG) { 1817 if (nack_reg_mem.reg != INVALIDr) { 1818 LOG_ERROR(BSL_LS_SOC_COMMON, 1819 (BSL_META_U(unit, 1820 "unit %d %s REG SCHAN NACK analysis\n"), 1821 unit, SOC_REG_NAME(unit, nack_reg_mem.reg))); 1822 soc_reg32_set(unit, ainfo.reg, ainfo.port, ainfo.idx, 0); 1823 } else { 1824 LOG_ERROR(BSL_LS_SOC_COMMON, 1825 (BSL_META_U(unit, 1826 "unit %d invalid register for REG SCHAN NACK analysis\n"), 1827 unit)); 1828 } 1829 } else { 1830 LOG_INFO(BSL_LS_SOC_SCHAN, 1831 (BSL_META_U(unit, 1832 "unit %d %s entry %d SCHAN NACK analysis\n"), 1833 unit, SOC_MEM_NAME(unit, mem), 1834 offset - min_addr)); 1835 } 1836 } 1837 1838 1839 static int 1840 soc_hurricane2_pipe_mem_clear(int unit) 1841 { 1842 uint32 rval, index; 1843 int blk_port; 1844 soc_block_t blk; 1845 int pipe_init_usec; 1846 soc_timeout_t to; 1847 int tcam_protect_write; 1848 static const soc_mem_t cam[] = { 1849 VLAN_SUBNETm, 1850 VLAN_SUBNET_ONLYm, 1851 VFP_TCAMm, 1852 L2_USER_ENTRYm, 1853 L2_USER_ENTRY_ONLYm, 1854 L3_DEFIPm, 1855 L3_DEFIP_ONLYm, 1856 FP_TCAMm, 1857 FP_GLOBAL_MASK_TCAMm, 1858 CPU_COS_MAPm, 1859 CPU_COS_MAP_ONLYm, 1860 EFP_TCAMm 1861 }; 1862 1863 /* 1864 * Reset the IPIPE and EPIPE block 1865 */ 1866 rval = 0; 1867 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_1r(unit, rval)); 1868 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, RESET_ALLf, 1); 1869 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, VALIDf, 1); 1870 /* Set count to # entries in largest IPIPE table, L2_ENTRYm */ 1871 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, COUNTf, 0x8000); 1872 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval)); 1873 1874 rval = 0; 1875 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_0r(unit, rval)); 1876 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, RESET_ALLf, 1); 1877 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, VALIDf, 1); 1878 /* Set count to # entries in largest EPIPE table, EGR_L3_NEXT_HOPm */ 1879 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, COUNTf, 0x4000); 1880 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval)); 1881 1882 /* For simulation, set timeout to 10 sec. Otherwise, timeout = 50 ms */ 1883 if (SAL_BOOT_SIMULATION) { 1884 pipe_init_usec = 10000000; 1885 } else { 1886 pipe_init_usec = 50000; 1887 } 1888 soc_timeout_init(&to, pipe_init_usec, 0); 1889 1890 /* Wait for IPIPE memory initialization done. */ 1891 do { 1892 SOC_IF_ERROR_RETURN(READ_ING_HW_RESET_CONTROL_2r(unit, &rval)); 1893 if (soc_reg_field_get(unit, ING_HW_RESET_CONTROL_2r, rval, DONEf)) { 1894 break; 1895 } 1896 if (soc_timeout_check(&to)) { 1897 LOG_WARN(BSL_LS_SOC_COMMON, 1898 (BSL_META_U(unit, 1899 "unit %d : ING_HW_RESET timeout\n"), unit)); 1900 break; 1901 } 1902 } while (TRUE); 1903 1904 /* Wait for EPIPE memory initialization done. */ 1905 do { 1906 SOC_IF_ERROR_RETURN(READ_EGR_HW_RESET_CONTROL_1r(unit, &rval)); 1907 if (soc_reg_field_get(unit, EGR_HW_RESET_CONTROL_1r, rval, DONEf)) { 1908 break; 1909 } 1910 if (soc_timeout_check(&to)) { 1911 LOG_WARN(BSL_LS_SOC_COMMON, 1912 (BSL_META_U(unit, 1913 "unit %d : EGR_HW_RESET timeout\n"), unit)); 1914 break; 1915 } 1916 } while (TRUE); 1917 1918 rval = 0; 1919 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval)); 1920 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval)); 1921 1922 if (!SAL_BOOT_SIMULATION || SAL_BOOT_BCMSIM) { 1923 /* TCAM tables are not handled by hardware reset control */ 1924 tcam_protect_write = SOC_CONTROL(unit)->tcam_protect_write; 1925 SOC_CONTROL(unit)->tcam_protect_write = FALSE; 1926 for (index = 0; index < sizeof(cam) / sizeof(soc_mem_t); index++) { 1927 if (SOC_MEM_IS_VALID(unit, cam[index])) { 1928 if (SAL_BOOT_BCMSIM && 1929 !((cam[index] == VLAN_SUBNET_ONLYm) || 1930 (cam[index] == CPU_COS_MAP_ONLYm) || 1931 (cam[index] == L2_USER_ENTRY_ONLYm) || 1932 (cam[index] == L3_DEFIP_ONLYm))) { 1933 continue; 1934 } 1935 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, cam[index], 1936 COPYNO_ALL, TRUE)); 1937 } 1938 } 1939 SOC_CONTROL(unit)->tcam_protect_write = tcam_protect_write; 1940 1941 /* MMU_IPMC_VLAN_TBL */ 1942 SOC_IF_ERROR_RETURN 1943 (soc_mem_clear(unit, MMU_IPMC_VLAN_TBLm, COPYNO_ALL, TRUE)); 1944 /* MMU_IPMC_GROUP_TBL0 */ 1945 SOC_IF_ERROR_RETURN 1946 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL0m, COPYNO_ALL, TRUE)); 1947 /* MMU_IPMC_GROUP_TBL1 */ 1948 SOC_IF_ERROR_RETURN 1949 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL1m, COPYNO_ALL, TRUE)); 1950 } 1951 1952 /* Need to clear ING_PW_TERM_COUNTERS since it's not handled by reset control */ 1953 if (!(SAL_BOOT_QUICKTURN) && SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 1954 SOC_IF_ERROR_RETURN 1955 (soc_mem_clear(unit, ING_PW_TERM_COUNTERSm, COPYNO_ALL, TRUE)); 1956 } 1957 1958 /* Reset XLPORT MIB counter (registers implemented in memory) */ 1959 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 1960 blk_port = SOC_BLOCK_PORT(unit, blk); 1961 if (blk_port < 0) { 1962 continue; 1963 } 1964 rval = 0; 1965 /* All Ports */ 1966 soc_reg_field_set(unit, XLPORT_MIB_RESETr, &rval, CLR_CNTf, 0xf); 1967 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, blk_port, rval)); 1968 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, blk_port, 0)); 1969 } 1970 1971 return SOC_E_NONE; 1972 } 1973 1974 1975 #define HU2_NUM_COS 8 1976 int soc_hu2_xq_mem(int unit, soc_port_t port, soc_mem_t *xq) 1977 { 1978 soc_mem_t xq_mems[] = { MMU_XQ0m, 1979 MMU_XQ1m, 1980 MMU_XQ2m, 1981 MMU_XQ3m, 1982 MMU_XQ4m, 1983 MMU_XQ5m, 1984 MMU_XQ6m, 1985 MMU_XQ7m, 1986 MMU_XQ8m, 1987 MMU_XQ9m, 1988 MMU_XQ10m, 1989 MMU_XQ11m, 1990 MMU_XQ12m, 1991 MMU_XQ13m, 1992 MMU_XQ14m, 1993 MMU_XQ15m, 1994 MMU_XQ16m, 1995 MMU_XQ17m, 1996 MMU_XQ18m, 1997 MMU_XQ19m, 1998 MMU_XQ20m, 1999 MMU_XQ21m, 2000 MMU_XQ22m, 2001 MMU_XQ23m, 2002 MMU_XQ24m, 2003 MMU_XQ25m, 2004 MMU_XQ26m, 2005 MMU_XQ27m, 2006 MMU_XQ28m, 2007 MMU_XQ29m 2008 }; 2009 int max_port; 2010 max_port = sizeof(xq_mems) / sizeof(xq_mems[0]); 2011 if (port >= max_port) { 2012 return(SOC_E_PORT); 2013 } 2014 *xq = xq_mems[port]; 2015 return(SOC_E_NONE); 2016 } 2017 2018 /* Hurricane uses 1.5MB of internal Buffers */ 2019 #define HU2_MMU_BUFFER_SIZE (1.5 * 1024 * 1024) 2020 2021 /* 24GE + 4HG +1CPU ports */ 2022 #define HU2_MMU_TOTAL_PORTS 29 2023 2024 #define HU2_MMU_NUM_COS 8 2025 #define HU2_MMU_CELL_SIZE 128 2026 2027 /* total cells = 1.5MB/128 = 12288 */ 2028 #define HU2_MMU_TOTAL_CELLS (HU2_MMU_BUFFER_SIZE/HU2_MMU_CELL_SIZE) 2029 2030 #define HU2_MMU_IN_COS_MIN_CELLS 12 2031 #define HU2_MMU_IN_COS_MIN_XQS 8 2032 2033 /* cos(8) * reserved cells(12) = 96 */ 2034 #define HU2_MMU_IN_PORT_STATIC_CELLS (HU2_MMU_IN_COS_MIN_XQS * HU2_MMU_IN_COS_MIN_CELLS) 2035 2036 /* ports(29) * per port cells(96) = 2784 */ 2037 #define HU2_MMU_TOTAL_STATIC_CELLS (HU2_MMU_TOTAL_PORTS * HU2_MMU_IN_PORT_STATIC_CELLS) 2038 2039 /* total cells(12288) - static cells(2784) = 9504 */ 2040 #define HU2_MMU_TOTAL_DYNAMIC_CELLS (HU2_MMU_TOTAL_CELLS - HU2_MMU_TOTAL_STATIC_CELLS) 2041 2042 /* Every port has 1536 packet pointers(XQs) */ 2043 #define HU2_MMU_IN_PORT_TOTAL_XQS 1536 2044 /* number of cos(8) * minimum xqs per cos(8) = 64 */ 2045 #define HU2_MMU_IN_PORT_STATIC_XQS (HU2_MMU_NUM_COS * HU2_MMU_IN_COS_MIN_XQS) 2046 /* total xqs (1536)- static xqs(64) = 1472 */ 2047 #define HU2_MMU_IN_PORT_DYNAMIC_XQS (HU2_MMU_IN_PORT_TOTAL_XQS - HU2_MMU_IN_PORT_STATIC_XQS) 2048 2049 #define HU2_MMU_MAX_PKT_SIZE 9728 2050 /* xoff threshold = 80 */ 2051 #define HU2_MMU_XOFF_CELL_LIMIT ((HU2_MMU_MAX_PKT_SIZE/HU2_MMU_CELL_SIZE) + 4) 2052 2053 /* max limit for pri-0 = (xoff threshold(80) + max packet size/128 *2 + 16)*23 */ 2054 #define HU2_MMU_MAX_CELL_LIMIT_PRI_0 5704 2055 /* max limit for pri-1-7 = (total xqs/128 * 4)= 1536/128*4 */ 2056 #define HU2_MMU_MAX_CELL_LIMIT_PRI_1_7 48 2057 2058 /* cell limit0 + 7 * cell limit for pri1-7 = 6040 */ 2059 #define HU2_MMU_DYN_CELL_LIMIT (HU2_MMU_MAX_CELL_LIMIT_PRI_0 + \ 2060 ((HU2_MMU_NUM_COS -1) * HU2_MMU_MAX_CELL_LIMIT_PRI_1_7)) 2061 2062 static int port_speed_max[SOC_MAX_PHY_PORTS]; /* max phy port speed */ 2063 2064 int 2065 soc_hu2_init_port_mapping(int unit) 2066 { 2067 soc_info_t *si; 2068 soc_mem_t mem; 2069 uint32 rval; 2070 ing_physical_to_logical_port_number_mapping_table_entry_t entry; 2071 int port, phy_port; 2072 int num_port, num_phy_port; 2073 2074 si = &SOC_INFO(unit); 2075 2076 /* Ingress physical to logical port mapping */ 2077 mem = ING_PHYSICAL_TO_LOGICAL_PORT_NUMBER_MAPPING_TABLEm; 2078 num_phy_port = soc_mem_index_count(unit, mem); 2079 sal_memset(&entry, 0, sizeof(entry)); 2080 for (phy_port = 0; phy_port < num_phy_port; phy_port++) { 2081 port = si->port_p2l_mapping[phy_port]; 2082 soc_mem_field32_set(unit, mem, &entry, LOGICAL_PORT_NUMBERf, 2083 port == -1 ? 0x1f : port); 2084 SOC_IF_ERROR_RETURN 2085 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, phy_port, &entry)); 2086 } 2087 num_port = soc_mem_index_count(unit, PORT_TABm); 2088 /* Egress logical to physical port mapping */ 2089 for (port = 0; port < num_port; port++) { 2090 phy_port = si->port_l2p_mapping[port]; 2091 rval = 0; 2092 soc_reg_field_set(unit, EGR_LOGICAL_TO_PHYSICAL_PORT_NUMBER_MAPPINGr, 2093 &rval, PHYSICAL_PORT_NUMBERf, 2094 phy_port == -1 ? 0x3f : phy_port); 2095 SOC_IF_ERROR_RETURN 2096 (WRITE_EGR_LOGICAL_TO_PHYSICAL_PORT_NUMBER_MAPPINGr(unit, port, 2097 rval)); 2098 } 2099 /* MMU logical to physical port mapping */ 2100 /*(Here, Same as Egress logical to physical port mapping) */ 2101 for (port = 0; port < num_port; port++) { 2102 phy_port = si->port_m2p_mapping[port]; 2103 if (phy_port != -1) { 2104 rval = 0; 2105 soc_reg_field_set(unit, LOG_TO_PHY_PORT_MAPPINGr, &rval, 2106 PHY_PORTf, phy_port); 2107 SOC_IF_ERROR_RETURN 2108 (WRITE_LOG_TO_PHY_PORT_MAPPINGr(unit, port, rval)); 2109 } 2110 } 2111 2112 return SOC_E_NONE; 2113 } 2114 2115 2116 #define CUSTOM_MAPPING_ARRAY_SIZE 34 2117 #define CUSTOM_TSC_PORTMAP_COUNT 8 2118 #define TSCPORT_OFFSET 26 2119 typedef struct _custom_portmap_info_s { 2120 int phy_port_default; 2121 int phy_port_custom; 2122 } _custom_portmap_info_t; 2123 2124 static 2125 _custom_portmap_info_t hu2_custom_tsc_portmap[CUSTOM_TSC_PORTMAP_COUNT] = { 2126 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, 2127 {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} 2128 }; 2129 2130 /* 2131 * Hu2 port mapping 2132 * cpu port number is fixed: physical 0, logical 0, mmu 0 2133 */ 2134 int 2135 soc_hu2_get_port_mapping(int unit, uint16 dev_id) 2136 { 2137 2138 /* Port Mappings */ 2139 static const int p2l_mapping_24_4_0[] = { /* Non-Cascade, Powersave Plus */ 2140 0, -1, 2141 9, 8, 7, 6, 5, 4, 3, 2, 2142 10, 11, 12, 13, 14, 15, 16, 17, 2143 18, 19, 20, 21, 22, 23, 24, 25, 2144 26, 27, 28, 29, 2145 -1, -1, -1, -1 2146 }; 2147 static const int p2l_mapping_24_0_4[] = { /* Non-Cascade, Powersave Plus */ 2148 0, -1, 2149 9, 8, 7, 6, 5, 4, 3, 2, 2150 10, 11, 12, 13, 14, 15, 16, 17, 2151 18, 19, 20, 21, 22, 23, 24, 25, 2152 -1, -1, -1, -1, 2153 26, 27, 28, 29 2154 }; 2155 /* The mapping mode for QSGMII been forced at SGMII mode */ 2156 static const int p2l_mapping_18_4_0[] = { /* Non-Cascade, Powersave Plus */ 2157 0, -1, 2158 9, 8, 7, 6, 5, 4, 3, 2, 2159 10, 11, 12, 13, 14, 15, 16, 17, 2160 18, -1, -1, -1, 22, -1, -1, -1, 2161 26, 27, 28, 29, 2162 -1, -1, -1, -1 2163 }; 2164 static const int p2l_mapping_18_0_4[] = { /* Non-Cascade, Powersave Plus */ 2165 0, -1, 2166 9, 8, 7, 6, 5, 4, 3, 2, 2167 10, 11, 12, 13, 14, 15, 16, 17, 2168 18, -1, -1, -1, 22, -1, -1, -1, 2169 -1, -1, -1, -1, 2170 26, 27, 28, 29 2171 }; 2172 static const int p2l_mapping_24_4_0_x[] = { /* Non-Cascade (No Phy) */ 2173 0, -1, 2174 2, 3, 4, 5, 6, 7, 8, 9, 2175 10, 11, 12, 13, 14, 15, 16, 17, 2176 18, 19, 20, 21, 22, 23, 24, 25, 2177 26, 27, 28, 29, 2178 -1, -1, -1, -1 2179 }; 2180 static const int p2l_mapping_24_0_4_x[] = { /* Non-Cascade (No Phy) */ 2181 0, -1, 2182 2, 3, 4, 5, 6, 7, 8, 9, 2183 10, 11, 12, 13, 14, 15, 16, 17, 2184 18, 19, 20, 21, 22, 23, 24, 25, 2185 -1, -1, -1, -1, 2186 26, 27, 28, 29 2187 }; 2188 /* The mapping mode for QSGMII been forced at SGMII mode */ 2189 static const int p2l_mapping_18_4_0_x[] = { /* Non-Cascade (No Phy) */ 2190 0, -1, 2191 2, 3, 4, 5, 6, 7, 8, 9, 2192 10, 11, 12, 13, 14, 15, 16, 17, 2193 18, -1, -1, -1, 22, -1, -1, -1, 2194 26, 27, 28, 29, 2195 -1, -1, -1, -1 2196 }; 2197 static const int p2l_mapping_18_0_4_x[] = { /* Non-Cascade (No Phy) */ 2198 0, -1, 2199 2, 3, 4, 5, 6, 7, 8, 9, 2200 10, 11, 12, 13, 14, 15, 16, 17, 2201 18, -1, -1, -1, 22, -1, -1, -1, 2202 -1, -1, -1, -1, 2203 26, 27, 28, 29 2204 }; 2205 static const int p2l_mapping_24_2_2[] = { /* Cascade */ 2206 0, -1, 2207 9, 8, 7, 6, 5, 4, 3, 2, 2208 10, 11, 12, 13, 14, 15, 16, 17, 2209 18, 19, 20, 21, 22, 23, 24, 25, 2210 26, -1, 27, -1, 2211 28, -1, 29, -1 2212 }; 2213 /* The mapping mode for QSGMII been forced at SGMII mode */ 2214 static const int p2l_mapping_18_2_2[] = { /* Cascade */ 2215 0, -1, 2216 9, 8, 7, 6, 5, 4, 3, 2, 2217 10, 11, 12, 13, 14, 15, 16, 17, 2218 18, -1, -1, -1, 22, -1, -1, -1, 2219 26, -1, 27, -1, 2220 28, -1, 29, -1 2221 }; 2222 static const int p2l_mapping_24_2_2_x[] = { /* Cascade (No Phy) */ 2223 0, -1, 2224 2, 3, 4, 5, 6, 7, 8, 9, 2225 10, 11, 12, 13, 14, 15, 16, 17, 2226 18, 19, 20, 21, 22, 23, 24, 25, 2227 26, -1, 27, -1, 2228 28, -1, 29, -1 2229 }; 2230 /* The mapping mode for QSGMII been forced at SGMII mode */ 2231 static const int p2l_mapping_18_2_2_x[] = { /* Cascade (No Phy) */ 2232 0, -1, 2233 2, 3, 4, 5, 6, 7, 8, 9, 2234 10, 11, 12, 13, 14, 15, 16, 17, 2235 18, -1, -1, -1, 22, -1, -1, -1, 2236 26, -1, 27, -1, 2237 28, -1, 29, -1 2238 }; 2239 static const int p2l_mapping_24_3_1[] = { /* XAUI */ 2240 0, -1, 2241 9, 8, 7, 6, 5, 4, 3, 2, 2242 10, 11, 12, 13, 14, 15, 16, 17, 2243 18, 19, 20, 21, 22, 23, 24, 25, 2244 26, 27, 28, -1, 2245 29, -1, -1, -1 2246 }; 2247 /* The mapping mode for QSGMII been forced at SGMII mode */ 2248 static const int p2l_mapping_18_3_1[] = { /* XAUI */ 2249 0, -1, 2250 9, 8, 7, 6, 5, 4, 3, 2, 2251 10, 11, 12, 13, 14, 15, 16, 17, 2252 18, -1, -1, -1, 22, -1, -1, -1, 2253 26, 27, 28, -1, 2254 29, -1, -1, -1 2255 }; 2256 static const int p2l_mapping_24_1_1[] = { /* 2xXAUI */ 2257 0, -1, 2258 9, 8, 7, 6, 5, 4, 3, 2, 2259 10, 11, 12, 13, 14, 15, 16, 17, 2260 18, 19, 20, 21, 22, 23, 24, 25, 2261 26, -1, -1, -1, 2262 27, -1, -1, -1 2263 }; 2264 /* The mapping mode for QSGMII been forced at SGMII mode */ 2265 static const int p2l_mapping_18_1_1[] = { /* 2xXAUI */ 2266 0, -1, 2267 9, 8, 7, 6, 5, 4, 3, 2, 2268 10, 11, 12, 13, 14, 15, 16, 17, 2269 18, -1, -1, -1, 22, -1, -1, -1, 2270 26, -1, -1, -1, 2271 27, -1, -1, -1 2272 }; 2273 static const int p2l_mapping_24_3_1_x[] = { /* XAUI (No Phy) */ 2274 0, -1, 2275 2, 3, 4, 5, 6, 7, 8, 9, 2276 10, 11, 12, 13, 14, 15, 16, 17, 2277 18, 19, 20, 21, 22, 23, 24, 25, 2278 26, 27, 28, -1, 2279 29, -1, -1, -1 2280 }; 2281 /* The mapping mode for QSGMII been forced at SGMII mode */ 2282 static const int p2l_mapping_18_3_1_x[] = { /* XAUI (No Phy) */ 2283 0, -1, 2284 2, 3, 4, 5, 6, 7, 8, 9, 2285 10, 11, 12, 13, 14, 15, 16, 17, 2286 18, -1, -1, -1, 22, -1, -1, -1, 2287 26, 27, 28, -1, 2288 29, -1, -1, -1 2289 }; 2290 static const int p2l_mapping_24_1_1_x[] = { /* 2xXAUI (No Phy) */ 2291 0, -1, 2292 2, 3, 4, 5, 6, 7, 8, 9, 2293 10, 11, 12, 13, 14, 15, 16, 17, 2294 18, 19, 20, 21, 22, 23, 24, 25, 2295 26, -1, -1, -1, 2296 27, -1, -1, -1 2297 }; 2298 /* The mapping mode for QSGMII been forced at SGMII mode */ 2299 static const int p2l_mapping_18_1_1_x[] = { /* 2xXAUI (No Phy) */ 2300 0, -1, 2301 2, 3, 4, 5, 6, 7, 8, 9, 2302 10, 11, 12, 13, 14, 15, 16, 17, 2303 18, -1, -1, -1, 22, -1, -1, -1, 2304 26, -1, -1, -1, 2305 27, -1, -1, -1 2306 }; 2307 static const int p2l_mapping_24_0_0[] = { /* Powersave */ 2308 0, -1, 2309 9, 8, 7, 6, 5, 4, 3, 2, 2310 10, 11, 12, 13, 14, 15, 16, 17, 2311 18, 19, 20, 21, 22, 23, 24, 25, 2312 -1, -1, -1, -1, 2313 -1, -1, -1, -1 2314 }; 2315 static const int p2l_mapping_16_0_0[] = { /* Powersave */ 2316 0, -1, 2317 9, 8, 7, 6, 5, 4, 3, 2, 2318 10, 11, 12, 13, 14, 15, 16, 17, 2319 -1, -1, -1, -1, -1, -1, -1, -1, 2320 -1, -1, -1, -1, 2321 -1, -1, -1, -1 2322 }; 2323 static const int p2l_mapping_16_4_0[] = { /* Powersave */ 2324 0, -1, 2325 9, 8, 7, 6, 5, 4, 3, 2, 2326 10, 11, 12, 13, 14, 15, 16, 17, 2327 -1, -1, -1, -1, -1, -1, -1, -1, 2328 26, 27, 28, 29, 2329 -1, -1, -1, -1 2330 }; 2331 static const int p2l_mapping_8_0_0[] = { /* Powersave */ 2332 0, -1, 2333 9, 8, 7, 6, 5, 4, 3, 2, 2334 -1, -1, -1, -1, -1, -1, -1, -1, 2335 -1, -1, -1, -1, -1, -1, -1, -1, 2336 -1, -1, -1, -1, 2337 -1, -1, -1, -1 2338 }; 2339 static const int p2l_mapping_6_4_4[] = { /* Embedded */ 2340 0, -1, 2341 2, -1, -1, -1, 6, -1, -1, -1, 2342 10, -1, -1, -1, 14, -1, -1, -1, 2343 18, -1, -1, -1, 22, -1, -1, -1, 2344 26, 27, 28, 29, 2345 21, 23, 24, 25 2346 }; 2347 static const int p2l_mapping_6_1_4[] = { /* Embedded - XAUI */ 2348 0, -1, 2349 2, -1, -1, -1, 6, -1, -1, -1, 2350 10, -1, -1, -1, 14, -1, -1, -1, 2351 18, -1, -1, -1, 22, -1, -1, -1, 2352 26, -1, -1, -1, 2353 21, 23, 24, 25 2354 }; 2355 static const int p2l_mapping_6_1_3[] = { /* Embedded Plus - XAUI */ 2356 0, -1, 2357 2, -1, -1, -1, 6, -1, -1, -1, 2358 10, -1, -1, -1, 14, -1, -1, -1, 2359 18, -1, -1, -1, 22, -1, -1, -1, 2360 26, -1, -1, -1, 2361 27, 28, 29, -1 2362 }; 2363 /* In Wolfhound ref platform, TSC ports are Even-Odd swapped */ 2364 /* Wolfhound Non-Cascade: only for the BCM953344R reference board */ 2365 /* static const int p2l_mapping_24_4_0_wh[] = { 2366 0, -1, 2367 9, 8, 7, 6, 5, 4, 3, 2, 2368 10, 11, 12, 13, 14, 15, 16, 17, 2369 18, 19, 20, 21, 22, 23, 24, 25, 2370 27, 26, 29, 28, 2371 -1, -1, -1, -1 2372 }; */ 2373 /* The mapping mode for QSGMII been forced at SGMII mode */ 2374 /* Wolfhound Non-Cascade: only for the BCM953344R reference board */ 2375 /* static const int p2l_mapping_18_4_0_wh[] = { 2376 0, -1, 2377 9, 8, 7, 6, 5, 4, 3, 2, 2378 10, 11, 12, 13, 14, 15, 16, 17, 2379 18, -1, -1, -1, 22, -1, -1, -1, 2380 27, 26, 29, 28, 2381 -1, -1, -1, -1 2382 }; */ 2383 2384 /* Port Max Speeds */ 2385 static const int port_speed_max_24x1g_4x10g[] = { 2386 -1, -1, 2387 10, 10, 10, 10, 10, 10, 10, 10, 2388 10, 10, 10, 10, 10, 10, 10, 10, 2389 10, 10, 10, 10, 10, 10, 10, 10, 2390 110,110,110,110, 2391 -1, -1, -1, -1 2392 }; 2393 static const int port_speed_max_24x1g_4x10g_tsc1[] = { 2394 -1, -1, 2395 10, 10, 10, 10, 10, 10, 10, 10, 2396 10, 10, 10, 10, 10, 10, 10, 10, 2397 10, 10, 10, 10, 10, 10, 10, 10, 2398 -1, -1, -1, -1, 2399 110,110,110,110 2400 }; 2401 /* The mapping mode for QSGMII been forced at SGMII mode */ 2402 static const int port_speed_max_18x1g_4x10g[] = { 2403 -1, -1, 2404 10, 10, 10, 10, 10, 10, 10, 10, 2405 10, 10, 10, 10, 10, 10, 10, 10, 2406 10, -1, -1, -1, 10, -1, -1, -1, 2407 110,110,110,110, 2408 -1, -1, -1, -1 2409 }; 2410 static const int port_speed_max_18x1g_4x10g_tsc1[] = { 2411 -1, -1, 2412 10, 10, 10, 10, 10, 10, 10, 10, 2413 10, 10, 10, 10, 10, 10, 10, 10, 2414 10, -1, -1, -1, 10, -1, -1, -1, 2415 -1, -1, -1, -1, 2416 110,110,110,110 2417 }; 2418 static const int port_speed_max_24x1g_3x10g_1x10g[] = { 2419 -1, -1, 2420 10, 10, 10, 10, 10, 10, 10, 10, 2421 10, 10, 10, 10, 10, 10, 10, 10, 2422 10, 10, 10, 10, 10, 10, 10, 10, 2423 110,110,110, -1, 2424 100, -1, -1, -1 2425 }; 2426 /* The mapping mode for QSGMII been forced at SGMII mode */ 2427 static const int port_speed_max_18x1g_3x10g_1x10g[] = { 2428 -1, -1, 2429 10, 10, 10, 10, 10, 10, 10, 10, 2430 10, 10, 10, 10, 10, 10, 10, 10, 2431 10, -1, -1, -1, 10, -1, -1, -1, 2432 110,110,110, -1, 2433 100, -1, -1, -1 2434 }; 2435 static const int port_speed_max_24x1g_1x10g_1x10g[] = { 2436 -1, -1, 2437 10, 10, 10, 10, 10, 10, 10, 10, 2438 10, 10, 10, 10, 10, 10, 10, 10, 2439 10, 10, 10, 10, 10, 10, 10, 10, 2440 100, -1, -1, -1, 2441 100, -1, -1, -1 2442 }; 2443 /* The mapping mode for QSGMII been forced at SGMII mode */ 2444 static const int port_speed_max_18x1g_1x10g_1x10g[] = { 2445 -1, -1, 2446 10, 10, 10, 10, 10, 10, 10, 10, 2447 10, 10, 10, 10, 10, 10, 10, 10, 2448 10, -1, -1, -1, 10, -1, -1, -1, 2449 100, -1, -1, -1, 2450 100, -1, -1, -1 2451 }; 2452 static const int port_speed_max_24x1g_2x10g_2x13g[] = { 2453 -1, -1, 2454 10, 10, 10, 10, 10, 10, 10, 10, 2455 10, 10, 10, 10, 10, 10, 10, 10, 2456 10, 10, 10, 10, 10, 10, 10, 10, 2457 110, -1,110, -1, 2458 130, -1,130, -1 2459 }; 2460 /* The mapping mode for QSGMII been forced at SGMII mode */ 2461 static const int port_speed_max_18x1g_2x10g_2x13g[] = { 2462 -1, -1, 2463 10, 10, 10, 10, 10, 10, 10, 10, 2464 10, 10, 10, 10, 10, 10, 10, 10, 2465 10, -1, -1, -1, 10, -1, -1, -1, 2466 110, -1,110, -1, 2467 130, -1,130, -1 2468 }; 2469 static const int port_speed_max_24x1g_2x10g_2x10g[] = { 2470 -1, -1, 2471 10, 10, 10, 10, 10, 10, 10, 10, 2472 10, 10, 10, 10, 10, 10, 10, 10, 2473 10, 10, 10, 10, 10, 10, 10, 10, 2474 110, -1,110, -1, 2475 110, -1,110, -1 2476 }; 2477 /* The mapping mode for QSGMII been forced at SGMII mode */ 2478 static const int port_speed_max_18x1g_2x10g_2x10g[] = { 2479 -1, -1, 2480 10, 10, 10, 10, 10, 10, 10, 10, 2481 10, 10, 10, 10, 10, 10, 10, 10, 2482 10, -1, -1, -1, 10, -1, -1, -1, 2483 110, -1,110, -1, 2484 110, -1,110, -1 2485 }; 2486 static const int port_speed_max_24x1g_2x13g_2x10g[] = { 2487 -1, -1, 2488 10, 10, 10, 10, 10, 10, 10, 10, 2489 10, 10, 10, 10, 10, 10, 10, 10, 2490 10, 10, 10, 10, 10, 10, 10, 10, 2491 130, -1,130, -1, 2492 110, -1,110, -1 2493 }; 2494 /* The mapping mode for QSGMII been forced at SGMII mode */ 2495 static const int port_speed_max_18x1g_2x13g_2x10g[] = { 2496 -1, -1, 2497 10, 10, 10, 10, 10, 10, 10, 10, 2498 10, 10, 10, 10, 10, 10, 10, 10, 2499 10, -1, -1, -1, 10, -1, -1, -1, 2500 130, -1,130, -1, 2501 110, -1,110, -1 2502 }; 2503 static const int port_speed_max_24x1g_2x1g_2x13g[] = { 2504 -1, -1, 2505 10, 10, 10, 10, 10, 10, 10, 10, 2506 10, 10, 10, 10, 10, 10, 10, 10, 2507 10, 10, 10, 10, 10, 10, 10, 10, 2508 10, -1, 10, -1, 2509 130, -1,130, -1 2510 }; 2511 static const int port_speed_max_24x1g_2x2500k_2x13g[] = { 2512 -1, -1, 2513 10, 10, 10, 10, 10, 10, 10, 10, 2514 10, 10, 10, 10, 10, 10, 10, 10, 2515 10, 10, 10, 10, 10, 10, 10, 10, 2516 25, -1, 25, -1, 2517 130, -1,130, -1 2518 }; 2519 /* The mapping mode for QSGMII been forced at SGMII mode */ 2520 static const int port_speed_max_18x1g_2x1g_2x13g[] = { 2521 -1, -1, 2522 10, 10, 10, 10, 10, 10, 10, 10, 2523 10, 10, 10, 10, 10, 10, 10, 10, 2524 10, -1, -1, -1, 10, -1, -1, -1, 2525 10, -1, 10, -1, 2526 130, -1,130, -1 2527 }; 2528 static const int port_speed_max_18x1g_2x2500k_2x13g[] = { 2529 -1, -1, 2530 10, 10, 10, 10, 10, 10, 10, 10, 2531 10, 10, 10, 10, 10, 10, 10, 10, 2532 10, -1, -1, -1, 10, -1, -1, -1, 2533 25, -1, 25, -1, 2534 130, -1,130, -1 2535 }; 2536 static const int port_speed_max_24x1g_2x13g_2x1g[] = { 2537 -1, -1, 2538 10, 10, 10, 10, 10, 10, 10, 10, 2539 10, 10, 10, 10, 10, 10, 10, 10, 2540 10, 10, 10, 10, 10, 10, 10, 10, 2541 130, -1,130, -1, 2542 10, -1, 10, -1 2543 }; 2544 static const int port_speed_max_24x1g_2x13g_2x2500k[] = { 2545 -1, -1, 2546 10, 10, 10, 10, 10, 10, 10, 10, 2547 10, 10, 10, 10, 10, 10, 10, 10, 2548 10, 10, 10, 10, 10, 10, 10, 10, 2549 130, -1,130, -1, 2550 25, -1, 25, -1 2551 }; 2552 /* The mapping mode for QSGMII been forced at SGMII mode */ 2553 static const int port_speed_max_18x1g_2x13g_2x1g[] = { 2554 -1, -1, 2555 10, 10, 10, 10, 10, 10, 10, 10, 2556 10, 10, 10, 10, 10, 10, 10, 10, 2557 10, -1, -1, -1, 10, -1, -1, -1, 2558 130, -1,130, -1, 2559 10, -1, 10, -1 2560 }; 2561 static const int port_speed_max_18x1g_2x13g_2x2500k[] = { 2562 -1, -1, 2563 10, 10, 10, 10, 10, 10, 10, 10, 2564 10, 10, 10, 10, 10, 10, 10, 10, 2565 10, -1, -1, -1, 10, -1, -1, -1, 2566 130, -1,130, -1, 2567 25, -1, 25, -1 2568 }; 2569 static const int port_speed_max_24x1g_4x1g[] = { 2570 -1, -1, 2571 10, 10, 10, 10, 10, 10, 10, 10, 2572 10, 10, 10, 10, 10, 10, 10, 10, 2573 10, 10, 10, 10, 10, 10, 10, 10, 2574 10, 10, 10, 10, 2575 -1, -1, -1, -1 2576 }; 2577 static const int port_speed_max_24x1g_4x2500k[] = { 2578 -1, -1, 2579 10, 10, 10, 10, 10, 10, 10, 10, 2580 10, 10, 10, 10, 10, 10, 10, 10, 2581 10, 10, 10, 10, 10, 10, 10, 10, 2582 25, 25, 25, 25, 2583 -1, -1, -1, -1 2584 }; 2585 static const int port_speed_max_24x1g_4x2500k_tsc1[] = { 2586 -1, -1, 2587 10, 10, 10, 10, 10, 10, 10, 10, 2588 10, 10, 10, 10, 10, 10, 10, 10, 2589 10, 10, 10, 10, 10, 10, 10, 10, 2590 -1, -1, -1, -1, 2591 25, 25, 25, 25 2592 }; 2593 /* The mapping mode for QSGMII been forced at SGMII mode */ 2594 static const int port_speed_max_18x1g_4x1g[] = { 2595 -1, -1, 2596 10, 10, 10, 10, 10, 10, 10, 10, 2597 10, 10, 10, 10, 10, 10, 10, 10, 2598 10, -1, -1, -1, 10, -1, -1, -1, 2599 10, 10, 10, 10, 2600 -1, -1, -1, -1 2601 }; 2602 static const int port_speed_max_18x1g_4x2500k[] = { 2603 -1, -1, 2604 10, 10, 10, 10, 10, 10, 10, 10, 2605 10, 10, 10, 10, 10, 10, 10, 10, 2606 10, -1, -1, -1, 10, -1, -1, -1, 2607 25, 25, 25, 25, 2608 -1, -1, -1, -1 2609 }; 2610 static const int port_speed_max_18x1g_4x2500k_tsc1[] = { 2611 -1, -1, 2612 10, 10, 10, 10, 10, 10, 10, 10, 2613 10, 10, 10, 10, 10, 10, 10, 10, 2614 10, -1, -1, -1, 10, -1, -1, -1, 2615 -1, -1, -1, -1, 2616 25, 25, 25, 25 2617 }; 2618 static const int port_speed_max_24x1g[] = { 2619 -1, -1, 2620 10, 10, 10, 10, 10, 10, 10, 10, 2621 10, 10, 10, 10, 10, 10, 10, 10, 2622 10, 10, 10, 10, 10, 10, 10, 10, 2623 -1, -1, -1, -1, 2624 -1, -1, -1, -1 2625 }; 2626 static const int port_speed_max_16x1g[] = { 2627 -1, -1, 2628 10, 10, 10, 10, 10, 10, 10, 10, 2629 10, 10, 10, 10, 10, 10, 10, 10, 2630 -1, -1, -1, -1, -1, -1, -1, -1, 2631 -1, -1, -1, -1, 2632 -1, -1, -1, -1 2633 }; 2634 static const int port_speed_max_16x1g_4x1g[] = { 2635 -1, -1, 2636 10, 10, 10, 10, 10, 10, 10, 10, 2637 10, 10, 10, 10, 10, 10, 10, 10, 2638 -1, -1, -1, -1, -1, -1, -1, -1, 2639 10, 10, 10, 10, 2640 -1, -1, -1, -1 2641 }; 2642 static const int port_speed_max_8x1g[] = { 2643 -1, -1, 2644 10, 10, 10, 10, 10, 10, 10, 10, 2645 -1, -1, -1, -1, -1, -1, -1, -1, 2646 -1, -1, -1, -1, -1, -1, -1, -1, 2647 -1, -1, -1, -1, 2648 -1, -1, -1, -1 2649 }; 2650 static const int port_speed_max_6x1g_4x10g_4x1g[] = { 2651 -1, -1, 2652 10, -1, -1, -1, 10, -1, -1, -1, 2653 10, -1, -1, -1, 10, -1, -1, -1, 2654 10, -1, -1, -1, 10, -1, -1, -1, 2655 110,110,110,110, 2656 10, 10, 10, 10 2657 }; 2658 static const int port_speed_max_6x1g_4x1g_4x1g[] = { 2659 -1, -1, 2660 10, -1, -1, -1, 10, -1, -1, -1, 2661 10, -1, -1, -1, 10, -1, -1, -1, 2662 10, -1, -1, -1, 10, -1, -1, -1, 2663 10, 10, 10, 10, 2664 10, 10, 10, 10 2665 }; 2666 static const int port_speed_max_6x1g_1x10g_4x1g[] = { 2667 -1, -1, 2668 10, -1, -1, -1, 10, -1, -1, -1, 2669 10, -1, -1, -1, 10, -1, -1, -1, 2670 10, -1, -1, -1, 10, -1, -1, -1, 2671 100, -1, -1, -1, 2672 10, 10, 10, 10 2673 }; 2674 static const int port_speed_max_6x1g_1x10g_3x10g[] = { 2675 -1, -1, 2676 10, -1, -1, -1, 10, -1, -1, -1, 2677 10, -1, -1, -1, 10, -1, -1, -1, 2678 10, -1, -1, -1, 10, -1, -1, -1, 2679 100, -1, -1, -1, 2680 110,110,110, -1 2681 }; 2682 2683 soc_info_t *si; 2684 int rv = SOC_E_NONE; 2685 int phy_port; 2686 const int *p2l_mapping=NULL, *speed_max=NULL; 2687 int hu2_config_id; 2688 uint32 qsgmii_override = 0; 2689 int i; 2690 int j; 2691 int index; 2692 int logical_port; 2693 int port_bandwidth; 2694 char *config_str, *sub_str, *sub_str_end; 2695 int custom_port_mapping = 0; 2696 int tmp_p2l_mapping[CUSTOM_MAPPING_ARRAY_SIZE]; 2697 int default_p2l_mapping[CUSTOM_MAPPING_ARRAY_SIZE]; 2698 int p2l_mapping_custom[CUSTOM_MAPPING_ARRAY_SIZE] = { /* customized p2l mapping */ 2699 0, -1, 2700 -1, -1, -1, -1, -1, -1, -1, -1, 2701 -1, -1, -1, -1, -1, -1, -1, -1, 2702 -1, -1, -1, -1, -1, -1, -1, -1, 2703 -1, -1, -1, -1, 2704 -1, -1, -1, -1 2705 }; 2706 int port_speed_max_custom[CUSTOM_MAPPING_ARRAY_SIZE] = { 2707 -1, -1, 2708 -1, -1, -1, -1, -1, -1, -1, -1, 2709 -1, -1, -1, -1, -1, -1, -1, -1, 2710 -1, -1, -1, -1, -1, -1, -1, -1, 2711 -1, -1, -1, -1, 2712 -1, -1, -1, -1 2713 }; 2714 2715 hu2_config_id = soc_property_get(unit, spn_BCM5615X_CONFIG, 0); 2716 2717 qsgmii_override = soc_property_get(unit, 2718 spn_SERDES_QSGMII_SGMII_OVERRIDE, 0); 2719 2720 switch (dev_id) { 2721 case BCM56150_DEVICE_ID: 2722 case BCM53346_DEVICE_ID: 2723 if (hu2_config_id == 0) { 2724 /* Option 1: 24P 1G +4P 1G/10G (PHY) */ 2725 if (qsgmii_override == 2) { 2726 /* (to-2SGMII): 18P 1G +4P 1G/10G (PHY) */ 2727 p2l_mapping = p2l_mapping_18_4_0; 2728 speed_max = port_speed_max_18x1g_4x10g; 2729 } else { 2730 p2l_mapping = p2l_mapping_24_4_0; 2731 speed_max = port_speed_max_24x1g_4x10g; 2732 } 2733 } else if ((hu2_config_id == 1) || 2734 (hu2_config_id == 10)) { 2735 /* Option 2: 24P 1G + 2P 1G/10G + 2P 13G (PHY) */ 2736 if (qsgmii_override == 2) { 2737 /* (to-2SGMII): 18P 1G + 2P 1G/10G + 2P 13G (PHY) */ 2738 p2l_mapping = p2l_mapping_18_2_2; 2739 speed_max = port_speed_max_18x1g_2x10g_2x13g; 2740 } else { 2741 p2l_mapping = p2l_mapping_24_2_2; 2742 speed_max = port_speed_max_24x1g_2x10g_2x13g; 2743 } 2744 } else if (hu2_config_id == 11) { 2745 /* Option 2A: 24P 1G + 2P 13G + 2P 1G/10G (PHY) */ 2746 if (qsgmii_override == 2) { 2747 /* (to-2SGMII): 18P 1G + 2P 13G + 2P 1G/10G (PHY) */ 2748 p2l_mapping = p2l_mapping_18_2_2; 2749 speed_max = port_speed_max_18x1g_2x13g_2x10g; 2750 } else { 2751 p2l_mapping = p2l_mapping_24_2_2; 2752 speed_max = port_speed_max_24x1g_2x13g_2x10g; 2753 } 2754 } else if (hu2_config_id == 12) { 2755 /* Option 1A: 24P 1G + 2P 1G/10G + 2P 1G/10G (PHY) */ 2756 if (qsgmii_override == 2) { 2757 /* (to-2SGMII): 18P 1G + 2P 1G/10G + 2P 1G/10G (PHY) */ 2758 p2l_mapping = p2l_mapping_18_2_2; 2759 speed_max = port_speed_max_18x1g_2x10g_2x10g; 2760 } else { 2761 p2l_mapping = p2l_mapping_24_2_2; 2762 speed_max = port_speed_max_24x1g_2x10g_2x10g; 2763 } 2764 } else if (hu2_config_id == 13) { 2765 /* Option 1B: 24P 1G + 4P 1G/10G (PHY, TSC1) */ 2766 if (qsgmii_override == 2) { 2767 /* (to-2SGMII): 18P 1G + 4P 1G/10G (PHY) */ 2768 p2l_mapping = p2l_mapping_18_0_4; 2769 speed_max = port_speed_max_18x1g_4x10g_tsc1; 2770 } else { 2771 p2l_mapping = p2l_mapping_24_0_4; 2772 speed_max = port_speed_max_24x1g_4x10g_tsc1; 2773 } 2774 } else if (hu2_config_id == 2) { 2775 /* Option 3: 24P 1G + 3P 1G/10G + 1P XAUI (PHY) */ 2776 if (qsgmii_override == 2) { 2777 /* (to-2SGMII): 18P 1G + 3P 1G/10G + 1P XAUI (PHY) */ 2778 p2l_mapping = p2l_mapping_18_3_1; 2779 speed_max = port_speed_max_18x1g_3x10g_1x10g; 2780 } else { 2781 p2l_mapping = p2l_mapping_24_3_1; 2782 speed_max = port_speed_max_24x1g_3x10g_1x10g; 2783 } 2784 } else if (hu2_config_id == 3) { 2785 /* Option 4: 24P 1G + 1P XAUI + 1P XAUI (PHY) */ 2786 if (qsgmii_override == 2) { 2787 /* (to-2SGMII): 18P 1G + 1P XAUI + 1P XAUI (PHY) */ 2788 p2l_mapping = p2l_mapping_18_1_1; 2789 speed_max = port_speed_max_18x1g_1x10g_1x10g; 2790 } else { 2791 p2l_mapping = p2l_mapping_24_1_1; 2792 speed_max = port_speed_max_24x1g_1x10g_1x10g; 2793 } 2794 } 2795 break; 2796 case BCM56151_DEVICE_ID: 2797 case BCM53347_DEVICE_ID: 2798 if (hu2_config_id == 0) { 2799 /* Option 1: 24P 1G + 4P 1G/10G (no Phy) */ 2800 if (qsgmii_override == 2) { 2801 /* (to-2SGMII): 18P 1G + 4P 1G/10G (no Phy) */ 2802 p2l_mapping = p2l_mapping_18_4_0_x; 2803 speed_max = port_speed_max_18x1g_4x10g; 2804 } else { 2805 p2l_mapping = p2l_mapping_24_4_0_x; 2806 speed_max = port_speed_max_24x1g_4x10g; 2807 } 2808 } else if ((hu2_config_id == 1) || 2809 (hu2_config_id == 10)) { 2810 /* Option 2: 24P 1G + 2P 1G/10G + 2P 13G (no Phy) */ 2811 if (qsgmii_override == 2) { 2812 /* (to-2SGMII): 18P 1G + 2P 1G/10G + 2P 13G (no Phy) */ 2813 p2l_mapping = p2l_mapping_18_2_2_x; 2814 speed_max = port_speed_max_18x1g_2x10g_2x13g; 2815 } else { 2816 p2l_mapping = p2l_mapping_24_2_2_x; 2817 speed_max = port_speed_max_24x1g_2x10g_2x13g; 2818 } 2819 } else if (hu2_config_id == 11) { 2820 /* Option 2A: 24P 1G + 2P 13G + 2P 1G/10G (no Phy) */ 2821 if (qsgmii_override == 2) { 2822 /* (to-2SGMII): 18P 1G + 2P 13G + 2P 1G/10G (no Phy) */ 2823 p2l_mapping = p2l_mapping_18_2_2_x; 2824 speed_max = port_speed_max_18x1g_2x13g_2x10g; 2825 } else { 2826 p2l_mapping = p2l_mapping_24_2_2_x; 2827 speed_max = port_speed_max_24x1g_2x13g_2x10g; 2828 } 2829 } else if (hu2_config_id == 12) { 2830 /* Option 1A: 24P 1G + 2P 1G/10G + 2P 1G/10G (no PHY) */ 2831 if (qsgmii_override == 2) { 2832 /* (to-2SGMII): 18P 1G + 2P 1G/10G + 2P 1G/10G (no PHY) */ 2833 p2l_mapping = p2l_mapping_18_2_2_x; 2834 speed_max = port_speed_max_18x1g_2x10g_2x10g; 2835 } else { 2836 p2l_mapping = p2l_mapping_24_2_2_x; 2837 speed_max = port_speed_max_24x1g_2x10g_2x10g; 2838 } 2839 } else if (hu2_config_id == 13) { 2840 /* Option 1B: 24P 1G + 4P 1G/10G (no PHY, TSC1) */ 2841 if (qsgmii_override == 2) { 2842 /* (to-2SGMII): 18P 1G + 4P 1G/10G (no Phy) */ 2843 p2l_mapping = p2l_mapping_18_0_4_x; 2844 speed_max = port_speed_max_18x1g_4x10g_tsc1; 2845 } else { 2846 p2l_mapping = p2l_mapping_24_0_4_x; 2847 speed_max = port_speed_max_24x1g_4x10g_tsc1; 2848 } 2849 } else if (hu2_config_id == 2) { 2850 /* Option 2A: 24P 1G + 3P 1G/10G + 1P XAUI (no Phy) */ 2851 if (qsgmii_override == 2) { 2852 /* (to-2SGMII): 18P 1G + 3P 1G/10G + 1P XAUI (no Phy) */ 2853 p2l_mapping = p2l_mapping_18_3_1_x; 2854 speed_max = port_speed_max_18x1g_3x10g_1x10g; 2855 } else { 2856 p2l_mapping = p2l_mapping_24_3_1_x; 2857 speed_max = port_speed_max_24x1g_3x10g_1x10g; 2858 } 2859 } else if (hu2_config_id == 3) { 2860 /* Option 2A: 24P 1G + 1P XAUI + 1P XAUI (no Phy) */ 2861 if (qsgmii_override == 2) { 2862 /* (to-2SGMII): 18P 1G + 1P XAUI + 1P XAUI (no Phy) */ 2863 p2l_mapping = p2l_mapping_18_1_1_x; 2864 speed_max = port_speed_max_18x1g_1x10g_1x10g; 2865 } else { 2866 p2l_mapping = p2l_mapping_24_1_1_x; 2867 speed_max = port_speed_max_24x1g_1x10g_1x10g; 2868 } 2869 } 2870 break; 2871 case BCM53344_DEVICE_ID: 2872 if (hu2_config_id == 0) { 2873 /* Option 1: 24P 1G +4P 1G (PHY) */ 2874 if (qsgmii_override == 2) { 2875 /* (to-2SGMII): 18P 1G +4P 1G (PHY) */ 2876 p2l_mapping = p2l_mapping_18_4_0; 2877 speed_max = port_speed_max_18x1g_4x1g; 2878 } else { 2879 p2l_mapping = p2l_mapping_24_4_0; 2880 speed_max = port_speed_max_24x1g_4x1g; 2881 } 2882 } else if ((hu2_config_id == 1) || 2883 (hu2_config_id == 10)) { 2884 /* Option 2: 24P 1G + 2P 1G + 2P 13G (PHY) */ 2885 if (qsgmii_override == 2) { 2886 /* (to-2SGMII): 18P 1G + 2P 1G + 2P 13G (PHY) */ 2887 p2l_mapping = p2l_mapping_18_2_2; 2888 speed_max = port_speed_max_18x1g_2x1g_2x13g; 2889 } else { 2890 p2l_mapping = p2l_mapping_24_2_2; 2891 speed_max = port_speed_max_24x1g_2x1g_2x13g; 2892 } 2893 } else if (hu2_config_id == 11) { 2894 /* Option 2A: 24P 1G + 2P 13G + 2P 1G (PHY) */ 2895 if (qsgmii_override == 2) { 2896 /* (to-2SGMII): 18P 1G + 2P 13G + 2P 1G (PHY) */ 2897 p2l_mapping = p2l_mapping_18_2_2; 2898 speed_max = port_speed_max_18x1g_2x13g_2x1g; 2899 } else { 2900 p2l_mapping = p2l_mapping_24_2_2; 2901 speed_max = port_speed_max_24x1g_2x13g_2x1g; 2902 } 2903 } 2904 break; 2905 case BCM56152_DEVICE_ID: 2906 if (hu2_config_id == 0) { 2907 /* Option 1: 24P 1G +4P 1G/2.5G (PHY) */ 2908 if (qsgmii_override == 2) { 2909 /* (to-2SGMII): 18P 1G +4P 1G/2.5G (PHY) */ 2910 p2l_mapping = p2l_mapping_18_4_0; 2911 speed_max = port_speed_max_18x1g_4x2500k; 2912 } else { 2913 p2l_mapping = p2l_mapping_24_4_0; 2914 speed_max = port_speed_max_24x1g_4x2500k; 2915 } 2916 } else if ((hu2_config_id == 1) || 2917 (hu2_config_id == 10)) { 2918 /* Option 2: 24P 1G + 2P 1G/2.5G + 2P 13G (PHY) */ 2919 if (qsgmii_override == 2) { 2920 /* (to-2SGMII): 18P 1G + 2P 1G/2.5G + 2P 13G (PHY) */ 2921 p2l_mapping = p2l_mapping_18_2_2; 2922 speed_max = port_speed_max_18x1g_2x2500k_2x13g; 2923 } else { 2924 p2l_mapping = p2l_mapping_24_2_2; 2925 speed_max = port_speed_max_24x1g_2x2500k_2x13g; 2926 } 2927 } else if (hu2_config_id == 11) { 2928 /* Option 2A: 24P 1G + 2P 13G + 2P 1G/2.5G (PHY) */ 2929 if (qsgmii_override == 2) { 2930 /* (to-2SGMII): 18P 1G + 2P 13G + 2P 1G/2.5G (PHY) */ 2931 p2l_mapping = p2l_mapping_18_2_2; 2932 speed_max = port_speed_max_18x1g_2x13g_2x2500k; 2933 } else { 2934 p2l_mapping = p2l_mapping_24_2_2; 2935 speed_max = port_speed_max_24x1g_2x13g_2x2500k; 2936 } 2937 } else if (hu2_config_id == 13) { 2938 /* Option 1B: 24P 1G +4P 1G (PHY, TSC1) */ 2939 if (qsgmii_override == 2) { 2940 /* (to-2SGMII): 18P 1G +4P 1G (PHY) */ 2941 p2l_mapping = p2l_mapping_18_0_4; 2942 speed_max = port_speed_max_18x1g_4x2500k_tsc1; 2943 } else { 2944 p2l_mapping = p2l_mapping_24_0_4; 2945 speed_max = port_speed_max_24x1g_4x2500k_tsc1; 2946 } 2947 } 2948 break; 2949 case BCM53334_DEVICE_ID: 2950 /* 24P 1G (PHY) */ 2951 p2l_mapping = p2l_mapping_24_0_0; 2952 speed_max = port_speed_max_24x1g; 2953 break; 2954 case BCM53333_DEVICE_ID: 2955 /* 16P 1G (PHY) */ 2956 p2l_mapping = p2l_mapping_16_0_0; 2957 speed_max = port_speed_max_16x1g; 2958 break; 2959 case BCM53343_DEVICE_ID: 2960 /* 16P 1G (PHY) + 4P 1G */ 2961 p2l_mapping = p2l_mapping_16_4_0; 2962 speed_max = port_speed_max_16x1g_4x1g; 2963 break; 2964 case BCM53342_DEVICE_ID: 2965 /* 8P 1G (PHY) */ 2966 p2l_mapping = p2l_mapping_8_0_0; 2967 speed_max = port_speed_max_8x1g; 2968 break; 2969 case BCM53393_DEVICE_ID: 2970 /* 14P 1G, (no PHY) */ 2971 p2l_mapping = p2l_mapping_6_4_4; 2972 speed_max = port_speed_max_6x1g_4x1g_4x1g; 2973 break; 2974 case BCM53394_DEVICE_ID: 2975 if (hu2_config_id == 0) { 2976 /* 10P 1G + 4x1/2.5/5/10G (no PHY) */ 2977 p2l_mapping = p2l_mapping_6_4_4; 2978 speed_max = port_speed_max_6x1g_4x10g_4x1g; 2979 } else if (hu2_config_id == 1) { 2980 /* 10P 1G + 1P XAUI (no Phy) */ 2981 p2l_mapping = p2l_mapping_6_1_4; 2982 speed_max = port_speed_max_6x1g_1x10g_4x1g; 2983 } else if (hu2_config_id == 2) { 2984 /* 6P 1G + 3x1/10G + 1P XAUI (no Phy) */ 2985 p2l_mapping = p2l_mapping_6_1_3; 2986 speed_max = port_speed_max_6x1g_1x10g_3x10g; 2987 } 2988 break; 2989 default : 2990 break; 2991 } 2992 2993 if ((p2l_mapping == NULL) || (speed_max == NULL)) { 2994 return SOC_E_CONFIG; 2995 } 2996 2997 /* save the default p2l mapping */ 2998 sal_memcpy(default_p2l_mapping, p2l_mapping, sizeof(default_p2l_mapping)); 2999 sal_memcpy(tmp_p2l_mapping, p2l_mapping, sizeof(tmp_p2l_mapping)); 3000 sal_memcpy(port_speed_max_custom, speed_max, sizeof(port_speed_max_custom)); 3001 3002 for (logical_port = 2; logical_port < CUSTOM_MAPPING_ARRAY_SIZE; logical_port++) { 3003 config_str = soc_property_port_get_str(unit, logical_port, spn_PORTMAP); 3004 if (config_str == NULL) { 3005 continue; 3006 } 3007 custom_port_mapping = 1; 3008 3009 /* 3010 * portmap.<port>=<physical port number>:<bandwidth in Gb> 3011 * [:<queue config>] 3012 */ 3013 sub_str = config_str; 3014 3015 /* Parsing physical port number */ 3016 phy_port = sal_ctoi(sub_str, &sub_str_end); 3017 if (sub_str == sub_str_end) { 3018 LOG_ERROR(BSL_LS_SOC_COMMON, 3019 (BSL_META_U(unit, 3020 "Port %d: Missing physical port information \"%s\"\n"), 3021 logical_port, config_str)); 3022 rv = SOC_E_FAIL; 3023 continue; 3024 } 3025 if (phy_port < 2 || phy_port > 33) { 3026 LOG_ERROR(BSL_LS_SOC_COMMON, 3027 (BSL_META_U(unit, 3028 "Port %d: Invalid physical port number %d\n"), 3029 logical_port, phy_port)); 3030 rv = SOC_E_FAIL; 3031 continue; 3032 } 3033 3034 if (p2l_mapping_custom[phy_port] != -1) { 3035 LOG_ERROR(BSL_LS_SOC_COMMON, 3036 (BSL_META_U(unit, 3037 "Port %d: Physical port %d is used by port %d\n"), 3038 logical_port, phy_port, p2l_mapping_custom[phy_port])); 3039 rv = SOC_E_FAIL; 3040 continue; 3041 } 3042 3043 /* Skip ':' */ 3044 sub_str = sub_str_end; 3045 if (*sub_str != '\0') { 3046 if (*sub_str != ':') { 3047 LOG_ERROR(BSL_LS_SOC_COMMON, 3048 (BSL_META_U(unit, 3049 "Port %d: Bad config string \"%s\"\n"), 3050 logical_port, config_str)); 3051 rv = SOC_E_FAIL; 3052 continue; 3053 } 3054 sub_str++; 3055 } 3056 3057 /* Parsing bandwidth */ 3058 port_bandwidth = sal_ctoi(sub_str, &sub_str_end); 3059 if (sub_str == sub_str_end) { 3060 LOG_ERROR(BSL_LS_SOC_COMMON, 3061 (BSL_META_U(unit, 3062 "Port %d: Missing bandwidth information \"%s\"\n"), 3063 logical_port, config_str)); 3064 rv = SOC_E_FAIL; 3065 continue; 3066 } 3067 if (port_bandwidth != 1 && port_bandwidth != 10 && 3068 port_bandwidth != 13 && port_bandwidth != 11) { 3069 LOG_ERROR(BSL_LS_SOC_COMMON, 3070 (BSL_META_U(unit, 3071 "Port %d: Invalid bandwidth %d Gb\n"), 3072 logical_port, port_bandwidth)); 3073 rv = SOC_E_FAIL; 3074 continue; 3075 } 3076 3077 p2l_mapping_custom[phy_port] = logical_port; 3078 port_speed_max_custom[phy_port] = port_bandwidth * 10; 3079 tmp_p2l_mapping[phy_port] = logical_port; 3080 } 3081 3082 if (custom_port_mapping) { 3083 p2l_mapping = tmp_p2l_mapping; 3084 speed_max = port_speed_max_custom; 3085 3086 for (i = 0; i < CUSTOM_TSC_PORTMAP_COUNT; i++) { 3087 for (j = 0; j < CUSTOM_MAPPING_ARRAY_SIZE; j++) { 3088 if (default_p2l_mapping[j] == i + TSCPORT_OFFSET) { 3089 hu2_custom_tsc_portmap[i].phy_port_default = j; 3090 /* init customer port mapping at default */ 3091 hu2_custom_tsc_portmap[i].phy_port_custom = j; 3092 break; 3093 } 3094 } 3095 for (j = 0; j < CUSTOM_MAPPING_ARRAY_SIZE; j++) { 3096 if (p2l_mapping_custom[j] == i + TSCPORT_OFFSET) { 3097 /* apply real customer port mapping */ 3098 hu2_custom_tsc_portmap[i].phy_port_custom = j; 3099 break; 3100 } 3101 } 3102 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3103 (BSL_META_U(unit, 3104 "Customized TSC port mapping[%d] = %d, %d\n"), 3105 i, hu2_custom_tsc_portmap[i].phy_port_default, 3106 hu2_custom_tsc_portmap[i].phy_port_custom)); 3107 } 3108 } 3109 3110 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3111 (BSL_META_U(unit, 3112 "P2L mapping: \n"))); 3113 for (index = 0;index < CUSTOM_MAPPING_ARRAY_SIZE;index++) { 3114 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3115 (BSL_META_U(unit, 3116 "%d "), 3117 p2l_mapping[index])); 3118 } 3119 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3120 (BSL_META_U(unit, 3121 "\n"))); 3122 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3123 (BSL_META_U(unit, 3124 "MAX SPEED: \n"))); 3125 for (index = 0;index < CUSTOM_MAPPING_ARRAY_SIZE;index++) { 3126 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3127 (BSL_META_U(unit, 3128 "%d "), 3129 speed_max[index])); 3130 } 3131 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3132 (BSL_META_U(unit, 3133 "\n"))); 3134 3135 si = &SOC_INFO(unit); 3136 si->bandwidth = 64000; 3137 for (phy_port = 0; phy_port < SOC_MAX_PHY_PORTS; phy_port++) { 3138 si->port_p2l_mapping[phy_port] = p2l_mapping[phy_port]; 3139 si->port_p2m_mapping[phy_port] = p2l_mapping[phy_port]; /* Same as Egr P2L */ 3140 si->max_port_p2m_mapping[phy_port] = p2l_mapping[phy_port]; /* For COSQ programming */ 3141 port_speed_max[phy_port] = 0; 3142 if (speed_max[phy_port] != -1) { 3143 si->port_speed_max[si->port_p2l_mapping[phy_port]] = 3144 speed_max[phy_port] * 100; 3145 port_speed_max[phy_port] = speed_max[phy_port] * 100; 3146 } 3147 } 3148 return rv; 3149 } 3150 3151 /* 3152 * HU2 port mapping 3153 */ 3154 int 3155 soc_hu2_port_config_init(int unit, uint16 dev_id) 3156 { 3157 int b, p; 3158 /* Map of block to first physical port in the block */ 3159 int _hu2_b2pp[SOC_MAX_NUM_BLKS]; 3160 3161 for (b=0; SOC_BLOCK_TYPE(unit, b) != -1; b++) { 3162 _hu2_b2pp[b] = -1; 3163 for (p=0; SOC_PORT_BLOCK(unit, p)!= -1; p++) { 3164 if (b == SOC_PORT_BLOCK(unit, p)) { 3165 _hu2_b2pp[b] = p; 3166 break; 3167 } 3168 } 3169 } 3170 SOC_INFO(unit).blk_fpp = _hu2_b2pp; 3171 return soc_hu2_get_port_mapping(unit, dev_id); 3172 } 3173 3174 int 3175 soc_hurricane2_tsc_reset(int unit) 3176 { 3177 int blk, port; 3178 uint32 rval; 3179 3180 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 3181 port = SOC_BLOCK_PORT(unit, blk); 3182 SOC_IF_ERROR_RETURN(soc_tsc_xgxs_reset(unit, port, 0)); 3183 } 3184 3185 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 3186 port = SOC_BLOCK_PORT(unit, blk); 3187 3188 SOC_IF_ERROR_RETURN(READ_XLPORT_MAC_CONTROLr(unit, port, &rval)); 3189 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1); 3190 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval)); 3191 sal_udelay(10); 3192 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0); 3193 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval)); 3194 } 3195 3196 return SOC_E_NONE; 3197 } 3198 3199 int 3200 _soc_hu2_tdm_init(int unit, uint16 dev_id) 3201 { 3202 3203 /* Embedded Mode TDM */ 3204 uint32 hu2_tdm_embedded[60] = {26,27,28,29,30,31, 3205 26,27,28,29,63,63, 3206 26,27,28,29,2,63, 3207 26,27,28,29,10,63, 3208 26,27,28,29,18,0, 3209 26,27,28,29,32,33, 3210 26,27,28,29,63,63, 3211 26,27,28,29,6,63, 3212 26,27,28,29,14,63, 3213 26,27,28,29,22,63}; 3214 3215 /* Embedded Plus Mode TDM */ 3216 uint32 hu2_tdm_embedded_plus[60] = {26,30,31,32,63,63, 3217 26,30,31,32,63,63, 3218 26,30,31,32,2,63, 3219 26,30,31,32,10,63, 3220 26,30,31,32,18,0, 3221 26,30,31,32,63,63, 3222 26,30,31,32,63,63, 3223 26,30,31,32,6,63, 3224 26,30,31,32,14,63, 3225 26,30,31,32,22,63}; 3226 3227 /* Powersave Mode TDM */ 3228 uint32 hu2_tdm_powersave[48] = {2,10,18,63,63,0, 3229 3,11,19,63,63,63, 3230 4,12,20,63,63,63, 3231 5,13,21,63,63,63, 3232 6,14,22,63,63,63, 3233 7,15,23,63,63,63, 3234 8,16,24,63,63,63, 3235 9,17,25,63,63,63}; 3236 3237 /* Cascade Mode TDM */ 3238 uint32 hu2_tdm_cascade[75] = {2,14,26,28,30,32, 3239 3,15,26,28,30,32, 3240 4,16,26,28,30,32, 3241 5,17,26,28,30,32, 3242 0, 3243 6,18,26,28,30,32, 3244 7,19,26,28,30,32, 3245 8,20,26,28,30,32, 3246 9,21,26,28,30,32, 3247 63, 3248 10,22,26,28,30,32, 3249 11,23,26,28,30,32, 3250 12,24,26,28,30,32, 3251 13,25,26,28,30,32, 3252 63}; 3253 3254 /* XAUI Mode TDM */ 3255 uint32 hu2_tdm_xaui[75] = {2,14,26,27,28,30, 3256 3,15,26,27,28,30, 3257 4,16,26,27,28,30, 3258 5,17,26,27,28,30, 3259 0, 3260 6,18,26,27,28,30, 3261 7,19,26,27,28,30, 3262 8,20,26,27,28,30, 3263 9,21,26,27,28,30, 3264 63, 3265 10,22,26,27,28,30, 3266 11,23,26,27,28,30, 3267 12,24,26,27,28,30, 3268 13,25,26,27,28,30, 3269 63}; 3270 3271 /* Non-Cascade Mode TDM */ 3272 uint32 hu2_tdm_non_cascade[75] = {2,14,26,27,28,29, 3273 3,15,26,27,28,29, 3274 4,16,26,27,28,29, 3275 5,17,26,27,28,29, 3276 0, 3277 6,18,26,27,28,29, 3278 7,19,26,27,28,29, 3279 8,20,26,27,28,29, 3280 9,21,26,27,28,29, 3281 63, 3282 10,22,26,27,28,29, 3283 11,23,26,27,28,29, 3284 12,24,26,27,28,29, 3285 13,25,26,27,28,29, 3286 63}; 3287 3288 /* Non-Cascade Mode TDM (option 1b)*/ 3289 uint32 hu2_tdm_non_cascade_1b[75] = {2,14,30,31,32,33, 3290 3,15,30,31,32,33, 3291 4,16,30,31,32,33, 3292 5,17,30,31,32,33, 3293 0, 3294 6,18,30,31,32,33, 3295 7,19,30,31,32,33, 3296 8,20,30,31,32,33, 3297 9,21,30,31,32,33, 3298 63, 3299 10,22,30,31,32,33, 3300 11,23,30,31,32,33, 3301 12,24,30,31,32,33, 3302 13,25,30,31,32,33, 3303 63}; 3304 3305 /* Powersave Plus Mode TDM */ 3306 uint32 hu2_tdm_powersave_plus[48] = {2,10,18,26,63,0, 3307 3,11,19,63,63,63, 3308 4,12,20,27,63,63, 3309 5,13,21,63,63,63, 3310 6,14,22,28,63,63, 3311 7,15,23,63,63,63, 3312 8,16,24,29,63,63, 3313 9,17,25,63,63,63}; 3314 uint32 *arr = NULL; 3315 int tdm_size = 0; 3316 uint32 rval; 3317 iarb_tdm_table_entry_t iarb_tdm; 3318 mmu_arb_tdm_table_entry_t mmu_arb_tdm; 3319 int i, port, phy_port; 3320 int hu2_config_id; 3321 int j; 3322 3323 hu2_config_id = soc_property_get(unit, spn_BCM5615X_CONFIG, 0); 3324 3325 SOC_IF_ERROR_RETURN(READ_IARB_TDM_CONTROLr(unit, &rval)); 3326 soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, DISABLEf, 1); 3327 soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, TDM_WRAP_PTRf, 83); 3328 SOC_IF_ERROR_RETURN(WRITE_IARB_TDM_CONTROLr(unit, rval)); 3329 3330 switch (dev_id) { 3331 case BCM56150_DEVICE_ID: 3332 case BCM56151_DEVICE_ID: 3333 case BCM53346_DEVICE_ID: 3334 case BCM53347_DEVICE_ID: 3335 if (hu2_config_id == 0) { 3336 tdm_size = 75; 3337 arr = hu2_tdm_non_cascade; 3338 } else if (hu2_config_id == 13) { 3339 tdm_size = 75; 3340 arr = hu2_tdm_non_cascade_1b; 3341 } else if ((hu2_config_id == 1) || 3342 (hu2_config_id == 10) || 3343 (hu2_config_id == 11) || 3344 (hu2_config_id == 12)) { 3345 tdm_size = 75; 3346 arr = hu2_tdm_cascade; 3347 } else if ((hu2_config_id == 2) || 3348 (hu2_config_id == 3)) { 3349 tdm_size = 75; 3350 arr = hu2_tdm_xaui; 3351 } 3352 break; 3353 case BCM53344_DEVICE_ID: 3354 if (hu2_config_id == 0) { 3355 tdm_size = 48; 3356 arr = hu2_tdm_powersave_plus; 3357 } else if ((hu2_config_id == 1) || 3358 (hu2_config_id == 10) || 3359 (hu2_config_id == 11)) { 3360 tdm_size = 75; 3361 arr = hu2_tdm_cascade; 3362 } 3363 break; 3364 case BCM56152_DEVICE_ID: 3365 if (hu2_config_id == 0) { 3366 tdm_size = 75; 3367 arr = hu2_tdm_non_cascade; 3368 } else if (hu2_config_id == 13) { 3369 tdm_size = 75; 3370 arr = hu2_tdm_non_cascade_1b; 3371 } else if ((hu2_config_id == 1) || 3372 (hu2_config_id == 10) || 3373 (hu2_config_id == 11)) { 3374 tdm_size = 75; 3375 arr = hu2_tdm_cascade; 3376 } 3377 break; 3378 case BCM53333_DEVICE_ID: 3379 case BCM53334_DEVICE_ID: 3380 case BCM53342_DEVICE_ID: 3381 tdm_size = 48; 3382 arr = hu2_tdm_powersave; 3383 break; 3384 case BCM53343_DEVICE_ID: 3385 tdm_size = 48; 3386 arr = hu2_tdm_powersave_plus; 3387 break; 3388 case BCM53393_DEVICE_ID: 3389 tdm_size = 60; 3390 arr = hu2_tdm_embedded; 3391 break; 3392 case BCM53394_DEVICE_ID: 3393 tdm_size = 60; 3394 if (hu2_config_id == 2) { 3395 arr = hu2_tdm_embedded_plus; 3396 } else { 3397 arr = hu2_tdm_embedded; 3398 } 3399 break; 3400 default : 3401 break; 3402 } 3403 3404 if ((arr == NULL) || (tdm_size == 0)) { 3405 return SOC_E_CONFIG; 3406 } 3407 3408 for (i = 0; i < tdm_size; i++) { 3409 for (j = 0; j < CUSTOM_TSC_PORTMAP_COUNT; j++) { 3410 if (arr[i] == hu2_custom_tsc_portmap[j].phy_port_default) { 3411 if (hu2_custom_tsc_portmap[j].phy_port_default != hu2_custom_tsc_portmap[j].phy_port_custom) { 3412 arr[i] = hu2_custom_tsc_portmap[j].phy_port_custom; 3413 } 3414 break; 3415 } 3416 } 3417 } 3418 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3419 (BSL_META_U(unit, 3420 "TDM table (size %d):\n"), 3421 tdm_size)); 3422 for (i = 0; i < tdm_size; i++) { 3423 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3424 (BSL_META_U(unit, 3425 "%d "), 3426 arr[i])); 3427 } 3428 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3429 (BSL_META_U(unit, 3430 "\n"))); 3431 3432 for (i = 0; i < tdm_size; i++) { 3433 phy_port = arr[i]; 3434 port = (phy_port != 63) ? SOC_INFO(unit).port_p2l_mapping[phy_port] : 63; 3435 3436 sal_memset(&iarb_tdm, 0, sizeof(iarb_tdm_table_entry_t)); 3437 sal_memset(&mmu_arb_tdm, 0, sizeof(mmu_arb_tdm_table_entry_t)); 3438 3439 soc_IARB_TDM_TABLEm_field32_set(unit, &iarb_tdm, PORT_NUMf, 3440 phy_port); 3441 3442 soc_MMU_ARB_TDM_TABLEm_field32_set(unit, &mmu_arb_tdm, PORT_NUMf, 3443 (port != -1) ? port : 63); 3444 if (i == tdm_size - 1) { 3445 soc_MMU_ARB_TDM_TABLEm_field32_set(unit, &mmu_arb_tdm, WRAP_ENf, 1); 3446 } 3447 SOC_IF_ERROR_RETURN(WRITE_IARB_TDM_TABLEm(unit, SOC_BLOCK_ALL, i, 3448 &iarb_tdm)); 3449 SOC_IF_ERROR_RETURN(WRITE_MMU_ARB_TDM_TABLEm(unit, SOC_BLOCK_ALL, i, 3450 &mmu_arb_tdm)); 3451 } 3452 rval = 0; 3453 soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, DISABLEf, 0); 3454 soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, TDM_WRAP_PTRf, 3455 tdm_size -1); 3456 SOC_IF_ERROR_RETURN(WRITE_IARB_TDM_CONTROLr(unit, rval)); 3457 return SOC_E_NONE; 3458 } 3459 3460 int 3461 soc_hurricane2_mmu_init(int unit) 3462 { 3463 int cos; 3464 soc_port_t port; 3465 uint32 val, oval, cfap_max_idx, tm; 3466 int age[HU2_NUM_COS], max_age, min_age; 3467 int age_enable, disabled_age; 3468 int skid_mark; 3469 uint32 dyn_xq_per_port; 3470 uint32 limit; 3471 uint32 xq_limit, pkt_limit, cell_limit; 3472 uint32 cos_min_xqs, cos_min_cells; 3473 uint16 dev_id; 3474 uint8 rev_id; 3475 3476 soc_cm_get_id(unit, &dev_id, &rev_id); 3477 3478 SOC_IF_ERROR_RETURN(_soc_hu2_tdm_init(unit, dev_id)); 3479 3480 cfap_max_idx = soc_mem_index_max(unit, MMU_CFAPm); 3481 SOC_IF_ERROR_RETURN(READ_CFAPCONFIGr(unit, &val)); 3482 oval = val; 3483 soc_reg_field_set(unit, CFAPCONFIGr, &val, CFAPPOOLSIZEf, cfap_max_idx); 3484 if (oval != val) { 3485 SOC_IF_ERROR_RETURN(WRITE_CFAPCONFIGr(unit, val)); 3486 } 3487 3488 /* set skidmarker to 3 */ 3489 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &val)); 3490 soc_reg_field_set(unit, MISCCONFIGr, &val, SKIDMARKERf, 3); 3491 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, val)); 3492 3493 /* Every inactive COSQ consumes skid mark + 4 XQs; remove them from pool */ 3494 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &val)); 3495 skid_mark = soc_reg_field_get(unit, MISCCONFIGr, val, SKIDMARKERf) + 4; 3496 3497 /* Enable IP to CMICM credit transfer */ 3498 val = 0; 3499 soc_reg_field_set(unit, IP_TO_CMICM_CREDIT_TRANSFERr, &val, TRANSFER_ENABLEf, 1); 3500 soc_reg_field_set(unit, IP_TO_CMICM_CREDIT_TRANSFERr, &val, NUM_OF_CREDITSf, 32); 3501 SOC_IF_ERROR_RETURN(WRITE_IP_TO_CMICM_CREDIT_TRANSFERr(unit, val)); 3502 3503 if (dev_id != BCM56147_DEVICE_ID) { 3504 /* total dynamic xqs - skid mark - 9(reserved xqs) */ 3505 dyn_xq_per_port = HU2_MMU_IN_PORT_DYNAMIC_XQS - skid_mark - 9; 3506 /* limit includes the static minimum cells as well */ 3507 xq_limit = dyn_xq_per_port + 8; 3508 cos_min_xqs = HU2_MMU_IN_COS_MIN_XQS; 3509 cos_min_cells = HU2_MMU_IN_COS_MIN_CELLS; 3510 } 3511 else { 3512 /* dynamic xqs = total xqs - static xqs(num of cos * per cos reserve(4)) */ 3513 dyn_xq_per_port = HU2_MMU_IN_PORT_TOTAL_XQS - (HU2_MMU_NUM_COS * 4); 3514 /* total dynamic xqs = dynamic xqs - skid mark - 9(reserved xqs) */ 3515 dyn_xq_per_port = dyn_xq_per_port - skid_mark - 9; 3516 /* limit includes the static minimum cells as well */ 3517 xq_limit = dyn_xq_per_port + 4; 3518 cos_min_xqs = HU2_MMU_IN_COS_MIN_XQS/2; 3519 cos_min_cells = HU2_MMU_IN_COS_MIN_CELLS + 4; 3520 } 3521 3522 PBMP_ALL_ITER(unit, port) { 3523 3524 for (cos = 0; cos < NUM_COS(unit); cos++) { 3525 /* 3526 * The HOLCOSPKTSETLIMITr register controls BOTH the XQ 3527 * size per cosq AND the HOL set limit for that cosq. 3528 */ 3529 SOC_IF_ERROR_RETURN 3530 (READ_HOLCOSPKTSETLIMITr(unit, port, cos, &val)); 3531 soc_reg_field_set(unit, HOLCOSPKTSETLIMITr, &val, 3532 PKTSETLIMITf, 3533 xq_limit); 3534 SOC_IF_ERROR_RETURN 3535 (WRITE_HOLCOSPKTSETLIMITr(unit, port, cos, val)); 3536 3537 /* reset limit is set limit - 4 */ 3538 SOC_IF_ERROR_RETURN 3539 (READ_HOLCOSPKTRESETLIMITr(unit, port, cos, &val)); 3540 soc_reg_field_set(unit, HOLCOSPKTRESETLIMITr, &val, 3541 PKTRESETLIMITf, 3542 xq_limit-4); 3543 SOC_IF_ERROR_RETURN 3544 (WRITE_HOLCOSPKTRESETLIMITr(unit, port, cos, val)); 3545 3546 val = 0; 3547 soc_reg_field_set(unit, HOLCOSMINXQCNTr, &val, 3548 HOLCOSMINXQCNTf, cos_min_xqs); 3549 SOC_IF_ERROR_RETURN 3550 (WRITE_HOLCOSMINXQCNTr(unit, port, cos, val)); 3551 3552 val = 0; 3553 soc_reg_field_set(unit, LWMCOSCELLSETLIMITr, &val, 3554 CELLSETLIMITf, cos_min_cells); 3555 soc_reg_field_set(unit, LWMCOSCELLSETLIMITr, &val, 3556 CELLRESETLIMITf, cos_min_cells); 3557 SOC_IF_ERROR_RETURN 3558 (WRITE_LWMCOSCELLSETLIMITr(unit, port, cos, val)); 3559 3560 cell_limit = 0; 3561 if (dev_id != BCM56147_DEVICE_ID) { 3562 if(!cos) { 3563 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 3564 CELLMAXLIMITf, HU2_MMU_MAX_CELL_LIMIT_PRI_0); 3565 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 3566 CELLMAXRESUMELIMITf, HU2_MMU_MAX_CELL_LIMIT_PRI_0 - 12); 3567 } else { 3568 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 3569 CELLMAXLIMITf, HU2_MMU_MAX_CELL_LIMIT_PRI_1_7); 3570 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 3571 CELLMAXRESUMELIMITf, HU2_MMU_MAX_CELL_LIMIT_PRI_1_7 - 12); 3572 } 3573 } 3574 else { 3575 /* use the settings given by design team for 56147 */ 3576 if(!cos) { 3577 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 3578 CELLMAXLIMITf, 8000); 3579 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 3580 CELLMAXRESUMELIMITf, 7238); 3581 } else { 3582 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 3583 CELLMAXLIMITf, 7250); 3584 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 3585 CELLMAXRESUMELIMITf, 7238); 3586 } 3587 } 3588 SOC_IF_ERROR_RETURN 3589 (WRITE_HOLCOSCELLMAXLIMITr(unit, port, cos, cell_limit)); 3590 } 3591 3592 val = 0; 3593 soc_reg_field_set(unit, DYNXQCNTPORTr, &val, 3594 DYNXQCNTPORTf, dyn_xq_per_port); 3595 SOC_IF_ERROR_RETURN(WRITE_DYNXQCNTPORTr(unit, port, val)); 3596 3597 val = 0; 3598 soc_reg_field_set(unit, DYNRESETLIMPORTr, &val, 3599 DYNRESETLIMPORTf, dyn_xq_per_port - 4); 3600 SOC_IF_ERROR_RETURN(WRITE_DYNRESETLIMPORTr(unit, port, val)); 3601 3602 cell_limit = 0; 3603 soc_reg_field_set(unit, IBPDISCARDSETLIMITr, &cell_limit, 3604 DISCARDSETLIMITf, HU2_MMU_TOTAL_CELLS-1); 3605 SOC_IF_ERROR_RETURN(WRITE_IBPDISCARDSETLIMITr(unit, port, cell_limit)); 3606 3607 if (dev_id != BCM56147_DEVICE_ID) { 3608 val = 0; 3609 soc_reg_field_set(unit, DYNCELLLIMITr, &val, 3610 DYNCELLSETLIMITf, HU2_MMU_DYN_CELL_LIMIT); 3611 soc_reg_field_set(unit, DYNCELLLIMITr, &val, 3612 DYNCELLRESETLIMITf, HU2_MMU_DYN_CELL_LIMIT - 24); 3613 SOC_IF_ERROR_RETURN(WRITE_DYNCELLLIMITr(unit, port, val)); 3614 3615 pkt_limit = 0; 3616 soc_reg_field_set(unit, IBPPKTSETLIMITr, &pkt_limit, 3617 PKTSETLIMITf, HU2_MMU_IN_COS_MIN_CELLS); 3618 SOC_IF_ERROR_RETURN(WRITE_IBPPKTSETLIMITr(unit, port, pkt_limit)); 3619 3620 cell_limit = 0; 3621 soc_reg_field_set(unit, IBPCELLSETLIMITr, &cell_limit, 3622 CELLSETLIMITf, HU2_MMU_XOFF_CELL_LIMIT); 3623 SOC_IF_ERROR_RETURN(WRITE_IBPCELLSETLIMITr(unit, port, cell_limit)); 3624 } 3625 else { 3626 /* use the settings given by design team for 56147 */ 3627 val = 0; 3628 /* dyn cell limit = 8000 + (total cos -1)*4*2048/128 */ 3629 soc_reg_field_set(unit, DYNCELLLIMITr, &val, 3630 DYNCELLSETLIMITf, 8448); 3631 soc_reg_field_set(unit, DYNCELLLIMITr, &val, 3632 DYNCELLRESETLIMITf, 8424); 3633 SOC_IF_ERROR_RETURN(WRITE_DYNCELLLIMITr(unit, port, val)); 3634 3635 pkt_limit = 0; 3636 soc_reg_field_set(unit, IBPPKTSETLIMITr, &pkt_limit, 3637 PKTSETLIMITf, 33); 3638 SOC_IF_ERROR_RETURN(WRITE_IBPPKTSETLIMITr(unit, port, pkt_limit)); 3639 3640 cell_limit = 0; 3641 soc_reg_field_set(unit, IBPCELLSETLIMITr, &cell_limit, 3642 CELLSETLIMITf, 36); 3643 SOC_IF_ERROR_RETURN(WRITE_IBPCELLSETLIMITr(unit, port, cell_limit)); 3644 3645 /* E2EFC configuration */ 3646 if (IS_HG_PORT(unit, port)){ 3647 SOC_IF_ERROR_RETURN(READ_XPORT_CONFIGr(unit, port, &val)); 3648 soc_reg_field_set(unit, XPORT_CONFIGr, &val, E2E_IBP_ENf, 1); 3649 SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, val)); 3650 3651 SOC_IF_ERROR_RETURN(READ_IE2E_CONTROLr(unit, port, &val)); 3652 soc_reg_field_set(unit, IE2E_CONTROLr, &val, IBP_ENABLEf, 1); 3653 SOC_IF_ERROR_RETURN(WRITE_IE2E_CONTROLr(unit, port, val)); 3654 3655 val = 0; 3656 soc_reg_field_set(unit, E2EFC_HG_MIN_TX_TIMERr, &val, 3657 LGf, 0); 3658 soc_reg_field_set(unit, E2EFC_HG_MIN_TX_TIMERr, &val, 3659 TIMERf, 1); 3660 SOC_IF_ERROR_RETURN(WRITE_E2EFC_HG_MIN_TX_TIMERr(unit, port-26, val)); 3661 3662 val = 0; 3663 soc_reg_field_set(unit, E2EFC_HG_MAX_TX_TIMERr, &val, 3664 LGf, 1); 3665 soc_reg_field_set(unit, E2EFC_HG_MAX_TX_TIMERr, &val, 3666 TIMERf, 640); 3667 SOC_IF_ERROR_RETURN(WRITE_E2EFC_HG_MAX_TX_TIMERr(unit, port-26, val)); 3668 3669 limit = 0; 3670 soc_reg_field_set(unit, E2EFC_CNT_SET_LIMITr, &limit, 3671 PKT_SET_LIMITf, 1456); 3672 soc_reg_field_set(unit, E2EFC_CNT_SET_LIMITr, &limit, 3673 CELL_SET_LIMITf, 9504); 3674 SOC_IF_ERROR_RETURN(WRITE_E2EFC_CNT_SET_LIMITr(unit, port, limit)); 3675 3676 limit = 0; 3677 soc_reg_field_set(unit, E2EFC_CNT_RESET_LIMITr, &limit, 3678 PKT_RESET_LIMITf, 1456); 3679 soc_reg_field_set(unit, E2EFC_CNT_RESET_LIMITr, &limit, 3680 CELL_RESET_LIMITf, 9504); 3681 SOC_IF_ERROR_RETURN(WRITE_E2EFC_CNT_RESET_LIMITr(unit, port, limit)); 3682 3683 limit = 0; 3684 soc_reg_field_set(unit, E2EFC_CNT_DISC_LIMITr, &limit, 3685 PKT_DISC_LIMITf, 1456); 3686 soc_reg_field_set(unit, E2EFC_CNT_DISC_LIMITr, &limit, 3687 CELL_DISC_LIMITf, 9504); 3688 SOC_IF_ERROR_RETURN(WRITE_E2EFC_CNT_DISC_LIMITr(unit, port, limit)); 3689 } 3690 else { 3691 limit = 0; 3692 soc_reg_field_set(unit, E2EFC_CNT_SET_LIMITr, &limit, 3693 PKT_SET_LIMITf, 33); 3694 soc_reg_field_set(unit, E2EFC_CNT_SET_LIMITr, &limit, 3695 CELL_SET_LIMITf, 36); 3696 SOC_IF_ERROR_RETURN(WRITE_E2EFC_CNT_SET_LIMITr(unit, port, limit)); 3697 3698 limit = 0; 3699 soc_reg_field_set(unit, E2EFC_CNT_RESET_LIMITr, &limit, 3700 PKT_RESET_LIMITf, 24); 3701 soc_reg_field_set(unit, E2EFC_CNT_RESET_LIMITr, &limit, 3702 CELL_RESET_LIMITf, 26); 3703 SOC_IF_ERROR_RETURN(WRITE_E2EFC_CNT_RESET_LIMITr(unit, port, limit)); 3704 3705 limit = 0; 3706 soc_reg_field_set(unit, E2EFC_CNT_DISC_LIMITr, &limit, 3707 PKT_DISC_LIMITf, 1456); 3708 soc_reg_field_set(unit, E2EFC_CNT_DISC_LIMITr, &limit, 3709 CELL_DISC_LIMITf, 9504); 3710 SOC_IF_ERROR_RETURN(WRITE_E2EFC_CNT_DISC_LIMITr(unit, port, limit)); 3711 3712 } 3713 3714 } 3715 3716 } 3717 3718 /* device specific dynamic cell limit */ 3719 if (dev_id != BCM56147_DEVICE_ID) { 3720 cell_limit = 0; 3721 soc_reg_field_set(unit, TOTALDYNCELLSETLIMITr, 3722 &cell_limit, TOTALDYNCELLSETLIMITf, HU2_MMU_TOTAL_DYNAMIC_CELLS); 3723 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLSETLIMITr(unit, cell_limit)); 3724 cell_limit = 0; 3725 soc_reg_field_set(unit, TOTALDYNCELLRESETLIMITr, 3726 &cell_limit, TOTALDYNCELLRESETLIMITf, HU2_MMU_TOTAL_DYNAMIC_CELLS - 24); 3727 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLRESETLIMITr(unit, cell_limit)); 3728 } 3729 else { 3730 cell_limit = 0; 3731 soc_reg_field_set(unit, TOTALDYNCELLSETLIMITr, 3732 &cell_limit, TOTALDYNCELLSETLIMITf, 8576); 3733 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLSETLIMITr(unit, cell_limit)); 3734 cell_limit = 0; 3735 soc_reg_field_set(unit, TOTALDYNCELLRESETLIMITr, 3736 &cell_limit, TOTALDYNCELLRESETLIMITf, 8552); 3737 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLRESETLIMITr(unit, cell_limit)); 3738 3739 /* E2EFC configuration */ 3740 SOC_IF_ERROR_RETURN(READ_E2EFC_IBP_ENr(unit, &val)); 3741 soc_reg_field_set(unit, E2EFC_IBP_ENr, &val, ENf, 1); 3742 SOC_IF_ERROR_RETURN(WRITE_E2EFC_IBP_ENr(unit, val)); 3743 } 3744 3745 /* 3746 * Configure per-XQ packet aging for the various COSQs. 3747 * 3748 * The shortest age allowed by H/W is 250 microseconds. 3749 * The longest age allowed is 7.162 seconds (7162 msec). 3750 * The maximum ratio between the longest age and the shortest 3751 * (nonzero) age is 7:2. 3752 */ 3753 age_enable = disabled_age = max_age = 0; 3754 min_age = 7162; 3755 for (cos = 0; cos < NUM_COS(unit); cos++) { 3756 if ((age[cos] = 3757 soc_property_suffix_num_get(unit, cos, spn_MMU_XQ_AGING, 3758 "cos", 0)) > 0) { 3759 age_enable = 1; 3760 if (age[cos] > 7162) { 3761 age[cos] = 7162; 3762 } 3763 if (age[cos] < min_age) { 3764 min_age = age[cos]; 3765 } 3766 } else { 3767 disabled_age = 1; 3768 age[cos] = 0; 3769 } 3770 if (age[cos] > max_age) { 3771 max_age = age[cos]; 3772 } 3773 } 3774 if (!age_enable) { 3775 /* Disable packet aging on all COSQs */ 3776 SOC_IF_ERROR_RETURN(WRITE_PKTAGINGTIMERr(unit, 0)); 3777 SOC_IF_ERROR_RETURN(WRITE_PKTAGINGLIMITr(unit, 0)); /* Aesthetic */ 3778 } else { 3779 uint32 regval = 0; 3780 uint32 timerval; 3781 3782 /* Enforce the 7:2 ratio between min and max values */ 3783 if ((((max_age * 2)+6) / 7) > min_age) { 3784 /* Keep requested max age; make min_age comply */ 3785 min_age = ((max_age * 2) + 6) / 7; 3786 } 3787 3788 /* 3789 * Give up granularity for range, if we need to 3790 * "disable" (max out) aging for any COSQ(s). 3791 */ 3792 if (disabled_age) { 3793 /* Max range */ 3794 max_age = min_age * 7 / 2; 3795 } 3796 3797 /* 3798 * Compute shortest duration of one PKTAGINGTIMERr cycle. 3799 * This duration is 1/7th of the longest packet age. 3800 * This duration is in units of 125 usec (msec * 8). 3801 */ 3802 timerval = ((8 * max_age) + 6) / 7; 3803 SOC_IF_ERROR_RETURN(WRITE_PKTAGINGTIMERr(unit, timerval)); 3804 3805 for (cos = 0; cos < NUM_COS(unit); cos++) { 3806 if (!age[cos]) { 3807 /* 3808 * Requested to be disabled, but cannot disable individual 3809 * COSQs once packet aging is enabled. Therefore, mark 3810 * this COSQ's aging duration as maxed out. 3811 */ 3812 age[cos] = -1; 3813 } else if (age[cos] < min_age) { 3814 age[cos] = min_age; 3815 } 3816 3817 /* Normalize each "age" into # of PKTAGINGTIMERr cycles. */ 3818 if (age[cos] > 0) { 3819 /* coverity[divide_by_zero : FALSE] */ 3820 age[cos] = ((8 * age[cos]) + timerval - 1) / timerval; 3821 } 3822 else { 3823 age[cos] = 7; 3824 } 3825 /* Format each "age" for its appropriate field */ 3826 regval |= ((7 - age[cos]) << (cos * 3)); 3827 } 3828 SOC_IF_ERROR_RETURN(WRITE_PKTAGINGLIMITr(unit, regval)); 3829 } 3830 3831 /* Apply TM=0x10 setting for all CAMs */ 3832 tm=0x10; 3833 val = 0; 3834 soc_reg_field_set(unit, SW2_RAM_CONTROL_4r, &val, 3835 CPU_COS_MAP_TCAM_TMf, tm); 3836 SOC_IF_ERROR_RETURN(WRITE_SW2_RAM_CONTROL_4r_REG32(unit, val)); 3837 3838 val = 0; 3839 soc_reg_field_set(unit, L2_USER_ENTRY_CAM_DBGCTRLr, &val, 3840 TMf, tm); 3841 SOC_IF_ERROR_RETURN(WRITE_L2_USER_ENTRY_CAM_DBGCTRLr(unit, val)); 3842 3843 3844 SOC_IF_ERROR_RETURN(READ_VLAN_SUBNET_CAM_DBGCTRLr(unit, &val)); 3845 soc_reg_field_set(unit, VLAN_SUBNET_CAM_DBGCTRLr, &val, 3846 TMf, tm); 3847 SOC_IF_ERROR_RETURN(WRITE_VLAN_SUBNET_CAM_DBGCTRLr(unit, val)); 3848 3849 /* 3850 * Port enable 3851 */ 3852 val = 0; 3853 soc_reg_field_set(unit, MMUPORTENABLEr, &val, MMUPORTENABLEf, 3854 SOC_PBMP_WORD_GET(PBMP_ALL(unit), 0)); 3855 SOC_IF_ERROR_RETURN(WRITE_MMUPORTENABLEr(unit, val)); 3856 3857 return SOC_E_NONE; 3858 } 3859 3860 STATIC int 3861 _hurricane2_ledup_init(int unit) 3862 { 3863 int ix, pval1, pval2, pval3, pval4; 3864 uint32 rval = 0; 3865 struct led_remap { 3866 uint32 reg_addr; 3867 uint32 port0; 3868 uint32 port1; 3869 uint32 port2; 3870 uint32 port3; 3871 } led0_remap[] = { 3872 {CMIC_LEDUP0_PORT_ORDER_REMAP_0_3r, 3873 REMAP_PORT_0f,REMAP_PORT_1f,REMAP_PORT_2f,REMAP_PORT_3f}, 3874 {CMIC_LEDUP0_PORT_ORDER_REMAP_4_7r, 3875 REMAP_PORT_4f,REMAP_PORT_5f,REMAP_PORT_6f,REMAP_PORT_7f}, 3876 {CMIC_LEDUP0_PORT_ORDER_REMAP_8_11r, 3877 REMAP_PORT_8f,REMAP_PORT_9f,REMAP_PORT_10f,REMAP_PORT_11f}, 3878 {CMIC_LEDUP0_PORT_ORDER_REMAP_12_15r, 3879 REMAP_PORT_12f,REMAP_PORT_13f,REMAP_PORT_14f,REMAP_PORT_15f}, 3880 {CMIC_LEDUP0_PORT_ORDER_REMAP_16_19r, 3881 REMAP_PORT_16f,REMAP_PORT_17f,REMAP_PORT_18f,REMAP_PORT_19f}, 3882 {CMIC_LEDUP0_PORT_ORDER_REMAP_20_23r, 3883 REMAP_PORT_20f,REMAP_PORT_21f,REMAP_PORT_22f,REMAP_PORT_23f}, 3884 {CMIC_LEDUP0_PORT_ORDER_REMAP_24_27r, 3885 REMAP_PORT_24f,REMAP_PORT_25f,REMAP_PORT_26f,REMAP_PORT_27f}, 3886 {CMIC_LEDUP0_PORT_ORDER_REMAP_28_31r, 3887 REMAP_PORT_28f,REMAP_PORT_29f,REMAP_PORT_30f,REMAP_PORT_31f} 3888 }; 3889 3890 /* initialize the led remap register settings. 3891 * port 0 entry will not be used for easy index of the physical port starting 1 3892 */ 3893 for (ix = 0; ix < sizeof(led0_remap)/sizeof(led0_remap[0]); ix++) { 3894 pval1 = (ix * 4) + 2; 3895 pval2 = pval1 + 1; 3896 pval3 = pval1 + 2; 3897 pval4 = pval1 + 3; 3898 if ((pval1 == 26) || (pval1 == 30)) { 3899 /* Transpose MXQ Block ports */ 3900 pval4 = pval1; 3901 pval3 = pval4 + 1; 3902 pval2 = pval4 + 2; 3903 pval1 = pval1 + 3; 3904 } 3905 3906 rval = 0; 3907 soc_reg_field_set(unit, led0_remap[ix].reg_addr, &rval, 3908 led0_remap[ix].port0, pval1); 3909 soc_reg_field_set(unit, led0_remap[ix].reg_addr, &rval, 3910 led0_remap[ix].port1, pval2); 3911 soc_reg_field_set(unit, led0_remap[ix].reg_addr, &rval, 3912 led0_remap[ix].port2, pval3); 3913 soc_reg_field_set(unit, led0_remap[ix].reg_addr, &rval, 3914 led0_remap[ix].port3, pval4); 3915 /* coverity[result_independent_of_operands] */ 3916 SOC_IF_ERROR_RETURN 3917 (soc_pci_write(unit, 3918 soc_reg_addr(unit, led0_remap[ix].reg_addr, REG_PORT_ANY, 0), 3919 rval)); 3920 } 3921 3922 /* Do Raw schan ops because Not all ports may be enabled */ 3923 { 3924 /* XLPORT_LED_CHAIN_CONFIGr */ 3925 _soc_reg32_set(unit, 5, 0, (0x2022b00), (0x00000006)); 3926 _soc_reg32_set(unit, 6, 0, (0x2022b00), (0x00000006)); 3927 } 3928 3929 /* initialize the UP0 data ram */ 3930 rval = 0; 3931 for (ix = 0; ix < 256; ix++) { 3932 /* coverity[result_independent_of_operands] */ 3933 SOC_IF_ERROR_RETURN(WRITE_CMIC_LEDUP0_DATA_RAMr(unit,ix, rval)); 3934 } 3935 3936 /* Apply LEDUP delays. */ 3937 /* coverity[result_independent_of_operands] */ 3938 SOC_IF_ERROR_RETURN(READ_CMIC_LEDUP0_CTRLr(unit, &rval)); 3939 soc_reg_field_set(unit,CMIC_LEDUP0_CTRLr, 3940 &rval, LEDUP_SCAN_START_DELAYf, 0x6); 3941 soc_reg_field_set(unit,CMIC_LEDUP0_CTRLr, 3942 &rval, LEDUP_SCAN_INTRA_PORT_DELAYf, 0x5); 3943 /* coverity[result_independent_of_operands] */ 3944 SOC_IF_ERROR_RETURN(WRITE_CMIC_LEDUP0_CTRLr(unit, rval)); 3945 3946 return SOC_E_NONE; 3947 } 3948 3949 STATIC int 3950 _soc_hu2_power_Optimize(int unit) { 3951 int blk; 3952 uint32 rval; 3953 3954 /* Turn on Per Stage Clock Gating */ 3955 SOC_IF_ERROR_RETURN(READ_TOP_CLOCKING_ENFORCE_PSGr(unit,&rval)); 3956 soc_reg_field_set(unit, TOP_CLOCKING_ENFORCE_PSGr, &rval, 3957 CLK_ENFORCE_XLPORTf, 0); 3958 SOC_IF_ERROR_RETURN(WRITE_TOP_CLOCKING_ENFORCE_PSGr(unit,rval)); 3959 3960 /* Power Down Unused XLPORT Blocks */ 3961 /* Since these regis are not accessible normally, use direct schan access */ 3962 for (blk=5; blk<=6; blk++) { 3963 _soc_reg32_get(unit, blk,0, (0x02020b00), &rval); /*XLPORT_ENABLE_REG */ 3964 if (rval == 0) { /* No Ports Enabled */ 3965 rval = 0; 3966 soc_reg_field_set(unit, XLPORT_POWER_SAVEr, &rval, 3967 XPORT_CORE0f, 1); 3968 _soc_reg32_set(unit, blk,0, (0x02020d00), rval); 3969 3970 _soc_reg32_get(unit, blk,0, (0x02021400), &rval); 3971 soc_reg_field_set(unit, XLPORT_XGXS0_CTRL_REGr, &rval, 3972 PWRDWNf, 1); 3973 soc_reg_field_set(unit, XLPORT_XGXS0_CTRL_REGr, &rval, 3974 IDDQf, 1); 3975 soc_reg_field_set(unit, XLPORT_XGXS0_CTRL_REGr, &rval, 3976 TSCCLK_ENf, 0); 3977 _soc_reg32_set(unit, blk,0, (0x02021400), rval); 3978 } 3979 } 3980 3981 return SOC_E_NONE; 3982 } 3983 3984 #if defined(SER_TR_TEST_SUPPORT) 3985 soc_ser_test_functions_t ser_hu2_test_fun; 3986 #endif 3987 3988 3989 int 3990 soc_hurricane2_misc_init(int unit) 3991 { 3992 #define NUM_XLPORT 4 3993 static const soc_field_t port_field[] = { 3994 PORT0f, PORT1f, PORT2f, PORT3f 3995 }; 3996 uint32 rval; 3997 uint32 prev_reg_addr; 3998 uint64 reg64; 3999 int port; 4000 uint32 entry[SOC_MAX_MEM_WORDS]; 4001 soc_field_t fields[3]; 4002 uint32 values[3]; 4003 int blk, bindex, mode; 4004 int phy_port_base; 4005 soc_info_t *si = &SOC_INFO(unit); 4006 uint16 dev_id; 4007 uint8 rev_id; 4008 int divisor, dividend; 4009 int hu2_config_id; 4010 uint32 qsgmii_override = 0; 4011 int core_clock_freq = 0, parity_enable; 4012 uint32 eee_duration_time_pulse = 0; 4013 pbmp_t blk_bitmap; 4014 int led_intensity = -1; 4015 uint32 fval; 4016 4017 /* Stop the mem scan task before all of the parity init takes place */ 4018 SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_stop(unit)); 4019 4020 soc_cm_get_id(unit, &dev_id, &rev_id); 4021 hu2_config_id = soc_property_get(unit, spn_BCM5615X_CONFIG, 0); 4022 4023 if (!SOC_IS_RELOADING(unit) && !SOC_WARM_BOOT(unit)) { 4024 /* Clear IPIPE/EIPIE Memories */ 4025 SOC_IF_ERROR_RETURN(soc_hurricane2_pipe_mem_clear(unit)); 4026 } 4027 4028 SOC_IF_ERROR_RETURN(soc_hu2_init_port_mapping(unit)); 4029 4030 4031 /* Turn on ingress/egress/mmu parity */ 4032 parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE); 4033 if (soc_feature(unit, soc_feature_field_multi_stage)) { 4034 _soc_hu2_parity_group_info = _soc_hu2_parity_group_info_template; 4035 } else { 4036 _soc_hu2_parity_group_info = _soc_wf_parity_group_info_template; 4037 } 4038 if (parity_enable) { 4039 _soc_hurricane2_parity_enable(unit, TRUE); 4040 #if defined(SER_TR_TEST_SUPPORT) 4041 soc_hu2_ser_test_register(unit); 4042 #endif /*defined(SER_TR_TEST_SUPPORT*/ 4043 4044 (void)_soc_hurricane2_tcam_ser_init(unit); 4045 memset(&_hu2_ser_functions, 0, sizeof(soc_ser_functions_t)); 4046 #ifdef INCLUDE_MEM_SCAN 4047 soc_mem_scan_ser_list_register(unit, TRUE, _soc_hu2_tcam_ser_info); 4048 #endif /* INCLUDE_MEM_SCAN */ 4049 memset(&_hu2_ser_functions, 0, sizeof(soc_ser_functions_t)); 4050 _hu2_ser_functions._soc_ser_fail_f = &soc_hurricane2_ser_fail; 4051 _hu2_ser_functions._soc_ser_parity_error_cmicm_intr_f = 4052 &soc_hurricane2_parity_error; 4053 _hu2_ser_functions._soc_ser_mem_nack_f = 4054 &soc_hurricane2_mem_nack; 4055 soc_ser_function_register(unit, &_hu2_ser_functions); 4056 } else { 4057 _soc_hurricane2_parity_enable(unit, FALSE); 4058 } 4059 4060 core_clock_freq = 0; /* 0 means run in native frequency */ 4061 switch (dev_id) { 4062 case BCM56151_DEVICE_ID: 4063 case BCM53347_DEVICE_ID: 4064 case BCM53346_DEVICE_ID: 4065 if ((hu2_config_id == 0) || (hu2_config_id == 12) || \ 4066 (hu2_config_id == 13)) { 4067 core_clock_freq = soc_property_get(unit, spn_CORE_CLOCK_SPEED, 0); 4068 } 4069 break; 4070 case BCM56152_DEVICE_ID: 4071 if ((hu2_config_id == 0) || (hu2_config_id == 13)) { 4072 core_clock_freq = soc_property_get(unit, spn_CORE_CLOCK_SPEED, 0); 4073 } 4074 break; 4075 case BCM53344_DEVICE_ID: 4076 if (hu2_config_id == 0) { 4077 core_clock_freq = soc_property_get(unit, spn_CORE_CLOCK_SPEED, 0); 4078 } 4079 break; 4080 case BCM53343_DEVICE_ID: 4081 case BCM53342_DEVICE_ID: 4082 core_clock_freq = soc_property_get(unit, spn_CORE_CLOCK_SPEED, 0); 4083 break; 4084 default : 4085 break; 4086 } 4087 4088 eee_duration_time_pulse = 0x53; /* time pulse value for 1 us at 84.375MHz */ 4089 if (core_clock_freq == 25) { /* core clock at 25MHz */ 4090 SOC_IF_ERROR_RETURN(READ_TOP_MISC_CONTROL_1r(unit, &rval)); 4091 soc_reg_field_set(unit, TOP_MISC_CONTROL_1r, &rval, CMIC_TO_CORE_PLL_LOADf, 1); 4092 SOC_IF_ERROR_RETURN(WRITE_TOP_MISC_CONTROL_1r(unit, rval)); 4093 4094 SOC_IF_ERROR_RETURN(READ_TOP_CORE_PLL_CTRL4r(unit, &rval)); 4095 soc_reg_field_set(unit, TOP_CORE_PLL_CTRL4r, &rval, MSTR_CH0_MDIVf, 135); 4096 SOC_IF_ERROR_RETURN(WRITE_TOP_CORE_PLL_CTRL4r(unit, rval)); 4097 4098 SOC_IF_ERROR_RETURN(READ_TOP_CORE_PLL_CTRL2r(unit, &rval)); 4099 soc_reg_field_set(unit, TOP_CORE_PLL_CTRL2r, &rval, LOAD_EN_CH0f, 1); 4100 soc_reg_field_set(unit, TOP_CORE_PLL_CTRL2r, &rval, LOAD_EN_CH1f, 1); 4101 SOC_IF_ERROR_RETURN(WRITE_TOP_CORE_PLL_CTRL2r(unit, rval)); 4102 4103 eee_duration_time_pulse = 0x18; /* time pulse value for 1 us at 25MHz */ 4104 } else { /* native 84.375 or 135 MHz */ 4105 core_clock_freq = 84; 4106 /* Bump up core clock to 135 MHz if any TSC port is > 1G */ 4107 for (port = 26; port <= 33; port++) { /* All TSC ports */ 4108 if (port_speed_max[port] > 1000) { 4109 SOC_IF_ERROR_RETURN(READ_TOP_MISC_CONTROL_1r(unit, &rval)); 4110 soc_reg_field_set(unit, TOP_MISC_CONTROL_1r, &rval, CMIC_TO_CORE_PLL_LOADf, 1); 4111 SOC_IF_ERROR_RETURN(WRITE_TOP_MISC_CONTROL_1r(unit, rval)); 4112 4113 SOC_IF_ERROR_RETURN(READ_TOP_CORE_PLL_CTRL4r(unit, &rval)); 4114 soc_reg_field_set(unit, TOP_CORE_PLL_CTRL4r, &rval, MSTR_CH0_MDIVf, 25); 4115 SOC_IF_ERROR_RETURN(WRITE_TOP_CORE_PLL_CTRL4r(unit, rval)); 4116 4117 SOC_IF_ERROR_RETURN(READ_TOP_CORE_PLL_CTRL2r(unit, &rval)); 4118 soc_reg_field_set(unit, TOP_CORE_PLL_CTRL2r, &rval, LOAD_EN_CH0f, 1); 4119 soc_reg_field_set(unit, TOP_CORE_PLL_CTRL2r, &rval, LOAD_EN_CH1f, 1); 4120 SOC_IF_ERROR_RETURN(WRITE_TOP_CORE_PLL_CTRL2r(unit, rval)); 4121 4122 eee_duration_time_pulse = 0x86; /* time pulse value for 1 us at 135MHz */ 4123 core_clock_freq = 135; 4124 break; 4125 } 4126 } 4127 } 4128 4129 si->frequency = core_clock_freq; 4130 4131 SOC_BLOCK_ITER(unit, blk, SOC_BLK_GPORT) { 4132 blk_bitmap = SOC_BLOCK_BITMAP(unit, blk); 4133 PBMP_ITER(blk_bitmap, port) { 4134 SOC_IF_ERROR_RETURN(READ_GE0_EEE_CONFIGr(unit, port, &rval)); 4135 soc_reg_field_set(unit, GE0_EEE_CONFIGr, &rval, 4136 EEE_DURATION_TIMER_PULSEf, eee_duration_time_pulse); 4137 SOC_IF_ERROR_RETURN(WRITE_GE0_EEE_CONFIGr(unit, port, rval)); 4138 SOC_IF_ERROR_RETURN(WRITE_GE1_EEE_CONFIGr(unit, port, rval)); 4139 SOC_IF_ERROR_RETURN(WRITE_GE2_EEE_CONFIGr(unit, port, rval)); 4140 SOC_IF_ERROR_RETURN(WRITE_GE3_EEE_CONFIGr(unit, port, rval)); 4141 SOC_IF_ERROR_RETURN(WRITE_GE4_EEE_CONFIGr(unit, port, rval)); 4142 SOC_IF_ERROR_RETURN(WRITE_GE5_EEE_CONFIGr(unit, port, rval)); 4143 SOC_IF_ERROR_RETURN(WRITE_GE6_EEE_CONFIGr(unit, port, rval)); 4144 SOC_IF_ERROR_RETURN(WRITE_GE7_EEE_CONFIGr(unit, port, rval)); 4145 } 4146 } 4147 4148 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 4149 soc_reg_field_set(unit, MISCCONFIGr, &rval, METERING_CLK_ENf, 1); 4150 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval)); 4151 4152 /* HR2 WAR for SDK-60041 : for GE port with UNIMAC only 4153 * - Wrong UMAC_EEE_REF_COUNT configuration causes packet loss 4154 * 4155 * 1. UMAC_EEE_REF_COUNT set to 0x1f4 for core_clk=500Mhz. 4156 * for HR2, core_clk=tsc_pll_clk. 4157 * 2. Wake/Delay timer for GMII and MII register's reset value 4158 * need be revised. 4159 * - WAKE_TIMER set to 0x1e for MII and 0x11 for GMII 4160 * - DELAY_ENTRY_TIMER set to 0x3c for MII and 0x22 for GMII 4161 */ 4162 PBMP_E_ITER(unit, port) { 4163 if (!IS_GE_PORT(unit, port) || IS_XL_PORT(unit, port)) { 4164 continue; 4165 } 4166 SOC_IF_ERROR_RETURN(READ_UMAC_EEE_REF_COUNTr(unit, port, &rval)); 4167 soc_reg_field_set(unit, 4168 UMAC_EEE_REF_COUNTr, &rval, EEE_REF_COUNTf, 0x1f4); 4169 SOC_IF_ERROR_RETURN(WRITE_UMAC_EEE_REF_COUNTr(unit, port, rval)); 4170 4171 SOC_IF_ERROR_RETURN(WRITE_MII_EEE_WAKE_TIMERr(unit, port, 0x1e)); 4172 SOC_IF_ERROR_RETURN(WRITE_GMII_EEE_WAKE_TIMERr(unit, port, 0x11)); 4173 SOC_IF_ERROR_RETURN(WRITE_MII_EEE_DELAY_ENTRY_TIMERr(unit, port, 0x3c)); 4174 SOC_IF_ERROR_RETURN(WRITE_GMII_EEE_DELAY_ENTRY_TIMERr(unit, port, 0x22)); 4175 } 4176 4177 /* Enable dual hash on L2 and L3 tables */ 4178 fields[0] = ENABLEf; 4179 values[0] = 1; 4180 fields[1] = HASH_SELECTf; 4181 values[1] = FB_HASH_CRC32_LOWER; 4182 fields[2] = INSERT_LEAST_FULL_HALFf; 4183 values[2] = 1; 4184 SOC_IF_ERROR_RETURN 4185 (soc_reg_fields32_modify(unit, L2_AUX_HASH_CONTROLr, REG_PORT_ANY, 3, 4186 fields, values)); 4187 SOC_IF_ERROR_RETURN 4188 (soc_reg_fields32_modify(unit, L3_AUX_HASH_CONTROLr, REG_PORT_ANY, 3, 4189 fields, values)); 4190 4191 /* 4192 * Egress Enable 4193 */ 4194 sal_memset(entry, 0, sizeof(egr_enable_entry_t)); 4195 soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, 1); 4196 PBMP_ALL_ITER(unit, port) { 4197 SOC_IF_ERROR_RETURN 4198 (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, SOC_INFO(unit).port_l2p_mapping[port], entry)); 4199 } 4200 4201 COMPILER_64_ZERO(reg64); 4202 soc_reg64_field32_set(unit, EPC_LINK_BMAP_64r, ®64, PORT_BITMAP_LOf, 4203 SOC_PBMP_WORD_GET(PBMP_CMIC(unit), 0)); 4204 SOC_IF_ERROR_RETURN(WRITE_EPC_LINK_BMAP_64r(unit, reg64)); 4205 4206 /* GMAC init should be moved to mac */ 4207 rval = 0; 4208 soc_reg_field_set(unit, GPORT_CONFIGr, &rval, CLR_CNTf, 1); 4209 prev_reg_addr = 0xffffffff; 4210 PBMP_E_ITER(unit, port) { 4211 uint32 reg_addr; 4212 si->port_num_lanes[port] = 1; 4213 if (!IS_GE_PORT(unit, port) || IS_XL_PORT(unit, port)) { 4214 continue; 4215 } 4216 reg_addr = soc_reg_addr(unit, GPORT_CONFIGr, port, 0); 4217 if (reg_addr != prev_reg_addr) { 4218 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, rval)); 4219 prev_reg_addr = reg_addr; 4220 } 4221 switch (dev_id) { 4222 case BCM53393_DEVICE_ID: 4223 case BCM53394_DEVICE_ID: 4224 si->port_num_lanes[port] = 4; 4225 break; 4226 case BCM56150_DEVICE_ID: 4227 case BCM56151_DEVICE_ID: 4228 case BCM56152_DEVICE_ID: 4229 case BCM53347_DEVICE_ID: 4230 case BCM53346_DEVICE_ID: 4231 case BCM53344_DEVICE_ID: 4232 qsgmii_override = soc_property_get(unit, 4233 spn_SERDES_QSGMII_SGMII_OVERRIDE, 0); 4234 if (qsgmii_override == 2) { 4235 if (port == 18 || port == 22) { 4236 si->port_num_lanes[port] = 4; 4237 } 4238 } 4239 break; 4240 default: 4241 break; 4242 } 4243 } 4244 prev_reg_addr = 0xffffffff; 4245 soc_reg_field_set(unit, GPORT_CONFIGr, &rval, CLR_CNTf, 0); 4246 PBMP_E_ITER(unit, port) { 4247 uint32 reg_addr; 4248 if (!IS_GE_PORT(unit, port) || IS_XL_PORT(unit, port)) { 4249 continue; 4250 } 4251 reg_addr = soc_reg_addr(unit, GPORT_CONFIGr, port, 0); 4252 if (reg_addr != prev_reg_addr) { 4253 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, rval)); 4254 prev_reg_addr = reg_addr; 4255 } 4256 } 4257 4258 PBMP_PORT_ITER(unit, port) { 4259 if (!IS_HG_PORT(unit, port)) { 4260 continue; 4261 } 4262 si->port_num_lanes[port] = 1; 4263 SOC_IF_ERROR_RETURN(READ_XLPORT_CONFIGr(unit, port, &rval)); 4264 soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, HIGIG_MODEf, 1); 4265 SOC_IF_ERROR_RETURN(WRITE_XLPORT_CONFIGr(unit, port, rval)); 4266 } 4267 4268 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 4269 port = SOC_BLOCK_PORT(unit, blk); 4270 if (port == -1) { 4271 continue; 4272 } 4273 phy_port_base = si->port_l2p_mapping[port]; 4274 4275 /* Assert XLPORT soft reset */ 4276 rval = 0; 4277 for (bindex = 0; bindex < NUM_XLPORT; bindex++) { 4278 if (si->port_p2l_mapping[phy_port_base + bindex] != -1) { 4279 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, 4280 port_field[bindex], 1); 4281 } 4282 } 4283 SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, rval)); 4284 4285 mode = SOC_HU2_PORT_MODE_QUAD; 4286 4287 switch (dev_id) { 4288 case BCM56150_DEVICE_ID: 4289 case BCM56151_DEVICE_ID: 4290 case BCM53346_DEVICE_ID: 4291 case BCM53347_DEVICE_ID: 4292 if ((hu2_config_id == 3) || 4293 ((hu2_config_id == 2) && (port !=26))) { 4294 mode = SOC_HU2_PORT_MODE_SINGLE; 4295 si->port_num_lanes[port] = 4; 4296 si->port_num_lanes[port+1] = 4; 4297 si->port_num_lanes[port+2] = 4; 4298 si->port_num_lanes[port+3] = 4; 4299 } 4300 /* Fall Thru */ 4301 case BCM56152_DEVICE_ID: 4302 case BCM53344_DEVICE_ID: 4303 if ((hu2_config_id == 1) || (hu2_config_id == 10)) { 4304 if (port != 26) { 4305 mode = SOC_HU2_PORT_MODE_DUAL; 4306 si->port_num_lanes[port] = 2; 4307 si->port_num_lanes[port+1] = 2; 4308 } 4309 } else if (hu2_config_id == 11) { 4310 if (port == 26) { 4311 mode = SOC_HU2_PORT_MODE_DUAL; 4312 si->port_num_lanes[port] = 2; 4313 si->port_num_lanes[port+1] = 2; 4314 } 4315 } 4316 break; 4317 case BCM53394_DEVICE_ID: 4318 if (hu2_config_id == 1) { 4319 if (port == 26) { 4320 mode = SOC_HU2_PORT_MODE_SINGLE; 4321 si->port_num_lanes[port] = 4; 4322 si->port_num_lanes[port+1] = 4; 4323 si->port_num_lanes[port+2] = 4; 4324 si->port_num_lanes[port+3] = 4; 4325 } 4326 } else if (hu2_config_id == 2) { 4327 if (port == 26) { 4328 mode = SOC_HU2_PORT_MODE_SINGLE; 4329 si->port_num_lanes[port] = 4; 4330 } 4331 } 4332 break; 4333 default : 4334 break; 4335 } 4336 4337 rval = 0; 4338 soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, 4339 XPORT0_CORE_PORT_MODEf, mode); 4340 soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, 4341 XPORT0_PHY_PORT_MODEf, mode); 4342 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MODE_REGr(unit, port, rval)); 4343 4344 /* De-assert XLPORT soft reset */ 4345 SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, 0)); 4346 4347 /* Enable XLPORT */ 4348 rval = 0; 4349 for (bindex = 0; bindex < NUM_XLPORT; bindex++) { 4350 if (si->port_p2l_mapping[phy_port_base + bindex] != -1) { 4351 soc_reg_field_set(unit, XLPORT_ENABLE_REGr, &rval, 4352 port_field[bindex], 1); 4353 } 4354 } 4355 SOC_IF_ERROR_RETURN(WRITE_XLPORT_ENABLE_REGr(unit, port, rval)); 4356 } 4357 4358 SOC_IF_ERROR_RETURN(READ_ING_CONFIG_64r(unit, ®64)); 4359 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 4360 L3SRC_HIT_ENABLEf, 1); 4361 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 4362 L2DST_HIT_ENABLEf, 1); 4363 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 4364 APPLY_EGR_MASK_ON_L2f, 1); 4365 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 4366 APPLY_EGR_MASK_ON_L3f, 1); 4367 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 4368 ARP_RARP_TO_FPf, 0x3); /* enable both ARP & RARP */ 4369 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 4370 ARP_VALIDATION_ENf, 1); 4371 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 4372 IGNORE_HG_HDR_LAG_FAILOVERf, 1); 4373 SOC_IF_ERROR_RETURN(WRITE_ING_CONFIG_64r(unit, reg64)); 4374 4375 SOC_IF_ERROR_RETURN(READ_EGR_CONFIG_1r(unit, &rval)); 4376 soc_reg_field_set(unit, EGR_CONFIG_1r, &rval, RING_MODEf, 1); 4377 SOC_IF_ERROR_RETURN(WRITE_EGR_CONFIG_1r(unit, rval)); 4378 4379 /* 4380 * Set reference clock (based on 200MHz core clock) 4381 * to be 200MHz * (1/40) = 5MHz 4382 */ 4383 divisor = soc_property_get(unit, spn_RATE_EXT_MDIO_DIVISOR, 40); 4384 dividend = soc_property_get(unit, spn_RATE_EXT_MDIO_DIVIDEND, 1); 4385 rval = 0; 4386 soc_reg_field_set(unit, CMIC_RATE_ADJUSTr, &rval, DIVISORf, divisor); 4387 soc_reg_field_set(unit, CMIC_RATE_ADJUSTr, &rval, DIVIDENDf, dividend); 4388 /* coverity[result_independent_of_operands] */ 4389 SOC_IF_ERROR_RETURN(WRITE_CMIC_RATE_ADJUSTr(unit, rval)); 4390 4391 /* Match the Internal MDC freq with above for External MDC */ 4392 divisor = soc_property_get(unit, spn_RATE_INT_MDIO_DIVISOR, 40); 4393 dividend = soc_property_get(unit, spn_RATE_INT_MDIO_DIVIDEND, 1); 4394 rval = 0; 4395 soc_reg_field_set (unit, CMIC_RATE_ADJUST_INT_MDIOr, &rval, DIVISORf, divisor); 4396 soc_reg_field_set (unit, CMIC_RATE_ADJUST_INT_MDIOr, &rval, DIVIDENDf, dividend); 4397 /* coverity[result_independent_of_operands] */ 4398 SOC_IF_ERROR_RETURN(WRITE_CMIC_RATE_ADJUST_INT_MDIOr(unit, rval)); 4399 4400 rval = 0; 4401 soc_reg_field_set(unit, GPORT_CONFIGr, &rval, CLR_CNTf, 1); 4402 soc_reg_field_set(unit, GPORT_CONFIGr, &rval, GPORT_ENf, 1); 4403 PBMP_E_ITER(unit, port) { 4404 if (!IS_GE_PORT(unit, port) || IS_XL_PORT(unit, port)) { 4405 continue; 4406 } 4407 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, rval)); 4408 } 4409 soc_reg_field_set(unit, GPORT_CONFIGr, &rval, CLR_CNTf, 0); 4410 PBMP_E_ITER(unit, port) { 4411 if (!IS_GE_PORT(unit, port) || IS_XL_PORT(unit, port)) { 4412 continue; 4413 } 4414 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, rval)); 4415 } 4416 4417 /* The HW defaults for EGR_VLAN_CONTROL_1.VT_MISS_UNTAG == 1, which 4418 * causes the outer tag to be removed from packets that don't have 4419 * a hit in the egress vlan tranlation table. Set to 0 to disable this. 4420 */ 4421 rval = 0; 4422 soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &rval, VT_MISS_UNTAGf, 0); 4423 4424 /* Enable pri/cfi remarking on egress ports. */ 4425 soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &rval, REMARK_OUTER_DOT1Pf, 4426 1); 4427 PBMP_ALL_ITER(unit, port) { 4428 SOC_IF_ERROR_RETURN(WRITE_EGR_VLAN_CONTROL_1r(unit, port, rval)); 4429 } 4430 4431 /* Multicast range initialization */ 4432 SOC_IF_ERROR_RETURN 4433 (soc_hbx_higig2_mcast_sizes_set(unit, 4434 soc_property_get(unit, spn_HIGIG2_MULTICAST_VLAN_RANGE, 4435 SOC_HBX_MULTICAST_RANGE_DEFAULT), 4436 soc_property_get(unit, spn_HIGIG2_MULTICAST_L2_RANGE, 4437 SOC_HBX_MULTICAST_RANGE_DEFAULT), 4438 soc_property_get(unit, spn_HIGIG2_MULTICAST_L3_RANGE, 4439 SOC_HBX_MULTICAST_RANGE_DEFAULT))); 4440 4441 /* Setup SW2_FP_DST_ACTION_CONTROL */ 4442 fields[0] = HGTRUNK_RES_ENf; 4443 fields[1] = LAG_RES_ENf; 4444 values[0] = values[1] = 1; 4445 SOC_IF_ERROR_RETURN 4446 (soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr, 4447 REG_PORT_ANY, 2, fields, values)); 4448 4449 /* Directed Mirroring ON by default except for CPU port */ 4450 /* The src_port info will be changed as egress port if EM_SRCMOD_CHANGEf = 1 */ 4451 PBMP_PORT_ITER(unit, port) { 4452 SOC_IF_ERROR_RETURN(READ_EGR_PORTr(unit, port, &rval)); 4453 soc_reg_field_set(unit, EGR_PORTr, &rval, EM_SRCMOD_CHANGEf, 1); 4454 SOC_IF_ERROR_RETURN(WRITE_EGR_PORTr(unit, port, rval)); 4455 SOC_IF_ERROR_RETURN(READ_IEGR_PORTr(unit, port, &rval)); 4456 soc_reg_field_set(unit, IEGR_PORTr, &rval, EM_SRCMOD_CHANGEf, 1); 4457 SOC_IF_ERROR_RETURN(WRITE_IEGR_PORTr(unit, port, rval)); 4458 } 4459 4460 #ifdef _HURRICANE2_QT_DEBUG 4461 if (soc_feature(unit, soc_feature_gphy)) { 4462 rval = 0; 4463 soc_reg_field_set(unit, GPORT_LINK_STATUS_TO_CMICr, &rval, TRANSPOSEf, 1); 4464 WRITE_GPORT_LINK_STATUS_TO_CMICr(unit, 0, rval); 4465 } 4466 #endif 4467 4468 /* initialize LED UP0 */ 4469 if (!SOC_WARM_BOOT(unit)) { 4470 SOC_IF_ERROR_RETURN(_hurricane2_ledup_init(unit)); 4471 } 4472 4473 /* Turn on Power Optimization */ 4474 SOC_IF_ERROR_RETURN(_soc_hu2_power_Optimize(unit)); 4475 4476 led_intensity = soc_property_get(unit, spn_LED_INTENSITY, -1); 4477 4478 if ((led_intensity >= 1) && (led_intensity <= 12)) { 4479 fval = 0x0; 4480 } else if ((led_intensity >= 13) && (led_intensity <= 25)) { 4481 fval = 0x1; 4482 } else if ((led_intensity >= 26) && (led_intensity <= 37)) { 4483 fval = 0x2; 4484 } else if ((led_intensity >= 38) && (led_intensity <= 50)) { 4485 fval = 0x3; 4486 } else if ((led_intensity >= 51) && (led_intensity <= 62)) { 4487 fval = 0x4; 4488 } else if ((led_intensity >= 63) && (led_intensity <= 75)) { 4489 fval = 0x5; 4490 } else if ((led_intensity >= 76) && (led_intensity <= 88)) { 4491 fval = 0x6; 4492 } else if ((led_intensity >= 89) && (led_intensity <= 100)) { 4493 fval = 0x7; 4494 } else { 4495 fval = 0xffffffff; /* use chip default */ 4496 } 4497 4498 if (fval != 0xffffffff) { 4499 SOC_IF_ERROR_RETURN(READ_TOP_PARALLEL_LED_CTRLr(unit, &rval)); 4500 soc_reg_field_set(unit, TOP_PARALLEL_LED_CTRLr, &rval, LED_CURRENT_SELf, fval); 4501 SOC_IF_ERROR_RETURN(WRITE_TOP_PARALLEL_LED_CTRLr(unit, rval)); 4502 } 4503 4504 4505 if (soc_mspi_init(unit) != SOC_E_NONE) { 4506 LOG_WARN(BSL_LS_SOC_COMMON, 4507 (BSL_META_U(unit, 4508 "unit %d : MSPI Init Failed\n"), unit)); 4509 } 4510 4511 if (parity_enable) { 4512 SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_start(unit)); 4513 } 4514 return SOC_E_NONE; 4515 } 4516 4517 /* soc_hu2_mem_config: 4518 * Over-ride the default table sizes (from regsfile) for any SKUs here 4519 */ 4520 int 4521 soc_hu2_mem_config(int unit, int dev_id) 4522 { 4523 int rv = SOC_E_NONE; 4524 soc_persist_t *sop = SOC_PERSIST(unit); 4525 4526 switch (dev_id) { 4527 case BCM53342_DEVICE_ID: 4528 case BCM53343_DEVICE_ID: 4529 case BCM53344_DEVICE_ID: 4530 case BCM53346_DEVICE_ID: 4531 case BCM53347_DEVICE_ID: 4532 case BCM53393_DEVICE_ID: 4533 case BCM53394_DEVICE_ID: 4534 /* -- L2 related -- */ 4535 sop->memState[L2MCm].index_max = 511; 4536 /* -- L3 related -- */ 4537 sop->memState[L3_IPMCm].index_max = 63; 4538 sop->memState[L3_DEFIPm].index_max = 63; 4539 sop->memState[L3_DEFIP_ONLYm].index_max = 63; 4540 sop->memState[L3_DEFIP_DATA_ONLYm].index_max = 63; 4541 sop->memState[ING_L3_NEXT_HOPm].index_max = 511; 4542 sop->memState[INITIAL_ING_L3_NEXT_HOPm].index_max = 511; 4543 SOC_CONTROL(unit)->l3_defip_max_tcams = 1; 4544 SOC_CONTROL(unit)->l3_defip_tcam_size = 64; 4545 break; 4546 default: 4547 SOC_CONTROL(unit)->l3_defip_max_tcams = 8; 4548 SOC_CONTROL(unit)->l3_defip_tcam_size = 64; 4549 break; 4550 } 4551 return rv; 4552 } 4553 4554 int 4555 soc_hurricane2_age_timer_get(int unit, int *age_seconds, int *enabled) 4556 { 4557 uint32 value; 4558 4559 SOC_IF_ERROR_RETURN(READ_L2_AGE_TIMERr(unit, &value)); 4560 *enabled = soc_reg_field_get(unit, L2_AGE_TIMERr, value, AGE_ENAf); 4561 *age_seconds = soc_reg_field_get(unit, L2_AGE_TIMERr, value, AGE_VALf); 4562 4563 return SOC_E_NONE; 4564 } 4565 4566 int 4567 soc_hurricane2_age_timer_max_get(int unit, int *max_seconds) 4568 { 4569 *max_seconds = 4570 soc_reg_field_get(unit, L2_AGE_TIMERr, 0xffffffff, AGE_VALf); 4571 4572 return SOC_E_NONE; 4573 } 4574 4575 int 4576 soc_hurricane2_age_timer_set(int unit, int age_seconds, int enable) 4577 { 4578 uint32 value; 4579 4580 value = 0; 4581 soc_reg_field_set(unit, L2_AGE_TIMERr, &value, AGE_ENAf, enable); 4582 soc_reg_field_set(unit, L2_AGE_TIMERr, &value, AGE_VALf, age_seconds); 4583 SOC_IF_ERROR_RETURN(WRITE_L2_AGE_TIMERr(unit, value)); 4584 4585 return SOC_E_NONE; 4586 } 4587 4588 void soc_hurricane2_oam_handler_register(int unit, soc_hurricane2_oam_handler_t handler) 4589 { 4590 uint32 rval; 4591 int rv, fidx = 0; 4592 hu2_oam_handler[unit] = handler; 4593 rv = READ_IP1_INTR_ENABLEr(unit, &rval); 4594 if (rv) { 4595 LOG_ERROR(BSL_LS_SOC_COMMON, 4596 (BSL_META_U(unit, 4597 "unit %d: Error reading %s reg !!\n"), 4598 unit, SOC_REG_NAME(unit, IP1_INTR_ENABLEr))); 4599 } 4600 while (_soc_hu2_oam_interrupt_fields[fidx] != INVALIDf) { 4601 soc_reg_field_set(unit, IP1_INTR_ENABLEr, &rval, 4602 _soc_hu2_oam_interrupt_fields[fidx], 1); 4603 fidx++; 4604 } 4605 rv = WRITE_IP1_INTR_ENABLEr(unit, rval); 4606 if (rv) { 4607 LOG_ERROR(BSL_LS_SOC_COMMON, 4608 (BSL_META_U(unit, 4609 "unit %d: Error writing %s reg !!\n"), 4610 unit, SOC_REG_NAME(unit, IP1_INTR_ENABLEr))); 4611 } 4612 } 4613 4614 #if defined(INCLUDE_L3) 4615 4616 /* Hurricane2 HU2_LPM TCAM table insert/delete/lookup routines 4617 * soc_hu2_lpm_init - Called from bcm_l3_init 4618 * soc_hu2_lpm_insert - Insert/Update an IPv4/IPV6 route entry into HU2_LPM table 4619 * soc_hu2_lpm_delete - Delete an IPv4/IPV6 route entry from HU2_LPM table 4620 * soc_hu2_lpm_match - (Exact match for the key. Will match both IP address 4621 * and mask) 4622 * soc_hu2_lpm_lookup (HU2_LPM search) - Not Implemented 4623 */ 4624 4625 4626 4627 /* 4628 * TCAM based HU2_LPM implementation. Each table entry can hold one IPV4 entries or 4629 * one IPV6 entry. 4630 * 4631 * MAX_PFX_INDEX 4632 * lpm_prefix_index[98].begin ---> =============================== 4633 * == == 4634 * == 0 == 4635 * lpm_prefix_index[98].end ---> =============================== 4636 * 4637 * lpm_prefix_index[97].begin ---> =============================== 4638 * == == 4639 * == IPV6 Prefix Len = 64 == 4640 * lpm_prefix_index[97].end ---> =============================== 4641 * 4642 * 4643 * 4644 * lpm_prefix_index[x].begin ---> =============================== 4645 * == == 4646 * == == 4647 * lpm_prefix_index[x].end ---> =============================== 4648 * 4649 * 4650 * IPV6_PFX_ZERO 4651 * lpm_prefix_index[33].begin ---> =============================== 4652 * == == 4653 * == IPV6 Prefix Len = 0 == 4654 * lpm_prefix_index[33].end ---> =============================== 4655 * 4656 * 4657 * lpm_prefix_index[32].begin ---> =============================== 4658 * == == 4659 * == IPV4 Prefix Len = 32 == 4660 * lpm_prefix_index[32].end ---> =============================== 4661 * 4662 * 4663 * 4664 * lpm_prefix_index[0].begin ---> =============================== 4665 * == == 4666 * == IPV4 Prefix Len = 0 == 4667 * lpm_prefix_index[0].end ---> =============================== 4668 */ 4669 4670 #ifndef HU2_LPM_HASH_SUPPORT 4671 #define HU2_LPM_HASH_SUPPORT 1 4672 #endif 4673 4674 #define SOC_MEM_COMPARE_RETURN(a, b) { \ 4675 if ((a) < (b)) { return -1; } \ 4676 if ((a) > (b)) { return 1; } \ 4677 } 4678 4679 /* Can move to SOC Control structures */ 4680 soc_hu2_lpm_state_p soc_hu2_lpm_state[SOC_MAX_NUM_DEVICES]; 4681 4682 #define SOC_HU2_LPM_LOCK(u) soc_mem_lock(u, L3_DEFIPm) 4683 #define SOC_HU2_LPM_UNLOCK(u) soc_mem_unlock(u, L3_DEFIPm) 4684 4685 #define SOC_HU2_LPM_CACHE_FIELD_CREATE(m, f) soc_field_info_t * m##f 4686 #define SOC_HU2_LPM_CACHE_FIELD_ASSIGN(m_u, s, m, f) \ 4687 (s)->m##f = soc_mem_fieldinfo_get(m_u, m, f) 4688 typedef struct soc_hu2_lpm_field_cache_s { 4689 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, HITf); 4690 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_ROUTE0f); 4691 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, CLASS_ID0f); 4692 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DST_DISCARD0f); 4693 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, SRC_DISCARD0f); 4694 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPE0f); 4695 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, PRI0f); 4696 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DEFAULTROUTE0f); 4697 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_UNUSED0f); 4698 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_PTR0f); 4699 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, UPPER_NEXT_HOP_INDEX0f); 4700 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, NEXT_HOP_INDEX0f); 4701 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP0f); 4702 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MASKf); 4703 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_U_MASKf); 4704 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_L_MASKf); 4705 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MODE_MASKf); 4706 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_Uf); 4707 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_Lf); 4708 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MODEf); 4709 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VALIDf); 4710 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_IDf); 4711 SOC_HU2_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_MASKf); 4712 } soc_hu2_lpm_field_cache_t, *soc_hu2_lpm_field_cache_p; 4713 static 4714 soc_hu2_lpm_field_cache_p soc_hu2_lpm_field_cache_state[SOC_MAX_NUM_DEVICES]; 4715 4716 #define SOC_MEM_OPT_F32_GET(m_unit, m_mem, m_entry_data, m_field) \ 4717 soc_meminfo_fieldinfo_field32_get( \ 4718 (&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), \ 4719 (soc_hu2_lpm_field_cache_state[(m_unit)]->m_mem##m_field)) 4720 4721 #define SOC_MEM_OPT_F32_SET(m_unit, m_mem, m_entry_data, m_field, m_val) \ 4722 soc_meminfo_fieldinfo_field32_set( \ 4723 (&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), \ 4724 (soc_hu2_lpm_field_cache_state[(m_unit)]->m_mem##m_field), (m_val)) 4725 4726 4727 #define SOC_MEM_OPT_FIELD_VALID(m_unit, m_mem, m_field) \ 4728 ((soc_hu2_lpm_field_cache_state[(m_unit)]->m_mem##m_field) != NULL) 4729 4730 4731 #ifdef HU2_LPM_HASH_SUPPORT 4732 typedef struct soc_hu2_lpm_hash_s { 4733 int unit; 4734 int entry_count; /* Number entries in hash table */ 4735 int index_count; /* Hash index max value + 1 */ 4736 uint16 *table; /* Hash table with 16 bit index */ 4737 uint16 *link_table; /* To handle collisions */ 4738 } soc_hu2_lpm_hash_t; 4739 4740 /* 4741 * LPM key fields extended from 4 to 6 for VRF supporting 4742 * - for HR2/GH/HR3, the VRF also the LPM key for hash but static at vrf=0 4743 */ 4744 #define NUM_KEY_FIELDS 6 4745 typedef uint32 soc_hu2_lpm_hash_entry_t[NUM_KEY_FIELDS]; 4746 typedef int (*soc_hu2_lpm_hash_compare_fn)(soc_hu2_lpm_hash_entry_t key1, 4747 soc_hu2_lpm_hash_entry_t key2); 4748 static soc_hu2_lpm_hash_t *soc_hu2_lpm_hash_tab[SOC_MAX_NUM_DEVICES]; 4749 #define SOC_HU2_LPM_STATE_HASH(u) (soc_hu2_lpm_hash_tab[(u)]) 4750 4751 #define HU2_LPM_HASH_INDEX_NULL (0xFFFF) 4752 #define HU2_LPM_HASH_INDEX_MASK (0x3FFF) 4753 #define HU2_LPM_HASH_IPV6_MASK (0x8000) 4754 4755 #define SOC_HU2_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, odata) \ 4756 odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_Lf); \ 4757 odata[1] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_L_MASKf);\ 4758 odata[2] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_Uf); \ 4759 odata[3] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_U_MASKf);\ 4760 if ((SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_IDf))) { \ 4761 odata[4] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VRF_IDf); \ 4762 soc_hu2_lpm_hash_vrf_get(u, entry_data, &odata[5]); \ 4763 } else { \ 4764 odata[4] = 0; \ 4765 odata[5] = 0; \ 4766 } 4767 4768 #define SOC_HU2_LPM_HASH_ENTRY_IPV4_GET(u, entry_data, odata) \ 4769 odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_Lf); \ 4770 odata[1] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_L_MASKf); \ 4771 odata[2] = 0; \ 4772 odata[3] = 0x80000001; \ 4773 if ((SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_IDf))) { \ 4774 odata[4] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VRF_IDf); \ 4775 soc_hu2_lpm_hash_vrf_get(u, entry_data, &odata[5]); \ 4776 } else { \ 4777 odata[4] = 0; \ 4778 odata[5] = 0; \ 4779 } 4780 4781 #define SOC_HU2_LPM_HASH_ENTRY_GET soc_hu2_lpm_hash_entry_get 4782 4783 static 4784 void soc_hu2_lpm_hash_entry_get(int u, void *e, 4785 int index, soc_hu2_lpm_hash_entry_t r_entry); 4786 static 4787 uint16 soc_hu2_lpm_hash_compute(uint8 *data, int data_nbits); 4788 static 4789 int soc_hu2_lpm_hash_create(int unit, 4790 int entry_count, 4791 int index_count, 4792 soc_hu2_lpm_hash_t **hu2_lpm_hash_ptr); 4793 static 4794 int soc_hu2_lpm_hash_destroy(soc_hu2_lpm_hash_t *hu2_lpm_hash); 4795 static 4796 int _soc_hu2_lpm_hash_lookup(soc_hu2_lpm_hash_t *hash, 4797 soc_hu2_lpm_hash_compare_fn key_cmp_fn, 4798 soc_hu2_lpm_hash_entry_t entry, 4799 int pfx, 4800 uint16 *key_index); 4801 static 4802 int _soc_hu2_lpm_hash_insert(soc_hu2_lpm_hash_t *hash, 4803 soc_hu2_lpm_hash_compare_fn key_cmp_fn, 4804 soc_hu2_lpm_hash_entry_t entry, 4805 int pfx, 4806 uint16 old_index, 4807 uint16 new_index); 4808 4809 static 4810 int _soc_hu2_lpm_hash_delete(soc_hu2_lpm_hash_t *hash, 4811 soc_hu2_lpm_hash_compare_fn key_cmp_fn, 4812 soc_hu2_lpm_hash_entry_t entry, 4813 int pfx, 4814 uint16 delete_index); 4815 4816 /* 4817 * Function: 4818 * soc_hu2_lpm_hash_vrf_get 4819 * Purpose: 4820 * Service routine used to determine the vrf type 4821 * Parameters: 4822 * unit - (IN)SOC unit number. 4823 * lpm_entry - (IN)Route info buffer from hw. 4824 * vrf_id - (OUT)Virtual router id. 4825 * Returns: 4826 * BCM_E_XXX 4827 * Note : 4828 * - soc_hu2_lpm_hash_xxx() are SW LPM hash routines for HRx/GHx devices. 4829 * - VRF is once of the key in LPM but only be the valid field after GH2. 4830 */ 4831 STATIC void 4832 soc_hu2_lpm_hash_vrf_get(int unit, void *lpm_entry, uint32 *vrf) 4833 { 4834 int vrf_id; 4835 4836 /* Get Virtual Router id if supported. */ 4837 if (SOC_MEM_OPT_FIELD_VALID(unit, L3_DEFIPm, VRF_ID_MASKf)){ 4838 vrf_id = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_IDf); 4839 4840 /* Special vrf's handling. */ 4841 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASKf)) { 4842 *vrf = _SOC_HASH_L3_VRF_SPECIFIC; 4843 } else if (SOC_VRF_MAX(unit) == vrf_id) { 4844 *vrf = _SOC_HASH_L3_VRF_GLOBAL; 4845 } else { 4846 *vrf = _SOC_HASH_L3_VRF_OVERRIDE; 4847 if (SOC_MEM_OPT_FIELD_VALID(unit, L3_DEFIPm, GLOBAL_ROUTE0f)) { 4848 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f)) { 4849 *vrf = _SOC_HASH_L3_VRF_GLOBAL; 4850 } 4851 } 4852 } 4853 } else { 4854 /* No vrf support on this device. */ 4855 *vrf = _SOC_HASH_L3_VRF_DEFAULT; 4856 } 4857 } 4858 4859 /* 4860 * Extract key data from an entry at the given index. 4861 */ 4862 static 4863 void soc_hu2_lpm_hash_entry_get(int u, void *e, 4864 int index, soc_hu2_lpm_hash_entry_t r_entry) 4865 { 4866 int is_ipv6; 4867 4868 is_ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, MODEf); 4869 4870 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALIDf)) { 4871 if (is_ipv6) { 4872 SOC_HU2_LPM_HASH_ENTRY_IPV6_GET(u, e, r_entry); 4873 } else { 4874 SOC_HU2_LPM_HASH_ENTRY_IPV4_GET(u, e, r_entry); 4875 } 4876 } 4877 } 4878 4879 /* 4880 * Function: 4881 * soc_hu2_lpm_hash_compare_key 4882 * Purpose: 4883 * Comparison function for hash table operations. 4884 */ 4885 static 4886 int soc_hu2_lpm_hash_compare_key(soc_hu2_lpm_hash_entry_t key1, 4887 soc_hu2_lpm_hash_entry_t key2) 4888 { 4889 int idx; 4890 4891 for (idx = 0; idx < NUM_KEY_FIELDS; idx++) { 4892 SOC_MEM_COMPARE_RETURN(key1[idx], key2[idx]); 4893 } 4894 return (0); 4895 } 4896 4897 /* #define HU2_LPM_DEBUG*/ 4898 #ifdef HU2_LPM_DEBUG 4899 #define H_INDEX_MATCH(str, tab_index, match_index) \ 4900 LOG_ERROR(BSL_LS_SOC_COMMON, \ 4901 (BSL_META_U(unit, \ 4902 "%s index: H %d A %d\n"), \ 4903 str, (int)tab_index, match_index) 4904 #else 4905 #define H_INDEX_MATCH(str, tab_index, match_index) 4906 #endif 4907 4908 #define HU2_LPM_NO_MATCH_INDEX 0x4000 4909 #define HU2_LPM_HASH_INSERT(u, entry_data, tab_index) \ 4910 soc_hu2_lpm_hash_insert(u, entry_data, tab_index, HU2_LPM_NO_MATCH_INDEX, 0) 4911 4912 #define HU2_LPM_HASH_DELETE(u, key_data, tab_index) \ 4913 soc_hu2_lpm_hash_delete(u, key_data, tab_index) 4914 4915 #define HU2_LPM_HASH_LOOKUP(u, key_data, pfx, tab_index) \ 4916 soc_hu2_lpm_hash_lookup(u, key_data, pfx, tab_index) 4917 4918 void soc_hu2_lpm_hash_insert(int u, void *entry_data, uint32 tab_index, 4919 uint32 old_index, int pfx) 4920 { 4921 soc_hu2_lpm_hash_entry_t key_hash; 4922 4923 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALIDf)) { 4924 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, MODEf)) { 4925 /* IPV6 entry */ 4926 SOC_HU2_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash); 4927 } else { 4928 /* IPV4 entry */ 4929 SOC_HU2_LPM_HASH_ENTRY_IPV4_GET(u, entry_data, key_hash); 4930 } 4931 _soc_hu2_lpm_hash_insert(SOC_HU2_LPM_STATE_HASH(u), 4932 soc_hu2_lpm_hash_compare_key, 4933 key_hash, 4934 pfx, 4935 old_index, 4936 (uint16)tab_index); 4937 } 4938 } 4939 4940 void soc_hu2_lpm_hash_delete(int u, void *key_data, uint32 tab_index) 4941 { 4942 soc_hu2_lpm_hash_entry_t key_hash; 4943 int pfx = -1; 4944 int rv; 4945 uint16 index; 4946 4947 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, MODEf)) { 4948 SOC_HU2_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash); 4949 } else { 4950 SOC_HU2_LPM_HASH_ENTRY_IPV4_GET(u, key_data, key_hash); 4951 } 4952 index = tab_index; 4953 4954 rv = _soc_hu2_lpm_hash_delete(SOC_HU2_LPM_STATE_HASH(u), 4955 soc_hu2_lpm_hash_compare_key, 4956 key_hash, pfx, index); 4957 if (SOC_FAILURE(rv)) { 4958 LOG_ERROR(BSL_LS_SOC_COMMON, 4959 (BSL_META_U(u, 4960 "\ndel index: H %d error %d\n"), index, rv)); 4961 } 4962 } 4963 4964 int soc_hu2_lpm_hash_lookup(int u, void *key_data, int pfx, int *key_index) 4965 { 4966 soc_hu2_lpm_hash_entry_t key_hash; 4967 int is_ipv6; 4968 int rv; 4969 uint16 index = HU2_LPM_HASH_INDEX_NULL; 4970 4971 is_ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, MODEf); 4972 if (is_ipv6) { 4973 SOC_HU2_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash); 4974 } else { 4975 SOC_HU2_LPM_HASH_ENTRY_IPV4_GET(u, key_data, key_hash); 4976 } 4977 4978 rv = _soc_hu2_lpm_hash_lookup(SOC_HU2_LPM_STATE_HASH(u), 4979 soc_hu2_lpm_hash_compare_key, 4980 key_hash, pfx, &index); 4981 if (SOC_FAILURE(rv)) { 4982 *key_index = 0xFFFFFFFF; 4983 return(rv); 4984 } 4985 4986 *key_index = index; 4987 4988 return(SOC_E_NONE); 4989 } 4990 4991 /* 4992 * Function: 4993 * soc_hu2_lpm_hash_compute 4994 * Purpose: 4995 * Compute CRC hash for key data. 4996 * Parameters: 4997 * data - Key data 4998 * data_nbits - Number of data bits 4999 * Returns: 5000 * Computed 16 bit hash 5001 */ 5002 static 5003 uint16 soc_hu2_lpm_hash_compute(uint8 *data, int data_nbits) 5004 { 5005 return (_shr_crc16b(0, data, data_nbits)); 5006 } 5007 5008 /* 5009 * Function: 5010 * soc_hu2_lpm_hash_create 5011 * Purpose: 5012 * Create an empty hash table 5013 * Parameters: 5014 * unit - Device unit 5015 * entry_count - Limit for number of entries in table 5016 * index_count - Hash index max + 1. (index_count <= count) 5017 * hu2_lpm_hash_ptr - Return pointer (handle) to new Hash Table 5018 * Returns: 5019 * SOC_E_NONE Success 5020 * SOC_E_MEMORY Out of memory (system allocator) 5021 */ 5022 5023 static 5024 int soc_hu2_lpm_hash_create(int unit, 5025 int entry_count, 5026 int index_count, 5027 soc_hu2_lpm_hash_t **hu2_lpm_hash_ptr) 5028 { 5029 soc_hu2_lpm_hash_t *hash; 5030 int index; 5031 5032 if (index_count > entry_count) { 5033 return SOC_E_MEMORY; 5034 } 5035 hash = sal_alloc(sizeof (soc_hu2_lpm_hash_t), "lpm_hash"); 5036 if (hash == NULL) { 5037 return SOC_E_MEMORY; 5038 } 5039 5040 sal_memset(hash, 0, sizeof (*hash)); 5041 5042 hash->unit = unit; 5043 hash->entry_count = entry_count; 5044 hash->index_count = index_count; 5045 5046 /* 5047 * Pre-allocate the hash table storage. 5048 */ 5049 hash->table = sal_alloc(hash->index_count * sizeof(*(hash->table)), 5050 "hash_table"); 5051 5052 if (hash->table == NULL) { 5053 sal_free(hash); 5054 return SOC_E_MEMORY; 5055 } 5056 /* 5057 * In case where all the entries should hash into the same bucket 5058 * this will prevent the hash table overflow 5059 */ 5060 hash->link_table = sal_alloc( 5061 hash->entry_count * sizeof(*(hash->link_table)), 5062 "link_table"); 5063 if (hash->link_table == NULL) { 5064 sal_free(hash->table); 5065 sal_free(hash); 5066 return SOC_E_MEMORY; 5067 } 5068 5069 /* 5070 * Set the entries in the hash table to HU2_LPM_HASH_INDEX_NULL 5071 * Link the entries beyond hash->index_max for handling collisions 5072 */ 5073 for(index = 0; index < hash->index_count; index++) { 5074 hash->table[index] = HU2_LPM_HASH_INDEX_NULL; 5075 } 5076 for(index = 0; index < hash->entry_count; index++) { 5077 hash->link_table[index] = HU2_LPM_HASH_INDEX_NULL; 5078 } 5079 *hu2_lpm_hash_ptr = hash; 5080 return SOC_E_NONE; 5081 } 5082 5083 /* 5084 * Function: 5085 * soc_hu2_lpm_hash_destroy 5086 * Purpose: 5087 * Destroy the hash table 5088 * Parameters: 5089 * hu2_lpm_hash - Pointer (handle) to Hash Table 5090 * Returns: 5091 * SOC_E_NONE Success 5092 */ 5093 static 5094 int soc_hu2_lpm_hash_destroy(soc_hu2_lpm_hash_t *hu2_lpm_hash) 5095 { 5096 if (hu2_lpm_hash != NULL) { 5097 sal_free(hu2_lpm_hash->table); 5098 sal_free(hu2_lpm_hash->link_table); 5099 sal_free(hu2_lpm_hash); 5100 } 5101 5102 return SOC_E_NONE; 5103 } 5104 5105 /* 5106 * Function: 5107 * _soc_hu2_lpm_hash_lookup 5108 * Purpose: 5109 * Look up a key in the hash table 5110 * Parameters: 5111 * hash - Pointer (handle) to Hash Table 5112 * key_cmp_fn - Compare function which should compare key 5113 * entry - The key to lookup 5114 * pfx - Prefix length for lookup acceleration. 5115 * key_index - (OUT) Index where the key was found. 5116 * Returns: 5117 * SOC_E_NONE Key found 5118 * SOC_E_NOT_FOUND Key not found 5119 */ 5120 5121 static 5122 int _soc_hu2_lpm_hash_lookup(soc_hu2_lpm_hash_t *hash, 5123 soc_hu2_lpm_hash_compare_fn key_cmp_fn, 5124 soc_hu2_lpm_hash_entry_t entry, 5125 int pfx, 5126 uint16 *key_index) 5127 { 5128 int u = hash->unit; 5129 5130 uint16 hash_val; 5131 uint16 index; 5132 5133 hash_val = soc_hu2_lpm_hash_compute((uint8 *)entry, 5134 (32 * NUM_KEY_FIELDS)) % hash->index_count; 5135 index = hash->table[hash_val]; 5136 H_INDEX_MATCH("lhash", entry[0], hash_val); 5137 H_INDEX_MATCH("lkup ", entry[0], index); 5138 while(index != HU2_LPM_HASH_INDEX_NULL) { 5139 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 5140 soc_hu2_lpm_hash_entry_t r_entry; 5141 /*int rindex; 5142 5143 rindex = (index & HU2_LPM_HASH_INDEX_MASK) >> 1;*/ 5144 5145 SOC_IF_ERROR_RETURN(READ_L3_DEFIPm(u, MEM_BLOCK_ANY, index, e)); 5146 SOC_HU2_LPM_HASH_ENTRY_GET(u, e, index, r_entry); 5147 if ((*key_cmp_fn)(entry, r_entry) == 0) { 5148 *key_index = (index & HU2_LPM_HASH_INDEX_MASK); 5149 H_INDEX_MATCH("found", entry[0], index); 5150 return(SOC_E_NONE); 5151 } 5152 5153 index = hash->link_table[index & HU2_LPM_HASH_INDEX_MASK]; 5154 H_INDEX_MATCH("lkup1", entry[0], index); 5155 } 5156 H_INDEX_MATCH("not_found", entry[0], index); 5157 return(SOC_E_NOT_FOUND); 5158 } 5159 5160 /* 5161 * Function: 5162 * _soc_hu2_lpm_hash_insert 5163 * Purpose: 5164 * Insert/Update a key index in the hash table 5165 * Parameters: 5166 * hash - Pointer (handle) to Hash Table 5167 * key_cmp_fn - Compare function which should compare key 5168 * entry - The key to lookup 5169 * pfx - Prefix length for lookup acceleration. 5170 * old_index - Index where the key was moved from. 5171 * HU2_LPM_HASH_INDEX_NULL if new entry. 5172 * new_index - Index where the key was moved to. 5173 * Returns: 5174 * SOC_E_NONE Key found 5175 */ 5176 /* 5177 * Should be caled before updating the HU2_LPM table so that the 5178 * data in the hash table is consistent with the HU2_LPM table 5179 */ 5180 static 5181 int _soc_hu2_lpm_hash_insert(soc_hu2_lpm_hash_t *hash, 5182 soc_hu2_lpm_hash_compare_fn key_cmp_fn, 5183 soc_hu2_lpm_hash_entry_t entry, 5184 int pfx, 5185 uint16 old_index, 5186 uint16 new_index) 5187 { 5188 5189 #define INDEX_ADD(hash, hash_idx, new_idx) \ 5190 hash->link_table[new_idx & HU2_LPM_HASH_INDEX_MASK] = \ 5191 hash->table[hash_idx]; \ 5192 hash->table[hash_idx] = new_idx 5193 5194 #define INDEX_ADD_LINK(hash, t_index, new_idx) \ 5195 hash->link_table[new_idx & HU2_LPM_HASH_INDEX_MASK] = \ 5196 hash->link_table[t_index & HU2_LPM_HASH_INDEX_MASK]; \ 5197 hash->link_table[t_index & HU2_LPM_HASH_INDEX_MASK] = new_idx 5198 5199 #define INDEX_UPDATE(hash, hash_idx, old_idx, new_idx) \ 5200 hash->table[hash_idx] = new_idx; \ 5201 hash->link_table[new_idx & HU2_LPM_HASH_INDEX_MASK] = \ 5202 hash->link_table[old_idx & HU2_LPM_HASH_INDEX_MASK]; \ 5203 hash->link_table[old_idx & HU2_LPM_HASH_INDEX_MASK] = \ 5204 HU2_LPM_HASH_INDEX_NULL 5205 5206 #define INDEX_UPDATE_LINK(hash, prev_idx, old_idx, new_idx) \ 5207 hash->link_table[prev_idx & HU2_LPM_HASH_INDEX_MASK] = new_idx; \ 5208 hash->link_table[new_idx & HU2_LPM_HASH_INDEX_MASK] = \ 5209 hash->link_table[old_idx & HU2_LPM_HASH_INDEX_MASK]; \ 5210 hash->link_table[old_idx & HU2_LPM_HASH_INDEX_MASK] = \ 5211 HU2_LPM_HASH_INDEX_NULL 5212 5213 5214 int u = hash->unit; 5215 5216 uint16 hash_val; 5217 uint16 index; 5218 uint16 prev_index; 5219 5220 hash_val = soc_hu2_lpm_hash_compute((uint8 *)entry, 5221 (32 * NUM_KEY_FIELDS)) % hash->index_count; 5222 index = hash->table[hash_val]; 5223 H_INDEX_MATCH("ihash", entry[0], hash_val); 5224 H_INDEX_MATCH("ins ", entry[0], new_index); 5225 H_INDEX_MATCH("ins1 ", index, new_index); 5226 prev_index = HU2_LPM_HASH_INDEX_NULL; 5227 if (old_index != HU2_LPM_HASH_INDEX_NULL) { 5228 while(index != HU2_LPM_HASH_INDEX_NULL) { 5229 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 5230 soc_hu2_lpm_hash_entry_t r_entry; 5231 /*int rindex; 5232 5233 rindex = (index & HU2_LPM_HASH_INDEX_MASK) >> 1; */ 5234 5235 SOC_IF_ERROR_RETURN(READ_L3_DEFIPm(u, MEM_BLOCK_ANY, index, e)); 5236 SOC_HU2_LPM_HASH_ENTRY_GET(u, e, index, r_entry); 5237 if ((*key_cmp_fn)(entry, r_entry) == 0) { 5238 /* assert(old_index == index);*/ 5239 if (new_index != index) { 5240 H_INDEX_MATCH("imove", prev_index, new_index); 5241 if (prev_index == HU2_LPM_HASH_INDEX_NULL) { 5242 INDEX_UPDATE(hash, hash_val, index, new_index); 5243 } else { 5244 INDEX_UPDATE_LINK(hash, prev_index, index, new_index); 5245 } 5246 } 5247 H_INDEX_MATCH("imtch", index, new_index); 5248 return(SOC_E_NONE); 5249 } 5250 prev_index = index; 5251 index = hash->link_table[index & HU2_LPM_HASH_INDEX_MASK]; 5252 H_INDEX_MATCH("ins2 ", index, new_index); 5253 } 5254 } 5255 INDEX_ADD(hash, hash_val, new_index); /* new entry */ 5256 return(SOC_E_NONE); 5257 } 5258 5259 /* 5260 * Function: 5261 * _soc_hu2_lpm_hash_delete 5262 * Purpose: 5263 * Delete a key index in the hash table 5264 * Parameters: 5265 * hash - Pointer (handle) to Hash Table 5266 * key_cmp_fn - Compare function which should compare key 5267 * entry - The key to delete 5268 * pfx - Prefix length for lookup acceleration. 5269 * delete_index - Index to delete. 5270 * Returns: 5271 * SOC_E_NONE Success 5272 * SOC_E_NOT_FOUND Key index not found. 5273 */ 5274 static 5275 int _soc_hu2_lpm_hash_delete(soc_hu2_lpm_hash_t *hash, 5276 soc_hu2_lpm_hash_compare_fn key_cmp_fn, 5277 soc_hu2_lpm_hash_entry_t entry, 5278 int pfx, 5279 uint16 delete_index) 5280 { 5281 uint16 hash_val; 5282 uint16 index; 5283 uint16 prev_index; 5284 5285 hash_val = soc_hu2_lpm_hash_compute((uint8 *)entry, 5286 (32 * NUM_KEY_FIELDS)) % hash->index_count; 5287 index = hash->table[hash_val]; 5288 H_INDEX_MATCH("dhash", entry[0], hash_val); 5289 H_INDEX_MATCH("del ", entry[0], index); 5290 prev_index = HU2_LPM_HASH_INDEX_NULL; 5291 while(index != HU2_LPM_HASH_INDEX_NULL) { 5292 #define INDEX_DELETE(hash, hash_idx, del_idx) \ 5293 hash->table[hash_idx] = \ 5294 hash->link_table[del_idx & HU2_LPM_HASH_INDEX_MASK]; \ 5295 hash->link_table[del_idx & HU2_LPM_HASH_INDEX_MASK] = \ 5296 HU2_LPM_HASH_INDEX_NULL 5297 5298 #define INDEX_DELETE_LINK(hash, prev_idx, del_idx) \ 5299 hash->link_table[prev_idx & HU2_LPM_HASH_INDEX_MASK] = \ 5300 hash->link_table[del_idx & HU2_LPM_HASH_INDEX_MASK]; \ 5301 hash->link_table[del_idx & HU2_LPM_HASH_INDEX_MASK] = \ 5302 HU2_LPM_HASH_INDEX_NULL 5303 5304 if (delete_index == index) { 5305 H_INDEX_MATCH("dfoun", entry[0], index); 5306 if (prev_index == HU2_LPM_HASH_INDEX_NULL) { 5307 INDEX_DELETE(hash, hash_val, delete_index); 5308 } else { 5309 INDEX_DELETE_LINK(hash, prev_index, delete_index); 5310 } 5311 return(SOC_E_NONE); 5312 } 5313 prev_index = index; 5314 index = hash->link_table[index & HU2_LPM_HASH_INDEX_MASK]; 5315 H_INDEX_MATCH("del1 ", entry[0], index); 5316 } 5317 return(SOC_E_NOT_FOUND); 5318 } 5319 #else 5320 #define HU2_LPM_HASH_INSERT(u, entry_data, tab_index) 5321 #define HU2_LPM_HASH_DELETE(u, key_data, tab_index) 5322 #define HU2_LPM_HASH_LOOKUP(u, key_data, pfx, tab_index) 5323 #endif /* HU2_LPM_HASH_SUPPORT */ 5324 5325 static 5326 int 5327 _ip_mask2pfx(uint32 ipv4m, int *mask_len) 5328 { 5329 *mask_len = 0; 5330 while (ipv4m & (1 << 31)) { 5331 *mask_len += 1; 5332 ipv4m <<= 1; 5333 } 5334 5335 return ((ipv4m) ? SOC_E_PARAM : SOC_E_NONE); 5336 } 5337 5338 void 5339 soc_hu2_lpm_state_dump(int u) 5340 { 5341 int i; 5342 int max_pfx_len; 5343 max_pfx_len = MAX_PFX_INDEX(u); 5344 5345 if (!bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityVerbose, u)) { 5346 return; 5347 } 5348 for(i = max_pfx_len; i >= 0 ; i--) { 5349 if ((i != MAX_PFX_INDEX(u)) && (SOC_HU2_LPM_STATE_START(u, i) == -1)) { 5350 continue; 5351 } 5352 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 5353 (BSL_META_U(u, 5354 "PFX = %d P = %d N = %d START = %d END = %d VENT = %d FENT = %d\n"), 5355 i, 5356 SOC_HU2_LPM_STATE_PREV(u, i), 5357 SOC_HU2_LPM_STATE_NEXT(u, i), 5358 SOC_HU2_LPM_STATE_START(u, i), 5359 SOC_HU2_LPM_STATE_END(u, i), 5360 SOC_HU2_LPM_STATE_VENT(u, i), 5361 SOC_HU2_LPM_STATE_FENT(u, i))); 5362 } 5363 } 5364 5365 #ifdef BCM_HURRICANE3_SUPPORT 5366 /* 5367 * Replicate entry to the second half of the tcam if URPF check is ON. 5368 */ 5369 static 5370 int _lpm_hr3_urpf_entry_replicate(int u, int index, uint32 *e) 5371 { 5372 int src_tcam_offset; /* Defip memory size/2 urpf source lookup offset */ 5373 int ipv6; /* IPv6 entry. */ 5374 uint32 mask0; /* Mask field value. */ 5375 uint32 mask1; /* Mask field value. */ 5376 int def_gw_flag; /* Entry is default gateway. */ 5377 5378 if(!SOC_URPF_STATUS_GET(u)) { 5379 return (SOC_E_NONE); 5380 } 5381 5382 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1); 5383 5384 ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, MODEf); 5385 5386 /* Reset destination discard bit. */ 5387 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, 0); 5388 5389 /* Set/Reset default gateway flag based on ip mask value. */ 5390 mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_L_MASKf); 5391 mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_U_MASKf); 5392 5393 if (!ipv6) { 5394 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALIDf)) { 5395 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, (!mask0) ? 1 : 0); 5396 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, 5397 DEFAULTROUTE0f, (!mask0) ? 1 : 0); 5398 } 5399 } else { 5400 def_gw_flag = ((!mask0) && (!mask1)) ? 1 : 0; 5401 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, def_gw_flag); 5402 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DEFAULTROUTE0f, def_gw_flag); 5403 } 5404 5405 /* Write entry to the second half of the tcam. */ 5406 return WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, (index + src_tcam_offset), e); 5407 } 5408 #endif /* BCM_HURRICANE3_SUPPORT */ 5409 5410 /* 5411 * Create a slot for the new entry rippling the entries if required 5412 */ 5413 static 5414 int _lpm_hu2_entry_shift(int u, int from_ent, int to_ent) 5415 { 5416 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 5417 5418 #ifdef HU2_LPM_TABLE_CACHED 5419 SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm, 5420 MEM_BLOCK_ANY, from_ent)); 5421 #endif /* HU2_LPM_TABLE_CACHED */ 5422 5423 SOC_IF_ERROR_RETURN(READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, e)); 5424 HU2_LPM_HASH_INSERT(u, e, to_ent); 5425 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent, e)); 5426 #ifdef BCM_HURRICANE3_SUPPORT 5427 if (soc_feature(u, soc_feature_urpf)) { 5428 SOC_IF_ERROR_RETURN(_lpm_hr3_urpf_entry_replicate(u, to_ent, e)); 5429 } 5430 #endif /* BCM_HURRICANE3_SUPPORT */ 5431 return (SOC_E_NONE); 5432 } 5433 5434 5435 /* 5436 * Shift prefix entries 1 entry UP, while preserving 5437 * last half empty IPv4 entry if any. 5438 */ 5439 static 5440 int _lpm_hu2_shift_pfx_up(int u, int pfx) 5441 { 5442 int from_ent; 5443 int to_ent; 5444 5445 to_ent = SOC_HU2_LPM_STATE_END(u, pfx) + 1; 5446 5447 from_ent = SOC_HU2_LPM_STATE_START(u, pfx); 5448 if(from_ent != to_ent) { 5449 SOC_IF_ERROR_RETURN(_lpm_hu2_entry_shift(u, from_ent, to_ent)); 5450 } 5451 SOC_HU2_LPM_STATE_START(u, pfx) += 1; 5452 SOC_HU2_LPM_STATE_END(u, pfx) += 1; 5453 return (SOC_E_NONE); 5454 } 5455 5456 /* 5457 * Shift prefix entries 1 entry DOWN, while preserving 5458 * last half empty IPv4 entry if any. 5459 */ 5460 static 5461 int _lpm_hu2_shift_pfx_down(int u, int pfx) 5462 { 5463 int from_ent; 5464 int to_ent; 5465 5466 5467 to_ent = SOC_HU2_LPM_STATE_START(u, pfx) - 1; 5468 5469 /* Don't move empty prefix . */ 5470 if (SOC_HU2_LPM_STATE_VENT(u, pfx) == 0) { 5471 SOC_HU2_LPM_STATE_START(u, pfx) = to_ent; 5472 SOC_HU2_LPM_STATE_END(u, pfx) = to_ent - 1; 5473 return (SOC_E_NONE); 5474 } 5475 5476 from_ent = SOC_HU2_LPM_STATE_END(u, pfx); 5477 SOC_IF_ERROR_RETURN(_lpm_hu2_entry_shift(u, from_ent, to_ent)); 5478 SOC_HU2_LPM_STATE_START(u, pfx) -= 1; 5479 SOC_HU2_LPM_STATE_END(u, pfx) -= 1; 5480 5481 return (SOC_E_NONE); 5482 } 5483 5484 /* 5485 * Create a slot for the new entry rippling the entries if required 5486 */ 5487 static 5488 int _lpm_hu2_free_slot_create(int u, int pfx, void *e, int *free_slot) 5489 { 5490 int prev_pfx; 5491 int next_pfx; 5492 int free_pfx; 5493 int curr_pfx; 5494 5495 if (SOC_HU2_LPM_STATE_VENT(u, pfx) == 0) { 5496 /* 5497 * Find the prefix position. Only prefix with valid 5498 * entries are in the list. 5499 * next -> high to low prefix. low to high index 5500 * prev -> low to high prefix. high to low index 5501 * Unused prefix length MAX_PFX_INDEX is the head of the 5502 * list and is node corresponding to this is always 5503 * present. 5504 */ 5505 curr_pfx = MAX_PFX_INDEX(u); 5506 while (SOC_HU2_LPM_STATE_NEXT(u, curr_pfx) > pfx) { 5507 curr_pfx = SOC_HU2_LPM_STATE_NEXT(u, curr_pfx); 5508 } 5509 /* Insert the new prefix */ 5510 next_pfx = SOC_HU2_LPM_STATE_NEXT(u, curr_pfx); 5511 if (next_pfx != -1) { 5512 SOC_HU2_LPM_STATE_PREV(u, next_pfx) = pfx; 5513 } 5514 SOC_HU2_LPM_STATE_NEXT(u, pfx) = SOC_HU2_LPM_STATE_NEXT(u, curr_pfx); 5515 SOC_HU2_LPM_STATE_PREV(u, pfx) = curr_pfx; 5516 SOC_HU2_LPM_STATE_NEXT(u, curr_pfx) = pfx; 5517 5518 SOC_HU2_LPM_STATE_FENT(u, pfx) = (SOC_HU2_LPM_STATE_FENT(u, curr_pfx) + 1) / 2; 5519 SOC_HU2_LPM_STATE_FENT(u, curr_pfx) -= SOC_HU2_LPM_STATE_FENT(u, pfx); 5520 SOC_HU2_LPM_STATE_START(u, pfx) = SOC_HU2_LPM_STATE_END(u, curr_pfx) + 5521 SOC_HU2_LPM_STATE_FENT(u, curr_pfx) + 1; 5522 SOC_HU2_LPM_STATE_END(u, pfx) = SOC_HU2_LPM_STATE_START(u, pfx) - 1; 5523 SOC_HU2_LPM_STATE_VENT(u, pfx) = 0; 5524 } 5525 5526 free_pfx = pfx; 5527 while(SOC_HU2_LPM_STATE_FENT(u, free_pfx) == 0) { 5528 free_pfx = SOC_HU2_LPM_STATE_NEXT(u, free_pfx); 5529 if (free_pfx == -1) { 5530 /* No free entries on this side try the other side */ 5531 free_pfx = pfx; 5532 break; 5533 } 5534 } 5535 5536 while(SOC_HU2_LPM_STATE_FENT(u, free_pfx) == 0) { 5537 free_pfx = SOC_HU2_LPM_STATE_PREV(u, free_pfx); 5538 if (free_pfx == -1) { 5539 if (SOC_HU2_LPM_STATE_VENT(u, pfx) == 0) { 5540 /* We failed to allocate entries for a newly allocated prefix.*/ 5541 prev_pfx = SOC_HU2_LPM_STATE_PREV(u, pfx); 5542 next_pfx = SOC_HU2_LPM_STATE_NEXT(u, pfx); 5543 if (-1 != prev_pfx) { 5544 SOC_HU2_LPM_STATE_NEXT(u, prev_pfx) = next_pfx; 5545 } 5546 if (-1 != next_pfx) { 5547 SOC_HU2_LPM_STATE_PREV(u, next_pfx) = prev_pfx; 5548 } 5549 } 5550 return(SOC_E_FULL); 5551 } 5552 } 5553 5554 /* 5555 * Ripple entries to create free space 5556 */ 5557 while (free_pfx > pfx) { 5558 next_pfx = SOC_HU2_LPM_STATE_NEXT(u, free_pfx); 5559 SOC_IF_ERROR_RETURN(_lpm_hu2_shift_pfx_down(u, next_pfx)); 5560 SOC_HU2_LPM_STATE_FENT(u, free_pfx) -= 1; 5561 SOC_HU2_LPM_STATE_FENT(u, next_pfx) += 1; 5562 free_pfx = next_pfx; 5563 } 5564 5565 while (free_pfx < pfx) { 5566 SOC_IF_ERROR_RETURN(_lpm_hu2_shift_pfx_up(u, free_pfx)); 5567 SOC_HU2_LPM_STATE_FENT(u, free_pfx) -= 1; 5568 prev_pfx = SOC_HU2_LPM_STATE_PREV(u, free_pfx); 5569 SOC_HU2_LPM_STATE_FENT(u, prev_pfx) += 1; 5570 free_pfx = prev_pfx; 5571 } 5572 5573 SOC_HU2_LPM_STATE_VENT(u, pfx) += 1; 5574 SOC_HU2_LPM_STATE_FENT(u, pfx) -= 1; 5575 SOC_HU2_LPM_STATE_END(u, pfx) += 1; 5576 *free_slot = SOC_HU2_LPM_STATE_END(u, pfx); 5577 sal_memcpy(e, soc_mem_entry_null(u, L3_DEFIPm), 5578 soc_mem_entry_words(u,L3_DEFIPm) * 4); 5579 5580 return(SOC_E_NONE); 5581 } 5582 5583 /* 5584 * Delete a slot and adjust entry pointers if required. 5585 * e - has the contents of entry at slot(useful for IPV4 only) 5586 */ 5587 static 5588 int _lpm_hu2_free_slot_delete(int u, int pfx, void *e, int slot) 5589 { 5590 int prev_pfx; 5591 int next_pfx; 5592 int from_ent; 5593 int to_ent; 5594 uint32 ef[SOC_MAX_MEM_FIELD_WORDS]; 5595 int rv; 5596 5597 from_ent = SOC_HU2_LPM_STATE_END(u, pfx); 5598 to_ent = slot; 5599 SOC_HU2_LPM_STATE_VENT(u, pfx) -= 1; 5600 SOC_HU2_LPM_STATE_FENT(u, pfx) += 1; 5601 SOC_HU2_LPM_STATE_END(u, pfx) -= 1; 5602 if (to_ent != from_ent) { 5603 #ifdef HU2_LPM_TABLE_CACHED 5604 if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm, 5605 MEM_BLOCK_ANY, from_ent)) < 0) { 5606 return rv; 5607 } 5608 #endif /* HU2_LPM_TABLE_CACHED */ 5609 if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, ef)) < 0) { 5610 return rv; 5611 } 5612 HU2_LPM_HASH_INSERT(u, ef, to_ent); 5613 if ((rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent, ef)) < 0) { 5614 return rv; 5615 } 5616 #ifdef BCM_HURRICANE3_SUPPORT 5617 if ((rv = _lpm_hr3_urpf_entry_replicate(u, to_ent, ef)) < 0) { 5618 return rv; 5619 } 5620 #endif /* BCM_HURRICANE3_SUPPORT */ 5621 } 5622 5623 sal_memcpy(ef, soc_mem_entry_null(u, L3_DEFIPm), 5624 soc_mem_entry_words(u,L3_DEFIPm) * 4); 5625 HU2_LPM_HASH_INSERT(u, ef, from_ent); 5626 if ((rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, ef)) < 0) { 5627 return rv; 5628 } 5629 #ifdef BCM_HURRICANE3_SUPPORT 5630 if ((rv = _lpm_hr3_urpf_entry_replicate(u, from_ent, ef)) < 0) { 5631 return rv; 5632 } 5633 #endif /* BCM_HURRICANE3_SUPPORT */ 5634 5635 if (SOC_HU2_LPM_STATE_VENT(u, pfx) == 0) { 5636 /* remove from the list */ 5637 prev_pfx = SOC_HU2_LPM_STATE_PREV(u, pfx); /* Always present */ 5638 assert(prev_pfx != -1); 5639 next_pfx = SOC_HU2_LPM_STATE_NEXT(u, pfx); 5640 SOC_HU2_LPM_STATE_NEXT(u, prev_pfx) = next_pfx; 5641 SOC_HU2_LPM_STATE_FENT(u, prev_pfx) += SOC_HU2_LPM_STATE_FENT(u, pfx); 5642 SOC_HU2_LPM_STATE_FENT(u, pfx) = 0; 5643 if (next_pfx != -1) { 5644 SOC_HU2_LPM_STATE_PREV(u, next_pfx) = prev_pfx; 5645 } 5646 SOC_HU2_LPM_STATE_NEXT(u, pfx) = -1; 5647 SOC_HU2_LPM_STATE_PREV(u, pfx) = -1; 5648 SOC_HU2_LPM_STATE_START(u, pfx) = -1; 5649 SOC_HU2_LPM_STATE_END(u, pfx) = -1; 5650 } 5651 5652 return(rv); 5653 } 5654 5655 5656 5657 /* 5658 * soc_hu2_lpm_prefix_length_get (Extract vrf weighted prefix lenght from the 5659 * hw entry based on ip, mask & vrf) 5660 */ 5661 static int 5662 soc_hu2_lpm_prefix_length_get(int u, void *entry, int *pfx_len) 5663 { 5664 int pfx; 5665 int rv; 5666 int ipv6; 5667 uint32 ipv4a; 5668 int vrf_id, vrf_type; 5669 5670 5671 5672 ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, MODEf); 5673 5674 if (ipv6) { 5675 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_L_MASKf); 5676 if ((rv = _ip_mask2pfx(ipv4a, &pfx)) < 0) { 5677 return(rv); 5678 } 5679 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_U_MASKf); 5680 if (pfx) { 5681 if (ipv4a != 0xffffffff) { 5682 return(SOC_E_PARAM); 5683 } 5684 pfx += 32; 5685 } else { 5686 if ((rv = _ip_mask2pfx(ipv4a, &pfx)) < 0) { 5687 return(rv); 5688 } 5689 } 5690 pfx += IPV6_PFX_ZERO; /* First 33 are for IPV4 addresses */ 5691 } else { 5692 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_L_MASKf); 5693 if ((rv = _ip_mask2pfx(ipv4a, &pfx)) < 0) { 5694 return(rv); 5695 } 5696 } 5697 5698 if (soc_mem_field_valid(u,L3_DEFIPm, VRF_IDf)) { 5699 uint32 vrf_mask_val = 0; 5700 vrf_id = soc_L3_DEFIPm_field32_get(u, (uint32 *)entry, VRF_IDf); 5701 vrf_mask_val = soc_L3_DEFIPm_field32_get(u, (uint32 *)entry, VRF_ID_MASKf); 5702 if (vrf_mask_val) { 5703 vrf_type = vrf_id; 5704 } else if (SOC_VRF_MAX(u) == vrf_id) { 5705 vrf_type = SOC_L3_VRF_GLOBAL; 5706 } else { 5707 vrf_type = SOC_L3_VRF_OVERRIDE; 5708 if (soc_mem_field_valid(u, L3_DEFIPm, GLOBAL_ROUTE0f)) { 5709 if (soc_L3_DEFIPm_field32_get(u, (uint32 *)entry, GLOBAL_ROUTE0f)) { 5710 vrf_type = SOC_L3_VRF_GLOBAL; 5711 } 5712 } 5713 } 5714 } else { 5715 /* No vrf support on this device. */ 5716 vrf_type = SOC_L3_VRF_DEFAULT; 5717 } 5718 5719 switch (vrf_type) { 5720 case SOC_L3_VRF_GLOBAL: 5721 *pfx_len = pfx; 5722 break; 5723 case SOC_L3_VRF_OVERRIDE: 5724 *pfx_len = pfx + 2 * (MAX_PFX_ENTRIES(u) / 6); 5725 break; 5726 default: 5727 *pfx_len = pfx + (MAX_PFX_ENTRIES(u) / 6); 5728 break; 5729 } 5730 5731 return (SOC_E_NONE); 5732 } 5733 5734 /* 5735 * _soc_hu2_lpm_match (Exact match for the key. Will match both IP address 5736 * and mask) 5737 */ 5738 static 5739 int 5740 _soc_hu2_lpm_match(int u, 5741 void *key_data, 5742 void *e, /* return entry data if found */ 5743 int *index_ptr, /* return key location */ 5744 int *pfx_len) /* Key prefix length */ 5745 { 5746 int pfx = 0; 5747 5748 /* Calculate vrf weighted prefix lengh. */ 5749 soc_hu2_lpm_prefix_length_get(u, key_data, &pfx); 5750 *pfx_len = pfx; 5751 5752 #if defined(HU2_LPM_HASH_SUPPORT) 5753 { 5754 int rv; 5755 int key_index = 0; 5756 if (HU2_LPM_HASH_LOOKUP(u, key_data, pfx, &key_index) == SOC_E_NONE) { 5757 *index_ptr = key_index; 5758 if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY,*index_ptr, e)) < 0) { 5759 return rv; 5760 } 5761 return(SOC_E_NONE); 5762 } else { 5763 return(SOC_E_NOT_FOUND); 5764 } 5765 } 5766 #endif 5767 } 5768 5769 5770 /* 5771 * Initialize the start/end tracking pointers for each prefix length 5772 */ 5773 int 5774 soc_hu2_lpm_init(int u) 5775 { 5776 int max_pfx_len; 5777 int defip_table_size; 5778 int pfx_state_size; 5779 int i; 5780 5781 if (! soc_feature(u, soc_feature_lpm_tcam)) { 5782 return(SOC_E_UNAVAIL); 5783 } 5784 5785 max_pfx_len = MAX_PFX_ENTRIES(u); 5786 pfx_state_size = sizeof(soc_hu2_lpm_state_t) * (max_pfx_len); 5787 5788 if (!SOC_HU2_LPM_INIT_CHECK(u)) { 5789 soc_hu2_lpm_field_cache_state[u] = 5790 sal_alloc(sizeof(soc_hu2_lpm_field_cache_t), "lpm_field_state"); 5791 if (NULL == soc_hu2_lpm_field_cache_state[u]) { 5792 return (SOC_E_MEMORY); 5793 } 5794 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5795 L3_DEFIPm, HITf); 5796 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5797 L3_DEFIPm, GLOBAL_ROUTE0f); 5798 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5799 L3_DEFIPm, CLASS_ID0f); 5800 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5801 L3_DEFIPm, DST_DISCARD0f); 5802 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5803 L3_DEFIPm, SRC_DISCARD0f); 5804 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5805 L3_DEFIPm, RPE0f); 5806 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5807 L3_DEFIPm, PRI0f); 5808 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5809 L3_DEFIPm, DEFAULTROUTE0f); 5810 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5811 L3_DEFIPm, ECMP_UNUSED0f); 5812 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5813 L3_DEFIPm, ECMP_PTR0f); 5814 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5815 L3_DEFIPm, UPPER_NEXT_HOP_INDEX0f); 5816 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5817 L3_DEFIPm, NEXT_HOP_INDEX0f); 5818 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5819 L3_DEFIPm, ECMP0f); 5820 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5821 L3_DEFIPm, MASKf); 5822 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5823 L3_DEFIPm, IP_ADDR_U_MASKf); 5824 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5825 L3_DEFIPm, IP_ADDR_L_MASKf); 5826 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5827 L3_DEFIPm, MODE_MASKf); 5828 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5829 L3_DEFIPm, IP_ADDR_Uf); 5830 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5831 L3_DEFIPm, IP_ADDR_Lf); 5832 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5833 L3_DEFIPm, MODEf); 5834 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5835 L3_DEFIPm, VALIDf); 5836 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5837 L3_DEFIPm, VRF_IDf); 5838 SOC_HU2_LPM_CACHE_FIELD_ASSIGN(u, soc_hu2_lpm_field_cache_state[u], 5839 L3_DEFIPm, VRF_ID_MASKf); 5840 SOC_HU2_LPM_STATE(u) = sal_alloc(pfx_state_size, "HU2_LPM prefix info"); 5841 if (NULL == SOC_HU2_LPM_STATE(u)) { 5842 sal_free(soc_hu2_lpm_field_cache_state[u]); 5843 soc_hu2_lpm_field_cache_state[u] = NULL; 5844 return (SOC_E_MEMORY); 5845 } 5846 } 5847 5848 #ifdef HU2_LPM_TABLE_CACHED 5849 SOC_IF_ERROR_RETURN (soc_mem_cache_set(u, L3_DEFIPm, MEM_BLOCK_ALL, TRUE)); 5850 #endif /* HU2_LPM_TABLE_CACHED */ 5851 SOC_HU2_LPM_LOCK(u); 5852 5853 sal_memset(SOC_HU2_LPM_STATE(u), 0, pfx_state_size); 5854 for(i = 0; i < max_pfx_len; i++) { 5855 SOC_HU2_LPM_STATE_START(u, i) = -1; 5856 SOC_HU2_LPM_STATE_END(u, i) = -1; 5857 SOC_HU2_LPM_STATE_PREV(u, i) = -1; 5858 SOC_HU2_LPM_STATE_NEXT(u, i) = -1; 5859 SOC_HU2_LPM_STATE_VENT(u, i) = 0; 5860 SOC_HU2_LPM_STATE_FENT(u, i) = 0; 5861 } 5862 5863 defip_table_size = soc_mem_index_count(u, L3_DEFIPm); 5864 #ifdef BCM_HURRICANE3_SUPPORT 5865 if (SOC_IS_HURRICANE3(u) || SOC_IS_GREYHOUND2(u)) { 5866 if (SOC_URPF_STATUS_GET(u)) { 5867 defip_table_size >>= 1; 5868 } 5869 } 5870 #endif /* BCM_HURRICANE3_SUPPORT */ 5871 5872 SOC_HU2_LPM_STATE_FENT(u, (MAX_PFX_INDEX(u))) = defip_table_size; 5873 5874 #ifdef HU2_LPM_HASH_SUPPORT 5875 if (SOC_HU2_LPM_STATE_HASH(u) != NULL) { 5876 if (soc_hu2_lpm_hash_destroy(SOC_HU2_LPM_STATE_HASH(u)) < 0) { 5877 SOC_HU2_LPM_UNLOCK(u); 5878 return SOC_E_INTERNAL; 5879 } 5880 SOC_HU2_LPM_STATE_HASH(u) = NULL; 5881 } 5882 5883 if (soc_hu2_lpm_hash_create(u, defip_table_size, defip_table_size, 5884 &SOC_HU2_LPM_STATE_HASH(u)) < 0) { 5885 SOC_HU2_LPM_UNLOCK(u); 5886 return SOC_E_MEMORY; 5887 } 5888 #endif 5889 5890 SOC_HU2_LPM_UNLOCK(u); 5891 5892 return(SOC_E_NONE); 5893 } 5894 /* 5895 * De-initialize the start/end tracking pointers for each prefix length 5896 */ 5897 int 5898 soc_hu2_lpm_deinit(int u) 5899 { 5900 if (!soc_feature(u, soc_feature_lpm_tcam)) { 5901 return(SOC_E_UNAVAIL); 5902 } 5903 5904 SOC_HU2_LPM_LOCK(u); 5905 5906 #ifdef HU2_LPM_HASH_SUPPORT 5907 if (SOC_HU2_LPM_STATE_HASH(u) != NULL) { 5908 soc_hu2_lpm_hash_destroy(SOC_HU2_LPM_STATE_HASH(u)); 5909 SOC_HU2_LPM_STATE_HASH(u) = NULL; 5910 } 5911 #endif 5912 5913 if (SOC_HU2_LPM_INIT_CHECK(u)) { 5914 sal_free(soc_hu2_lpm_field_cache_state[u]); 5915 soc_hu2_lpm_field_cache_state[u] = NULL; 5916 sal_free(SOC_HU2_LPM_STATE(u)); 5917 SOC_HU2_LPM_STATE(u) = NULL; 5918 } 5919 5920 SOC_HU2_LPM_UNLOCK(u); 5921 5922 return(SOC_E_NONE); 5923 } 5924 5925 #ifdef BCM_WARM_BOOT_SUPPORT 5926 int 5927 soc_hu2_lpm_reinit_done(int unit) 5928 { 5929 int idx; 5930 int prev_idx = MAX_PFX_INDEX(unit); 5931 5932 5933 int defip_table_size = soc_mem_index_count(unit, L3_DEFIPm); 5934 5935 SOC_HU2_LPM_STATE_PREV(unit, MAX_PFX_INDEX(unit)) = -1; 5936 5937 for (idx = MAX_PFX_INDEX(unit); idx > 0 ; idx--) { 5938 if (-1 == SOC_HU2_LPM_STATE_START(unit, idx)) { 5939 continue; 5940 } 5941 5942 SOC_HU2_LPM_STATE_PREV(unit, idx) = prev_idx; 5943 SOC_HU2_LPM_STATE_NEXT(unit, prev_idx) = idx; 5944 5945 SOC_HU2_LPM_STATE_FENT(unit, prev_idx) = \ 5946 SOC_HU2_LPM_STATE_START(unit, idx) - \ 5947 SOC_HU2_LPM_STATE_END(unit, prev_idx) - 1; 5948 prev_idx = idx; 5949 5950 } 5951 5952 SOC_HU2_LPM_STATE_NEXT(unit, prev_idx) = -1; 5953 SOC_HU2_LPM_STATE_FENT(unit, prev_idx) = \ 5954 defip_table_size - \ 5955 SOC_HU2_LPM_STATE_END(unit, prev_idx) - 1; 5956 5957 return (SOC_E_NONE); 5958 } 5959 5960 int 5961 soc_hu2_lpm_reinit(int unit, int idx, uint32 *lpm_entry) 5962 { 5963 int pfx_len; 5964 5965 5966 SOC_IF_ERROR_RETURN 5967 (soc_hu2_lpm_prefix_length_get(unit, lpm_entry, &pfx_len)); 5968 5969 if (SOC_HU2_LPM_STATE_VENT(unit, pfx_len) == 0) { 5970 SOC_HU2_LPM_STATE_START(unit, pfx_len) = idx; 5971 SOC_HU2_LPM_STATE_END(unit, pfx_len) = idx; 5972 } else { 5973 SOC_HU2_LPM_STATE_END(unit, pfx_len) = idx; 5974 } 5975 5976 SOC_HU2_LPM_STATE_VENT(unit, pfx_len)++; 5977 HU2_LPM_HASH_INSERT(unit, lpm_entry, idx); 5978 5979 return (SOC_E_NONE); 5980 } 5981 #endif /* BCM_WARM_BOOT_SUPPORT */ 5982 5983 5984 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 5985 /* 5986 * Function: 5987 * soc_hu2_lpm_sw_dump 5988 * Purpose: 5989 * Displays FB HU2_LPM information maintained by software. 5990 * Parameters: 5991 * unit - Device unit number 5992 * Returns: 5993 * None 5994 */ 5995 void 5996 soc_hu2_lpm_sw_dump(int unit) 5997 { 5998 soc_hu2_lpm_state_p lpm_state; 5999 int i; 6000 6001 LOG_CLI((BSL_META_U(unit, 6002 "\n FB HU2_LPM State -\n"))); 6003 LOG_CLI((BSL_META_U(unit, 6004 " Prefix entries : %d\n"), MAX_PFX_ENTRIES(unit))); 6005 6006 lpm_state = soc_hu2_lpm_state[unit]; 6007 if (lpm_state == NULL) { 6008 return; 6009 } 6010 6011 for (i = 0; i < MAX_PFX_ENTRIES(unit); i++) { 6012 if (lpm_state[i].vent != 0 ) { 6013 LOG_CLI((BSL_META_U(unit, 6014 " Prefix %d\n"), i)); 6015 LOG_CLI((BSL_META_U(unit, 6016 " Start : %d\n"), lpm_state[i].start)); 6017 LOG_CLI((BSL_META_U(unit, 6018 " End : %d\n"), lpm_state[i].end)); 6019 LOG_CLI((BSL_META_U(unit, 6020 " Prev : %d\n"), lpm_state[i].prev)); 6021 LOG_CLI((BSL_META_U(unit, 6022 " Next : %d\n"), lpm_state[i].next)); 6023 LOG_CLI((BSL_META_U(unit, 6024 " Valid Entries : %d\n"), lpm_state[i].vent)); 6025 LOG_CLI((BSL_META_U(unit, 6026 " Free Entries : %d\n"), lpm_state[i].fent)); 6027 } 6028 } 6029 6030 return; 6031 } 6032 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 6033 6034 /* 6035 * Implementation using soc_mem_read/write using entry rippling technique 6036 * Advantage: A completely sorted table is not required. Lookups can be slow 6037 * as it will perform a linear search on the entries for a given prefix length. 6038 * No device access necessary for the search if the table is cached. Auxiliary 6039 * hash table can be maintained to speed up search(Not implemented) instead of 6040 * performing a linear search. 6041 * Small number of entries need to be moved around (97 worst case) 6042 * for performing insert/update/delete. However CPU needs to do all 6043 * the work to move the entries. 6044 */ 6045 6046 /* 6047 * soc_hu2_lpm_insert 6048 * For IPV4 assume only both IP_ADDR0 is valid 6049 * Moving multiple entries around in h/w vs doing a linear search in s/w 6050 */ 6051 int 6052 soc_hu2_lpm_insert(int u, void *entry_data) 6053 { 6054 int pfx; 6055 int index; 6056 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 6057 int rv = SOC_E_NONE; 6058 int found = 0; 6059 6060 sal_memcpy(e, soc_mem_entry_null(u, L3_DEFIPm), 6061 soc_mem_entry_words(u,L3_DEFIPm) * 4); 6062 6063 SOC_HU2_LPM_LOCK(u); 6064 rv = _soc_hu2_lpm_match(u, entry_data, e, &index, &pfx); 6065 if (rv == SOC_E_NOT_FOUND) { 6066 rv = _lpm_hu2_free_slot_create(u, pfx, e, &index); 6067 if (rv < 0) { 6068 SOC_HU2_LPM_UNLOCK(u); 6069 return(rv); 6070 } 6071 } else { 6072 found = 1; 6073 } 6074 6075 if (rv == SOC_E_NONE) { 6076 /* Entry already present. Update the entry */ 6077 soc_hu2_lpm_state_dump(u); 6078 LOG_INFO(BSL_LS_SOC_SOCMEM, 6079 (BSL_META_U(u, 6080 "\nsoc_hu2_lpm_insert: %d %d\n"), 6081 index, pfx)); 6082 if (!found) { 6083 HU2_LPM_HASH_INSERT(u, entry_data, index); 6084 } 6085 rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, index, entry_data); 6086 #ifdef BCM_HURRICANE3_SUPPORT 6087 if (rv >= 0 && soc_feature(u, soc_feature_urpf)) { 6088 rv = _lpm_hr3_urpf_entry_replicate(u, index, entry_data); 6089 } 6090 #endif /* BCM_HURRICANE3_SUPPORT */ 6091 } 6092 6093 SOC_HU2_LPM_UNLOCK(u); 6094 6095 return(rv); 6096 } 6097 6098 /* 6099 * soc_hu2_lpm_delete 6100 */ 6101 int 6102 soc_hu2_lpm_delete(int u, void *key_data) 6103 { 6104 int pfx; 6105 int index; 6106 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 6107 int rv = SOC_E_NONE; 6108 6109 SOC_HU2_LPM_LOCK(u); 6110 rv = _soc_hu2_lpm_match(u, key_data, e, &index, &pfx); 6111 if (rv == SOC_E_NONE) { 6112 LOG_INFO(BSL_LS_SOC_SOCMEM, 6113 (BSL_META_U(u, 6114 "\nsoc_hu2_lpm_delete: %d %d\n"), 6115 index, pfx)); 6116 HU2_LPM_HASH_DELETE(u, key_data, index); 6117 rv = _lpm_hu2_free_slot_delete(u, pfx, e, index); 6118 } 6119 soc_hu2_lpm_state_dump(u); 6120 SOC_HU2_LPM_UNLOCK(u); 6121 return(rv); 6122 } 6123 6124 /* 6125 * soc_hu2_lpm_match (Exact match for the key. Will match both IP 6126 * address and mask) 6127 */ 6128 int 6129 soc_hu2_lpm_match(int u, 6130 void *key_data, 6131 void *e, /* return entry data if found */ 6132 int *index_ptr) /* return key location */ 6133 { 6134 int pfx; 6135 int rv; 6136 6137 SOC_HU2_LPM_LOCK(u); 6138 rv = _soc_hu2_lpm_match(u, key_data, e, index_ptr, &pfx); 6139 SOC_HU2_LPM_UNLOCK(u); 6140 return(rv); 6141 } 6142 6143 #endif 6144 6145 static const soc_reg_t pvtmon_result_reg[] = { 6146 TOP_PVTMON_RESULT_0r 6147 }; 6148 6149 int 6150 soc_hu2_temperature_monitor_get(int unit, 6151 int temperature_max, 6152 soc_switch_temperature_monitor_t *temperature_array, 6153 int *temperature_count) 6154 { 6155 soc_reg_t reg; 6156 int index; 6157 uint32 rval; 6158 int fval, cur, peak; 6159 int num_entries_out; 6160 6161 *temperature_count = 0; 6162 if (COUNTOF(pvtmon_result_reg) > temperature_max) { 6163 num_entries_out = temperature_max; 6164 } else { 6165 num_entries_out = COUNTOF(pvtmon_result_reg); 6166 } 6167 6168 for (index = 0; index < num_entries_out; index++) { 6169 reg = pvtmon_result_reg[index]; 6170 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 6171 6172 fval = soc_reg_field_get(unit, reg, rval, TEMP_DATAf); 6173 cur = (4180000 - (5556 * fval)) / 1000; 6174 fval = soc_reg_field_get(unit, reg, rval, PEAK_TEMP_DATAf); 6175 peak = (4180000 - (5556 * fval)) / 1000; 6176 (temperature_array + index)->curr = cur; 6177 (temperature_array + index)->peak = peak; 6178 } 6179 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 6180 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 6181 TOP_TEMP_MON_PEAK_RST_Lf, 0); 6182 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 6183 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 6184 TOP_TEMP_MON_PEAK_RST_Lf, 1); 6185 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 6186 6187 *temperature_count=num_entries_out; 6188 return SOC_E_NONE; 6189 } 6190 6191 6192 int 6193 soc_hu2_show_ring_osc(int unit) 6194 { 6195 static const struct { 6196 int osc_sel; 6197 soc_field_t field0; 6198 int value0; 6199 soc_field_t field1; 6200 int value1; 6201 char *name; 6202 } osc_tbl[] = { 6203 { 0, OSC_0_SELf, 0, INVALIDf, -1, "IO ring 0 HVT min" }, 6204 { 0, OSC_0_SELf, 1, INVALIDf, -1, "IO ring 0 HVT mid" }, 6205 { 0, OSC_0_SELf, 2, INVALIDf, -1, "IO ring 0 HVT max" }, 6206 { 0, OSC_0_SELf, 3, INVALIDf, -1, "IO ring 0 SVT min" }, 6207 { 1, OSC_1_SELf, 0, INVALIDf, -1, "IO ring 1 HVT min" }, 6208 { 1, OSC_1_SELf, 1, INVALIDf, -1, "IO ring 1 HVT mid" }, 6209 { 1, OSC_1_SELf, 2, INVALIDf, -1, "IO ring 1 HVT max" }, 6210 { 1, OSC_1_SELf, 3, INVALIDf, -1, "IO ring 1 SVT min" }, 6211 { 2, IROSC_SELf, 0, INVALIDf, -1, "Core ring 0 five stages" }, 6212 { 2, IROSC_SELf, 1, INVALIDf, -1, "Core ring 0 nine stages" }, 6213 { 3, IROSC_SELf, 0, INVALIDf, -1, "Core ring 1 five stages" }, 6214 { 3, IROSC_SELf, 1, INVALIDf, -1, "Core ring 1 nine stages" }, 6215 { 4, SRAM_OSC_0_PENf, 0, SRAM_OSC_0_NENf, 1, "SRAM ring 0 NMOS" }, 6216 { 5, SRAM_OSC_0_PENf, 1, SRAM_OSC_0_NENf, 0, "SRAM ring 0 PMOS" }, 6217 { 6, SRAM_OSC_1_PENf, 0, SRAM_OSC_1_NENf, 1, "SRAM ring 1 NMOS" }, 6218 { 7, SRAM_OSC_1_PENf, 1, SRAM_OSC_1_NENf, 0, "SRAM ring 1 PMOS" }, 6219 { 8, SRAM_OSC_2_PENf, 0, SRAM_OSC_2_NENf, 1, "SRAM ring 2 NMOS" }, 6220 { 9, SRAM_OSC_2_PENf, 1, SRAM_OSC_2_NENf, 0, "SRAM ring 2 PMOS" }, 6221 { 10, SRAM_OSC_3_PENf, 0, SRAM_OSC_3_NENf, 1, "SRAM ring 3 NMOS" }, 6222 { 11, SRAM_OSC_3_PENf, 1, SRAM_OSC_3_NENf, 0, "SRAM ring 3 PMOS" }, 6223 { 12, SRAM_OSC_4_PENf, 0, SRAM_OSC_4_NENf, 1, "SRAM ring 4 NMOS" }, 6224 { 13, SRAM_OSC_4_PENf, 1, SRAM_OSC_4_NENf, 0, "SRAM ring 4 PMOS" }, 6225 { 14, SRAM_OSC_5_PENf, 0, SRAM_OSC_5_NENf, 1, "SRAM ring 5 NMOS" }, 6226 { 15, SRAM_OSC_5_PENf, 1, SRAM_OSC_5_NENf, 0, "SRAM ring 5 PMOS" }, 6227 }; 6228 uint32 rval, fval; 6229 int index, core_clk, quo, rem, frac, retry; 6230 6231 core_clk = 133 * 1024; 6232 6233 for (index = 0; index < COUNTOF(osc_tbl); index++) { 6234 rval = 0; 6235 /* 6236 * set OSC_CNT_RSTBf to 0 to do softreset 6237 * set OSC_CNT_START to 0 to hold the counter until it selects 6238 * the input signal 6239 */ 6240 SOC_IF_ERROR_RETURN(READ_TOP_RING_OSC_CTRLr(unit, &rval)); 6241 soc_reg_field_set(unit, TOP_RING_OSC_CTRLr, &rval, OSC_ENABLEf, 1); 6242 soc_reg_field_set(unit, TOP_RING_OSC_CTRLr, &rval, IROSC_ENf, 1); 6243 soc_reg_field_set(unit, TOP_RING_OSC_CTRLr, &rval, osc_tbl[index].field0, 6244 osc_tbl[index].value0); 6245 if (osc_tbl[index].field1 != INVALIDf) { 6246 soc_reg_field_set(unit, TOP_RING_OSC_CTRLr, &rval, osc_tbl[index].field1, 6247 osc_tbl[index].value1); 6248 } 6249 soc_reg_field_set(unit, TOP_RING_OSC_CTRLr, &rval, OSC_SELf, 6250 osc_tbl[index].osc_sel); 6251 SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval)); 6252 soc_reg_field_set(unit, TOP_RING_OSC_CTRLr, &rval, OSC_CNT_RSTBf, 1); 6253 SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval)); 6254 soc_reg_field_set(unit, TOP_RING_OSC_CTRLr, &rval, OSC_CNT_STARTf, 1); 6255 SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval)); 6256 6257 for (retry = 0; retry < 10; retry++) { 6258 sal_usleep(1000); 6259 SOC_IF_ERROR_RETURN(READ_TOP_OSC_COUNT_STATr(unit, &rval)); 6260 if (!soc_reg_field_get(unit, TOP_OSC_COUNT_STATr, rval, OSC_CNT_DONEf)) { 6261 continue; 6262 } 6263 6264 fval = soc_reg_field_get(unit, TOP_OSC_COUNT_STATr, rval, OSC_CNT_VALUEf); 6265 quo = core_clk / fval; 6266 rem = core_clk - quo * fval; 6267 frac = (rem * 10000) / fval; 6268 LOG_CLI((BSL_META_U(unit, 6269 "%s: %d.%04d Mhz\n"), 6270 osc_tbl[index].name, quo, frac)); 6271 break; 6272 } 6273 6274 SOC_IF_ERROR_RETURN(READ_TOP_RING_OSC_CTRLr(unit, &rval)); 6275 soc_reg_field_set(unit, TOP_RING_OSC_CTRLr, &rval, OSC_CNT_STARTf, 0); 6276 /* Clearing theStart bit Clears the Counter */ 6277 SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval)); 6278 6279 } 6280 6281 return SOC_E_NONE; 6282 } 6283 6284 6285 int 6286 soc_hu2_show_material_process(int unit) 6287 { 6288 soc_reg_t reg; 6289 int index; 6290 uint32 rval, fval, nmos[COUNTOF(pvtmon_result_reg)], n_avg, p_avg; 6291 6292 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_1r(unit, &rval)); 6293 soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_RESET_Nf, 0); 6294 WRITE_TOP_PVTMON_CTRL_1r(unit, rval); 6295 sal_usleep(1000); 6296 soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_RESET_Nf, 1); 6297 WRITE_TOP_PVTMON_CTRL_1r(unit, rval); 6298 sal_usleep(1000); 6299 6300 SOC_IF_ERROR_RETURN 6301 (soc_reg_field32_modify(unit, TOP_PVTMON_CTRL_1r, REG_PORT_ANY, 6302 PVTMON_SELECTf, 1)); 6303 sal_usleep(1000); 6304 6305 p_avg = 0; 6306 6307 /* Read NMOS information */ 6308 SOC_IF_ERROR_RETURN 6309 (soc_reg_field32_modify(unit, TOP_PVTMON_CTRL_0r, REG_PORT_ANY, 6310 MEASUREMENT_CALLIBRATIONf, 5)); 6311 6312 sal_usleep(1000); 6313 6314 n_avg = 0; 6315 for (index = 0; index < COUNTOF(pvtmon_result_reg); index++) { 6316 reg = pvtmon_result_reg[index]; 6317 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 6318 nmos[index] = soc_reg_field_get(unit, reg, rval, TEMP_DATAf); 6319 n_avg += nmos[index]; 6320 } 6321 6322 /* Read PMOS information and print both NMOS and PMOS value */ 6323 SOC_IF_ERROR_RETURN 6324 (soc_reg_field32_modify(unit, TOP_PVTMON_CTRL_0r, REG_PORT_ANY, 6325 MEASUREMENT_CALLIBRATIONf, 7)); 6326 6327 sal_usleep(1000); 6328 6329 p_avg = 0; 6330 for (index = 0; index < COUNTOF(pvtmon_result_reg); index++) { 6331 reg = pvtmon_result_reg[index]; 6332 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 6333 fval = soc_reg_field_get(unit, reg, rval, TEMP_DATAf); 6334 p_avg += fval; 6335 6336 LOG_CLI((BSL_META_U(unit, 6337 "Material process location %d: NMOS = %3d PMOS = %3d\n"), 6338 index, nmos[index], fval)); 6339 } 6340 6341 LOG_CLI((BSL_META_U(unit, 6342 "Average: NMOS = %3d PMOS = %3d\n"), 6343 n_avg / COUNTOF(pvtmon_result_reg), 6344 p_avg / COUNTOF(pvtmon_result_reg))); 6345 6346 return SOC_E_NONE; 6347 } 6348 6349 6350 #if defined(SER_TR_TEST_SUPPORT) 6351 /* 6352 * Function: 6353 * soc_hu2_ser_mem_test 6354 * Purpose: 6355 * Performs a SER test on a single Hurricane2 memory 6356 * Parameters: 6357 * unit - (IN) Device Number 6358 * mem - (IN) The memory to test 6359 * test_type - (IN) How many indices in the memory to test 6360 */ 6361 int soc_hu2_ser_mem_test(int unit, soc_mem_t mem, 6362 _soc_ser_test_t test_type, int cmd) { 6363 int group, table, i, rv; 6364 _soc_parity_info_t *info; 6365 soc_mem_t memTable; 6366 soc_port_t block_port; 6367 soc_block_t blk; 6368 int testErrors = 0; 6369 /*Prevent compiler error for common function signature.*/ 6370 (void) cmd; 6371 /*TCAM_test*/ 6372 for (i = 0; _soc_hu2_tcam_ser_info[i].mem != INVALIDm; i++) { 6373 if (_soc_hu2_tcam_ser_info[i].mem == mem) { 6374 6375 /* coverity[negative_returns : FALSE] */ 6376 rv = ser_test_mem_pipe(unit, SER_RANGE_ENABLEr, 6377 i, -1, _soc_hu2_tcam_ser_info[i].mem, VALIDf, 6378 test_type, MEM_BLOCK_ANY, 6379 REG_PORT_ANY, _SOC_ACC_TYPE_PIPE_ANY, &testErrors); 6380 if (rv != SOC_E_NONE) { 6381 LOG_CLI((BSL_META_U(unit, 6382 "Error during TCAM test. Aborting.\n"))); 6383 return rv; 6384 } 6385 } 6386 } 6387 /*H/W memory Test*/ 6388 for (group = 0; _soc_hu2_parity_group_info[group].cpi_bit; group++) { 6389 info = _soc_hu2_parity_group_info[group].info; 6390 6391 SOC_BLOCK_ITER(unit, blk, 6392 _soc_hu2_parity_group_info[group].blocktype) { 6393 if (_soc_hurricane2_parity_block_port(unit, blk, &block_port) < 0) { 6394 continue; 6395 } 6396 6397 for (table = 0; info[table].error_field != INVALIDf; table++) { 6398 memTable = info[table].mem; 6399 if (memTable == INVALIDm) { 6400 continue; 6401 } 6402 if (memTable == mem) { 6403 if (_soc_hu2_parity_group_info[group].blocktype 6404 == SOC_BLK_MMU) { 6405 if ((mem == MMU_IPMC_VLAN_TBLm) || 6406 (mem == MMU_IPMC_GROUP_TBL0m) || 6407 (mem == MMU_IPMC_GROUP_TBL1m)) { 6408 /* The parity value is generated by software */ 6409 continue; 6410 } 6411 rv = ser_test_mem_pipe(unit, MISCCONFIGr, -1, 6412 PARITY_CHECK_ENf, 6413 mem, INVALIDf, test_type, blk, block_port, 6414 _SOC_ACC_TYPE_PIPE_ANY, &testErrors); 6415 } else { 6416 rv = ser_test_mem_pipe(unit,info[table].control_reg, -1, 6417 info[table].enable_field, 6418 mem, INVALIDf, test_type, blk, block_port, 6419 _SOC_ACC_TYPE_PIPE_ANY, &testErrors); 6420 } 6421 if (rv != SOC_E_NONE) { 6422 LOG_CLI((BSL_META_U(unit, 6423 "Error during H/W test. Aborting.\n"))); 6424 return rv; 6425 } 6426 } 6427 } 6428 6429 } 6430 } 6431 if (testErrors == 0) { 6432 LOG_CLI((BSL_META_U(unit, 6433 "SER Test passed on unit: %d for memory %s\n"), unit, 6434 SOC_MEM_NAME(unit,mem))); 6435 } 6436 else { 6437 LOG_CLI((BSL_META_U(unit, 6438 "SER Test failed on unit: %d for memory %s\n"), unit, 6439 SOC_MEM_NAME(unit,mem))); 6440 return SOC_E_MEMORY; 6441 } 6442 return SOC_E_NONE; 6443 } 6444 6445 /* 6446 * Function: 6447 * soc_hu2_ser_test 6448 * Purpose: 6449 * Performs a SER test on all Hurricane2 Memories 6450 * Parameters: 6451 * unit - (IN) Device Number 6452 * test_type - (IN) Determines how comprehensive of a test to run 6453 */ 6454 int soc_hu2_ser_test(int unit, _soc_ser_test_t test_type) { 6455 int i, group, rv, table; 6456 _soc_parity_info_t *info; 6457 soc_port_t block_port; 6458 soc_mem_t memTable; 6459 soc_block_t blk; 6460 int numTCAMErr = 0; 6461 int numHwMemErr = 0; 6462 6463 /*Test each TCAM memory*/ 6464 for (i = 0; _soc_hu2_tcam_ser_info[i].mem != INVALIDm; i++) { 6465 rv = ser_test_mem_pipe(unit, SER_RANGE_ENABLEr, i, -1, 6466 _soc_hu2_tcam_ser_info[i].mem, VALIDf, test_type, 6467 MEM_BLOCK_ANY, REG_PORT_ANY, 6468 _SOC_ACC_TYPE_PIPE_ANY, &numTCAMErr); 6469 if (rv != SOC_E_NONE) { 6470 LOG_CLI((BSL_META_U(unit, 6471 "Error during TCAM test. Aborting.\n"))); 6472 return rv; 6473 } 6474 } 6475 /*H/W memory Test*/ 6476 for (group = 0; _soc_hu2_parity_group_info[group].cpi_bit; group++) { 6477 info = _soc_hu2_parity_group_info[group].info; 6478 6479 SOC_BLOCK_ITER(unit, blk, 6480 _soc_hu2_parity_group_info[group].blocktype) { 6481 if (_soc_hurricane2_parity_block_port(unit, blk, &block_port) < 0) { 6482 continue; 6483 } 6484 6485 for (table = 0; info[table].error_field != INVALIDf; table++) { 6486 memTable = info[table].mem; 6487 if (memTable == INVALIDm) { 6488 continue; 6489 } 6490 if (_soc_hu2_parity_group_info[group].blocktype == 6491 SOC_BLK_MMU) { 6492 if ((memTable == MMU_IPMC_VLAN_TBLm) || 6493 (memTable == MMU_IPMC_GROUP_TBL0m) || 6494 (memTable == MMU_IPMC_GROUP_TBL1m)) { 6495 /* The parity value is generated by software */ 6496 continue; 6497 } 6498 rv = ser_test_mem_pipe(unit,MISCCONFIGr, -1, 6499 PARITY_CHECK_ENf, 6500 info[table].mem, INVALIDf, test_type, 6501 blk, block_port, 6502 _SOC_ACC_TYPE_PIPE_ANY, &numHwMemErr); 6503 } else { 6504 rv = ser_test_mem_pipe(unit,info[table].control_reg, -1, 6505 info[table].enable_field, 6506 info[table].mem, INVALIDf, test_type, 6507 blk, block_port, 6508 _SOC_ACC_TYPE_PIPE_ANY, &numHwMemErr); 6509 } 6510 if (rv != SOC_E_NONE) { 6511 LOG_CLI((BSL_META_U(unit, 6512 "Error during H/W test. Aborting.\n"))); 6513 return rv; 6514 } 6515 } 6516 6517 } 6518 } 6519 6520 LOG_CLI((BSL_META_U(unit, 6521 "Total TCAM errors on unit %d: %d\n"), unit, numTCAMErr)); 6522 LOG_CLI((BSL_META_U(unit, 6523 "Total H/W parity errors on unit %d: %d\n"),unit, numHwMemErr)); 6524 return SOC_E_NONE; 6525 } 6526 6527 STATIC soc_error_t 6528 _ser_hu2_ser_error_injection_support(int unit, soc_mem_t mem, 6529 int pipe_target) 6530 { 6531 6532 int rv = SOC_E_UNAVAIL; 6533 int i = 0, hw_enable_ix = 0, group = 0, table = 0; 6534 uint32 range_enable; 6535 _soc_generic_ser_info_t *tcam_ser_info; 6536 _soc_hu2_parity_group_info_t * gp; 6537 _soc_parity_info_t *info; 6538 soc_port_t block_port; 6539 soc_mem_t memTable; 6540 soc_block_t blk; 6541 6542 LOG_VERBOSE(BSL_LS_SOC_SER, 6543 (BSL_META_U(unit, 6544 "unit %d, mem %s, pipe_target %d\n"), 6545 unit, SOC_MEM_NAME(unit,mem), pipe_target)); 6546 6547 if (!SOC_MEM_IS_VALID(unit, mem)) { 6548 LOG_ERROR(BSL_LS_SOC_COMMON, 6549 (BSL_META_U(unit, 6550 "unit %d, mem %d is INVALID or not valid " 6551 "for this unit !!\n"), 6552 unit, mem)); 6553 return SOC_E_UNAVAIL; 6554 } 6555 6556 tcam_ser_info = _soc_hu2_tcam_ser_info; 6557 6558 /* Search TCAMs */ 6559 if (tcam_ser_info != NULL) { 6560 /* Check if enable */ 6561 SOC_IF_ERROR_RETURN 6562 (READ_SER_RANGE_ENABLEr(unit, &range_enable)); 6563 LOG_DEBUG(BSL_LS_SOC_SER, 6564 (BSL_META_U(unit, 6565 "Search TCAMs: SER_RANGE_ENABLE 0x%X\n"), 6566 range_enable)); 6567 for (i = 0; tcam_ser_info[i].mem != INVALIDm; i++) { 6568 if (tcam_ser_info[i].mem == mem) { 6569 hw_enable_ix = tcam_ser_info[i].ser_hw_index; 6570 LOG_DEBUG(BSL_LS_SOC_SER, 6571 (BSL_META_U(unit, 6572 "SER Range HW Enable index %d\n"), 6573 hw_enable_ix)); 6574 if (((range_enable >> hw_enable_ix) & 0x1) == 0) { 6575 LOG_WARN(BSL_LS_SOC_SER, 6576 (BSL_META_U(unit, 6577 "matched mem but SER detection is disabled\n" 6578 "SER_RANGE_ENABLE 0x%X, SER Range HW index %d\n"), 6579 range_enable,hw_enable_ix)); 6580 return rv; /* matched mem but ser_detection is disabled */ 6581 } 6582 LOG_VERBOSE(BSL_LS_SOC_SER, 6583 (BSL_META_U(unit, 6584 "TCAM found\n"))); 6585 return SOC_E_NONE; /* found */ 6586 } 6587 } 6588 } 6589 6590 /*H/W memory Test*/ 6591 for (group = 0; ; group++) { 6592 gp = &_soc_hu2_parity_group_info[group]; 6593 info = gp->info; 6594 if (gp->cpi_bit == 0) { 6595 /* End of table */ 6596 break; 6597 } 6598 SOC_BLOCK_ITER(unit, blk, gp->blocktype) { 6599 if (_soc_hurricane2_parity_block_port(unit, blk, &block_port) < 0) { 6600 continue; 6601 } 6602 for (table = 0; info[table].error_field != INVALIDf; table++) { 6603 memTable = info[table].mem; 6604 if (memTable == INVALIDm) { 6605 continue; 6606 } 6607 if (gp->blocktype == SOC_BLK_MMU) { 6608 if ((memTable == MMU_IPMC_VLAN_TBLm) || 6609 (memTable == MMU_IPMC_GROUP_TBL0m) || 6610 (memTable == MMU_IPMC_GROUP_TBL1m)) { 6611 /* The parity value is generated by software */ 6612 continue; 6613 } 6614 } 6615 if (memTable == mem) { 6616 LOG_VERBOSE(BSL_LS_SOC_SER, 6617 (BSL_META_U(unit, 6618 "H/W memory found\n"))); 6619 return SOC_E_NONE; /* found */ 6620 } 6621 } 6622 6623 } 6624 } 6625 /* The tested memory is not found in SER enabled list, can't inject error of it */ 6626 return rv; 6627 } 6628 6629 /* 6630 * Function: 6631 * soc_hu2_ser_mem_test 6632 * Purpose: 6633 * Performs a SER test on a single Hurricane2 memory 6634 * Parameters: 6635 * unit - (IN) Device Number 6636 * mem - (IN) The memory to test 6637 * test_type - (IN) How many indices in the memory to test 6638 */ 6639 int soc_hu2_ser_inject_error(int unit, uint32 flags, soc_mem_t mem, 6640 int pipeTarget, int block, int index) { 6641 int group, table, i; 6642 _soc_parity_info_t *info; 6643 soc_mem_t memTable; 6644 soc_port_t block_port; 6645 soc_block_t blk; 6646 ser_test_data_t test_data; 6647 uint32 tmp_entry[SOC_MAX_MEM_WORDS], fieldData[SOC_MAX_REG_FIELD_WORDS]; 6648 test_data.entry_buf = tmp_entry; 6649 test_data.field_buf = fieldData; 6650 /*TCAM_test*/ 6651 for (i = 0; _soc_hu2_tcam_ser_info[i].mem != INVALIDm; i++) { 6652 if (_soc_hu2_tcam_ser_info[i].mem == mem) { 6653 soc_ser_create_test_data(unit, tmp_entry, fieldData, 6654 SER_RANGE_ENABLEr, i, INVALIDf, mem, 6655 INVALIDf, MEM_BLOCK_ANY, REG_PORT_ANY, 6656 _SOC_ACC_TYPE_PIPE_ANY, index, &test_data); 6657 /*Read the memory for successful injection*/ 6658 SOC_IF_ERROR_RETURN(ser_test_mem_read(unit, 0, &test_data)); 6659 /*Disable parity*/ 6660 SOC_IF_ERROR_RETURN(_ser_test_parity_control(unit, &test_data, 0)); 6661 /*Inject error*/ 6662 SOC_IF_ERROR_RETURN(soc_ser_test_inject_full(unit, flags, 6663 &test_data)); 6664 /*Enable parity*/ 6665 SOC_IF_ERROR_RETURN(_ser_test_parity_control(unit, &test_data, 1)); 6666 return SOC_E_NONE; 6667 6668 } 6669 } 6670 /*H/W memory Test*/ 6671 for (group = 0; _soc_hu2_parity_group_info[group].cpi_bit; group++) { 6672 info = _soc_hu2_parity_group_info[group].info; 6673 6674 SOC_BLOCK_ITER(unit, blk, 6675 _soc_hu2_parity_group_info[group].blocktype) { 6676 if (_soc_hurricane2_parity_block_port(unit, blk, &block_port) < 0) { 6677 continue; 6678 } 6679 6680 for (table = 0; info[table].error_field != INVALIDf; table++) { 6681 memTable = info[table].mem; 6682 if (memTable == INVALIDm) { 6683 continue; 6684 } 6685 if (memTable == mem) { 6686 if((blk == block) || (block == MEM_BLOCK_ANY)) 6687 { 6688 /*Inject error*/ 6689 test_data.mem = mem; 6690 test_data.tcam_parity_bit = -1; 6691 if (_soc_hu2_parity_group_info[group].blocktype 6692 == SOC_BLK_MMU) { 6693 if ((mem == MMU_IPMC_VLAN_TBLm) || 6694 (mem == MMU_IPMC_GROUP_TBL0m) || 6695 (mem == MMU_IPMC_GROUP_TBL1m)) { 6696 /* the parity value is generated by software */ 6697 continue; 6698 } 6699 soc_ser_create_test_data(unit, tmp_entry, fieldData, 6700 MISCCONFIGr, 6701 SOC_INVALID_TCAM_PARITY_BIT, 6702 PARITY_CHECK_ENf, 6703 mem, EVEN_PARITYf, blk, 6704 block_port, _SOC_ACC_TYPE_PIPE_ANY, 6705 index, &test_data); 6706 } else { 6707 soc_ser_create_test_data(unit, tmp_entry, fieldData, 6708 info[table].control_reg, 6709 SOC_INVALID_TCAM_PARITY_BIT, 6710 info[table].enable_field, 6711 mem, EVEN_PARITYf, blk, 6712 block_port, _SOC_ACC_TYPE_PIPE_ANY, 6713 index, &test_data); 6714 } 6715 SOC_IF_ERROR_RETURN( 6716 ser_test_mem_read(unit, 0, &test_data)); 6717 /*Disable parity*/ 6718 SOC_IF_ERROR_RETURN( 6719 _ser_test_parity_control(unit, &test_data, 0)); 6720 /*Inject error*/ 6721 SOC_IF_ERROR_RETURN( 6722 soc_ser_test_inject_full(unit, flags, 6723 &test_data)); 6724 /*Enable parity*/ 6725 SOC_IF_ERROR_RETURN( 6726 _ser_test_parity_control(unit, &test_data, 1)); 6727 } 6728 } 6729 } 6730 6731 } 6732 } 6733 return SOC_E_NONE; 6734 } 6735 6736 void 6737 soc_hu2_ser_test_register(int unit) 6738 { 6739 /*Initialize chip-specific functions for SER testing*/ 6740 memset(&ser_hu2_test_fun, 0, sizeof(soc_ser_test_functions_t)); 6741 ser_hu2_test_fun.inject_error_f = &soc_hu2_ser_inject_error; 6742 ser_hu2_test_fun.test_mem = &soc_hu2_ser_mem_test; 6743 ser_hu2_test_fun.test = &soc_hu2_ser_test; 6744 ser_hu2_test_fun.injection_support = &_ser_hu2_ser_error_injection_support; 6745 6746 soc_ser_test_functions_register(unit, &ser_hu2_test_fun); 6747 } 6748 #endif /* SER_TR_TEST_SUPPORT */ 6749 6750 6751 6752 #endif /* BCM_HURRICANE2_SUPPORT */