hurricane.c (104783B)
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: hurricane.c 8 * Purpose: 9 * Requires: 10 */ 11 12 13 #include <sal/core/boot.h> 14 #include <shared/bsl.h> 15 #include <soc/firebolt.h> 16 #include <soc/bradley.h> 17 #include <soc/hurricane.h> 18 #include <soc/drv.h> 19 #include <soc/mem.h> 20 #include <soc/hash.h> 21 #include <soc/lpm.h> 22 #include <soc/error.h> 23 #include <soc/debug.h> 24 #include <soc/er_tcam.h> 25 #include <soc/memtune.h> 26 #include <soc/devids.h> 27 28 #ifdef BCM_HURRICANE_SUPPORT 29 30 /* 31 * Enduro chip driver functions. 32 */ 33 soc_functions_t soc_hurricane_drv_funs = { 34 soc_hurricane_misc_init, 35 soc_hurricane_mmu_init, 36 soc_hurricane_age_timer_get, 37 soc_hurricane_age_timer_max_get, 38 soc_hurricane_age_timer_set, 39 }; 40 41 typedef enum { 42 _SOC_PARITY_INFO_TYPE_GENERIC, 43 _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 44 _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 45 _SOC_PARITY_INFO_TYPE_SINGLE_COUNTER, 46 _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 47 _SOC_PARITY_INFO_TYPE_MMU_PARITY, 48 _SOC_PARITY_INFO_TYPE_MMUIPMC, 49 _SOC_PARITY_INFO_TYPE_MMUWRED, 50 _SOC_PARITY_INFO_TYPE_OAM, /* Not parity, but same interrupt */ 51 _SOC_PARITY_INFO_TYPE_NUM 52 } _soc_parity_info_type_t; 53 54 typedef struct _soc_parity_info_s { 55 soc_field_t enable_field; 56 soc_field_t error_field; 57 char *msg; 58 soc_mem_t mem; 59 _soc_parity_info_type_t type; 60 soc_reg_t control_reg; 61 soc_reg_t intr_status0_reg; 62 soc_reg_t intr_status1_reg; /* Also SBE force for ECC */ 63 soc_reg_t nack_status0_reg; 64 soc_reg_t nack_status1_reg; /* Also DBE force for ECC */ 65 } _soc_parity_info_t; 66 67 /* 68 * _SOC_PARITY_INFO_TYPE_SINGLE_PARITY 69 * PARITY_EN 70 * ENTRY_IDX, MULTIPLE_ERR, PARITY_ERR 71 * 72 * _SOC_PARITY_INFO_TYPE_SINGLE_ECC 73 * ECC_EN 74 * ENTRY_IDX, DOUBLE_BIT_ERR, MULTIPLE_ERR, ECC_ERR 75 * 76 * _SOC_PARITY_INFO_TYPE_SINGLE_COUNTER 77 * PARITY_EN 78 * PORT_IDX, COUNTER_IDX, MULTIPLE_ERR, PARITY_ERR 79 * 80 * _SOC_PARITY_INFO_TYPE_DUAL_PARITY 81 * PARITY_EN 82 * BUCKET_IDX, MULTIPLE_ERR, PARITY_ERR_BM 83 */ 84 85 STATIC _soc_parity_info_t _soc_hu_ip0_parity_info[] = { 86 { PARITY_ENf, VXLT_PAR_ERRf, NULL, 87 VLAN_XLATEm, _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 88 VLAN_XLATE_PARITY_CONTROLr, 89 VLAN_XLATE_PARITY_STATUS_0r, VLAN_XLATE_PARITY_STATUS_1r, 90 INVALIDr, INVALIDr }, 91 /* { PPA_CMD_COMPLETEf }, */ 92 /* { MEM_RESET_COMPLETEf }, */ 93 /* { AGE_CMD_COMPLETEf }, */ 94 { PARITY_ENf, VLAN_SUBNET_DATA_PARITY_ERRf, NULL, 95 VLAN_SUBNET_DATA_ONLYm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 96 VLAN_SUBNET_DATA_PARITY_CONTROLr, 97 VLAN_SUBNET_DATA_PARITY_STATUSr, INVALIDr, 98 INVALIDr, INVALIDr }, 99 { PARITY_ENf, VLAN_PROTOCOL_DATA_PARITY_ERRf, NULL, 100 VLAN_PROTOCOL_DATAm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 101 VLAN_PROTOCOL_DATA_PARITY_CONTROLr, 102 VLAN_PROTOCOL_DATA_PARITY_STATUSr, INVALIDr, 103 INVALIDr, INVALIDr }, 104 { PARITY_ENf, VLAN_PARITY_ERRf, NULL, 105 VLAN_TABm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 106 VLAN_PARITY_CONTROLr, 107 VLAN_PARITY_STATUSr, INVALIDr, 108 INVALIDr, INVALIDr }, 109 { PARITY_ENf, VLAN_STG_PARITY_ERRf, NULL, 110 STG_TABm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 111 VLAN_STG_PARITY_CONTROLr, 112 VLAN_STG_PARITY_STATUSr, INVALIDr, 113 INVALIDr, INVALIDr }, 114 { PARITY_ENf, L3_TUNNEL_RAM_PARITY_ERRf, NULL, 115 L3_TUNNELm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 116 L3_TUNNEL_DATA_ONLY_PARITY_CONTROLr, 117 L3_TUNNEL_DATA_ONLY_PARITY_STATUSr, INVALIDr, 118 INVALIDr, INVALIDr }, 119 { PARITY_ENf, SOURCE_TRUNK_MAP_PARITY_ERRf, NULL, 120 SOURCE_TRUNK_MAP_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 121 SOURCE_TRUNK_MAP_PARITY_CONTROLr, 122 SOURCE_TRUNK_MAP_PARITY_STATUSr, INVALIDr, 123 INVALIDr, INVALIDr }, 124 { PARITY_ENf, VFP_POLICY_PAR_ERRf, NULL, 125 VFP_POLICY_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 126 VFP_POLICY_PARITY_CONTROLr, 127 VFP_POLICY_PARITY_STATUS_INTRr, INVALIDr, 128 INVALIDr, INVALIDr }, 129 { PARITY_ENf, LMEP_PAR_ERRf, NULL, 130 LMEPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 131 LMEP_PARITY_CONTROLr, 132 LMEP_PARITY_STATUSr, INVALIDr, 133 INVALIDr, INVALIDr }, 134 { ECC_ENf, IARB_PKT_ECC_INTRf, "Iarb packet ecc error", 135 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 136 IARB_PKT_ECC_CONTROLr, 137 IARB_PKT_ECC_STATUS_INTRr, INVALIDr, 138 INVALIDr, INVALIDr }, 139 { ECC_ENf, IARB_HDR_ECC_INTRf, "Iarb header ecc error", 140 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 141 IARB_HDR_ECC_CONTROLr, 142 IARB_HDR_ECC_STATUS_INTRr, INVALIDr, 143 INVALIDr, INVALIDr }, 144 { INVALIDf, INVALIDf }, /* table terminator */ 145 }; 146 147 STATIC _soc_parity_info_t _soc_hu_ip1_parity_info[] = { 148 { PARITY_ENf, VFI_PAR_ERRf, NULL, 149 VFIm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 150 VFI_PARITY_CONTROLr, 151 VFI_PARITY_STATUS_INTRr, INVALIDr, 152 VFI_PARITY_STATUS_NACKr, INVALIDr }, 153 { PARITY_ENf, SVP_PAR_ERRf, NULL, 154 SOURCE_VPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 155 SOURCE_VP_PARITY_CONTROLr, 156 SOURCE_VP_PARITY_STATUSr, INVALIDr, 157 SOURCE_VP_PARITY_STATUS_NACKr, INVALIDr }, 158 { PARITY_ENf, L3_IIF_PAR_ERRf, NULL, 159 L3_IIFm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 160 L3_IIF_PARITY_CONTROLr, 161 L3_IIF_PARITY_STATUSr, INVALIDr, 162 L3_IIF_PARITY_STATUS_NACKr, INVALIDr }, 163 { PARITY_ENf, MPLS_ENTRY_PAR_ERRf, NULL, 164 MPLS_ENTRYm, _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 165 MPLS_ENTRY_PARITY_CONTROLr, 166 MPLS_ENTRY_PARITY_STATUS_INTR_0r, MPLS_ENTRY_PARITY_STATUS_INTR_1r, 167 MPLS_ENTRY_PARITY_STATUS_NACK_0r, MPLS_ENTRY_PARITY_STATUS_NACK_1r }, 168 { PARITY_ENf, L2_ENTRY_PAR_ERRf, NULL, 169 L2Xm, _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 170 L2_ENTRY_PARITY_CONTROLr, 171 L2_ENTRY_PARITY_STATUS_0r, L2_ENTRY_PARITY_STATUS_1r, 172 INVALIDr, INVALIDr }, 173 { PARITY_ENf, L2MC_PAR_ERRf, NULL, 174 L2MCm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 175 L2MC_PARITY_CONTROLr, 176 L2MC_PARITY_STATUSr, INVALIDr, 177 INVALIDr, INVALIDr }, 178 { PARITY_ENf, L3_ENTRY_PAR_ERRf, NULL, 179 L3_ENTRY_ONLYm, _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 180 L3_ENTRY_PARITY_CONTROLr, 181 L3_ENTRY_PARITY_STATUS_0r, L3_ENTRY_PARITY_STATUS_1r, 182 INVALIDr, INVALIDr }, 183 { PARITY_ENf, L3_DEFIP_DATA_PAR_ERRf, NULL, 184 L3_DEFIP_DATA_ONLYm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 185 L3_DEFIP_PARITY_CONTROLr, 186 L3_DEFIP_PARITY_STATUSr, INVALIDr 187 INVALIDr, INVALIDr }, 188 { PARITY_ENf, L3MC_PAR_ERRf, NULL, 189 L3_IPMCm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 190 L3MC_PARITY_CONTROLr, 191 L3MC_PARITY_STATUSr, INVALIDr, 192 INVALIDr, INVALIDr }, 193 { PARITY_ENf, MA_STATE_PAR_ERRf, NULL, 194 MA_STATEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 195 MA_STATE_PARITY_CONTROLr, 196 MA_STATE_PARITY_STATUSr, INVALIDr, 197 INVALIDr, INVALIDr }, 198 { PARITY_ENf, RMEP_PAR_ERRf, NULL, 199 RMEPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 200 RMEP_PARITY_CONTROLr, 201 RMEP_PARITY_STATUSr, INVALIDr, 202 INVALIDr, INVALIDr }, 203 { PARITY_ENf, MAID_REDUCTION_PAR_ERRf, NULL, 204 MAID_REDUCTIONm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 205 MAID_REDUCTION_PARITY_CONTROLr, 206 MAID_REDUCTION_PARITY_STATUSr, INVALIDr, 207 INVALIDr, INVALIDr }, 208 { PARITY_ENf, MA_INDEX_PAR_ERRf, NULL, 209 MA_INDEXm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 210 MA_INDEX_PARITY_CONTROLr, 211 MA_INDEX_PARITY_STATUSr, INVALIDr, 212 INVALIDr, INVALIDr }, 213 { PARITY_ENf, PORT_CBL_TABLE_PAR_ERRf, NULL, 214 PORT_CBL_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 215 PORT_CBL_TABLE_PARITY_CONTROLr, 216 PORT_CBL_TABLE_PARITY_STATUSr, INVALIDr, 217 INVALIDr, INVALIDr }, 218 { PARITY_ENf, INITIAL_NHOP_PAR_ERRf, NULL, 219 INITIAL_ING_L3_NEXT_HOPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 220 INITIAL_NHOP_PARITY_CONTROLr, 221 INITIAL_NHOP_PARITY_STATUSr, INVALIDr, 222 INVALIDr, INVALIDr }, 223 /* Start of parity-unrelated OAM faults */ 224 225 { ANY_RMEP_TLV_PORT_DOWN_INTRf, ANY_RMEP_TLV_PORT_DOWN_INTRf, NULL, 226 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 227 INVALIDr, 228 INVALIDr, INVALIDr, 229 INVALIDr, INVALIDr }, 230 231 { ANY_RMEP_TLV_PORT_UP_INTRf, ANY_RMEP_TLV_PORT_UP_INTRf, NULL, 232 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 233 INVALIDr, 234 INVALIDr, INVALIDr, 235 INVALIDr, INVALIDr }, 236 237 { ANY_RMEP_TLV_INTERFACE_DOWN_INTRf, ANY_RMEP_TLV_INTERFACE_DOWN_INTRf, NULL, 238 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 239 INVALIDr, 240 INVALIDr, INVALIDr, 241 INVALIDr, INVALIDr }, 242 243 { ANY_RMEP_TLV_INTERFACE_UP_INTRf, ANY_RMEP_TLV_INTERFACE_UP_INTRf, NULL, 244 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 245 INVALIDr, 246 INVALIDr, INVALIDr, 247 INVALIDr, INVALIDr }, 248 249 { XCON_CCM_DEFECT_INTRf, XCON_CCM_DEFECT_INTRf, NULL, 250 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 251 INVALIDr, 252 INVALIDr, INVALIDr, 253 INVALIDr, INVALIDr }, 254 255 { ERROR_CCM_DEFECT_INTRf, ERROR_CCM_DEFECT_INTRf, NULL, 256 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 257 INVALIDr, 258 INVALIDr, INVALIDr, 259 INVALIDr, INVALIDr }, 260 261 { SOME_RDI_DEFECT_INTRf, SOME_RDI_DEFECT_INTRf, NULL, 262 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 263 INVALIDr, 264 INVALIDr, INVALIDr, 265 INVALIDr, INVALIDr }, 266 267 { SOME_RMEP_CCM_DEFECT_INTRf, SOME_RMEP_CCM_DEFECT_INTRf, NULL, 268 INVALIDm, _SOC_PARITY_INFO_TYPE_OAM, 269 INVALIDr, 270 INVALIDr, INVALIDr, 271 INVALIDr, INVALIDr }, 272 273 /* End of parity-unrelated OAM faults */ 274 { PARITY_ENf, VFI_1_PAR_INTRf, NULL, 275 VFI_1m, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 276 VFI_1_PARITY_CONTROLr, 277 VFI_1_PARITY_STATUS_INTRr, INVALIDr, 278 VFI_1_PARITY_STATUS_NACKr, INVALIDr }, 279 { INVALIDf, INVALIDf }, /* table terminator */ 280 }; 281 282 STATIC _soc_parity_info_t _soc_hu_ip2_parity_info[] = { 283 { PARITY_ENf, ING_NHOP_PAR_ERRf, NULL, 284 ING_L3_NEXT_HOPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 285 ING_L3_NEXT_HOP_PARITY_CONTROLr, 286 ING_L3_NEXT_HOP_PARITY_STATUSr, INVALIDr, 287 INVALIDr, INVALIDr }, 288 { PARITY_ENf, IFP_METER_PAR_ERRf, NULL, 289 FP_METER_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 290 IFP_METER_PARITY_CONTROLr, 291 IFP_METER_PARITY_STATUSr, INVALIDr, 292 INVALIDr, INVALIDr }, 293 { PARITY_ENf, IFP_COUNTER_PAR_ERRf, NULL, 294 FP_COUNTER_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 295 IFP_COUNTER_PARITY_CONTROLr, 296 IFP_COUNTER_PARITY_STATUSr, INVALIDr, 297 INVALIDr, INVALIDr }, 298 { PARITY_ENf, IFP_POLICY_PAR_ERRf, NULL, 299 FP_POLICY_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 300 IFP_POLICY_PARITY_CONTROLr, 301 IFP_POLICY_PARITY_STATUSr, INVALIDr, 302 INVALIDr, INVALIDr }, 303 { PARITY_ENf, IFP_STORM_CONTROL_PAR_ERRf, NULL, 304 FP_STORM_CONTROL_METERSm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 305 IFP_STORM_CONTROL_PARITY_CONTROLr, 306 IFP_STORM_CONTROL_PARITY_STATUSr, INVALIDr, 307 INVALIDr, INVALIDr }, 308 { PARITY_ENf, L3_MTU_VALUES_PAR_ERRf, NULL, 309 L3_MTU_VALUESm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 310 L3_MTU_VALUES_PARITY_CONTROLr, 311 L3_MTU_VALUES_PARITY_STATUSr, INVALIDr, 312 INVALIDr, INVALIDr }, 313 { PARITY_ENf, EGR_MASK_PAR_ERRf, NULL, 314 EGR_MASKm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 315 EGR_MASK_PARITY_CONTROLr, 316 EGR_MASK_PARITY_STATUSr, INVALIDr, 317 INVALIDr, INVALIDr }, 318 { PARITY_ENf, MODPORT_MAP_SW_PAR_ERRf, NULL, 319 MODPORT_MAP_SWm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 320 MODPORT_MAP_SW_PARITY_CONTROLr, 321 MODPORT_MAP_SW_PARITY_STATUSr, INVALIDr, 322 INVALIDr, INVALIDr }, 323 { PARITY_ENf, MODPORT_MAP_SW_PAR_ERRf, NULL, 324 MODPORT_MAPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 325 MODPORT_MAP_SW_PARITY_CONTROLr, 326 MODPORT_MAP_SW_PARITY_STATUSr, INVALIDr, 327 INVALIDr, INVALIDr }, 328 { PARITY_ENf, MODPORT_MAP_IM_PAR_ERRf, NULL, 329 MODPORT_MAP_IMm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 330 MODPORT_MAP_IM_PARITY_CONTROLr, 331 MODPORT_MAP_IM_PARITY_STATUSr, INVALIDr, 332 INVALIDr, INVALIDr }, 333 { PARITY_ENf, MODPORT_MAP_EM_PAR_ERRf, NULL, 334 MODPORT_MAP_EMm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 335 MODPORT_MAP_EM_PARITY_CONTROLr, 336 MODPORT_MAP_EM_PARITY_STATUSr, INVALIDr, 337 INVALIDr, INVALIDr }, 338 { INVALIDf, INVALIDf }, /* table terminator */ 339 }; 340 341 STATIC _soc_parity_info_t _soc_hu_ep_parity_info[] = { 342 { PARITY_ENf, EGR_NHOP_PAR_ERRf, NULL, 343 EGR_L3_NEXT_HOPm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 344 EGR_L3_NEXT_HOP_PARITY_CONTROLr, 345 EGR_L3_NEXT_HOP_PARITY_STATUSr, INVALIDr, 346 INVALIDr, INVALIDr }, 347 { PARITY_ENf, EGR_L3_INTF_PAR_ERRf, NULL, 348 EGR_L3_INTFm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 349 EGR_L3_INTF_PARITY_CONTROLr, 350 EGR_L3_INTF_PARITY_STATUSr, INVALIDr, 351 INVALIDr, INVALIDr }, 352 /* { PARITY_ENf, EGR_MPLS_LABEL_PAR_ERRf, NULL, 353 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 354 EGR_MPLS_VC_AND_SWAP_LABEL_PARITY_CONTROLr, 355 EGR_MPLS_VC_AND_SWAP_LABEL_PARITY_STATUSr, INVALIDr, 356 INVALIDr, INVALIDr }, */ 357 { PARITY_ENf, EGR_VLAN_PAR_ERRf, NULL, 358 EGR_VLANm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 359 EGR_VLAN_PARITY_CONTROLr, 360 EGR_VLAN_PARITY_STATUSr, INVALIDr, 361 INVALIDr, INVALIDr }, 362 { PARITY_ENf, EGR_VLAN_STG_PAR_ERRf, NULL, 363 EGR_VLAN_STGm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 364 EGR_VLAN_STG_PARITY_CONTROLr, 365 EGR_VLAN_STG_PARITY_STATUSr, INVALIDr, 366 INVALIDr, INVALIDr }, 367 { PARITY_ENf, EGR_VXLT_PAR_ERRf, NULL, 368 EGR_VLAN_XLATEm, _SOC_PARITY_INFO_TYPE_DUAL_PARITY, 369 EGR_VLAN_XLATE_PARITY_CONTROLr, 370 EGR_VLAN_XLATE_PARITY_STATUS_0r, EGR_VLAN_XLATE_PARITY_STATUS_1r, 371 INVALIDr, INVALIDr }, 372 /* { PARITY_ENf, EGR_IP_TUNNEL_PAR_ERRf, NULL, 373 EGR_IP_TUNNELm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 374 EGR_IP_TUNNEL_PARITY_CONTROLr, 375 EGR_IP_TUNNEL_PARITY_STATUSr, INVALIDr, 376 INVALIDr, INVALIDr }, 377 { PARITY_ENf, EGR_PW_COUNT_PAR_ERRf, NULL, 378 EGR_PW_INIT_COUNTERSm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 379 EGR_PW_INIT_COUNTERS_PARITY_CONTROLr, 380 EGR_PW_INIT_COUNTERS_PARITY_STATUSr, INVALIDr, 381 INVALIDr, INVALIDr }, 382 { PARITY_ENf, EGR_IPFIX_SESS_PAR_ERRf, NULL, 383 EGR_IPFIX_SESSION_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 384 EGR_IPFIX_SESSION_PARITY_CONTROLr, 385 EGR_IPFIX_SESSION_PARITY_STATUSr, INVALIDr, 386 INVALIDr, INVALIDr }, 387 { PARITY_ENf, EGR_IPFIX_EXPORT_PAR_ERRf, NULL, 388 EGR_IPFIX_EXPORT_FIFOm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 389 EGR_IPFIX_EXPORT_FIFO_PARITY_CONTROLr, 390 EGR_IPFIX_EXPORT_FIFO_PARITY_STATUSr, INVALIDr, 391 INVALIDr, INVALIDr }, */ 392 { ECC_ENf, EP_INITBUF_DBEf, "EP_INITBUF double-bit ECC error", 393 INVALIDm,_SOC_PARITY_INFO_TYPE_SINGLE_ECC, 394 EGR_INITBUF_ECC_CONTROLr, 395 EGR_INITBUF_ECC_STATUS_DBEr, INVALIDr, 396 INVALIDr, INVALIDr }, 397 { ECC_ENf, EP_INITBUF_SBEf, "EP_INITBUF single-bit ECC error (corrected)", 398 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 399 EGR_INITBUF_ECC_CONTROLr, 400 EGR_INITBUF_ECC_STATUS_SBEr, INVALIDr, 401 INVALIDr, INVALIDr }, 402 { PARITY_ENf, EGR_PERQ_COUNTERf, "EP_PERQ_COUNTER table parity error", 403 EGR_PERQ_XMT_COUNTERSm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 404 EGR_PERQ_COUNTER_PARITY_CONTROLr, 405 EGR_PERQ_COUNTER_PARITY_STATUSr, INVALIDr, 406 INVALIDr, INVALIDr }, 407 /* { PARITY_ENf, EGR_FP_COUNTERf, NULL, 408 EFP_COUNTER_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 409 EGR_FP_COUNTER_PARITY_CONTROLr, 410 EGR_FP_COUNTER_PARITY_STATUSr, INVALIDr, 411 INVALIDr, INVALIDr }, */ 412 { PARITY_ENf, EGR_GP0_DBUFf, "EP_GP0_DATABUF memory parity error", 413 EFP_COUNTER_TABLEm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 414 EGR_GP0_DBUF_PARITY_CONTROLr, 415 EGR_GP0_DBUF_PARITY_STATUSr, INVALIDr, 416 INVALIDr, INVALIDr }, 417 { PARITY_ENf, EGR_GP1_DBUFf, "EP_GP1_DATABUF memory parity error", 418 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 419 EGR_GP1_DBUF_PARITY_CONTROLr, 420 EGR_GP1_DBUF_PARITY_STATUSr, INVALIDr, 421 INVALIDr, INVALIDr }, 422 { PARITY_ENf, EGR_GP2_DBUFf, "EP_GP2_DATABUF memory parity error", 423 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 424 EGR_GP2_DBUF_PARITY_CONTROLr, 425 EGR_GP2_DBUF_PARITY_STATUSr, INVALIDr, 426 INVALIDr, INVALIDr }, 427 { PARITY_ENf, EGR_XQ0_DBUFf, "EP_XQ0_DATABUF memory parity error", 428 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 429 EGR_XQ0_DBUF_PARITY_CONTROLr, 430 EGR_XQ0_DBUF_PARITY_STATUSr, INVALIDr, 431 INVALIDr, INVALIDr }, 432 { PARITY_ENf, EGR_XQ1_DBUFf, "EP_XQ1_DATABUF memory parity error", 433 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 434 EGR_XQ1_DBUF_PARITY_CONTROLr, 435 EGR_XQ1_DBUF_PARITY_STATUSr, INVALIDr, 436 INVALIDr, INVALIDr }, 437 { PARITY_ENf, EGR_XQ2_DBUFf, "EP_XQ2_DATABUF memory parity error", 438 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 439 EGR_XQ2_DBUF_PARITY_CONTROLr, 440 EGR_XQ2_DBUF_PARITY_STATUSr, INVALIDr, 441 INVALIDr, INVALIDr }, 442 { PARITY_ENf, EGR_XQ3_DBUFf, "EP_XQ3_DATABUF memory parity error", 443 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 444 EGR_XQ3_DBUF_PARITY_CONTROLr, 445 EGR_XQ3_DBUF_PARITY_STATUSr, INVALIDr, 446 INVALIDr, INVALIDr }, 447 /* { PARITY_ENf, EGR_LP_DBUFf, "EP_LP_DATABUF memory parity error", 448 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 449 EGR_LP_DBUF_PARITY_CONTROLr, 450 EGR_LP_DBUF_PARITY_STATUSr, INVALIDr, 451 INVALIDr, INVALIDr }, */ 452 { PARITY_ENf, EGR_CM_DBUFf, "EGR_CM_DBUF memory parity error", 453 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_PARITY, 454 EGR_CM_DBUF_PARITY_CONTROLr, 455 EGR_CM_DBUF_PARITY_STATUSr, INVALIDr, 456 INVALIDr, INVALIDr }, 457 { INVALIDf, INVALIDf }, /* table terminator */ 458 }; 459 460 STATIC _soc_parity_info_t _soc_hu_xqp_parity_info[] = { 461 { XQBOD_RXFIFOf, XQBOD_RXFIFOf, "XQBOD_RXFIFO", 462 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 463 XQPORT_PARITY_CONTROLr, 464 XQPORT_XQBOD_RXFIFO_PARITY_STATUS_INTRr, XQPORT_FORCE_SINGLE_BIT_ERRORr, 465 INVALIDr, XQPORT_FORCE_DOUBLE_BIT_ERRORr }, 466 { XQBODE_TXFIFOf, XQBODE_TXFIFOf, "XQBODE_TXFIFO", 467 INVALIDm, _SOC_PARITY_INFO_TYPE_SINGLE_ECC, 468 XQPORT_PARITY_CONTROLr, 469 XQPORT_XQBODE_TXFIFO_PARITY_STATUS_INTRr, XQPORT_FORCE_SINGLE_BIT_ERRORr, 470 INVALIDr, XQPORT_FORCE_DOUBLE_BIT_ERRORr }, 471 { INVALIDf, INVALIDf }, /* table terminator */ 472 }; 473 474 static struct { 475 uint32 cpi_bit; 476 soc_block_t blocktype; 477 soc_reg_t enable_reg; 478 soc_reg_t status_reg; 479 _soc_parity_info_t *info; 480 } _soc_hu_parity_group_info[] = { 481 { 0x00002, SOC_BLK_EPIPE, EP_INTR_ENABLEr, EP_INTR_STATUSr, _soc_hu_ep_parity_info }, 482 { 0x00004, SOC_BLK_IPIPE, IP0_INTR_ENABLEr, IP0_INTR_STATUSr, _soc_hu_ip0_parity_info }, 483 { 0x00008, SOC_BLK_IPIPE, IP1_INTR_ENABLEr, IP1_INTR_STATUSr, _soc_hu_ip1_parity_info }, 484 { 0x00010, SOC_BLK_IPIPE, IP2_INTR_ENABLEr, IP2_INTR_STATUSr, _soc_hu_ip2_parity_info }, 485 /* { 0x00020, PCIE_REPLAY_PERR, }, */ 486 { 0x00040, SOC_BLK_XQPORT, XQPORT_INTR_ENABLEr, XQPORT_INTR_STATUSr, _soc_hu_xqp_parity_info }, /* x4 */ 487 { 0 }, /* table terminator */ 488 }; 489 490 STATIC soc_hurricane_oam_handler_t hu_oam_handler = NULL; 491 492 static soc_ser_functions_t _hurricane_ser_functions; 493 494 STATIC int 495 _soc_hurricane_parity_block_port(int unit, soc_block_t block, soc_port_t *port) 496 { 497 *port = SOC_BLOCK_PORT(unit, block); 498 if ((*port != REG_PORT_ANY) && !SOC_PORT_VALID(unit, *port)) { 499 return SOC_E_PORT; 500 } 501 502 return SOC_E_NONE; 503 } 504 505 STATIC int 506 _soc_hurricane_parity_enable(int unit, int enable) 507 { 508 int group, table; 509 uint32 addr, group_enable, regval, cmic_enable = 0, cpi_blk_bit; 510 _soc_parity_info_t *info; 511 soc_reg_t group_reg, reg; 512 soc_port_t block_port; 513 soc_field_t enable_field; 514 soc_block_t blk; 515 516 /* loop through each group */ 517 for (group = 0; _soc_hu_parity_group_info[group].cpi_bit; group++) { 518 info = _soc_hu_parity_group_info[group].info; 519 group_reg = _soc_hu_parity_group_info[group].enable_reg; 520 group_enable = 0; 521 522 cpi_blk_bit = _soc_hu_parity_group_info[group].cpi_bit; 523 524 SOC_BLOCK_ITER(unit, blk, 525 _soc_hu_parity_group_info[group].blocktype) { 526 if (_soc_hurricane_parity_block_port(unit, blk, &block_port) < 0) { 527 cpi_blk_bit <<= 1; 528 continue; 529 } 530 /* loop through each table in the group */ 531 for (table = 0; info[table].enable_field != INVALIDf; table++) { 532 /* handle different parity error reporting style */ 533 switch (info[table].type) { 534 case _SOC_PARITY_INFO_TYPE_GENERIC: 535 case _SOC_PARITY_INFO_TYPE_MMU_PARITY: 536 case _SOC_PARITY_INFO_TYPE_MMUIPMC: 537 case _SOC_PARITY_INFO_TYPE_MMUWRED: 538 case _SOC_PARITY_INFO_TYPE_OAM: 539 enable_field = info[table].enable_field; 540 break; 541 case _SOC_PARITY_INFO_TYPE_SINGLE_PARITY: 542 case _SOC_PARITY_INFO_TYPE_SINGLE_ECC: 543 case _SOC_PARITY_INFO_TYPE_SINGLE_COUNTER: 544 case _SOC_PARITY_INFO_TYPE_DUAL_PARITY: 545 reg = info[table].control_reg; 546 if (!SOC_REG_IS_VALID(unit, reg)) { 547 continue; 548 } 549 addr = soc_reg_addr(unit, reg, block_port, 0); 550 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, ®val)); 551 soc_reg_field_set(unit, reg, ®val, 552 info[table].enable_field, 553 enable ? 1 : 0); 554 SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, regval)); 555 enable_field = info[table].error_field; 556 break; 557 default: 558 enable_field = INVALIDf; 559 break; 560 } /* handle different parity error reporting style */ 561 if (enable_field != INVALIDf) { 562 soc_reg_field_set(unit, group_reg, &group_enable, 563 enable_field, enable ? 1 : 0); 564 } 565 } /* loop through each table in the group */ 566 567 if (!SOC_REG_IS_VALID(unit, group_reg)) { 568 cpi_blk_bit <<= 1; 569 continue; 570 } 571 addr = soc_reg_addr(unit, group_reg, block_port, 0); 572 SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, group_enable)); 573 cmic_enable |= cpi_blk_bit; 574 cpi_blk_bit <<= 1; 575 } 576 } /* loop through each group */ 577 /* coverity[result_independent_of_operands] */ 578 SOC_IF_ERROR_RETURN(WRITE_CMIC_CHIP_PARITY_INTR_ENABLEr(unit, 579 cmic_enable)); 580 return SOC_E_NONE; 581 } 582 583 int 584 _soc_hurricane_mem_parity_control(int unit, soc_mem_t mem, 585 int copyno, int enable) 586 { 587 int group, table; 588 uint32 cpi_blk_bit, misc_cfg; 589 _soc_parity_info_t *info; 590 soc_reg_t group_reg, reg; 591 soc_port_t block_port; 592 soc_field_t enable_field; 593 soc_block_t blk; 594 595 if (!soc_property_get(unit, spn_PARITY_ENABLE, TRUE)) { 596 /* Parity checking is not enabled, nothing to do */ 597 return SOC_E_NONE; 598 } 599 600 /* Convert component/aggregate memories to the table for which 601 * the parity registers correspond. */ 602 switch(mem) { 603 case VLAN_SUBNETm: 604 mem = VLAN_SUBNET_DATA_ONLYm; /* Should be VLAN_SUBNET? */ 605 break; 606 case L2_ENTRY_ONLYm: 607 mem = L2Xm; 608 break; 609 case L2_USER_ENTRY_ONLYm: 610 case L2_USER_ENTRY_DATA_ONLYm: 611 mem = L2_USER_ENTRYm; 612 break; 613 case L3_DEFIPm: 614 mem = L3_DEFIP_DATA_ONLYm; 615 break; 616 case L3_DEFIP_128m: 617 mem = L3_DEFIP_128_DATA_ONLYm; 618 break; 619 case EGR_IP_TUNNEL_IPV6m: 620 case EGR_IP_TUNNEL_MPLSm: 621 mem = EGR_IP_TUNNELm; 622 break; 623 case L3_ENTRY_IPV4_UNICASTm: 624 case L3_ENTRY_IPV6_UNICASTm: 625 case L3_ENTRY_IPV4_MULTICASTm: 626 case L3_ENTRY_IPV6_MULTICASTm: 627 mem = L3_ENTRY_ONLYm; 628 break; 629 case VLAN_MACm: 630 mem = VLAN_XLATEm; 631 break; 632 default: 633 /* Do nothing, keep memory as provided */ 634 break; 635 } 636 637 638 /* loop through each group */ 639 for (group = 0; _soc_hu_parity_group_info[group].cpi_bit; group++) { 640 info = _soc_hu_parity_group_info[group].info; 641 group_reg = _soc_hu_parity_group_info[group].enable_reg; 642 cpi_blk_bit = _soc_hu_parity_group_info[group].cpi_bit; 643 644 SOC_BLOCK_ITER(unit, blk, 645 _soc_hu_parity_group_info[group].blocktype) { 646 if (_soc_hurricane_parity_block_port(unit, blk, &block_port) < 0) { 647 cpi_blk_bit <<= 1; 648 continue; 649 } 650 if ((copyno != MEM_BLOCK_ANY) && (blk != copyno)) { 651 cpi_blk_bit <<= 1; 652 continue; 653 } 654 655 /* loop through each table in the group */ 656 for (table = 0; info[table].enable_field != INVALIDf; table++) { 657 if (mem != info[table].mem) { 658 continue; 659 } 660 661 /* handle different parity error reporting style */ 662 switch (info[table].type) { 663 case _SOC_PARITY_INFO_TYPE_GENERIC: 664 case _SOC_PARITY_INFO_TYPE_MMU_PARITY: 665 case _SOC_PARITY_INFO_TYPE_MMUIPMC: 666 case _SOC_PARITY_INFO_TYPE_MMUWRED: 667 enable_field = info[table].enable_field; 668 SOC_IF_ERROR_RETURN 669 (soc_reg_field32_modify(unit, group_reg, block_port, 670 enable_field, 671 enable ? 1 : 0)); 672 break; 673 case _SOC_PARITY_INFO_TYPE_SINGLE_PARITY: 674 case _SOC_PARITY_INFO_TYPE_SINGLE_ECC: 675 case _SOC_PARITY_INFO_TYPE_SINGLE_COUNTER: 676 case _SOC_PARITY_INFO_TYPE_DUAL_PARITY: 677 reg = info[table].control_reg; 678 if (!SOC_REG_IS_VALID(unit, reg)) { 679 return SOC_E_NONE; 680 } 681 SOC_IF_ERROR_RETURN 682 (soc_reg_field32_modify(unit, reg, block_port, 683 info[table].enable_field, 684 enable ? 1 : 0)); 685 break; 686 default: 687 break; 688 } /* handle different parity error reporting style */ 689 } /* loop through each table in the group */ 690 cpi_blk_bit <<= 1; 691 } 692 } /* loop through each group */ 693 694 /* MMU controls */ 695 if (enable) { 696 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &misc_cfg)); 697 soc_reg_field_set(unit, MISCCONFIGr, &misc_cfg, 698 E2EFC_PARITY_STAT_CLEARf, 1); 699 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, misc_cfg)); 700 701 soc_reg_field_set(unit, MISCCONFIGr, &misc_cfg, PARITY_CHECK_ENf, 1); 702 soc_reg_field_set(unit, MISCCONFIGr, &misc_cfg, E2EFC_PARITY_GEN_ENf, 1); 703 soc_reg_field_set(unit, MISCCONFIGr, &misc_cfg, E2EFC_PARITY_STAT_CLEARf, 0); 704 soc_reg_field_set(unit, MISCCONFIGr, &misc_cfg, METERING_CLK_ENf, 1); 705 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, misc_cfg)); 706 } else { 707 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &misc_cfg)); 708 soc_reg_field_set(unit, MISCCONFIGr, &misc_cfg, PARITY_CHECK_ENf, 0); 709 soc_reg_field_set(unit, MISCCONFIGr, &misc_cfg, E2EFC_PARITY_GEN_ENf, 0); 710 soc_reg_field_set(unit, MISCCONFIGr, &misc_cfg, METERING_CLK_ENf, 0); 711 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, misc_cfg)); 712 } 713 714 return SOC_E_NONE; 715 } 716 717 STATIC int 718 _soc_hurricane_process_single_parity_error(int unit, int group, 719 soc_port_t block_port, int table, 720 int schan, char *msg) 721 { 722 _soc_parity_info_t *info; 723 soc_reg_t status_reg; 724 uint32 addr, reg_val; 725 int index, multiple, error; 726 727 info = _soc_hu_parity_group_info[group].info; 728 729 status_reg = schan ? info[table].nack_status0_reg : 730 info[table].intr_status0_reg; 731 if (status_reg == INVALIDr) { 732 return SOC_E_INTERNAL; 733 } 734 addr = soc_reg_addr(unit, status_reg, block_port, 0); 735 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, ®_val)); 736 index = soc_reg_field_get(unit, status_reg, reg_val, ENTRY_IDXf); 737 multiple = soc_reg_field_get(unit, status_reg, reg_val, MULTIPLE_ERRf); 738 error = soc_reg_field_get(unit, status_reg, reg_val, PARITY_ERRf); 739 740 if (error) { 741 LOG_ERROR(BSL_LS_SOC_COMMON, 742 (BSL_META_U(unit, 743 "unit %d %s entry %d parity error\n"), 744 unit, msg, index)); 745 if (multiple) { 746 LOG_ERROR(BSL_LS_SOC_COMMON, 747 (BSL_META_U(unit, 748 "unit %d %s has multiple parity errors\n"), 749 unit, msg)); 750 } 751 } else { 752 LOG_ERROR(BSL_LS_SOC_COMMON, 753 (BSL_META_U(unit, 754 "unit %d %s: parity hardware inconsistency\n"), 755 unit, msg)); 756 } 757 758 /* Clear parity status */ 759 SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, 0)); 760 return SOC_E_NONE; 761 } 762 763 STATIC int 764 _soc_hurricane_process_single_ecc_error(int unit, int group, 765 soc_port_t block_port, int table, 766 int schan, char *msg) 767 { 768 _soc_parity_info_t *info; 769 soc_reg_t status_reg; 770 uint32 addr, reg_val; 771 int index, double_bit, multiple, error; 772 773 info = _soc_hu_parity_group_info[group].info; 774 775 status_reg = schan ? info[table].nack_status0_reg : 776 info[table].intr_status0_reg; 777 if (status_reg == INVALIDr) { 778 return SOC_E_INTERNAL; 779 } 780 addr = soc_reg_addr(unit, status_reg, block_port, 0); 781 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, ®_val)); 782 index = soc_reg_field_get(unit, status_reg, reg_val, ENTRY_IDXf); 783 double_bit = soc_reg_field_get(unit, status_reg, 784 reg_val, DOUBLE_BIT_ERRf); 785 multiple = soc_reg_field_get(unit, status_reg, reg_val, MULTIPLE_ERRf); 786 error = soc_reg_field_get(unit, status_reg, reg_val, ECC_ERRf); 787 788 if (error) { 789 LOG_ERROR(BSL_LS_SOC_COMMON, 790 (BSL_META_U(unit, 791 "unit %d %s entry %d %s ECC error\n"), 792 unit, msg, index, double_bit ? "double-bit" : "")); 793 if (multiple) { 794 LOG_ERROR(BSL_LS_SOC_COMMON, 795 (BSL_META_U(unit, 796 "unit %d %s has multiple ECC errors\n"), 797 unit, msg)); 798 } 799 } else { 800 LOG_ERROR(BSL_LS_SOC_COMMON, 801 (BSL_META_U(unit, 802 "unit %d %s: parity hardware inconsistency\n"), 803 unit, msg)); 804 } 805 806 /* Clear parity status */ 807 SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, 0)); 808 return SOC_E_NONE; 809 } 810 811 STATIC int 812 _soc_hurricane_process_dual_parity_error(int unit, int group, 813 soc_port_t block_port, int table, 814 int schan, char *msg) 815 { 816 _soc_parity_info_t *info; 817 soc_reg_t status_reg; 818 uint32 addr, reg_val, bitmap; 819 int index, bucket_index, multiple, ix, bits, size; 820 821 info = _soc_hu_parity_group_info[group].info; 822 823 for (ix = 0; ix < 2; ix ++) { 824 if (ix == 1) { 825 status_reg = schan ? info[table].nack_status1_reg : 826 info[table].intr_status1_reg; 827 } else { 828 status_reg = schan ? info[table].nack_status0_reg : 829 info[table].intr_status0_reg; 830 } 831 832 if (status_reg == INVALIDr) { 833 continue; 834 } 835 836 addr = soc_reg_addr(unit, status_reg, block_port, 0); 837 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, ®_val)); 838 bucket_index = 839 soc_reg_field_get(unit, status_reg, reg_val, BUCKET_IDXf); 840 multiple = 841 soc_reg_field_get(unit, status_reg, reg_val, MULTIPLE_ERRf); 842 bitmap = 843 soc_reg_field_get(unit, status_reg, reg_val, PARITY_ERR_BMf); 844 size = soc_reg_field_length(unit, status_reg, PARITY_ERR_BMf); 845 846 if (bitmap != 0) { 847 for (bits = 0; bits < size; bits++) { 848 if (bitmap & (1 << bits)) { 849 index = 850 bucket_index * size * 2 + bits + (ix * size); 851 LOG_ERROR(BSL_LS_SOC_COMMON, 852 (BSL_META_U(unit, 853 "unit %d %s entry %d parity error\n"), 854 unit, msg, index)); 855 } 856 } 857 } 858 859 if (multiple) { 860 LOG_ERROR(BSL_LS_SOC_COMMON, 861 (BSL_META_U(unit, 862 "unit %d %s has multiple parity errors\n"), 863 unit, msg)); 864 } 865 866 /* Clear parity status */ 867 SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, 0)); 868 } 869 870 return SOC_E_NONE; 871 } 872 873 STATIC int 874 _soc_hurricane_process_mmu_parity_error(int unit, int group, 875 soc_port_t block_port, int table, 876 char *msg) 877 { 878 _soc_parity_info_t *info; 879 soc_reg_t status_reg, index_reg; 880 uint32 addr, reg_val; 881 int index; 882 883 info = _soc_hu_parity_group_info[group].info; 884 885 status_reg = info[table].intr_status1_reg; 886 index_reg = info[table].intr_status0_reg; 887 if (index_reg == INVALIDr) { 888 LOG_ERROR(BSL_LS_SOC_COMMON, 889 (BSL_META_U(unit, 890 "unit %d %s parity error\n"), 891 unit, msg)); 892 return SOC_E_NONE; 893 } 894 if (status_reg != INVALIDr) { 895 addr = soc_reg_addr(unit, status_reg, block_port, 0); 896 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, ®_val)); 897 if (reg_val == 0) { 898 LOG_ERROR(BSL_LS_SOC_COMMON, 899 (BSL_META_U(unit, 900 "unit %d %s: parity hardware inconsistency\n"), 901 unit, msg)); 902 return SOC_E_NONE; 903 } 904 } 905 addr = soc_reg_addr(unit, index_reg, block_port, 0); 906 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, ®_val)); 907 index = reg_val; 908 909 LOG_ERROR(BSL_LS_SOC_COMMON, 910 (BSL_META_U(unit, 911 "unit %d %s entry %d parity error\n"), 912 unit, msg, index)); 913 /* update soc stats for some cases */ 914 if (info[table].error_field == CCP_PAR_ERRf) { 915 SOC_CONTROL(unit)->stat.err_cpcrc++; 916 } else if (info[table].error_field == CFAP_PAR_ERRf) { 917 SOC_CONTROL(unit)->stat.err_cfap++; 918 } 919 920 return SOC_E_NONE; 921 } 922 923 924 STATIC int 925 _soc_hurricane_process_parity_error(int unit) 926 { 927 int group, table, index, size; 928 uint32 addr, cmic_status, group_status, status, 929 group_enable, cpi_blk_bit; 930 uint32 entry_idx; 931 _soc_parity_info_t *info; 932 soc_reg_t group_reg, reg; 933 soc_port_t block_port; 934 soc_block_t blk; 935 char *msg; 936 soc_hurricane_oam_handler_t oam_handler_snapshot; 937 938 /* coverity[result_independent_of_operands] */ 939 SOC_IF_ERROR_RETURN(READ_CMIC_CHIP_PARITY_INTR_STATUSr(unit, 940 &cmic_status)); 941 942 /* loop through each group */ 943 for (group = 0; _soc_hu_parity_group_info[group].cpi_bit; group++) { 944 info = _soc_hu_parity_group_info[group].info; 945 group_reg = _soc_hu_parity_group_info[group].status_reg; 946 LOG_VERBOSE(BSL_LS_SOC_COMMON, 947 (BSL_META_U(unit, 948 "unit %d %s parity processing\n"), 949 unit, SOC_REG_NAME(unit, group_reg))); 950 cpi_blk_bit = _soc_hu_parity_group_info[group].cpi_bit; 951 952 SOC_BLOCK_ITER(unit, blk, 953 _soc_hu_parity_group_info[group].blocktype) { 954 if (_soc_hurricane_parity_block_port(unit, blk, &block_port) < 0) { 955 cpi_blk_bit <<= 1; 956 continue; 957 } 958 if (!(cmic_status & cpi_blk_bit)) { 959 cpi_blk_bit <<= 1; 960 continue; 961 } 962 963 addr = soc_reg_addr(unit, group_reg, block_port, 0); 964 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &group_status)); 965 966 /* loop through each table in the group */ 967 for (table = 0; info[table].error_field != INVALIDf; table++) { 968 if (!soc_reg_field_valid(unit, group_reg, 969 info[table].error_field)) { 970 if (info[table].mem != INVALIDm) { 971 LOG_ERROR(BSL_LS_SOC_COMMON, 972 (BSL_META_U(unit, 973 "unit %d %s has bad error field\n"), 974 unit, SOC_MEM_NAME(unit, info[table].mem))); 975 } 976 continue; 977 } 978 979 if (!soc_reg_field_get(unit, group_reg, group_status, 980 info[table].error_field)) { 981 continue; 982 } 983 if (info[table].msg) { 984 msg = info[table].msg; 985 } else if (info[table].mem != INVALIDm) { 986 msg = SOC_MEM_NAME(unit, info[table].mem); 987 } else { 988 msg = SOC_FIELD_NAME(unit, info[table].error_field); 989 } 990 991 LOG_VERBOSE(BSL_LS_SOC_COMMON, 992 (BSL_META_U(unit, 993 "unit %d %s analysis\n"), 994 unit, msg)); 995 996 /* handle different parity error reporting style */ 997 switch (info[table].type) { 998 case _SOC_PARITY_INFO_TYPE_GENERIC: 999 LOG_ERROR(BSL_LS_SOC_COMMON, 1000 (BSL_META_U(unit, 1001 "unit %d %s asserted\n"), 1002 unit, msg)); 1003 break; 1004 case _SOC_PARITY_INFO_TYPE_SINGLE_PARITY: 1005 SOC_IF_ERROR_RETURN 1006 (_soc_hurricane_process_single_parity_error(unit, 1007 group, block_port, table, FALSE, msg)); 1008 break; 1009 case _SOC_PARITY_INFO_TYPE_SINGLE_ECC: 1010 SOC_IF_ERROR_RETURN 1011 (_soc_hurricane_process_single_ecc_error(unit, 1012 group, block_port, table, FALSE, msg)); 1013 break; 1014 case _SOC_PARITY_INFO_TYPE_DUAL_PARITY: 1015 SOC_IF_ERROR_RETURN 1016 (_soc_hurricane_process_dual_parity_error(unit, 1017 group, block_port, table, FALSE, msg)); 1018 break; 1019 case _SOC_PARITY_INFO_TYPE_MMU_PARITY: 1020 SOC_IF_ERROR_RETURN 1021 (_soc_hurricane_process_mmu_parity_error(unit, 1022 group, block_port, table, msg)); 1023 break; 1024 case _SOC_PARITY_INFO_TYPE_MMUIPMC: 1025 /* 1026 * status0 (MEM1_IPMCGRP_TBL_PARITYERRORPTRr) is index 1027 * status1 (MEM1_IPMCGRP_TBL_PARITYERROR_STATUSr) is table id 1028 * MMU_IPMC_GROUP_TBL0m - MMU_IPMC_GROUP_TBL8m 1029 */ 1030 reg = info[table].intr_status1_reg; 1031 addr = soc_reg_addr(unit, reg, block_port, 0); 1032 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &status)); 1033 size = soc_reg_field_length(unit, reg, STATUSf); 1034 reg = info[table].intr_status0_reg; 1035 for (index = 0; index < size; index++, status >>= 1) { 1036 if (!(status & 1)) { 1037 continue; 1038 } 1039 addr = soc_reg_addr(unit, reg, block_port, index); 1040 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, 1041 &entry_idx)); 1042 LOG_ERROR(BSL_LS_SOC_COMMON, 1043 (BSL_META_U(unit, 1044 "unit %d %s%d entry %d parity error\n"), 1045 unit, msg, index, entry_idx)); 1046 } 1047 break; 1048 case _SOC_PARITY_INFO_TYPE_MMUWRED: 1049 /* 1050 * status0 (WRED_PARITY_ERROR_INFOr) is index 1051 * status1 (WRED_PARITY_ERROR_BITMAPr) is table id 1052 */ 1053 reg = info[table].intr_status0_reg; 1054 addr = soc_reg_addr(unit, reg, block_port, 0); 1055 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, 1056 &entry_idx)); 1057 reg = info[table].intr_status1_reg; 1058 addr = soc_reg_addr(unit, reg, block_port, 0); 1059 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &status)); 1060 if (status & 0x000003) { 1061 msg = "WRED_CFG_CELL"; 1062 } else if (status & 0x00000c) { 1063 msg = "WRED_THD_0_CELL"; 1064 } else if (status & 0x000030) { 1065 msg = "WRED_THD_1_CELL"; 1066 } else if (status & 0x0000c0) { 1067 msg = "WRED_CFG_PACKET"; 1068 } else if (status & 0x000300) { 1069 msg = "WRED_THD_0_PACKET"; 1070 } else if (status & 0x000c00) { 1071 msg = "WRED_THD_1_PACKET"; 1072 } else if (status & 0x003000) { 1073 msg = "WRED_PORT_CFG_CELL"; 1074 } else if (status & 0x00c000) { 1075 msg = "WRED_PORT_THD_0_CELL"; 1076 } else if (status & 0x030000) { 1077 msg = "WRED_PORT_THD_1_CELL"; 1078 } else if (status & 0x0c0000) { 1079 msg = "WRED_PORT_CFG_PACKET"; 1080 } else if (status & 0x300000) { 1081 msg = "WRED_PORT_THD_0_PACKET"; 1082 } else if (status & 0xc00000) { 1083 msg = "WRED_PORT_THD_1_PACKET"; 1084 } else { 1085 break; 1086 } 1087 LOG_ERROR(BSL_LS_SOC_COMMON, 1088 (BSL_META_U(unit, 1089 "unit %d %s entry %d parity error\n"), 1090 unit, msg, entry_idx)); 1091 break; 1092 case _SOC_PARITY_INFO_TYPE_OAM: 1093 /* OAM isn't parity-related but shares an interrupt */ 1094 1095 oam_handler_snapshot = hu_oam_handler; 1096 1097 if (oam_handler_snapshot != NULL) 1098 { 1099 SOC_IF_ERROR_RETURN(oam_handler_snapshot(unit, 1100 info[table].error_field)); 1101 } 1102 1103 break; 1104 default: 1105 break; 1106 } /* handle different parity error reporting style */ 1107 } /* loop through each table in the group */ 1108 1109 reg = _soc_hu_parity_group_info[group].enable_reg; 1110 addr = soc_reg_addr(unit, reg, block_port, 0); 1111 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &group_enable)); 1112 group_enable &= ~group_status; 1113 SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, group_enable)); 1114 group_enable |= group_status; 1115 SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, group_enable)); 1116 } /* loop through each block for the group */ 1117 } /* loop through each group */ 1118 1119 return SOC_E_NONE; 1120 } 1121 1122 void 1123 soc_hurricane_parity_error(void *unit_vp, void *d1, void *d2, 1124 void *d3, void *d4) 1125 { 1126 int unit = PTR_TO_INT(unit_vp); 1127 1128 _soc_hurricane_process_parity_error(unit); 1129 soc_intr_enable(unit, IRQ_MEM_FAIL); 1130 } 1131 1132 STATIC int 1133 _soc_hurricane_mem_nack_error_process(int unit, soc_mem_t mem, int copyno) 1134 { 1135 int group, table; 1136 _soc_parity_info_t *info; 1137 soc_port_t block_port; 1138 soc_block_t blk; 1139 char *msg; 1140 1141 if (mem == INVALIDm) { 1142 return SOC_E_PARAM; 1143 } 1144 1145 /* loop through each group */ 1146 for (group = 0; _soc_hu_parity_group_info[group].cpi_bit; group++) { 1147 info = _soc_hu_parity_group_info[group].info; 1148 1149 SOC_BLOCK_ITER(unit, blk, 1150 _soc_hu_parity_group_info[group].blocktype) { 1151 if (copyno != blk) { 1152 continue; 1153 } 1154 if (_soc_hurricane_parity_block_port(unit, blk, &block_port) < 0) { 1155 continue; 1156 } 1157 /* loop through each table in the group */ 1158 for (table = 0; info[table].error_field != INVALIDf; table++) { 1159 if (info[table].mem != mem) { 1160 continue; 1161 } 1162 if (info[table].nack_status0_reg == INVALIDr) { 1163 return SOC_E_NOT_FOUND; 1164 } 1165 if (info[table].msg) { 1166 msg = info[table].msg; 1167 } else { /* mem must be valid to get her */ 1168 msg = SOC_MEM_NAME(unit, info[table].mem); 1169 } 1170 1171 /* handle different parity error reporting style */ 1172 switch (info[table].type) { 1173 case _SOC_PARITY_INFO_TYPE_SINGLE_PARITY: 1174 SOC_IF_ERROR_RETURN 1175 (_soc_hurricane_process_single_parity_error(unit, 1176 group, block_port, table, TRUE, msg)); 1177 break; 1178 case _SOC_PARITY_INFO_TYPE_SINGLE_ECC: 1179 SOC_IF_ERROR_RETURN 1180 (_soc_hurricane_process_single_ecc_error(unit, 1181 group, block_port, table, TRUE, msg)); 1182 break; 1183 case _SOC_PARITY_INFO_TYPE_DUAL_PARITY: 1184 SOC_IF_ERROR_RETURN 1185 (_soc_hurricane_process_dual_parity_error(unit, 1186 group, block_port, table, TRUE, msg)); 1187 break; 1188 default: 1189 break; 1190 } /* handle different parity error reporting style */ 1191 } /* loop through each table in the group */ 1192 } /* loop through each block of the group */ 1193 } /* loop through each group */ 1194 1195 return SOC_E_NONE; 1196 } 1197 1198 STATIC int 1199 _soc_hurricane_mem_ecc_force(int unit, soc_port_t block_port, 1200 _soc_parity_info_t *info) 1201 { 1202 soc_reg_t force_sbe_reg, force_dbe_reg; 1203 soc_field_t force_field; 1204 1205 force_field = info->error_field; 1206 if (force_field == RX_FIFO_MEM_ERRf) { 1207 force_field = RX_FIFO_MEMf; 1208 } else if (force_field == TX_FIFO_MEM_ERRf) { 1209 force_field = TX_FIFO_MEMf; 1210 } 1211 1212 force_sbe_reg = info->intr_status1_reg; 1213 force_dbe_reg = info->nack_status1_reg; 1214 1215 /* Single-bit error force */ 1216 if (SOC_REG_IS_VALID(unit, force_sbe_reg) && 1217 soc_reg_field_valid(unit, force_sbe_reg, force_field)) { 1218 SOC_IF_ERROR_RETURN 1219 (soc_reg_field32_modify(unit, force_sbe_reg, 1220 block_port, force_field, 1)); 1221 } else { 1222 LOG_ERROR(BSL_LS_SOC_COMMON, 1223 (BSL_META_U(unit, 1224 "unit %d %s.%s not valid\n"), 1225 unit, SOC_REG_NAME(unit, force_sbe_reg), 1226 SOC_FIELD_NAME(unit, force_field))); 1227 } 1228 1229 sal_usleep(1000); /* Wait for interrupt-mode logic to kick in */ 1230 1231 /* Double-bit error force */ 1232 if (SOC_REG_IS_VALID(unit, force_dbe_reg) && 1233 soc_reg_field_valid(unit, force_dbe_reg, force_field)) { 1234 SOC_IF_ERROR_RETURN 1235 (soc_reg_field32_modify(unit, force_dbe_reg, 1236 block_port, force_field, 1)); 1237 } else { 1238 LOG_ERROR(BSL_LS_SOC_COMMON, 1239 (BSL_META_U(unit, 1240 "unit %d %s.%s not valid\n"), 1241 unit, SOC_REG_NAME(unit, force_dbe_reg), 1242 SOC_FIELD_NAME(unit, force_field))); 1243 } 1244 1245 return SOC_E_NONE; 1246 } 1247 1248 int 1249 _soc_hurricane_mem_nack_error_test(int unit) 1250 { 1251 int group, table, index, rv; 1252 uint32 tmp_entry[SOC_MAX_MEM_WORDS]; 1253 uint32 parity, rval; 1254 _soc_parity_info_t *info; 1255 soc_mem_t mem; 1256 int index_min, index_max, index_range; 1257 soc_port_t block_port; 1258 soc_block_t blk; 1259 soc_field_t par_ecc_field; 1260 1261 /* loop through each group */ 1262 for (group = 0; _soc_hu_parity_group_info[group].cpi_bit; group++) { 1263 info = _soc_hu_parity_group_info[group].info; 1264 1265 SOC_BLOCK_ITER(unit, blk, 1266 _soc_hu_parity_group_info[group].blocktype) { 1267 if (_soc_hurricane_parity_block_port(unit, blk, &block_port) < 0) { 1268 continue; 1269 } 1270 1271 for (table = 0; info[table].error_field != INVALIDf; table++) { 1272 mem = info[table].mem; 1273 if (mem == INVALIDm) { 1274 continue; 1275 } 1276 if ((info[table].control_reg == INVALIDr) || 1277 !soc_reg_field_valid(unit, info[table].control_reg, 1278 info[table].enable_field)) { 1279 LOG_ERROR(BSL_LS_SOC_COMMON, 1280 (BSL_META_U(unit, 1281 "unit %d %s has no parity toggle\n"), 1282 unit, SOC_MEM_NAME(unit, mem))); 1283 continue; 1284 } 1285 1286 index_min = soc_mem_index_min(unit, mem); 1287 index_max = soc_mem_index_max(unit, mem); 1288 index_range = index_max - index_min + 1; 1289 index = index_min + (index_range / 2); 1290 1291 if ((rv = soc_mem_write(unit, mem, blk, index, 1292 soc_mem_entry_null(unit, mem))) < 0) { 1293 LOG_ERROR(BSL_LS_SOC_COMMON, 1294 (BSL_META_U(unit, 1295 "unit %d %s entry %d mem write error\n"), 1296 unit, SOC_MEM_NAME(unit, mem), index)); 1297 continue; 1298 } 1299 1300 /* Disable parity */ 1301 SOC_IF_ERROR_RETURN 1302 (soc_reg_field32_modify(unit, info[table].control_reg, 1303 block_port, info[table].enable_field, 0)); 1304 1305 if ((rv = soc_mem_read(unit, mem, blk, index, tmp_entry)) < 0) { 1306 LOG_ERROR(BSL_LS_SOC_COMMON, 1307 (BSL_META_U(unit, 1308 "unit %d %s entry %d mem read error\n"), 1309 unit, SOC_MEM_NAME(unit, mem), index)); 1310 continue; 1311 } 1312 1313 switch (info[table].type) { 1314 case _SOC_PARITY_INFO_TYPE_SINGLE_PARITY: 1315 case _SOC_PARITY_INFO_TYPE_SINGLE_COUNTER: 1316 case _SOC_PARITY_INFO_TYPE_DUAL_PARITY: 1317 par_ecc_field = EVEN_PARITYf; 1318 if (mem == L3_ECMP_COUNTm) { 1319 par_ecc_field = EVEN_PARITY_0f; 1320 } 1321 break; 1322 case _SOC_PARITY_INFO_TYPE_SINGLE_ECC: 1323 if (block_port != REG_PORT_ANY) { 1324 /* Force registers exist */ 1325 SOC_IF_ERROR_RETURN 1326 (_soc_hurricane_mem_ecc_force(unit, block_port, 1327 &(info[table]))); 1328 } 1329 par_ecc_field = ECCf; 1330 break; 1331 default: 1332 par_ecc_field = INVALIDf; 1333 } 1334 1335 if (!soc_mem_field_valid(unit, mem, par_ecc_field)) { 1336 #if !defined(SOC_NO_NAMES) 1337 if (par_ecc_field == INVALIDf) { 1338 LOG_ERROR(BSL_LS_SOC_COMMON, 1339 (BSL_META_U(unit, 1340 "unit %d %s doesn't contain INVALIDf\n"), 1341 unit, SOC_MEM_NAME(unit, mem))); 1342 } else { 1343 LOG_ERROR(BSL_LS_SOC_COMMON, 1344 (BSL_META_U(unit, 1345 "unit %d %s doesn't contain %s\n"), 1346 unit, SOC_MEM_NAME(unit, mem), 1347 soc_fieldnames[par_ecc_field])); 1348 } 1349 #endif 1350 continue; 1351 } 1352 1353 parity = 1354 soc_mem_field32_get(unit, mem, tmp_entry, par_ecc_field); 1355 parity ^= 0x1; /* Bad parity */ 1356 soc_mem_field32_set(unit, mem, tmp_entry, par_ecc_field, parity); 1357 1358 1359 if ((rv = soc_mem_write(unit, mem, blk, index, tmp_entry)) < 0) { 1360 LOG_ERROR(BSL_LS_SOC_COMMON, 1361 (BSL_META_U(unit, 1362 "unit %d %s entry %d mem write error\n"), 1363 unit, SOC_MEM_NAME(unit, mem), index)); 1364 continue; 1365 } 1366 1367 /* Enable parity */ 1368 SOC_IF_ERROR_RETURN 1369 (soc_reg_field32_modify(unit, info[table].control_reg, 1370 block_port, info[table].enable_field, 1)); 1371 1372 if ((rv = soc_mem_read(unit, mem, blk, index, tmp_entry)) < 0) { 1373 if (rv == SOC_E_FAIL) { 1374 LOG_ERROR(BSL_LS_SOC_COMMON, 1375 (BSL_META_U(unit, 1376 "unit %d NACK received for %s entry %d:\n\t"), 1377 unit, SOC_MEM_NAME(unit, mem), index)); 1378 if ((rv = _soc_hurricane_mem_nack_error_process(unit, 1379 mem, blk)) < 0) { 1380 LOG_ERROR(BSL_LS_SOC_COMMON, 1381 (BSL_META_U(unit, 1382 "unit %d %s entry %d SCHAN NACK analysis failure\n"), 1383 unit, SOC_MEM_NAME(unit, mem), index)); 1384 } 1385 } else { 1386 LOG_ERROR(BSL_LS_SOC_COMMON, 1387 (BSL_META_U(unit, 1388 "unit %d %s entry %d mem read error\n"), 1389 unit, SOC_MEM_NAME(unit, mem), index)); 1390 } 1391 } else { 1392 LOG_ERROR(BSL_LS_SOC_COMMON, 1393 (BSL_META_U(unit, 1394 "unit %d %s entry %d mem parity induction failed\n"), 1395 unit, SOC_MEM_NAME(unit, mem), index)); 1396 } 1397 sal_usleep(1000); 1398 } 1399 } 1400 } 1401 1402 /* Apply delay so LEDUP can capture correct status. */ 1403 /* coverity[result_independent_of_operands] */ 1404 SOC_IF_ERROR_RETURN(READ_CMIC_LEDUP_CTRLr(unit, &rval)); 1405 soc_reg_field_set(unit,CMIC_LEDUP_CTRLr, 1406 &rval, LEDUP_SCAN_START_DELAYf, 0x5); 1407 /* coverity[result_independent_of_operands] */ 1408 SOC_IF_ERROR_RETURN(WRITE_CMIC_LEDUP_CTRLr(unit, rval)); 1409 1410 return SOC_E_NONE; 1411 } 1412 1413 static int 1414 soc_hurricane_pipe_mem_clear(int unit) 1415 { 1416 uint32 rval; 1417 int pipe_init_usec; 1418 soc_timeout_t to; 1419 1420 /* 1421 * Reset the IPIPE and EPIPE block 1422 */ 1423 rval = 0; 1424 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_1r(unit, rval)); 1425 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, RESET_ALLf, 1); 1426 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, VALIDf, 1); 1427 /* Set count to # entries in largest IPIPE table, L2_ENTRYm */ 1428 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, COUNTf, 0x8000); 1429 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval)); 1430 1431 rval = 0; 1432 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_0r(unit, rval)); 1433 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, RESET_ALLf, 1); 1434 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, VALIDf, 1); 1435 /* Set count to # entries in largest EPIPE table, EGR_L3_NEXT_HOPm */ 1436 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, COUNTf, 0x4000); 1437 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval)); 1438 1439 /* For simulation, set timeout to 10 sec. Otherwise, timeout = 50 ms */ 1440 if (SAL_BOOT_SIMULATION) { 1441 pipe_init_usec = 10000000; 1442 } else { 1443 pipe_init_usec = 50000; 1444 } 1445 soc_timeout_init(&to, pipe_init_usec, 0); 1446 1447 /* Wait for IPIPE memory initialization done. */ 1448 do { 1449 SOC_IF_ERROR_RETURN(READ_ING_HW_RESET_CONTROL_2r(unit, &rval)); 1450 if (soc_reg_field_get(unit, ING_HW_RESET_CONTROL_2r, rval, DONEf)) { 1451 break; 1452 } 1453 if (soc_timeout_check(&to)) { 1454 LOG_WARN(BSL_LS_SOC_COMMON, 1455 (BSL_META_U(unit, 1456 "unit %d : ING_HW_RESET timeout\n"), unit)); 1457 break; 1458 } 1459 } while (TRUE); 1460 1461 /* Wait for EPIPE memory initialization done. */ 1462 do { 1463 SOC_IF_ERROR_RETURN(READ_EGR_HW_RESET_CONTROL_1r(unit, &rval)); 1464 if (soc_reg_field_get(unit, EGR_HW_RESET_CONTROL_1r, rval, DONEf)) { 1465 break; 1466 } 1467 if (soc_timeout_check(&to)) { 1468 LOG_WARN(BSL_LS_SOC_COMMON, 1469 (BSL_META_U(unit, 1470 "unit %d : EGR_HW_RESET timeout\n"), unit)); 1471 break; 1472 } 1473 } while (TRUE); 1474 1475 rval = 0; 1476 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval)); 1477 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval)); 1478 1479 /* Need to clear ING_PW_TERM_COUNTERS since it's not handled by reset control */ 1480 if (!(SAL_BOOT_QUICKTURN) && SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 1481 SOC_IF_ERROR_RETURN 1482 (soc_mem_clear(unit, ING_PW_TERM_COUNTERSm, COPYNO_ALL, TRUE)); 1483 } 1484 return SOC_E_NONE; 1485 } 1486 1487 1488 #define HU_NUM_COS 8 1489 int soc_hu_xq_mem(int unit, soc_port_t port, soc_mem_t *xq) 1490 { 1491 soc_mem_t xq_mems[] = { MMU_XQ0m, 1492 MMU_XQ1m, 1493 MMU_XQ2m, 1494 MMU_XQ3m, 1495 MMU_XQ4m, 1496 MMU_XQ5m, 1497 MMU_XQ6m, 1498 MMU_XQ7m, 1499 MMU_XQ8m, 1500 MMU_XQ9m, 1501 MMU_XQ10m, 1502 MMU_XQ11m, 1503 MMU_XQ12m, 1504 MMU_XQ13m, 1505 MMU_XQ14m, 1506 MMU_XQ15m, 1507 MMU_XQ16m, 1508 MMU_XQ17m, 1509 MMU_XQ18m, 1510 MMU_XQ19m, 1511 MMU_XQ20m, 1512 MMU_XQ21m, 1513 MMU_XQ22m, 1514 MMU_XQ23m, 1515 MMU_XQ24m, 1516 MMU_XQ25m, 1517 MMU_XQ26m, 1518 MMU_XQ27m, 1519 MMU_XQ28m, 1520 MMU_XQ29m 1521 }; 1522 int max_port; 1523 max_port = sizeof(xq_mems) / sizeof(xq_mems[0]); 1524 if (port >= max_port) { 1525 return(SOC_E_PORT); 1526 } 1527 *xq = xq_mems[port]; 1528 return(SOC_E_NONE); 1529 } 1530 1531 /* Hurricane uses 1.5MB of internal Buffers */ 1532 #define HU_MMU_BUFFER_SIZE (1.5 * 1024 * 1024) 1533 1534 /* 24GE + 4HG +1CPU ports */ 1535 #define HU_MMU_TOTAL_PORTS 29 1536 1537 #define HU_MMU_NUM_COS 8 1538 #define HU_MMU_CELL_SIZE 128 1539 1540 /* total cells = 1.5MB/128 = 12288 */ 1541 #define HU_MMU_TOTAL_CELLS (HU_MMU_BUFFER_SIZE/HU_MMU_CELL_SIZE) 1542 1543 #define HU_MMU_IN_COS_MIN_CELLS 12 1544 #define HU_MMU_IN_COS_MIN_XQS 8 1545 1546 /* cos(8) * reserved cells(12) = 96 */ 1547 #define HU_MMU_IN_PORT_STATIC_CELLS (HU_MMU_IN_COS_MIN_XQS * HU_MMU_IN_COS_MIN_CELLS) 1548 1549 /* ports(29) * per port cells(96) = 2784 */ 1550 #define HU_MMU_TOTAL_STATIC_CELLS (HU_MMU_TOTAL_PORTS * HU_MMU_IN_PORT_STATIC_CELLS) 1551 1552 /* total cells(12288) - static cells(2784) = 9504 */ 1553 #define HU_MMU_TOTAL_DYNAMIC_CELLS (HU_MMU_TOTAL_CELLS - HU_MMU_TOTAL_STATIC_CELLS) 1554 1555 /* Every port has 1536 packet pointers(XQs) */ 1556 #define HU_MMU_IN_PORT_TOTAL_XQS 1536 1557 /* number of cos(8) * minimum xqs per cos(8) = 64 */ 1558 #define HU_MMU_IN_PORT_STATIC_XQS (HU_MMU_NUM_COS * HU_MMU_IN_COS_MIN_XQS) 1559 /* total xqs (1536)- static xqs(64) = 1472 */ 1560 #define HU_MMU_IN_PORT_DYNAMIC_XQS (HU_MMU_IN_PORT_TOTAL_XQS - HU_MMU_IN_PORT_STATIC_XQS) 1561 1562 #define HU_MMU_MAX_PKT_SIZE 9728 1563 /* xoff threshold = 80 */ 1564 #define HU_MMU_XOFF_CELL_LIMIT ((HU_MMU_MAX_PKT_SIZE/HU_MMU_CELL_SIZE) + 4) 1565 1566 /* max limit for pri-0 = (xoff threshold(80) + max packet size/128 *2 + 16)*23 */ 1567 #define HU_MMU_MAX_CELL_LIMIT_PRI_0 5704 1568 /* max limit for pri-1-7 = (total xqs/128 * 4)= 1536/128*4 */ 1569 #define HU_MMU_MAX_CELL_LIMIT_PRI_1_7 48 1570 1571 /* cell limit0 + 7 * cell limit for pri1-7 = 6040 */ 1572 #define HU_MMU_DYN_CELL_LIMIT (HU_MMU_MAX_CELL_LIMIT_PRI_0 + \ 1573 ((HU_MMU_NUM_COS -1) * HU_MMU_MAX_CELL_LIMIT_PRI_1_7)) 1574 1575 int 1576 soc_hurricane_mmu_init(int unit) 1577 { 1578 int cos; 1579 soc_port_t port; 1580 uint32 val, oval, cfap_max_idx, tm; 1581 int age[HU_NUM_COS], max_age, min_age; 1582 int age_enable, disabled_age; 1583 int skid_mark; 1584 uint32 dyn_xq_per_port; 1585 uint32 limit; 1586 uint32 xq_limit, pkt_limit, cell_limit; 1587 uint32 cos_min_xqs, cos_min_cells; 1588 uint16 dev_id; 1589 uint8 rev_id; 1590 1591 cfap_max_idx = soc_mem_index_max(unit, MMU_CFAPm); 1592 SOC_IF_ERROR_RETURN(READ_CFAPCONFIGr(unit, &val)); 1593 oval = val; 1594 soc_reg_field_set(unit, CFAPCONFIGr, &val, CFAPPOOLSIZEf, cfap_max_idx); 1595 if (oval != val) { 1596 SOC_IF_ERROR_RETURN(WRITE_CFAPCONFIGr(unit, val)); 1597 } 1598 1599 /* set skidmarker to 3 */ 1600 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &val)); 1601 soc_reg_field_set(unit, MISCCONFIGr, &val, SKIDMARKERf, 3); 1602 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, val)); 1603 1604 /* Every inactive COSQ consumes skid mark + 4 XQs; remove them from pool */ 1605 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &val)); 1606 skid_mark = soc_reg_field_get(unit, MISCCONFIGr, val, SKIDMARKERf) + 4; 1607 1608 soc_cm_get_id(unit, &dev_id, &rev_id); 1609 1610 if (dev_id != BCM56147_DEVICE_ID) { 1611 /* total dynamic xqs - skid mark - 9(reserved xqs) */ 1612 dyn_xq_per_port = HU_MMU_IN_PORT_DYNAMIC_XQS - skid_mark - 9; 1613 /* limit includes the static minimum cells as well */ 1614 xq_limit = dyn_xq_per_port + 8; 1615 cos_min_xqs = HU_MMU_IN_COS_MIN_XQS; 1616 cos_min_cells = HU_MMU_IN_COS_MIN_CELLS; 1617 } 1618 else { 1619 /* dynamic xqs = total xqs - static xqs(num of cos * per cos reserve(4)) */ 1620 dyn_xq_per_port = HU_MMU_IN_PORT_TOTAL_XQS - (HU_MMU_NUM_COS * 4); 1621 /* total dynamic xqs = dynamic xqs - skid mark - 9(reserved xqs) */ 1622 dyn_xq_per_port = dyn_xq_per_port - skid_mark - 9; 1623 /* limit includes the static minimum cells as well */ 1624 xq_limit = dyn_xq_per_port + 4; 1625 cos_min_xqs = HU_MMU_IN_COS_MIN_XQS/2; 1626 cos_min_cells = HU_MMU_IN_COS_MIN_CELLS + 4; 1627 } 1628 1629 PBMP_ALL_ITER(unit, port) { 1630 1631 for (cos = 0; cos < NUM_COS(unit); cos++) { 1632 /* 1633 * The HOLCOSPKTSETLIMITr register controls BOTH the XQ 1634 * size per cosq AND the HOL set limit for that cosq. 1635 */ 1636 SOC_IF_ERROR_RETURN 1637 (READ_HOLCOSPKTSETLIMITr(unit, port, cos, &val)); 1638 soc_reg_field_set(unit, HOLCOSPKTSETLIMITr, &val, 1639 PKTSETLIMITf, 1640 xq_limit); 1641 SOC_IF_ERROR_RETURN 1642 (WRITE_HOLCOSPKTSETLIMITr(unit, port, cos, val)); 1643 1644 /* reset limit is set limit - 4 */ 1645 SOC_IF_ERROR_RETURN 1646 (READ_HOLCOSPKTRESETLIMITr(unit, port, cos, &val)); 1647 soc_reg_field_set(unit, HOLCOSPKTRESETLIMITr, &val, 1648 PKTRESETLIMITf, 1649 xq_limit-4); 1650 SOC_IF_ERROR_RETURN 1651 (WRITE_HOLCOSPKTRESETLIMITr(unit, port, cos, val)); 1652 1653 val = 0; 1654 soc_reg_field_set(unit, HOLCOSMINXQCNTr, &val, 1655 HOLCOSMINXQCNTf, cos_min_xqs); 1656 SOC_IF_ERROR_RETURN 1657 (WRITE_HOLCOSMINXQCNTr(unit, port, cos, val)); 1658 1659 val = 0; 1660 soc_reg_field_set(unit, LWMCOSCELLSETLIMITr, &val, 1661 CELLSETLIMITf, cos_min_cells); 1662 soc_reg_field_set(unit, LWMCOSCELLSETLIMITr, &val, 1663 CELLRESETLIMITf, cos_min_cells); 1664 SOC_IF_ERROR_RETURN 1665 (WRITE_LWMCOSCELLSETLIMITr(unit, port, cos, val)); 1666 1667 cell_limit = 0; 1668 if (dev_id != BCM56147_DEVICE_ID) { 1669 if(!cos) { 1670 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 1671 CELLMAXLIMITf, HU_MMU_MAX_CELL_LIMIT_PRI_0); 1672 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 1673 CELLMAXRESUMELIMITf, HU_MMU_MAX_CELL_LIMIT_PRI_0 - 12); 1674 } else { 1675 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 1676 CELLMAXLIMITf, HU_MMU_MAX_CELL_LIMIT_PRI_1_7); 1677 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 1678 CELLMAXRESUMELIMITf, HU_MMU_MAX_CELL_LIMIT_PRI_1_7 - 12); 1679 } 1680 } 1681 else { 1682 /* use the settings given by design team for 56147 */ 1683 if(!cos) { 1684 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 1685 CELLMAXLIMITf, 8000); 1686 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 1687 CELLMAXRESUMELIMITf, 7238); 1688 } else { 1689 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 1690 CELLMAXLIMITf, 7250); 1691 soc_reg_field_set(unit, HOLCOSCELLMAXLIMITr, &cell_limit, 1692 CELLMAXRESUMELIMITf, 7238); 1693 } 1694 } 1695 SOC_IF_ERROR_RETURN 1696 (WRITE_HOLCOSCELLMAXLIMITr(unit, port, cos, cell_limit)); 1697 } 1698 1699 val = 0; 1700 soc_reg_field_set(unit, DYNXQCNTPORTr, &val, 1701 DYNXQCNTPORTf, dyn_xq_per_port); 1702 SOC_IF_ERROR_RETURN(WRITE_DYNXQCNTPORTr(unit, port, val)); 1703 1704 val = 0; 1705 soc_reg_field_set(unit, DYNRESETLIMPORTr, &val, 1706 DYNRESETLIMPORTf, dyn_xq_per_port - 4); 1707 SOC_IF_ERROR_RETURN(WRITE_DYNRESETLIMPORTr(unit, port, val)); 1708 1709 cell_limit = 0; 1710 soc_reg_field_set(unit, IBPDISCARDSETLIMITr, &cell_limit, 1711 DISCARDSETLIMITf, HU_MMU_TOTAL_CELLS-1); 1712 SOC_IF_ERROR_RETURN(WRITE_IBPDISCARDSETLIMITr(unit, port, cell_limit)); 1713 1714 if (dev_id != BCM56147_DEVICE_ID) { 1715 val = 0; 1716 soc_reg_field_set(unit, DYNCELLLIMITr, &val, 1717 DYNCELLSETLIMITf, HU_MMU_DYN_CELL_LIMIT); 1718 soc_reg_field_set(unit, DYNCELLLIMITr, &val, 1719 DYNCELLRESETLIMITf, HU_MMU_DYN_CELL_LIMIT - 24); 1720 SOC_IF_ERROR_RETURN(WRITE_DYNCELLLIMITr(unit, port, val)); 1721 1722 pkt_limit = 0; 1723 soc_reg_field_set(unit, IBPPKTSETLIMITr, &pkt_limit, 1724 PKTSETLIMITf, HU_MMU_IN_COS_MIN_CELLS); 1725 SOC_IF_ERROR_RETURN(WRITE_IBPPKTSETLIMITr(unit, port, pkt_limit)); 1726 1727 cell_limit = 0; 1728 soc_reg_field_set(unit, IBPCELLSETLIMITr, &cell_limit, 1729 CELLSETLIMITf, HU_MMU_XOFF_CELL_LIMIT); 1730 SOC_IF_ERROR_RETURN(WRITE_IBPCELLSETLIMITr(unit, port, cell_limit)); 1731 } 1732 else { 1733 /* use the settings given by design team for 56147 */ 1734 val = 0; 1735 /* dyn cell limit = 8000 + (total cos -1)*4*2048/128 */ 1736 soc_reg_field_set(unit, DYNCELLLIMITr, &val, 1737 DYNCELLSETLIMITf, 8448); 1738 soc_reg_field_set(unit, DYNCELLLIMITr, &val, 1739 DYNCELLRESETLIMITf, 8424); 1740 SOC_IF_ERROR_RETURN(WRITE_DYNCELLLIMITr(unit, port, val)); 1741 1742 pkt_limit = 0; 1743 soc_reg_field_set(unit, IBPPKTSETLIMITr, &pkt_limit, 1744 PKTSETLIMITf, 33); 1745 SOC_IF_ERROR_RETURN(WRITE_IBPPKTSETLIMITr(unit, port, pkt_limit)); 1746 1747 cell_limit = 0; 1748 soc_reg_field_set(unit, IBPCELLSETLIMITr, &cell_limit, 1749 CELLSETLIMITf, 36); 1750 SOC_IF_ERROR_RETURN(WRITE_IBPCELLSETLIMITr(unit, port, cell_limit)); 1751 1752 /* E2EFC configuration */ 1753 if (IS_HG_PORT(unit, port)){ 1754 SOC_IF_ERROR_RETURN(READ_XPORT_CONFIGr(unit, port, &val)); 1755 soc_reg_field_set(unit, XPORT_CONFIGr, &val, E2E_IBP_ENf, 1); 1756 SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, val)); 1757 1758 SOC_IF_ERROR_RETURN(READ_IE2E_CONTROLr(unit, port, &val)); 1759 soc_reg_field_set(unit, IE2E_CONTROLr, &val, IBP_ENABLEf, 1); 1760 SOC_IF_ERROR_RETURN(WRITE_IE2E_CONTROLr(unit, port, val)); 1761 1762 val = 0; 1763 soc_reg_field_set(unit, E2EFC_HG_MIN_TX_TIMERr, &val, 1764 LGf, 0); 1765 soc_reg_field_set(unit, E2EFC_HG_MIN_TX_TIMERr, &val, 1766 TIMERf, 1); 1767 SOC_IF_ERROR_RETURN(WRITE_E2EFC_HG_MIN_TX_TIMERr(unit, port-26, val)); 1768 1769 val = 0; 1770 soc_reg_field_set(unit, E2EFC_HG_MAX_TX_TIMERr, &val, 1771 LGf, 1); 1772 soc_reg_field_set(unit, E2EFC_HG_MAX_TX_TIMERr, &val, 1773 TIMERf, 640); 1774 SOC_IF_ERROR_RETURN(WRITE_E2EFC_HG_MAX_TX_TIMERr(unit, port-26, val)); 1775 1776 limit = 0; 1777 soc_reg_field_set(unit, E2EFC_CNT_SET_LIMITr, &limit, 1778 PKT_SET_LIMITf, 1456); 1779 soc_reg_field_set(unit, E2EFC_CNT_SET_LIMITr, &limit, 1780 CELL_SET_LIMITf, 9504); 1781 SOC_IF_ERROR_RETURN(WRITE_E2EFC_CNT_SET_LIMITr(unit, port, limit)); 1782 1783 limit = 0; 1784 soc_reg_field_set(unit, E2EFC_CNT_RESET_LIMITr, &limit, 1785 PKT_RESET_LIMITf, 1456); 1786 soc_reg_field_set(unit, E2EFC_CNT_RESET_LIMITr, &limit, 1787 CELL_RESET_LIMITf, 9504); 1788 SOC_IF_ERROR_RETURN(WRITE_E2EFC_CNT_RESET_LIMITr(unit, port, limit)); 1789 1790 limit = 0; 1791 soc_reg_field_set(unit, E2EFC_CNT_DISC_LIMITr, &limit, 1792 PKT_DISC_LIMITf, 1456); 1793 soc_reg_field_set(unit, E2EFC_CNT_DISC_LIMITr, &limit, 1794 CELL_DISC_LIMITf, 9504); 1795 SOC_IF_ERROR_RETURN(WRITE_E2EFC_CNT_DISC_LIMITr(unit, port, limit)); 1796 } 1797 else { 1798 limit = 0; 1799 soc_reg_field_set(unit, E2EFC_CNT_SET_LIMITr, &limit, 1800 PKT_SET_LIMITf, 33); 1801 soc_reg_field_set(unit, E2EFC_CNT_SET_LIMITr, &limit, 1802 CELL_SET_LIMITf, 36); 1803 SOC_IF_ERROR_RETURN(WRITE_E2EFC_CNT_SET_LIMITr(unit, port, limit)); 1804 1805 limit = 0; 1806 soc_reg_field_set(unit, E2EFC_CNT_RESET_LIMITr, &limit, 1807 PKT_RESET_LIMITf, 24); 1808 soc_reg_field_set(unit, E2EFC_CNT_RESET_LIMITr, &limit, 1809 CELL_RESET_LIMITf, 26); 1810 SOC_IF_ERROR_RETURN(WRITE_E2EFC_CNT_RESET_LIMITr(unit, port, limit)); 1811 1812 limit = 0; 1813 soc_reg_field_set(unit, E2EFC_CNT_DISC_LIMITr, &limit, 1814 PKT_DISC_LIMITf, 1456); 1815 soc_reg_field_set(unit, E2EFC_CNT_DISC_LIMITr, &limit, 1816 CELL_DISC_LIMITf, 9504); 1817 SOC_IF_ERROR_RETURN(WRITE_E2EFC_CNT_DISC_LIMITr(unit, port, limit)); 1818 1819 } 1820 1821 } 1822 1823 } 1824 1825 /* device specific dynamic cell limit */ 1826 if (dev_id != BCM56147_DEVICE_ID) { 1827 cell_limit = 0; 1828 soc_reg_field_set(unit, TOTALDYNCELLSETLIMITr, 1829 &cell_limit, TOTALDYNCELLSETLIMITf, HU_MMU_TOTAL_DYNAMIC_CELLS); 1830 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLSETLIMITr(unit, cell_limit)); 1831 cell_limit = 0; 1832 soc_reg_field_set(unit, TOTALDYNCELLRESETLIMITr, 1833 &cell_limit, TOTALDYNCELLRESETLIMITf, HU_MMU_TOTAL_DYNAMIC_CELLS - 24); 1834 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLRESETLIMITr(unit, cell_limit)); 1835 } 1836 else { 1837 cell_limit = 0; 1838 soc_reg_field_set(unit, TOTALDYNCELLSETLIMITr, 1839 &cell_limit, TOTALDYNCELLSETLIMITf, 8576); 1840 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLSETLIMITr(unit, cell_limit)); 1841 cell_limit = 0; 1842 soc_reg_field_set(unit, TOTALDYNCELLRESETLIMITr, 1843 &cell_limit, TOTALDYNCELLRESETLIMITf, 8552); 1844 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLRESETLIMITr(unit, cell_limit)); 1845 1846 /* E2EFC configuration */ 1847 SOC_IF_ERROR_RETURN(READ_E2EFC_IBP_ENr(unit, &val)); 1848 soc_reg_field_set(unit, E2EFC_IBP_ENr, &val, ENf, 1); 1849 SOC_IF_ERROR_RETURN(WRITE_E2EFC_IBP_ENr(unit, val)); 1850 } 1851 1852 /* 1853 * Configure per-XQ packet aging for the various COSQs. 1854 * 1855 * The shortest age allowed by H/W is 250 microseconds. 1856 * The longest age allowed is 7.162 seconds (7162 msec). 1857 * The maximum ratio between the longest age and the shortest 1858 * (nonzero) age is 7:2. 1859 */ 1860 age_enable = disabled_age = max_age = 0; 1861 min_age = 7162; 1862 for (cos = 0; cos < NUM_COS(unit); cos++) { 1863 if ((age[cos] = 1864 soc_property_suffix_num_get(unit, cos, spn_MMU_XQ_AGING, 1865 "cos", 0)) > 0) { 1866 age_enable = 1; 1867 if (age[cos] > 7162) { 1868 age[cos] = 7162; 1869 } 1870 if (age[cos] < min_age) { 1871 min_age = age[cos]; 1872 } 1873 } else { 1874 disabled_age = 1; 1875 age[cos] = 0; 1876 } 1877 if (age[cos] > max_age) { 1878 max_age = age[cos]; 1879 } 1880 } 1881 if (!age_enable) { 1882 /* Disable packet aging on all COSQs */ 1883 SOC_IF_ERROR_RETURN(WRITE_PKTAGINGTIMERr(unit, 0)); 1884 SOC_IF_ERROR_RETURN(WRITE_PKTAGINGLIMITr(unit, 0)); /* Aesthetic */ 1885 } else { 1886 uint32 regval = 0; 1887 uint32 timerval; 1888 1889 /* Enforce the 7:2 ratio between min and max values */ 1890 if ((((max_age * 2)+6) / 7) > min_age) { 1891 /* Keep requested max age; make min_age comply */ 1892 min_age = ((max_age * 2) + 6) / 7; 1893 } 1894 1895 /* 1896 * Give up granularity for range, if we need to 1897 * "disable" (max out) aging for any COSQ(s). 1898 */ 1899 if (disabled_age) { 1900 /* Max range */ 1901 max_age = min_age * 7 / 2; 1902 } 1903 1904 /* 1905 * Compute shortest duration of one PKTAGINGTIMERr cycle. 1906 * This duration is 1/7th of the longest packet age. 1907 * This duration is in units of 125 usec (msec * 8). 1908 */ 1909 timerval = ((8 * max_age) + 6) / 7; 1910 SOC_IF_ERROR_RETURN(WRITE_PKTAGINGTIMERr(unit, timerval)); 1911 1912 for (cos = 0; cos < NUM_COS(unit); cos++) { 1913 if (!age[cos]) { 1914 /* 1915 * Requested to be disabled, but cannot disable individual 1916 * COSQs once packet aging is enabled. Therefore, mark 1917 * this COSQ's aging duration as maxed out. 1918 */ 1919 age[cos] = -1; 1920 } else if (age[cos] < min_age) { 1921 age[cos] = min_age; 1922 } 1923 1924 /* Normalize each "age" into # of PKTAGINGTIMERr cycles. */ 1925 if (age[cos] > 0) { 1926 /* coverity[divide_by_zero : FALSE] */ 1927 age[cos] = ((8 * age[cos]) + timerval - 1) / timerval; 1928 } 1929 else { 1930 age[cos] = 7; 1931 } 1932 /* Format each "age" for its appropriate field */ 1933 regval |= ((7 - age[cos]) << (cos * 3)); 1934 } 1935 SOC_IF_ERROR_RETURN(WRITE_PKTAGINGLIMITr(unit, regval)); 1936 } 1937 1938 /* Apply TM=0x10 setting for all CAMs */ 1939 tm=0x10; 1940 val = 0; 1941 soc_reg_field_set(unit, SW2_RAM_CONTROL_4r, &val, 1942 CPU_COS_MAP_TCAM_TMf, tm); 1943 SOC_IF_ERROR_RETURN(WRITE_SW2_RAM_CONTROL_4r_REG32(unit, val)); 1944 1945 val = 0; 1946 soc_reg_field_set(unit, L2_USER_ENTRY_CAM_DBGCTRLr, &val, 1947 TMf, tm); 1948 SOC_IF_ERROR_RETURN(WRITE_L2_USER_ENTRY_CAM_DBGCTRLr(unit, val)); 1949 1950 1951 SOC_IF_ERROR_RETURN(READ_VLAN_SUBNET_CAM_DBGCTRLr(unit, &val)); 1952 soc_reg_field_set(unit, VLAN_SUBNET_CAM_DBGCTRLr, &val, 1953 TMf, tm); 1954 SOC_IF_ERROR_RETURN(WRITE_VLAN_SUBNET_CAM_DBGCTRLr(unit, val)); 1955 1956 val = 0; 1957 soc_reg_field_set(unit, FP_CAM_CONTROL_TM_7_THRU_0r, &val, 1958 ALL_TCAMS_TM_7_0f, tm); 1959 soc_reg_field_set(unit, FP_CAM_CONTROL_TM_7_THRU_0r, &val, 1960 ALL_GLOBAL_MASK_TCAMS_TM_7_0f, tm); 1961 SOC_IF_ERROR_RETURN(WRITE_FP_CAM_CONTROL_TM_7_THRU_0r(unit, val)); 1962 1963 /* 1964 * Port enable 1965 */ 1966 val = 0; 1967 soc_reg_field_set(unit, MMUPORTENABLEr, &val, MMUPORTENABLEf, 1968 SOC_PBMP_WORD_GET(PBMP_ALL(unit), 0)); 1969 SOC_IF_ERROR_RETURN(WRITE_MMUPORTENABLEr(unit, val)); 1970 1971 return SOC_E_NONE; 1972 } 1973 1974 1975 1976 uint32 hu_tdm[75] = {2,14,26,27,28,29, 1977 3,15,26,27,28,29, 1978 4,16,26,27,28,29, 1979 5,17,26,27,28,29, 1980 0, 1981 6,18,26,27,28,29, 1982 7,19,26,27,28,29, 1983 8,20,26,27,28,29, 1984 9,21,26,27,28,29, 1985 0, 1986 10,22,26,27,28,29, 1987 11,23,26,27,28,29, 1988 12,24,26,27,28,29, 1989 13,25,26,27,28,29, 1990 30}; 1991 1992 int 1993 soc_hurricane_misc_init(int unit) 1994 { 1995 #define NUM_XQPORT 4 1996 uint32 rval; 1997 uint32 prev_reg_addr; 1998 uint64 reg64; 1999 int port, i; 2000 uint32 mode; 2001 uint32 *arr; 2002 int tdm_size; 2003 iarb_tdm_table_entry_t iarb_tdm; 2004 mmu_arb_tdm_table_entry_t mmu_arb_tdm; 2005 uint32 imask; 2006 soc_field_t fields[3]; 2007 uint32 values[3]; 2008 2009 for (port = 26; port <= 29; port++) { 2010 if (SOC_PORT_VALID(unit, port)) { 2011 mode = 1; /* gport mode */ 2012 if (IS_XE_PORT(unit, port) || IS_HG_PORT(unit, port)) { 2013 soc_port_cmap_set(unit, port, SOC_CTR_TYPE_XE); 2014 mode = 2; /* xport mode */ 2015 } 2016 SOC_IF_ERROR_RETURN(READ_XQPORT_MODE_REGr(unit, port, &rval)); 2017 soc_reg_field_set(unit, XQPORT_MODE_REGr, &rval, XQPORT_MODE_BITSf, mode); 2018 SOC_IF_ERROR_RETURN(WRITE_XQPORT_MODE_REGr(unit, port, rval)); 2019 } /* if SOC_PORT_VALID */ 2020 } /* for port= */ 2021 2022 SOC_IF_ERROR_RETURN(READ_IARB_TDM_CONTROLr(unit, &rval)); 2023 soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, DISABLEf, 1); 2024 soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, TDM_WRAP_PTRf, 83); 2025 SOC_IF_ERROR_RETURN(WRITE_IARB_TDM_CONTROLr(unit, rval)); 2026 2027 /* Program for Different TDM mode */ 2028 tdm_size = 75; 2029 arr = hu_tdm; 2030 for (i = 0; i < tdm_size; i++) { 2031 sal_memset(&iarb_tdm, 0, sizeof(iarb_tdm_table_entry_t)); 2032 sal_memset(&mmu_arb_tdm, 0, sizeof(mmu_arb_tdm_table_entry_t)); 2033 soc_IARB_TDM_TABLEm_field32_set(unit, &iarb_tdm, PORT_NUMf, 2034 arr[i]); 2035 soc_MMU_ARB_TDM_TABLEm_field32_set(unit, &mmu_arb_tdm, PORT_NUMf, 2036 arr[i]); 2037 if (i == tdm_size - 1) { 2038 soc_MMU_ARB_TDM_TABLEm_field32_set(unit, &mmu_arb_tdm, WRAP_ENf, 1); 2039 } 2040 SOC_IF_ERROR_RETURN(WRITE_IARB_TDM_TABLEm(unit, SOC_BLOCK_ALL, i, 2041 &iarb_tdm)); 2042 SOC_IF_ERROR_RETURN(WRITE_MMU_ARB_TDM_TABLEm(unit, SOC_BLOCK_ALL, i, 2043 &mmu_arb_tdm)); 2044 } 2045 rval = 0; 2046 soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, DISABLEf, 0); 2047 soc_reg_field_set(unit, IARB_TDM_CONTROLr, &rval, TDM_WRAP_PTRf, 2048 tdm_size -1); 2049 SOC_IF_ERROR_RETURN(WRITE_IARB_TDM_CONTROLr(unit, rval)); 2050 2051 if (!SOC_IS_RELOADING(unit)) { 2052 /* Clear IPIPE/EIPIE Memories */ 2053 SOC_IF_ERROR_RETURN(soc_hurricane_pipe_mem_clear(unit)); 2054 } 2055 2056 /* Turn on ingress/egress/mmu parity */ 2057 if (soc_property_get(unit, spn_PARITY_ENABLE, TRUE)) { 2058 _soc_hurricane_parity_enable(unit, TRUE); 2059 if (soc_property_get(unit, "parity_test", FALSE)) { 2060 _soc_hurricane_mem_nack_error_test(unit); 2061 } 2062 memset(&_hurricane_ser_functions, 0, sizeof(soc_ser_functions_t)); 2063 _hurricane_ser_functions._soc_ser_parity_error_intr_f = 2064 &soc_hurricane_parity_error; 2065 soc_ser_function_register(unit, &_hurricane_ser_functions); 2066 } 2067 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 2068 soc_reg_field_set(unit, MISCCONFIGr, &rval, METERING_CLK_ENf, 1); 2069 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval)); 2070 2071 /* Enable dual hash on L2 and L3 tables */ 2072 fields[0] = ENABLEf; 2073 values[0] = 1; 2074 fields[1] = HASH_SELECTf; 2075 values[1] = FB_HASH_CRC32_LOWER; 2076 fields[2] = INSERT_LEAST_FULL_HALFf; 2077 values[2] = 1; 2078 SOC_IF_ERROR_RETURN 2079 (soc_reg_fields32_modify(unit, L2_AUX_HASH_CONTROLr, REG_PORT_ANY, 3, 2080 fields, values)); 2081 SOC_IF_ERROR_RETURN 2082 (soc_reg_fields32_modify(unit, L3_AUX_HASH_CONTROLr, REG_PORT_ANY, 3, 2083 fields, values)); 2084 2085 /* 2086 * Egress Enable 2087 */ 2088 rval = 0; 2089 soc_reg_field_set(unit, EGR_ENABLEr, &rval, PRT_ENABLEf, 1); 2090 PBMP_ALL_ITER(unit, port) { 2091 SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, rval)); 2092 } 2093 2094 COMPILER_64_ZERO(reg64); 2095 soc_reg64_field32_set(unit, EPC_LINK_BMAP_64r, ®64, PORT_BITMAP_LOf, 2096 SOC_PBMP_WORD_GET(PBMP_CMIC(unit), 0)); 2097 SOC_IF_ERROR_RETURN(WRITE_EPC_LINK_BMAP_64r(unit, reg64)); 2098 2099 /* GMAC init should be moved to mac */ 2100 rval = 0; 2101 soc_reg_field_set(unit, GPORT_CONFIGr, &rval, CLR_CNTf, 1); 2102 prev_reg_addr = 0xffffffff; 2103 PBMP_E_ITER(unit, port) { 2104 uint32 reg_addr; 2105 if (IS_XQ_PORT(unit, port)) { 2106 continue; 2107 } 2108 reg_addr = soc_reg_addr(unit, GPORT_CONFIGr, port, 0); 2109 if (reg_addr != prev_reg_addr) { 2110 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, rval)); 2111 prev_reg_addr = reg_addr; 2112 } 2113 } 2114 prev_reg_addr = 0xffffffff; 2115 soc_reg_field_set(unit, GPORT_CONFIGr, &rval, CLR_CNTf, 0); 2116 PBMP_E_ITER(unit, port) { 2117 uint32 reg_addr; 2118 if (IS_XQ_PORT(unit, port)) { 2119 continue; 2120 } 2121 reg_addr = soc_reg_addr(unit, GPORT_CONFIGr, port, 0); 2122 if (reg_addr != prev_reg_addr) { 2123 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, rval)); 2124 prev_reg_addr = reg_addr; 2125 } 2126 } 2127 2128 /* XMAC init should be moved to mac */ 2129 if (SOC_PBMP_NOT_NULL(PBMP_XE_ALL(unit)) || 2130 SOC_PBMP_NOT_NULL(PBMP_HG_ALL(unit))) { 2131 rval = 0; 2132 soc_reg_field_set(unit, XPORT_CONFIGr, &rval, XPORT_ENf, 1); 2133 soc_reg_field_set(unit, XPORT_CONFIGr, &rval, HIGIG_MODEf, 1); 2134 PBMP_HG_ITER(unit, port) { 2135 SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, rval)); 2136 } 2137 soc_reg_field_set(unit, XPORT_CONFIGr, &rval, HIGIG_MODEf, 0); 2138 PBMP_XE_ITER(unit, port) { 2139 SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, rval)); 2140 } 2141 } 2142 2143 SOC_IF_ERROR_RETURN(READ_ING_CONFIG_64r(unit, ®64)); 2144 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 2145 L3SRC_HIT_ENABLEf, 1); 2146 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 2147 L2DST_HIT_ENABLEf, 1); 2148 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 2149 APPLY_EGR_MASK_ON_L2f, 1); 2150 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 2151 APPLY_EGR_MASK_ON_L3f, 1); 2152 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 2153 ARP_RARP_TO_FPf, 0x3); /* enable both ARP & RARP */ 2154 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 2155 ARP_VALIDATION_ENf, 1); 2156 soc_reg64_field32_set(unit, ING_CONFIG_64r, ®64, 2157 IGNORE_HG_HDR_LAG_FAILOVERf, 1); 2158 SOC_IF_ERROR_RETURN(WRITE_ING_CONFIG_64r(unit, reg64)); 2159 2160 SOC_IF_ERROR_RETURN(READ_EGR_CONFIG_1r(unit, &rval)); 2161 soc_reg_field_set(unit, EGR_CONFIG_1r, &rval, RING_MODEf, 1); 2162 SOC_IF_ERROR_RETURN(WRITE_EGR_CONFIG_1r(unit, rval)); 2163 2164 /* 2165 * Set reference clock (based on 200MHz core clock) 2166 * to be 200MHz * (1/40) = 5MHz 2167 */ 2168 rval = 0; 2169 soc_reg_field_set(unit, CMIC_RATE_ADJUSTr, &rval, DIVISORf, 40); 2170 soc_reg_field_set(unit, CMIC_RATE_ADJUSTr, &rval, DIVIDENDf, 1); 2171 /* coverity[result_independent_of_operands] */ 2172 SOC_IF_ERROR_RETURN(WRITE_CMIC_RATE_ADJUSTr(unit, rval)); 2173 2174 /* Match the Internal MDC freq with above for External MDC */ 2175 rval = 0; 2176 soc_reg_field_set (unit, CMIC_RATE_ADJUST_INT_MDIOr, &rval, DIVISORf, 40); 2177 soc_reg_field_set (unit, CMIC_RATE_ADJUST_INT_MDIOr, &rval, DIVIDENDf, 1); 2178 /* coverity[result_independent_of_operands] */ 2179 SOC_IF_ERROR_RETURN(WRITE_CMIC_RATE_ADJUST_INT_MDIOr(unit, rval)); 2180 2181 /* 2182 * Set reference clock (based on 200MHz core clock) 2183 * to be 200MHz * (1/8) = 25MHz 2184 */ 2185 rval = 0; 2186 soc_reg_field_set(unit, CMIC_RATE_ADJUST_I2Cr, &rval, DIVISORf, 8); 2187 soc_reg_field_set(unit, CMIC_RATE_ADJUST_I2Cr, &rval, DIVIDENDf, 1); 2188 /* coverity[result_independent_of_operands] */ 2189 SOC_IF_ERROR_RETURN(WRITE_CMIC_RATE_ADJUST_I2Cr(unit, rval)); 2190 2191 rval = 0; 2192 soc_reg_field_set(unit, CMIC_RATE_ADJUST_STDMAr, &rval, DIVISORf, 8); 2193 soc_reg_field_set(unit, CMIC_RATE_ADJUST_STDMAr, &rval, DIVIDENDf, 1); 2194 /* coverity[result_independent_of_operands] */ 2195 SOC_IF_ERROR_RETURN(WRITE_CMIC_RATE_ADJUST_STDMAr(unit, rval)); 2196 2197 rval = 0x01; /* 125KHz I2C sampling rate based on 5Mhz reference clock */ 2198 /* coverity[result_independent_of_operands] */ 2199 SOC_IF_ERROR_RETURN(WRITE_CMIC_I2C_STATr(unit, rval)); 2200 2201 /* GMAC init should be moved to mac */ 2202 rval = 0; 2203 soc_reg_field_set(unit, GPORT_CONFIGr, &rval, CLR_CNTf, 1); 2204 soc_reg_field_set(unit, GPORT_CONFIGr, &rval, GPORT_ENf, 1); 2205 PBMP_E_ITER(unit, port) { 2206 if (IS_XQ_PORT(unit, port)) { 2207 continue; 2208 } 2209 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, rval)); 2210 } 2211 soc_reg_field_set(unit, GPORT_CONFIGr, &rval, CLR_CNTf, 0); 2212 PBMP_E_ITER(unit, port) { 2213 if (IS_XQ_PORT(unit, port)) { 2214 continue; 2215 } 2216 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, rval)); 2217 } 2218 2219 /* The HW defaults for EGR_VLAN_CONTROL_1.VT_MISS_UNTAG == 1, which 2220 * causes the outer tag to be removed from packets that don't have 2221 * a hit in the egress vlan tranlation table. Set to 0 to disable this. 2222 */ 2223 rval = 0; 2224 soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &rval, VT_MISS_UNTAGf, 0); 2225 2226 /* Enable pri/cfi remarking on egress ports. */ 2227 soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &rval, REMARK_OUTER_DOT1Pf, 2228 1); 2229 PBMP_ALL_ITER(unit, port) { 2230 SOC_IF_ERROR_RETURN(WRITE_EGR_VLAN_CONTROL_1r(unit, port, rval)); 2231 } 2232 2233 /* Multicast range initialization */ 2234 SOC_IF_ERROR_RETURN 2235 (soc_hbx_higig2_mcast_sizes_set(unit, 2236 soc_property_get(unit, spn_HIGIG2_MULTICAST_VLAN_RANGE, 2237 SOC_HBX_MULTICAST_RANGE_DEFAULT), 2238 soc_property_get(unit, spn_HIGIG2_MULTICAST_L2_RANGE, 2239 SOC_HBX_MULTICAST_RANGE_DEFAULT), 2240 soc_property_get(unit, spn_HIGIG2_MULTICAST_L3_RANGE, 2241 SOC_HBX_MULTICAST_RANGE_DEFAULT))); 2242 2243 /* Setup SW2_FP_DST_ACTION_CONTROL */ 2244 fields[0] = HGTRUNK_RES_ENf; 2245 fields[1] = LAG_RES_ENf; 2246 values[0] = values[1] = 1; 2247 SOC_IF_ERROR_RETURN 2248 (soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr, 2249 REG_PORT_ANY, 2, fields, values)); 2250 2251 /* Enable MMU parity error interrupt */ 2252 SOC_IF_ERROR_RETURN(WRITE_MEMFAILINTSTATUSr(unit, 0)); 2253 SOC_IF_ERROR_RETURN(READ_MEMFAILINTMASKr(unit, &imask)); 2254 soc_reg_field_set(unit, MEMFAILINTMASKr, &imask, 2255 CFAPPARITYERRORINTMASKf, 1); 2256 soc_reg_field_set(unit, MEMFAILINTMASKr, &imask, 2257 CCPPARITYERRORINTMASKf, 1); 2258 soc_reg_field_set(unit, MEMFAILINTMASKr, &imask, 2259 CBPPKTHDRPARITYERRORINTMASKf, 1); 2260 soc_reg_field_set(unit, MEMFAILINTMASKr, &imask, 2261 CBPCELLHDRPARITYERRORINTMASKf, 1); 2262 soc_reg_field_set(unit, MEMFAILINTMASKr, &imask, 2263 XQPARITYERRORINTMASKf, 1); 2264 soc_reg_field_set(unit, MEMFAILINTMASKr, &imask, 2265 CELLECCERRORINTMASKf, 1); 2266 soc_reg_field_set(unit, MEMFAILINTMASKr, &imask, 2267 CFAPFAILINTMASKf, 1); 2268 soc_reg_field_set(unit, MEMFAILINTMASKr, &imask, 2269 SOFTRESETINTMASKf, 1); 2270 soc_reg_field_set(unit, MEMFAILINTMASKr, &imask, 2271 CELLNOTIPINTMASKf, 1); 2272 if (soc_feature(unit, soc_feature_ip_mcast_repl)) { 2273 soc_reg_field_set(unit, MEMFAILINTMASKr, &imask, 2274 IPMCREPOVERLIMITERRORINTMASKf, 1); 2275 } 2276 SOC_IF_ERROR_RETURN(WRITE_MEMFAILINTMASKr(unit, imask)); 2277 2278 /* Directed Mirroring ON by default except for CPU port */ 2279 /* The src_port info will be changed as egress port if EM_SRCMOD_CHANGEf = 1 */ 2280 PBMP_PORT_ITER(unit, port) { 2281 SOC_IF_ERROR_RETURN(READ_EGR_PORTr(unit, port, &rval)); 2282 soc_reg_field_set(unit, EGR_PORTr, &rval, EM_SRCMOD_CHANGEf, 1); 2283 SOC_IF_ERROR_RETURN(WRITE_EGR_PORTr(unit, port, rval)); 2284 SOC_IF_ERROR_RETURN(READ_IEGR_PORTr(unit, port, &rval)); 2285 soc_reg_field_set(unit, IEGR_PORTr, &rval, EM_SRCMOD_CHANGEf, 1); 2286 SOC_IF_ERROR_RETURN(WRITE_IEGR_PORTr(unit, port, rval)); 2287 } 2288 /* Apply delay so LEDUP can capture correct status. */ 2289 /* coverity[result_independent_of_operands] */ 2290 SOC_IF_ERROR_RETURN(READ_CMIC_LEDUP_CTRLr(unit, &rval)); 2291 soc_reg_field_set(unit,CMIC_LEDUP_CTRLr, 2292 &rval, LEDUP_SCAN_START_DELAYf, 0x5); 2293 /* coverity[result_independent_of_operands] */ 2294 SOC_IF_ERROR_RETURN(WRITE_CMIC_LEDUP_CTRLr(unit, rval)); 2295 2296 return SOC_E_NONE; 2297 } 2298 2299 int 2300 soc_hurricane_age_timer_get(int unit, int *age_seconds, int *enabled) 2301 { 2302 uint32 value; 2303 2304 SOC_IF_ERROR_RETURN(READ_L2_AGE_TIMERr(unit, &value)); 2305 *enabled = soc_reg_field_get(unit, L2_AGE_TIMERr, value, AGE_ENAf); 2306 *age_seconds = soc_reg_field_get(unit, L2_AGE_TIMERr, value, AGE_VALf); 2307 2308 return SOC_E_NONE; 2309 } 2310 2311 int 2312 soc_hurricane_age_timer_max_get(int unit, int *max_seconds) 2313 { 2314 *max_seconds = 2315 soc_reg_field_get(unit, L2_AGE_TIMERr, 0xffffffff, AGE_VALf); 2316 2317 return SOC_E_NONE; 2318 } 2319 2320 int 2321 soc_hurricane_age_timer_set(int unit, int age_seconds, int enable) 2322 { 2323 uint32 value; 2324 2325 value = 0; 2326 soc_reg_field_set(unit, L2_AGE_TIMERr, &value, AGE_ENAf, enable); 2327 soc_reg_field_set(unit, L2_AGE_TIMERr, &value, AGE_VALf, age_seconds); 2328 SOC_IF_ERROR_RETURN(WRITE_L2_AGE_TIMERr(unit, value)); 2329 2330 return SOC_E_NONE; 2331 } 2332 2333 void soc_hurricane_oam_handler_register(soc_hurricane_oam_handler_t handler) 2334 { 2335 hu_oam_handler = handler; 2336 } 2337 2338 int 2339 soc_hu_xqport_mode_change(int unit, soc_port_t port, soc_mac_mode_t mode) 2340 { 2341 int rv = SOC_E_NONE; 2342 uint32 old_bits, bits, rval, to_usec, max_sz; 2343 uint64 rval64, max_sz64; 2344 soc_field_t xq_rst2 = INVALIDf; 2345 soc_field_t ep_port_rst = INVALIDf; 2346 soc_field_t ep_mmu_rst = INVALIDf; 2347 mac_driver_t *macd; 2348 int autoneg, autoneg_done, speed, duplex, enable, master; 2349 int pause_rx, pause_tx, dual_modid; 2350 soc_port_ability_t ability; 2351 soc_reg_t reg; 2352 int reset_sleep_usec; 2353 int hypercore_mixed_mode = 0; 2354 2355 if (!SOC_PORT_VALID(unit, port)) { 2356 return SOC_E_PORT; 2357 } 2358 2359 hypercore_mixed_mode = 2360 soc_property_get(unit, spn_BCM5614X_HYPERCORE_MIXED_MODE, 0); 2361 2362 sal_memset(&ability, 0, sizeof(soc_port_ability_t)); 2363 2364 SOC_IF_ERROR_RETURN(READ_XQPORT_MODE_REGr(unit, port, &rval)); 2365 old_bits = soc_reg_field_get(unit, XQPORT_MODE_REGr, rval, 2366 XQPORT_MODE_BITSf); 2367 bits = mode == SOC_MAC_MODE_10000 ? 2 : 1; 2368 if (bits == old_bits) { 2369 return SOC_E_NONE; 2370 } 2371 2372 to_usec = SAL_BOOT_QUICKTURN ? (250 * MILLISECOND_USEC) : 2373 (10 * MILLISECOND_USEC); 2374 2375 /* get current MAC and PHY settings */ 2376 SOC_IF_ERROR_RETURN(soc_phyctrl_auto_negotiate_get(unit, port, &autoneg, 2377 &autoneg_done)); 2378 SOC_IF_ERROR_RETURN(soc_phyctrl_ability_advert_get(unit, port, &ability)); 2379 SOC_IF_ERROR_RETURN(soc_phyctrl_speed_get(unit, port, &speed)); 2380 SOC_IF_ERROR_RETURN(soc_phyctrl_duplex_get(unit, port, &duplex)); 2381 SOC_IF_ERROR_RETURN(soc_phyctrl_enable_get(unit, port, &enable)); 2382 SOC_IF_ERROR_RETURN(soc_phyctrl_master_get(unit, port, &master)); 2383 2384 SOC_IF_ERROR_RETURN(soc_mac_probe(unit, port, &macd)); 2385 SOC_IF_ERROR_RETURN(MAC_PAUSE_GET(macd, unit, port, &pause_tx, &pause_rx)); 2386 SOC_IF_ERROR_RETURN(READ_MAC_CNTMAXSZr(unit, port, &max_sz64)); 2387 SOC_IF_ERROR_RETURN(READ_QPORT_CNTMAXSIZEr(unit, port, &max_sz)); 2388 2389 SOC_IF_ERROR_RETURN(soc_mac_probe(unit, port, &macd)); 2390 2391 /* Disable MAC TX and RX */ 2392 SOC_IF_ERROR_RETURN(MAC_ENABLE_SET(macd, unit, port, FALSE)); 2393 2394 /* Change the XQPORT block mode */ 2395 SOC_IF_ERROR_RETURN(READ_XQPORT_MODE_REGr(unit, port, &rval)); 2396 soc_reg_field_set(unit, XQPORT_MODE_REGr, &rval, 2397 XQPORT_MODE_BITSf, bits); 2398 SOC_IF_ERROR_RETURN(WRITE_XQPORT_MODE_REGr(unit, port, rval)); 2399 2400 /* Disable MAC TX and RX */ 2401 SOC_IF_ERROR_RETURN(MAC_ENABLE_SET(macd, unit, port, FALSE)); 2402 2403 /* Block linkscan and sbus access */ 2404 soc_linkscan_pause(unit); 2405 COUNTER_LOCK(unit); 2406 /* Egress disable */ 2407 rval = 0; 2408 soc_reg_field_set(unit, EGR_ENABLEr, &rval, PRT_ENABLEf, 0); 2409 SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, rval)); 2410 sal_usleep(to_usec); 2411 2412 if (hypercore_mixed_mode == 0) { 2413 /* Disable mixed mode speed for XQPorts belongig to same hypercore. 2414 * In this mode changing speed on XQPort connected to lane0 impacts the setting on 2415 * XQPort connected to lane2.*/ 2416 switch (port) { 2417 case 26: 2418 ep_port_rst = EGR_XQP0_PORT_INT_RESETf; 2419 ep_mmu_rst = EGR_XQP0_MMU_INT_RESETf; 2420 xq_rst2 = XQ0_HOTSWAP_RST_Lf; 2421 break; 2422 case 27: 2423 ep_port_rst = EGR_XQP1_PORT_INT_RESETf; 2424 ep_mmu_rst = EGR_XQP1_MMU_INT_RESETf; 2425 xq_rst2 = XQ1_HOTSWAP_RST_Lf; 2426 break; 2427 case 28: 2428 ep_port_rst = EGR_XQP2_PORT_INT_RESETf; 2429 ep_mmu_rst = EGR_XQP2_MMU_INT_RESETf; 2430 xq_rst2 = XQ2_HOTSWAP_RST_Lf; 2431 break; 2432 case 29: 2433 ep_port_rst = EGR_XQP3_PORT_INT_RESETf; 2434 ep_mmu_rst = EGR_XQP3_MMU_INT_RESETf; 2435 xq_rst2 = XQ3_HOTSWAP_RST_Lf; 2436 break; 2437 default: 2438 return SOC_E_PORT; 2439 } 2440 2441 /* Hold the XQPORT hotswap reset */ 2442 rval = 0; 2443 /* coverity[result_independent_of_operands] */ 2444 SOC_IF_ERROR_RETURN(READ_CMIC_SOFT_RESET_REGr(unit, &rval)); 2445 soc_reg_field_set(unit, CMIC_SOFT_RESET_REGr, &rval, xq_rst2, 0); 2446 /* coverity[result_independent_of_operands] */ 2447 SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(unit, rval)); 2448 sal_usleep(to_usec); 2449 2450 /* Clear the ECRC register */ 2451 SOC_IF_ERROR_RETURN(WRITE_EGRESSCELLREQUESTCOUNTr(unit, port, 0)); 2452 2453 /* Reset the EP */ 2454 SOC_IF_ERROR_RETURN(READ_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, &rval)); 2455 soc_reg_field_set(unit, EDATABUF_XQP_FLEXPORT_CONFIGr, &rval, 2456 ep_port_rst, 1); 2457 soc_reg_field_set(unit, EDATABUF_XQP_FLEXPORT_CONFIGr, &rval, 2458 ep_mmu_rst, 1); 2459 SOC_IF_ERROR_RETURN(WRITE_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, rval)); 2460 sal_usleep(to_usec); 2461 2462 SOC_IF_ERROR_RETURN(READ_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, &rval)); 2463 soc_reg_field_set(unit, EDATABUF_XQP_FLEXPORT_CONFIGr, &rval, 2464 ep_port_rst, 0); 2465 soc_reg_field_set(unit, EDATABUF_XQP_FLEXPORT_CONFIGr, &rval, 2466 ep_mmu_rst, 0); 2467 SOC_IF_ERROR_RETURN(WRITE_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, rval)); 2468 sal_usleep(to_usec); 2469 2470 /* Bring the XQPORT block out of reset */ 2471 /* coverity[result_independent_of_operands] */ 2472 SOC_IF_ERROR_RETURN(READ_CMIC_SOFT_RESET_REGr(unit, &rval)); 2473 soc_reg_field_set(unit, CMIC_SOFT_RESET_REGr, &rval, xq_rst2, 1); 2474 /* coverity[result_independent_of_operands] */ 2475 SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(unit, rval)); 2476 sal_usleep(to_usec); 2477 2478 /* Bring the hyperlite out of reset */ 2479 soc_xgxs_reset(unit, port); 2480 SOC_IF_ERROR_RETURN( 2481 soc_reg_field32_modify(unit, XQPORT_XGXS_NEWCTL_REGr, 2482 port, TXD1G_FIFO_RSTBf, 0xf)); 2483 2484 /* Port probe and initialization */ 2485 PHY_FLAGS_CLR(unit,port,~PHY_FLAGS_INIT_DONE); 2486 SOC_COUNTER_IF_ERROR_RETURN(soc_phyctrl_detach(unit, port)); 2487 SOC_COUNTER_IF_ERROR_RETURN(soc_phyctrl_probe(unit, port)); 2488 SOC_COUNTER_IF_ERROR_RETURN(soc_phyctrl_init(unit, port)); 2489 /* end of disable mixed mode in hypercore */ 2490 } else { 2491 /* Enable mixed mode speed for XQPorts belongig to same hypercore. 2492 * In this mode, the XQPorts support mixed mode speed 2493 * without switch reset. Changing speed on a XQPort does not impact the 2494 * settings on the other XQPort in the same hypercore */ 2495 2496 /* Bring the hyperlite out of reset */ 2497 reset_sleep_usec = 1100; 2498 reg = MAC_XGXS_CTRLr; 2499 2500 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2501 soc_reg64_field32_set(unit, reg, &rval64, LCREFENf, 1); 2502 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2503 2504 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2505 soc_reg64_field32_set(unit, reg, &rval64, PWRDWNf, 0); 2506 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 2507 soc_reg64_field32_set(unit, reg, &rval64, HW_RSTLf, 1); 2508 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2509 sal_usleep(reset_sleep_usec); 2510 2511 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2512 soc_reg64_field32_set(unit, reg, &rval64, AFIFO_RSTf, 1); 2513 soc_reg64_field32_set(unit, reg, &rval64, TXFIFO_RSTLf, 0); 2514 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2515 sal_usleep(reset_sleep_usec); 2516 2517 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2518 soc_reg64_field32_set(unit, reg, &rval64, PWRDWNf, 0); 2519 soc_reg64_field32_set(unit, reg, &rval64, IDDQf, 0); 2520 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2521 sal_usleep(reset_sleep_usec); 2522 2523 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2524 soc_reg64_field32_set(unit, reg, &rval64, HW_RSTLf, 1); 2525 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2526 sal_usleep(reset_sleep_usec); 2527 2528 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2529 soc_reg64_field32_set(unit, reg, &rval64, RSTB_MDIOREGSf, 1); 2530 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2531 sal_usleep(reset_sleep_usec); 2532 2533 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2534 soc_reg64_field32_set(unit, reg, &rval64, RSTB_PLLf, 1); 2535 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2536 sal_usleep(reset_sleep_usec); 2537 2538 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2539 soc_reg64_field32_set(unit, reg, &rval64, BIGMACRSTLf, 1); 2540 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2541 2542 /* Bring Tx FIFO out of reset */ 2543 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2544 soc_reg64_field32_set(unit, reg, &rval64, TXFIFO_RSTLf, 1); 2545 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2546 2547 SOC_IF_ERROR_RETURN( 2548 soc_reg_field32_modify(unit, XQPORT_XGXS_NEWCTL_REGr, 2549 port, TXD1G_FIFO_RSTBf, 0xf)); 2550 /* end of enable mixed mode in hypercore */ 2551 } 2552 2553 /* Change the XQPORT block mode */ 2554 SOC_IF_ERROR_RETURN(READ_XQPORT_MODE_REGr(unit, port, &rval)); 2555 soc_reg_field_set(unit, XQPORT_MODE_REGr, &rval, 2556 XQPORT_MODE_BITSf, bits); 2557 SOC_IF_ERROR_RETURN(WRITE_XQPORT_MODE_REGr(unit, port, rval)); 2558 2559 /* Need to reset the Bigmac to make registers accessible */ 2560 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &rval64)); 2561 soc_reg64_field32_set(unit, MAC_CTRLr, &rval64, TXRESETf, 0); 2562 soc_reg64_field32_set(unit, MAC_CTRLr, &rval64, RXRESETf, 0); 2563 SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, rval64)); 2564 2565 /* restore PHY setting */ 2566 SOC_IF_ERROR_RETURN(soc_phyctrl_auto_negotiate_set(unit, port, autoneg)); 2567 SOC_IF_ERROR_RETURN(soc_phyctrl_ability_advert_set(unit, port, &ability)); 2568 if (!autoneg) { 2569 SOC_IF_ERROR_RETURN(soc_phyctrl_speed_set(unit, port, speed)); 2570 SOC_IF_ERROR_RETURN(soc_phyctrl_duplex_set(unit, port, duplex)); 2571 } 2572 SOC_IF_ERROR_RETURN(soc_phyctrl_enable_set(unit, port, enable)); 2573 SOC_IF_ERROR_RETURN(soc_phyctrl_master_set(unit, port, master)); 2574 2575 if (mode == SOC_MAC_MODE_10000) { 2576 soc_port_cmap_set(unit, port, SOC_CTR_TYPE_XE); 2577 } else { 2578 soc_port_cmap_set(unit, port, SOC_CTR_TYPE_GE); 2579 } 2580 2581 /* Port probe and initialization */ 2582 SOC_IF_ERROR_RETURN(MAC_INIT(macd, unit, port)); 2583 2584 /* Restore previous MAC settings */ 2585 SOC_IF_ERROR_RETURN(MAC_ENABLE_SET(macd, unit, port, enable)); 2586 SOC_IF_ERROR_RETURN(MAC_PAUSE_SET(macd, unit, port, pause_tx, pause_rx)); 2587 2588 /* Restore XQPORT registers that may have been reset */ 2589 dual_modid = (NUM_MODID(unit) == 2) ? 1 : 0; 2590 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XMODID_ENr, port, 2591 DUAL_MODID_ENf, dual_modid)); 2592 SOC_IF_ERROR_RETURN(WRITE_MAC_CNTMAXSZr(unit, port, max_sz64)); 2593 SOC_IF_ERROR_RETURN(WRITE_QPORT_CNTMAXSIZEr(unit, port, max_sz)); 2594 2595 /* Enable MAC TX and RX */ 2596 SOC_IF_ERROR_RETURN(MAC_ENABLE_SET(macd, unit, port, TRUE)); 2597 2598 /* Egress Enable */ 2599 rval = 0; 2600 soc_reg_field_set(unit, EGR_ENABLEr, &rval, PRT_ENABLEf, 1); 2601 SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, rval)); 2602 2603 /* Resume sbus access and linkscan */ 2604 COUNTER_UNLOCK(unit); 2605 soc_linkscan_continue(unit); 2606 return rv; 2607 } 2608 #endif /* BCM_HURRICANE_SUPPORT */