intr_cmicm.c (114465B)
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 * SOC CMICm Interrupt Handlers 8 * 9 * NOTE: These handlers are called from an interrupt context, so their 10 * actions are restricted accordingly. 11 */ 12 13 #include <shared/bsl.h> 14 15 #include <sal/core/libc.h> 16 #include <shared/alloc.h> 17 #include <sal/core/spl.h> 18 #include <sal/core/sync.h> 19 #include <sal/core/dpc.h> 20 21 #include <soc/debug.h> 22 #include <soc/drv.h> 23 #include <soc/dma.h> 24 #include <soc/i2c.h> 25 #include <soc/cmicm.h> 26 #include <soc/feature.h> 27 #include <soc/intr.h> 28 #include <soc/mem.h> 29 #ifdef BCM_PETRA_SUPPORT 30 #include <soc/dpp/PPD/ppd_api_oam.h> 31 #include <soc/dpp/ARAD/ARAD_PP/arad_pp_frwrd_mact_mgmt.h> 32 #include <soc/dpp/ARAD/ARAD_PP/arad_pp_sw_db.h> 33 #include <shared/swstate/access/sw_state_access.h> 34 #include <soc/dpp/JER/jer_mgmt.h> 35 #include <soc/dpp/JER/jer_intr.h> 36 #endif 37 #ifdef BCM_KATANA_SUPPORT 38 #include <soc/katana.h> 39 #endif /* BCM_KATANA_SUPPORT */ 40 #ifdef BCM_TRIUMPH3_SUPPORT 41 #include <soc/triumph3.h> 42 #endif /* BCM_TRIUMPH3_SUPPORT */ 43 #ifdef BCM_TRIDENT2_SUPPORT 44 #include <soc/trident2.h> 45 #endif /* BCM_TRIDENT2_SUPPORT */ 46 #ifdef BCM_MONTEREY_SUPPORT 47 #include <soc/monterey.h> 48 #endif /* BCM_MONTEREY_SUPPORT */ 49 #ifdef BCM_APACHE_SUPPORT 50 #include <soc/apache.h> 51 #endif /* BCM_APACHE_SUPPORT */ 52 #ifdef BCM_HURRICANE2_SUPPORT 53 #include <soc/hurricane2.h> 54 #endif /* BCM_HURRICANE2_SUPPORT */ 55 #ifdef BCM_GREYHOUND_SUPPORT 56 #include <soc/greyhound.h> 57 #endif /* BCM_GREYHOUND_SUPPORT */ 58 #ifdef BCM_TOMAHAWK_SUPPORT 59 #include <soc/tomahawk.h> 60 #endif /* BCM_TOMAHAWK_SUPPORT */ 61 #ifdef BCM_TRIDENT3_SUPPORT 62 #include <soc/trident3.h> 63 #endif /* BCM_TRIDENT3_SUPPORT */ 64 #ifdef BCM_DFE_SUPPORT 65 #include <soc/dfe/cmn/dfe_drv.h> 66 #endif 67 #ifdef BCM_TOMAHAWK3_SUPPORT 68 #include <soc/tomahawk3.h> 69 #endif /* BCM_TOMAHAWK_SUPPORT */ 70 #ifdef BCM_GREYHOUND2_SUPPORT 71 #include <soc/greyhound2.h> 72 #endif /* BCM_GREYHOUND_SUPPORT */ 73 #if defined(BCM_TIMESYNC_TIME_CAPTURE_SUPPORT) 74 extern void soc_esw_timesync_ts_intr(int unit); 75 #endif /* defined(BCM_GREYHOUND2_SUPPORT) || defined(BCM_TIMESYNC_TIME_CAPTURE_SUPPORT) */ 76 77 #ifdef BCM_CMICM_SUPPORT 78 79 #define HOST_IRQ_MASK_OFFSET_DIFF (CMIC_CMC0_UC0_IRQ_MASK0_OFFSET \ 80 - CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET) 81 82 static uint32 soc_cmicm_host_irq_offset[SOC_MAX_NUM_DEVICES] = {0}; 83 84 #define INTR_MASK_OFFSET(_u,_a) (_a + soc_cmicm_host_irq_offset[_u]) 85 86 #ifdef INCLUDE_KNET 87 #include <soc/knet.h> 88 #define IRQ_MASK0_SET_FUNC soc_knet_irq_mask_set 89 #else 90 #define IRQ_MASK0_SET_FUNC soc_pci_write 91 #endif 92 93 #define IRQ_MASK0_SET(_u,_a,_m) IRQ_MASK0_SET_FUNC(_u,INTR_MASK_OFFSET(_u,_a),_m) 94 #define IRQ_MASKx_SET(_u,_a,_m) soc_pci_write(_u,INTR_MASK_OFFSET(_u,_a),_m) 95 96 97 #include <soc/shared/mos_intr_common.h> 98 #include <soc/uc_msg.h> 99 100 /* Declare static functions for interrupt handler array */ 101 STATIC void soc_cmicm_intr_schan_done(int unit, uint32 vchan); 102 STATIC void soc_cmicm_intr_miim_op(int unit, uint32 ignored); 103 STATIC void soc_cmicm_intr_tdma_done(int unit, uint32 ignored); 104 STATIC void soc_cmicm_intr_tslam_done(int unit, uint32 ignored); 105 STATIC void soc_cmicm_intr_stat_dma(int unit, uint32 ignored); 106 STATIC void soc_cmicm_intr_ccmdma_done(int unit, uint32 vchan); 107 STATIC void soc_cmicm_fifo_dma_done(int unit, uint32 vchan); 108 STATIC void soc_cmicm_intr_sbusdma_done(int unit, uint32 vchan); 109 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) 110 STATIC void soc_cmicm_intr_common_schan_done(int unit, uint32 ignored); 111 STATIC void soc_cmicm_chip_func_intr(int unit, uint32 val); 112 STATIC void soc_cmicm_intr_link_stat(int unit, uint32 ignored); 113 STATIC void soc_cmicm_parity_intr(int unit, uint32 val); 114 STATIC void soc_cmicm_block_lo_intr(int unit, uint32 val); 115 STATIC void soc_cmicm_link_stat(int unit, uint32 ignored); 116 STATIC void soc_ser_engine_intr(int unit, uint32 val); 117 STATIC void soc_cmicm_timesync_intr(int unit, uint32 val); 118 STATIC void soc_cmicdv2_parity_intr(int unit, uint32 val); 119 STATIC void soc_cmicdv2_chip_parity_intr(int unit, uint32 val); 120 STATIC void soc_cmicdv2_block_intr4(int unit, uint32 val); 121 STATIC void soc_cmicdv2_block_intr5(int unit, uint32 val); 122 STATIC void soc_cmicdv4_block_intr6(int unit, uint32 val); 123 #endif 124 #ifdef INCLUDE_RCPU 125 STATIC void soc_cmicm_rcpu_intr_miim_op(int unit, uint32 ignored); 126 #endif 127 128 129 /* 130 * SOC Interrupt Table 131 * 132 * The table is stored in priority order: Interrupts that are listed 133 * first have their handlers called first. 134 * 135 * A handler can clear more than one interrupt bit to prevent a 136 * subsequent handler from being called. E.g., if the DMA CHAIN_DONE 137 * handler clears both CHAIN_DONE and DESC_DONE, the DESC_DONE handler 138 * will not be called. 139 */ 140 141 typedef void (*ifn_t)(int unit, uint32 data); 142 143 typedef struct { 144 uint32 mask; 145 ifn_t intr_fn; 146 uint32 intr_data; 147 char *intr_name; 148 } intr_handler_t; 149 150 static intr_handler_t soc_cmicm_intr_handlers[] = { 151 { IRQ_CMCx_SCH_OP_DONE, soc_cmicm_intr_schan_done, 0, "SCH_OP_DONE" }, 152 { IRQ_CMCx_MIIM_OP_DONE, soc_cmicm_intr_miim_op, 0, "MIIM_OP_DONE" }, 153 { IRQ_CMCx_TDMA_DONE, soc_cmicm_intr_tdma_done, 0, "TDMA_DONE" }, 154 { IRQ_CMCx_TSLAM_DONE, soc_cmicm_intr_tslam_done, 0, "TSLAM_DONE" }, 155 { IRQ_CMCx_CCMDMA_DONE, soc_cmicm_intr_ccmdma_done, 0, "CCMDMA_DONE" }, 156 157 { IRQ_CMCx_CHAIN_DONE(0), soc_dma_done_chain, 0, "CH0_CHAIN_DONE" }, 158 { IRQ_CMCx_CHAIN_DONE(1), soc_dma_done_chain, 1, "CH1_CHAIN_DONE" }, 159 { IRQ_CMCx_CHAIN_DONE(2), soc_dma_done_chain, 2, "CH2_CHAIN_DONE" }, 160 { IRQ_CMCx_CHAIN_DONE(3), soc_dma_done_chain, 3, "CH3_CHAIN_DONE" }, 161 162 { IRQ_CMCx_DESC_DONE(0), soc_dma_done_desc, 0, "CH0_DESC_DONE" }, 163 { IRQ_CMCx_DESC_DONE(1), soc_dma_done_desc, 1, "CH1_DESC_DONE" }, 164 { IRQ_CMCx_DESC_DONE(2), soc_dma_done_desc, 2, "CH2_DESC_DONE" }, 165 { IRQ_CMCx_DESC_DONE(3), soc_dma_done_desc, 3, "CH3_DESC_DONE" }, 166 167 { IRQ_CMCx_CNTLD_DESC_DONE(0), soc_dma_done_desc, 0, "CH0_CNTLD_DESC_DONE" }, 168 { IRQ_CMCx_CNTLD_DESC_DONE(1), soc_dma_done_desc, 1, "CH1_CNTLD_DESC_DONE" }, 169 { IRQ_CMCx_CNTLD_DESC_DONE(2), soc_dma_done_desc, 2, "CH2_CNTLD_DESC_DONE" }, 170 { IRQ_CMCx_CNTLD_DESC_DONE(3), soc_dma_done_desc, 3, "CH3_CNTLD_DESC_DONE" }, 171 { IRQ_CMCx_STAT_ITER_DONE, soc_cmicm_intr_stat_dma, 0, "STAT_ITER_DONE" }, 172 173 { IRQ_CMCx_SW_INTR(CMICM_SW_INTR_UC0), soc_cmic_sw_intr, CMICM_SW_INTR_UC0, "UC0_SW_INTR" }, 174 { IRQ_CMCx_SW_INTR(CMICM_SW_INTR_UC1), soc_cmic_sw_intr, CMICM_SW_INTR_UC1, "UC1_SW_INTR" }, 175 176 { 0, NULL, 0, "" } /* Termination */ 177 }; 178 179 #ifdef SEPARATE_PKTDMA_INTR_HANDLER 180 static intr_handler_t soc_cmicm_pktdma_intr_handlers[] = { 181 { IRQ_CMCx_CHAIN_DONE(0), soc_dma_done_chain, 0, "CH0_CHAIN_DONE" }, 182 { IRQ_CMCx_CHAIN_DONE(1), soc_dma_done_chain, 1, "CH1_CHAIN_DONE" }, 183 { IRQ_CMCx_CHAIN_DONE(2), soc_dma_done_chain, 2, "CH2_CHAIN_DONE" }, 184 { IRQ_CMCx_CHAIN_DONE(3), soc_dma_done_chain, 3, "CH3_CHAIN_DONE" }, 185 186 { IRQ_CMCx_DESC_DONE(0), soc_dma_done_desc, 0, "CH0_DESC_DONE" }, 187 { IRQ_CMCx_DESC_DONE(1), soc_dma_done_desc, 1, "CH1_DESC_DONE" }, 188 { IRQ_CMCx_DESC_DONE(2), soc_dma_done_desc, 2, "CH2_DESC_DONE" }, 189 { IRQ_CMCx_DESC_DONE(3), soc_dma_done_desc, 3, "CH3_DESC_DONE" }, 190 191 { IRQ_CMCx_CNTLD_DESC_DONE(0), soc_dma_done_desc, 0, "CH0_CNTLD_DESC_DONE" }, 192 { IRQ_CMCx_CNTLD_DESC_DONE(1), soc_dma_done_desc, 1, "CH1_CNTLD_DESC_DONE" }, 193 { IRQ_CMCx_CNTLD_DESC_DONE(2), soc_dma_done_desc, 2, "CH2_CNTLD_DESC_DONE" }, 194 { IRQ_CMCx_CNTLD_DESC_DONE(3), soc_dma_done_desc, 3, "CH3_CNTLD_DESC_DONE" }, 195 196 { 0, NULL, 0, "" } /* Termination */ 197 }; 198 #endif 199 200 static intr_handler_t soc_cmicm_intr_handlers0_fifo_dma[] = { 201 { IRQ_CMCx_SCH_OP_DONE, soc_cmicm_intr_schan_done, 0, "SCH_OP_DONE" }, 202 { IRQ_CMCx_MIIM_OP_DONE, soc_cmicm_intr_miim_op, 0, "MIIM_OP_DONE" }, 203 { IRQ_CMCx_TDMA_DONE, soc_cmicm_intr_tdma_done, 0, "TDMA_DONE" }, 204 { IRQ_CMCx_TSLAM_DONE, soc_cmicm_intr_tslam_done, 0, "TSLAM_DONE" }, 205 { IRQ_CMCx_CCMDMA_DONE, soc_cmicm_intr_ccmdma_done, 0, "CCMDMA_DONE" }, 206 207 { IRQ_CMCx_CHAIN_DONE(0), soc_dma_done_chain, 0, "CH0_CHAIN_DONE" }, 208 { IRQ_CMCx_CHAIN_DONE(1), soc_dma_done_chain, 1, "CH1_CHAIN_DONE" }, 209 { IRQ_CMCx_CHAIN_DONE(2), soc_dma_done_chain, 2, "CH2_CHAIN_DONE" }, 210 { IRQ_CMCx_CHAIN_DONE(3), soc_dma_done_chain, 3, "CH3_CHAIN_DONE" }, 211 212 { IRQ_CMCx_DESC_DONE(0), soc_dma_done_desc, 0, "CH0_DESC_DONE" }, 213 { IRQ_CMCx_DESC_DONE(1), soc_dma_done_desc, 1, "CH1_DESC_DONE" }, 214 { IRQ_CMCx_DESC_DONE(2), soc_dma_done_desc, 2, "CH2_DESC_DONE" }, 215 { IRQ_CMCx_DESC_DONE(3), soc_dma_done_desc, 3, "CH3_DESC_DONE" }, 216 217 { IRQ_CMCx_STAT_ITER_DONE, soc_cmicm_intr_stat_dma, 0, "STAT_ITER_DONE" }, 218 219 { IRQ_CMCx_SW_INTR(CMICM_SW_INTR_UC0), soc_cmic_sw_intr, CMICM_SW_INTR_UC0, "UC0_SW_INTR" }, 220 { IRQ_CMCx_SW_INTR(CMICM_SW_INTR_UC1), soc_cmic_sw_intr, CMICM_SW_INTR_UC1, "UC1_SW_INTR" }, 221 { IRQ_CMCx_FIFO_CH_DMA(0), soc_cmicm_fifo_dma_done, 0, "CH0_FIFO_DMA_DONE" }, 222 { IRQ_CMCx_FIFO_CH_DMA(1), soc_cmicm_fifo_dma_done, 1, "CH1_FIFO_DMA_DONE" }, 223 { IRQ_CMCx_FIFO_CH_DMA(2), soc_cmicm_fifo_dma_done, 2, "CH2_FIFO_DMA_DONE" }, 224 { IRQ_CMCx_FIFO_CH_DMA(3), soc_cmicm_fifo_dma_done, 3, "CH3_FIFO_DMA_DONE" }, 225 226 { 0, NULL, 0, "" } /* Termination */ 227 }; 228 229 230 STATIC intr_handler_t soc_cmicm_intr_handlers0[] = { 231 { IRQ_CMCx_SCH_OP_DONE, soc_cmicm_intr_schan_done, 0, "SCH_OP_DONE" }, 232 { IRQ_CMCx_MIIM_OP_DONE, soc_cmicm_intr_miim_op, 0, "MIIM_OP_DONE" }, 233 234 { IRQ_SBUSDMA_CH0_DONE, soc_cmicm_intr_sbusdma_done, 0, "SBUS_DMA0_DONE" }, 235 { IRQ_SBUSDMA_CH1_DONE, soc_cmicm_intr_sbusdma_done, 1, "SBUS_DMA1_DONE" }, 236 { IRQ_SBUSDMA_CH2_DONE, soc_cmicm_intr_sbusdma_done, 2, "SBUS_DMA2_DONE" }, 237 238 { IRQ_CMCx_CCMDMA_DONE, soc_cmicm_intr_ccmdma_done, 0, "CCMDMA_DONE" }, 239 240 { IRQ_CMCx_CHAIN_DONE(0), soc_dma_done_chain, 0, "CH0_CHAIN_DONE" }, 241 { IRQ_CMCx_CHAIN_DONE(1), soc_dma_done_chain, 1, "CH1_CHAIN_DONE" }, 242 { IRQ_CMCx_CHAIN_DONE(2), soc_dma_done_chain, 2, "CH2_CHAIN_DONE" }, 243 { IRQ_CMCx_CHAIN_DONE(3), soc_dma_done_chain, 3, "CH3_CHAIN_DONE" }, 244 245 { IRQ_CMCx_DESC_DONE(0), soc_dma_done_desc, 0, "CH0_DESC_DONE" }, 246 { IRQ_CMCx_DESC_DONE(1), soc_dma_done_desc, 1, "CH1_DESC_DONE" }, 247 { IRQ_CMCx_DESC_DONE(2), soc_dma_done_desc, 2, "CH2_DESC_DONE" }, 248 { IRQ_CMCx_DESC_DONE(3), soc_dma_done_desc, 3, "CH3_DESC_DONE" }, 249 250 { IRQ_CMCx_CNTLD_DESC_DONE(0), soc_dma_done_desc, 0, "CH0_CNTLD_DESC_DONE" }, 251 { IRQ_CMCx_CNTLD_DESC_DONE(1), soc_dma_done_desc, 1, "CH1_CNTLD_DESC_DONE" }, 252 { IRQ_CMCx_CNTLD_DESC_DONE(2), soc_dma_done_desc, 2, "CH2_CNTLD_DESC_DONE" }, 253 { IRQ_CMCx_CNTLD_DESC_DONE(3), soc_dma_done_desc, 3, "CH3_CNTLD_DESC_DONE" }, 254 255 { IRQ_CMCx_STAT_ITER_DONE, soc_cmicm_intr_stat_dma, 0, "STAT_ITER_DONE" }, 256 257 { IRQ_CMCx_SW_INTR(CMICM_SW_INTR_RCPU), soc_cmic_sw_intr, CMICM_SW_INTR_RCPU, "RCPU_SW_INTR" }, 258 { IRQ_CMCx_SW_INTR(CMICM_SW_INTR_UC0), soc_cmic_sw_intr, CMICM_SW_INTR_UC0, "UC0_SW_INTR" }, 259 { IRQ_CMCx_SW_INTR(CMICM_SW_INTR_UC1), soc_cmic_sw_intr, CMICM_SW_INTR_UC1, "UC1_SW_INTR" }, 260 261 { IRQ_CMCx_FIFO_CH_DMA(0), soc_cmicm_fifo_dma_done, 0, "CH0_FIFO_DMA_DONE" }, 262 { IRQ_CMCx_FIFO_CH_DMA(1), soc_cmicm_fifo_dma_done, 1, "CH1_FIFO_DMA_DONE" }, 263 { IRQ_CMCx_FIFO_CH_DMA(2), soc_cmicm_fifo_dma_done, 2, "CH2_FIFO_DMA_DONE" }, 264 { IRQ_CMCx_FIFO_CH_DMA(3), soc_cmicm_fifo_dma_done, 3, "CH3_FIFO_DMA_DONE" }, 265 266 { 0, NULL, 0, "" } /* Termination */ 267 }; 268 269 #ifdef SEPARATE_PKTDMA_INTR_HANDLER 270 STATIC intr_handler_t soc_cmicm_pktdma_intr_handlers0[] = { 271 { IRQ_CMCx_CHAIN_DONE(0), soc_dma_done_chain, 0, "CH0_CHAIN_DONE" }, 272 { IRQ_CMCx_CHAIN_DONE(1), soc_dma_done_chain, 1, "CH1_CHAIN_DONE" }, 273 { IRQ_CMCx_CHAIN_DONE(2), soc_dma_done_chain, 2, "CH2_CHAIN_DONE" }, 274 { IRQ_CMCx_CHAIN_DONE(3), soc_dma_done_chain, 3, "CH3_CHAIN_DONE" }, 275 276 { IRQ_CMCx_DESC_DONE(0), soc_dma_done_desc, 0, "CH0_DESC_DONE" }, 277 { IRQ_CMCx_DESC_DONE(1), soc_dma_done_desc, 1, "CH1_DESC_DONE" }, 278 { IRQ_CMCx_DESC_DONE(2), soc_dma_done_desc, 2, "CH2_DESC_DONE" }, 279 { IRQ_CMCx_DESC_DONE(3), soc_dma_done_desc, 3, "CH3_DESC_DONE" }, 280 281 { IRQ_CMCx_CNTLD_DESC_DONE(0), soc_dma_done_desc, 0, "CH0_CNTLD_DESC_DONE" }, 282 { IRQ_CMCx_CNTLD_DESC_DONE(1), soc_dma_done_desc, 1, "CH1_CNTLD_DESC_DONE" }, 283 { IRQ_CMCx_CNTLD_DESC_DONE(2), soc_dma_done_desc, 2, "CH2_CNTLD_DESC_DONE" }, 284 { IRQ_CMCx_CNTLD_DESC_DONE(3), soc_dma_done_desc, 3, "CH3_CNTLD_DESC_DONE" }, 285 286 { 0, NULL, 0, "" } /* Termination */ 287 }; 288 #endif 289 290 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) 291 STATIC intr_handler_t soc_cmicm_intr_handlers1[] = { 292 { IRQ_CMCx_COMMON_SCHAN_DONE, soc_cmicm_intr_common_schan_done, 0, "COM_SCH_DONE" }, 293 { IRQ_CMCx_CHIP_FUNC_INTR, soc_cmicm_chip_func_intr, 0, "CHIP FUNC INTR" }, 294 { IRQ_CMCx_LINK_STAT_MOD, soc_cmicm_link_stat, 0, "PHY_LINKSCAN_LINKSTATUS_CHD"}, 295 { IRQ_CMCx_LINK_STAT_MOD, soc_cmicm_intr_link_stat, 0, "LINK_STAT_MOD" }, 296 { IRQ_CMCx_SER_INTR, soc_ser_engine_intr, 0, "SER ENGINE INTR" }, 297 { IRQ_CMCx_TIMESYNC_INTR, soc_cmicm_timesync_intr, 0, "TIMESYNC INTR" }, 298 { 0, NULL, 0, "" } /* Termination */ 299 }; 300 301 STATIC intr_handler_t soc_cmicm_intr_handlers2[] = { 302 { IRQ_CMCx_PARITY, soc_cmicm_parity_intr, 0, "PARITY INTR" }, 303 { 0, NULL, 0, "" } /* Termination */ 304 }; 305 306 STATIC intr_handler_t soc_cmicm_intr_handlers3[] = { 307 { IRQ_CMCx_BLOCK(1), soc_cmicm_block_lo_intr, 1, "L2_MNGT INTR" }, 308 { IRQ_CMCx_BLOCK(2), soc_cmicm_block_lo_intr, 2, "BLOCK 4 INTR" }, 309 { IRQ_CMCx_BLOCK(4), soc_cmicm_block_lo_intr, 4, "BLOCK 4 INTR" }, 310 { IRQ_CMCx_BLOCK(5), soc_cmicm_block_lo_intr, 5, "BLOCK 4 INTR" }, 311 { IRQ_CMCx_BLOCK(6), soc_cmicm_block_lo_intr, 6, "BLOCK 6 INTR" }, 312 { IRQ_CMCx_BLOCK(7), soc_cmicm_block_lo_intr, 7, "BLOCK 4 INTR" }, 313 { IRQ_CMCx_BLOCK(8), soc_cmicm_block_lo_intr, 8, "BLOCK 4 INTR" }, 314 { IRQ_CMCx_BLOCK(9), soc_cmicm_block_lo_intr, 9, "BLOCK 4 INTR" }, 315 { IRQ_CMCx_BLOCK(10), soc_cmicm_block_lo_intr, 10, "BLOCK 4 INTR" }, 316 { IRQ_CMCx_BLOCK(11), soc_cmicm_block_lo_intr, 11, "BLOCK 4 INTR" }, 317 { IRQ_CMCx_BLOCK(12), soc_cmicm_block_lo_intr, 12, "BLOCK 4 INTR" }, 318 { IRQ_CMCx_BLOCK(13), soc_cmicm_block_lo_intr, 13, "BLOCK 4 INTR" }, 319 { IRQ_CMCx_BLOCK(14), soc_cmicm_block_lo_intr, 14, "BLOCK 4 INTR" }, 320 { IRQ_CMCx_BLOCK(15), soc_cmicm_block_lo_intr, 15, "BLOCK 4 INTR" }, 321 { IRQ_CMCx_BLOCK(16), soc_cmicm_block_lo_intr, 16, "BLOCK 4 INTR" }, 322 { IRQ_CMCx_BLOCK(25), soc_cmicm_block_lo_intr, 25, "BLOCK 25 INTR" }, 323 { IRQ_CMCx_BLOCK(26), soc_cmicm_block_lo_intr, 26, "BLOCK 26 INTR" }, 324 { IRQ_CMCx_BLOCK(27), soc_cmicm_block_lo_intr, 27, "BLOCK 27 INTR" }, 325 { 0, NULL, 0, "" } /* Termination */ 326 }; 327 328 STATIC intr_handler_t soc_cmicm_intr_handlers4[] = { 329 { 0, NULL, 0, "" } /* Termination */ 330 }; 331 332 STATIC intr_handler_t soc_cmicm_intr_handlers5[] = { 333 { 0, NULL, 0, "" } /* Termination */ 334 }; 335 336 STATIC intr_handler_t soc_cmicdv2_intr_handlers2[] = { 337 { IRQ_CMCx_BLOCK(19), soc_dma_pci_timeout_handle, 19, "PCI_TIMEOUT_INTR" }, 338 { IRQ_CMCx_BLOCK(24), soc_cmicdv2_chip_parity_intr, 24, "NS INTR" }, 339 { IRQ_CMCx_BLOCK(25), soc_cmicdv2_chip_parity_intr, 25, "NS DEBUG INTR" }, 340 { 0, NULL, 0, "" } /* Termination */ 341 }; 342 343 STATIC intr_handler_t soc_cmicdv2_intr_handlers3[] = { 344 { IRQ_CMCx_BLOCK(1), soc_cmicdv2_parity_intr, 1, "L2_MNGT INTR" }, 345 { IRQ_CMCx_BLOCK(2), soc_cmicdv2_parity_intr, 2, "BLOCK 2 INTR" }, 346 { IRQ_CMCx_BLOCK(3), soc_cmicdv2_parity_intr, 3, "BLOCK 3 INTR" }, 347 { IRQ_CMCx_BLOCK(4), soc_cmicdv2_parity_intr, 4, "BLOCK 4 INTR" }, 348 { IRQ_CMCx_BLOCK(5), soc_cmicdv2_parity_intr, 5, "BLOCK 5 INTR" }, 349 { IRQ_CMCx_BLOCK(6), soc_cmicdv2_parity_intr, 6, "BLOCK 6 INTR" }, 350 { IRQ_CMCx_BLOCK(7), soc_cmicdv2_parity_intr, 7, "BLOCK 7 INTR" }, 351 { IRQ_CMCx_BLOCK(8), soc_cmicdv2_parity_intr, 8, "BLOCK 8 INTR" }, 352 { IRQ_CMCx_BLOCK(9), soc_cmicdv2_parity_intr, 9, "BLOCK 9 INTR" }, 353 { IRQ_CMCx_BLOCK(10), soc_cmicdv2_parity_intr, 10, "BLOCK 10 INTR" }, 354 { IRQ_CMCx_BLOCK(11), soc_cmicdv2_parity_intr, 11, "BLOCK 11 INTR" }, 355 { IRQ_CMCx_BLOCK(12), soc_cmicdv2_parity_intr, 12, "BLOCK 12 INTR" }, 356 { IRQ_CMCx_BLOCK(13), soc_cmicdv2_parity_intr, 13, "BLOCK 13 INTR" }, 357 { IRQ_CMCx_BLOCK(14), soc_cmicdv2_parity_intr, 14, "BLOCK 14 INTR" }, 358 { IRQ_CMCx_BLOCK(15), soc_cmicdv2_parity_intr, 15, "BLOCK 15 INTR" }, 359 { IRQ_CMCx_BLOCK(16), soc_cmicdv2_parity_intr, 16, "BLOCK 16 INTR" }, 360 { IRQ_CMCx_BLOCK(26), soc_cmicdv2_parity_intr, 26, "BLOCK 26 INTR" }, 361 { IRQ_CMCx_BLOCK(27), soc_cmicdv2_parity_intr, 27, "BLOCK 27 INTR" }, 362 { IRQ_CMCx_BLOCK(28), soc_cmicdv2_parity_intr, 28, "BLOCK 28 INTR" }, 363 { IRQ_CMCx_BLOCK(29), soc_cmicdv2_parity_intr, 29, "BLOCK 29 INTR" }, 364 { IRQ_CMCx_PARITY, soc_cmicdv2_parity_intr, 0, "PARITY INTR" }, 365 { 0, NULL, 0, "" } /* Termination */ 366 }; 367 368 STATIC intr_handler_t soc_cmicdv2_intr_handlers4[] = { 369 { IRQ_CMCx_BLOCK(0), soc_cmicdv2_block_intr4, 0, "PARITY INTR" }, 370 { IRQ_CMCx_BLOCK(1), soc_cmicdv2_block_intr4, 1, "PARITY INTR" }, 371 { IRQ_CMCx_BLOCK(2), soc_cmicdv2_block_intr4, 2, "PARITY INTR" }, 372 { IRQ_CMCx_BLOCK(3), soc_cmicdv2_block_intr4, 3, "PARITY INTR" }, 373 { IRQ_CMCx_BLOCK(4), soc_cmicdv2_block_intr4, 4, "PARITY INTR" }, 374 { IRQ_CMCx_BLOCK(5), soc_cmicdv2_block_intr4, 5, "PARITY INTR" }, 375 { IRQ_CMCx_BLOCK(6), soc_cmicdv2_block_intr4, 6, "PARITY INTR" }, 376 { IRQ_CMCx_BLOCK(7), soc_cmicdv2_block_intr4, 7, "PARITY INTR" }, 377 { IRQ_CMCx_BLOCK(8), soc_cmicdv2_block_intr4, 8, "PARITY INTR" }, 378 { IRQ_CMCx_BLOCK(9), soc_cmicdv2_block_intr4, 9, "PARITY INTR" }, 379 { IRQ_CMCx_BLOCK(10), soc_cmicdv2_block_intr4, 10, "PARITY INTR" }, 380 { IRQ_CMCx_BLOCK(11), soc_cmicdv2_block_intr4, 11, "PARITY INTR" }, 381 { IRQ_CMCx_BLOCK(12), soc_cmicdv2_block_intr4, 12, "PARITY INTR" }, 382 { IRQ_CMCx_BLOCK(13), soc_cmicdv2_block_intr4, 13, "PARITY INTR" }, 383 { IRQ_CMCx_BLOCK(14), soc_cmicdv2_block_intr4, 14, "PARITY INTR" }, 384 { IRQ_CMCx_BLOCK(15), soc_cmicdv2_block_intr4, 15, "PARITY INTR" }, 385 { IRQ_CMCx_BLOCK(16), soc_cmicdv2_block_intr4, 16, "PARITY INTR" }, 386 { IRQ_CMCx_BLOCK(17), soc_cmicdv2_block_intr4, 17, "PARITY INTR" }, 387 { IRQ_CMCx_BLOCK(18), soc_cmicdv2_block_intr4, 18, "PARITY INTR" }, 388 { IRQ_CMCx_BLOCK(19), soc_cmicdv2_block_intr4, 19, "PARITY INTR" }, 389 { IRQ_CMCx_BLOCK(20), soc_cmicdv2_block_intr4, 20, "PARITY INTR" }, 390 { IRQ_CMCx_BLOCK(21), soc_cmicdv2_block_intr4, 21, "PARITY INTR" }, 391 { IRQ_CMCx_BLOCK(22), soc_cmicdv2_block_intr4, 22, "PARITY INTR" }, 392 { IRQ_CMCx_BLOCK(23), soc_cmicdv2_block_intr4, 23, "PARITY INTR" }, 393 { IRQ_CMCx_BLOCK(24), soc_cmicdv2_block_intr4, 24, "PARITY INTR" }, 394 { IRQ_CMCx_BLOCK(25), soc_cmicdv2_block_intr4, 25, "PARITY INTR" }, 395 { IRQ_CMCx_BLOCK(26), soc_cmicdv2_block_intr4, 26, "PARITY INTR" }, 396 { IRQ_CMCx_BLOCK(27), soc_cmicdv2_block_intr4, 27, "PARITY INTR" }, 397 { IRQ_CMCx_BLOCK(28), soc_cmicdv2_block_intr4, 28, "PARITY INTR" }, 398 { IRQ_CMCx_BLOCK(29), soc_cmicdv2_block_intr4, 29, "PARITY INTR" }, 399 { IRQ_CMCx_BLOCK(30), soc_cmicdv2_block_intr4, 30, "PARITY INTR" }, 400 { IRQ_CMCx_BLOCK(31), soc_cmicdv2_block_intr4, 31, "PARITY INTR" }, 401 { 0, NULL, 0, "" } /* Termination */ 402 403 }; 404 405 STATIC intr_handler_t soc_cmicdv2_intr_handlers5[] = { 406 { IRQ_CMCx_PARITY, soc_cmicdv2_block_intr5, 0, "PARITY INTR" }, 407 { 0, NULL, 0, "" } /* Termination */ 408 }; 409 410 STATIC intr_handler_t soc_cmicdv4_intr_handlers6[] = { 411 { IRQ_CMCx_BLOCK(0), soc_cmicdv4_block_intr6, 0, "PARITY INTR" }, 412 { IRQ_CMCx_BLOCK(1), soc_cmicdv4_block_intr6, 1, "PARITY INTR" }, 413 { IRQ_CMCx_BLOCK(2), soc_cmicdv4_block_intr6, 2, "PARITY INTR" }, 414 { IRQ_CMCx_BLOCK(3), soc_cmicdv4_block_intr6, 3, "PARITY INTR" }, 415 { IRQ_CMCx_BLOCK(4), soc_cmicdv4_block_intr6, 4, "PARITY INTR" }, 416 { IRQ_CMCx_BLOCK(5), soc_cmicdv4_block_intr6, 5, "PARITY INTR" }, 417 { IRQ_CMCx_BLOCK(6), soc_cmicdv4_block_intr6, 6, "PARITY INTR" }, 418 { IRQ_CMCx_BLOCK(7), soc_cmicdv4_block_intr6, 7, "PARITY INTR" }, 419 { IRQ_CMCx_BLOCK(8), soc_cmicdv4_block_intr6, 8, "PARITY INTR" }, 420 { IRQ_CMCx_BLOCK(9), soc_cmicdv4_block_intr6, 9, "PARITY INTR" }, 421 { IRQ_CMCx_BLOCK(10), soc_cmicdv4_block_intr6, 10, "PARITY INTR" }, 422 { IRQ_CMCx_BLOCK(11), soc_cmicdv4_block_intr6, 11, "PARITY INTR" }, 423 { IRQ_CMCx_BLOCK(12), soc_cmicdv4_block_intr6, 12, "PARITY INTR" }, 424 { IRQ_CMCx_BLOCK(13), soc_cmicdv4_block_intr6, 13, "PARITY INTR" }, 425 { IRQ_CMCx_BLOCK(14), soc_cmicdv4_block_intr6, 14, "PARITY INTR" }, 426 { IRQ_CMCx_BLOCK(15), soc_cmicdv4_block_intr6, 15, "PARITY INTR" }, 427 { IRQ_CMCx_BLOCK(16), soc_cmicdv4_block_intr6, 16, "PARITY INTR" }, 428 { IRQ_CMCx_BLOCK(17), soc_cmicdv4_block_intr6, 17, "PARITY INTR" }, 429 { IRQ_CMCx_BLOCK(18), soc_cmicdv4_block_intr6, 18, "PARITY INTR" }, 430 { IRQ_CMCx_BLOCK(19), soc_cmicdv4_block_intr6, 19, "PARITY INTR" }, 431 { IRQ_CMCx_BLOCK(20), soc_cmicdv4_block_intr6, 20, "PARITY INTR" }, 432 { IRQ_CMCx_BLOCK(21), soc_cmicdv4_block_intr6, 21, "PARITY INTR" }, 433 { IRQ_CMCx_BLOCK(22), soc_cmicdv4_block_intr6, 22, "PARITY INTR" }, 434 { IRQ_CMCx_BLOCK(23), soc_cmicdv4_block_intr6, 23, "PARITY INTR" }, 435 { IRQ_CMCx_BLOCK(24), soc_cmicdv4_block_intr6, 24, "PARITY INTR" }, 436 { IRQ_CMCx_BLOCK(25), soc_cmicdv4_block_intr6, 25, "PARITY INTR" }, 437 { IRQ_CMCx_BLOCK(26), soc_cmicdv4_block_intr6, 26, "PARITY INTR" }, 438 { IRQ_CMCx_BLOCK(27), soc_cmicdv4_block_intr6, 27, "PARITY INTR" }, 439 { IRQ_CMCx_BLOCK(28), soc_cmicdv4_block_intr6, 28, "PARITY INTR" }, 440 { IRQ_CMCx_BLOCK(29), soc_cmicdv4_block_intr6, 29, "PARITY INTR" }, 441 { IRQ_CMCx_BLOCK(30), soc_cmicdv4_block_intr6, 30, "PARITY INTR" }, 442 { IRQ_CMCx_BLOCK(31), soc_cmicdv4_block_intr6, 31, "PARITY INTR" }, 443 { 0, NULL, 0, "" } /* Termination */ 444 }; 445 446 /* IRQ0 handler for CMC of SOC_ARM_CMC(unit, 0) 447 * For now only support TSLAM (for Caladan3 TMU) 448 * and FIFO DMA 0/1 (for Caladan3 COP0/1) 449 */ 450 STATIC intr_handler_t soc_cmicm_intr_handlers0_arm_cmc[] = { 451 { IRQ_SBUSDMA_CH0_DONE, soc_cmicm_intr_sbusdma_done, 0, "SBUS_DMA0_DONE" }, 452 { IRQ_SBUSDMA_CH1_DONE, soc_cmicm_intr_sbusdma_done, 1, "SBUS_DMA1_DONE" }, 453 { IRQ_SBUSDMA_CH2_DONE, soc_cmicm_intr_sbusdma_done, 2, "SBUS_DMA2_DONE" }, 454 455 { IRQ_CMCx_FIFO_CH_DMA(0), soc_cmicm_fifo_dma_done, 0, "CH0_FIFO_DMA_DONE" }, 456 { IRQ_CMCx_FIFO_CH_DMA(1), soc_cmicm_fifo_dma_done, 1, "CH1_FIFO_DMA_DONE" }, 457 { IRQ_CMCx_FIFO_CH_DMA(2), soc_cmicm_fifo_dma_done, 2, "CH2_FIFO_DMA_DONE" }, 458 { IRQ_CMCx_FIFO_CH_DMA(3), soc_cmicm_fifo_dma_done, 3, "CH3_FIFO_DMA_DONE" }, 459 460 { 0, NULL, 0, "" } /* Termination */ 461 }; 462 #endif 463 464 #ifdef INCLUDE_RCPU 465 STATIC intr_handler_t soc_cmicm_rcpu_intr_handlers0[] = { 466 { IRQ_RCPU_MIIM_OP_DONE, soc_cmicm_rcpu_intr_miim_op, 0, "RCPU_MIIM_OP_DONE" }, 467 { 0, NULL, 0, "" } /* Termination */ 468 }; 469 #endif /* INCLUDE_RCPU */ 470 /* 471 * Interrupt handler functions 472 */ 473 474 STATIC void 475 soc_cmicm_intr_schan_done(int unit, uint32 vchan) 476 { 477 soc_control_t *soc = SOC_CONTROL(unit); 478 int cmc = vchan / N_DMA_CHAN; 479 480 /* Record the schan control regsiter */ 481 soc->schan_result[cmc] = soc_pci_read(unit, CMIC_CMCx_SCHAN_CTRL_OFFSET(cmc)); 482 soc_pci_write(unit, CMIC_CMCx_SCHAN_CTRL_OFFSET(cmc), 483 soc_pci_read(unit, CMIC_CMCx_SCHAN_CTRL_OFFSET(cmc)) & ~SC_CMCx_MSG_DONE); 484 485 soc->stat.intr_sc++; 486 487 if (soc->schanIntr[cmc]) { 488 sal_sem_give(soc->schanIntr[cmc]); 489 } 490 } 491 492 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) 493 STATIC void 494 soc_cmicm_intr_common_schan_done(int unit, uint32 ignored) 495 { 496 soc_control_t *soc = SOC_CONTROL(unit); 497 int cmc = CMIC_CMC_NUM_MAX; 498 499 COMPILER_REFERENCE(ignored); 500 501 /* Record the schan control regsiter */ 502 soc->schan_result[cmc] = soc_pci_read(unit, CMIC_COMMON_SCHAN_CTRL_OFFSET); 503 soc_pci_write(unit, CMIC_COMMON_SCHAN_CTRL_OFFSET, 504 soc_pci_read(unit, CMIC_COMMON_SCHAN_CTRL_OFFSET) & ~SC_CMCx_MSG_DONE); 505 506 soc->stat.intr_sc++; 507 508 if (soc->schanIntr[cmc]) { 509 sal_sem_give(soc->schanIntr[cmc]); 510 } 511 } 512 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)*/ 513 514 STATIC void 515 soc_cmicm_intr_miim_op(int unit, uint32 ignored) 516 { 517 soc_control_t *soc = SOC_CONTROL(unit); 518 int cmc = SOC_PCI_CMC(unit); 519 520 COMPILER_REFERENCE(ignored); 521 522 soc_pci_write(unit, CMIC_CMCx_MIIM_CTRL_OFFSET(cmc), 0); /* Clr Read & Write Stat */ 523 524 soc->stat.intr_mii++; 525 526 if (soc->miimIntr) { 527 sal_sem_give(soc->miimIntr); 528 } 529 } 530 531 STATIC int 532 _sbusdma_cmc_ch_op_proc(int unit, uint32 op, int cmc, int ch) 533 { 534 soc_control_t *soc = SOC_CONTROL(unit); 535 int rv = SOC_E_NONE; 536 537 if ((cmc >= SOC_CMCS_NUM_MAX) || 538 (ch < 0) || (ch >= SOC_SBUSDMA_CH_PER_CMC)) { 539 return SOC_E_PARAM; 540 } 541 LOG_VERBOSE(BSL_LS_SOC_INTR, 542 (BSL_META_U(unit, 543 "op = %u, cmc = %d, ch = %d\n"), op, cmc, ch)); 544 switch (op) { 545 case SOC_SBUSDMA_TYPE_TDMA: 546 soc->stat.intr_tdma++; 547 if (soc->tableDmaIntrEnb) { 548 sal_sem_give(soc->sbusDmaIntrs[cmc][ch]); 549 } 550 break; 551 case SOC_SBUSDMA_TYPE_SLAM: 552 soc->stat.intr_tslam++; 553 if (soc->tslamDmaIntrEnb) { 554 sal_sem_give(soc->sbusDmaIntrs[cmc][ch]); 555 } 556 break; 557 #ifdef BCM_SBUSDMA_SUPPORT 558 case SOC_SBUSDMA_TYPE_DESC: 559 soc->stat.intr_desc++; 560 if (SOC_SBUSDMA_DM_INTRENB(unit)) { 561 sal_sem_give(soc->sbusDmaIntrs[cmc][ch]); 562 } 563 break; 564 #endif 565 default: 566 LOG_INFO(BSL_LS_SOC_INTR, 567 (BSL_META_U(unit, 568 "Received unallocated sbusdma interrupt !!\n"))); 569 rv = SOC_E_PARAM; 570 break; 571 } 572 return rv; 573 } 574 575 STATIC void 576 soc_cmicm_intr_tdma_done(int unit, uint32 ignored) 577 { 578 soc_control_t *soc = SOC_CONTROL(unit); 579 int cmc = SOC_PCI_CMC(unit); 580 int ch = soc->tdma_ch; 581 582 COMPILER_REFERENCE(ignored); 583 584 (void)soc_cmicm_intr0_disable(unit, IRQ_CMCx_TDMA_DONE); 585 586 _sbusdma_cmc_ch_op_proc(unit, SOC_SBUSDMA_TYPE_TDMA, cmc, ch); 587 } 588 589 STATIC void 590 soc_cmicm_intr_tslam_done(int unit, uint32 ignored) 591 { 592 soc_control_t *soc = SOC_CONTROL(unit); 593 int cmc = SOC_PCI_CMC(unit); 594 int ch = soc->tslam_ch; 595 596 COMPILER_REFERENCE(ignored); 597 598 (void)soc_cmicm_intr0_disable(unit, IRQ_CMCx_TSLAM_DONE); 599 600 _sbusdma_cmc_ch_op_proc(unit, SOC_SBUSDMA_TYPE_SLAM, cmc, ch); 601 } 602 603 STATIC void 604 soc_cmicm_intr_stat_dma(int unit, uint32 ignored) 605 { 606 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 607 608 soc_control_t *soc = SOC_CONTROL(unit); 609 int cmc = SOC_PCI_CMC(unit); 610 611 COMPILER_REFERENCE(ignored); 612 if (SOC_IS_SAND(unit)) { 613 return; 614 } 615 616 soc_pci_write(unit, CMIC_CMCx_STAT_DMA_CFG_OFFSET(cmc), 617 soc_pci_read(unit, CMIC_CMCx_STAT_DMA_CFG_OFFSET(cmc)) | STDMA_ITER_DONE_CLR); 618 619 soc->stat.intr_stats++; 620 621 if (soc->counter_intr) { 622 sal_sem_give(soc->counter_intr); 623 } 624 #endif 625 } 626 627 STATIC void 628 soc_cmicm_intr_ccmdma_done(int unit, uint32 vchan) 629 { 630 int cmc; 631 soc_control_t *soc = SOC_CONTROL(unit); 632 633 if (soc_feature(unit, soc_feature_cmicm_multi_dma_cmc)) { 634 cmc = vchan / N_DMA_CHAN; 635 } else { 636 cmc = SOC_PCI_CMC(unit); 637 } 638 639 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, IRQ_CMCx_CCMDMA_DONE); 640 641 soc->stat.intr_ccmdma++; 642 643 if (soc->ccmDmaIntr[cmc]) { 644 sal_sem_give(soc->ccmDmaIntr[cmc]); 645 } 646 } 647 648 #ifdef BCM_SBUSDMA_SUPPORT 649 STATIC uint32 _soc_irq_cmic_sbusdma_ch[] = { 650 IRQ_SBUSDMA_CH0_DONE, 651 IRQ_SBUSDMA_CH1_DONE, 652 IRQ_SBUSDMA_CH2_DONE 653 }; 654 655 STATIC int 656 _sbusdma_cmc_ch_op_get(int unit, int ch, uint32 *op) 657 { 658 soc_control_t *soc = SOC_CONTROL(unit); 659 660 if (ch == soc->tdma_ch) { 661 *op = SOC_SBUSDMA_TYPE_TDMA; 662 } else if (ch == soc->tslam_ch) { 663 *op = SOC_SBUSDMA_TYPE_SLAM; 664 } else if (ch == soc->desc_ch) { 665 *op = SOC_SBUSDMA_TYPE_DESC; 666 } else { 667 return SOC_E_PARAM; 668 } 669 670 return SOC_E_NONE; 671 } 672 673 #endif 674 675 STATIC void 676 soc_cmicm_intr_sbusdma_done(int unit, uint32 vchan) 677 { 678 #ifdef BCM_SBUSDMA_SUPPORT 679 uint32 op; 680 int cmc; 681 int ch; 682 683 if (soc_feature(unit, soc_feature_cmicm_multi_dma_cmc)) { 684 /* vchan = cmc*N_DMA_CHAN + SBUS_CHANNEL (0 - CMIC_CMCx_SBUSDMA_CHAN_MAX-1) */ 685 cmc = vchan / N_DMA_CHAN; 686 ch = vchan % N_DMA_CHAN; 687 688 if (ch > CMIC_CMCx_SBUSDMA_CHAN_MAX - 1) { 689 LOG_ERROR(BSL_LS_SOC_INTR, 690 (BSL_META_U(unit, 691 "ERROR: sbusdma channel %d !!\n"), ch)); 692 return; 693 } 694 695 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, _soc_irq_cmic_sbusdma_ch[ch]); 696 697 { 698 if (SOC_FAILURE(_sbusdma_cmc_ch_op_get(unit, ch, &op))) { 699 LOG_INFO(BSL_LS_SOC_INTR, 700 (BSL_META_U(unit, 701 "Received unallocated sbusdma interrupt cmc %d ch %d !!\n"), 702 cmc, ch)); 703 } else { 704 (void)_sbusdma_cmc_ch_op_proc(unit, op, cmc, ch); 705 706 } 707 } 708 } else { 709 cmc = SOC_PCI_CMC(unit); 710 ch = vchan; 711 712 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, _soc_irq_cmic_sbusdma_ch[ch]); 713 714 if (SOC_FAILURE(_sbusdma_cmc_ch_op_get(unit, ch, &op))) { 715 LOG_INFO(BSL_LS_SOC_INTR, 716 (BSL_META_U(unit, 717 "Received unallocated sbusdma interrupt cmc %d ch %d !!\n"), 718 cmc, ch)); 719 } else { 720 (void)_sbusdma_cmc_ch_op_proc(unit, op, cmc, ch); 721 } 722 } 723 #else 724 COMPILER_REFERENCE(unit); 725 COMPILER_REFERENCE(vchan); 726 #endif 727 } 728 729 STATIC void 730 soc_cmicm_fifo_dma_done(int unit, uint32 vchan) 731 { 732 soc_control_t *soc = SOC_CONTROL(unit); 733 int cmc, ch; 734 int oam_status_channel = -1; 735 int oam_event_channel = -1; 736 int olp_channel = -1; 737 738 if (soc_feature(unit, soc_feature_cmicm_multi_dma_cmc)) { 739 cmc = vchan / N_DMA_CHAN; 740 ch = vchan % N_DMA_CHAN; 741 } else { 742 cmc = SOC_PCI_CMC(unit); 743 ch = vchan; 744 } 745 /* get the channel configure for each source type */ 746 #ifdef BCM_PETRA_SUPPORT 747 if(SOC_IS_JERICHO(unit)) 748 { 749 jer_mgmt_dma_fifo_channel_get(unit, dma_fifo_channel_src_oam_status, &oam_status_channel); 750 jer_mgmt_dma_fifo_channel_get(unit, dma_fifo_channel_src_oam_event, &oam_event_channel); 751 jer_mgmt_dma_fifo_channel_get(unit, dma_fifo_channel_src_olp, &olp_channel); 752 } 753 #endif 754 if (SOC_IS_JERICHO(unit) && (vchan == oam_status_channel)) { 755 #ifdef BCM_PETRA_SUPPORT 756 uint8 oam_is_init=0; 757 uint8 bfd_is_init=0; 758 uint32 rv; 759 760 rv = sw_state_access[unit].dpp.soc.arad.pp.oper_mode.oam_enable.get(unit, &oam_is_init); 761 rv = sw_state_access[unit].dpp.soc.arad.pp.oper_mode.bfd_enable.get(unit, &bfd_is_init); 762 /* Return value ignored: even if the above function failed we must clear the interrupt.*/ 763 (void) rv; 764 765 if (oam_is_init || bfd_is_init) { 766 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, IRQ_CMCx_FIFO_CH_DMA(ch)); 767 rv = sal_dpc(soc_ppd_oam_dma_event_handler, INT_TO_PTR(unit), INT_TO_PTR(SOC_PPC_OAM_DMA_EVENT_TYPE_STAT_EVENT), INT_TO_PTR(cmc), INT_TO_PTR(ch), 0); 768 if (rv) 769 { 770 LOG_INFO(BSL_LS_SOC_INTR, 771 (BSL_META_U(unit, 772 "sal_dpc failed to queue soc_ppd_oam_dma_event_handler !!\n"))); 773 774 /* sal_dpc failed. Enable the interrupt */ 775 soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_FIFO_CH_DMA(ch)); 776 } 777 } 778 #endif 779 } else if (SOC_IS_JERICHO(unit) && (vchan == oam_event_channel)) { 780 #ifdef BCM_PETRA_SUPPORT 781 uint8 oam_is_init=0; 782 uint8 bfd_is_init=0; 783 uint32 rv; 784 785 rv = sw_state_access[unit].dpp.soc.arad.pp.oper_mode.oam_enable.get(unit, &oam_is_init); 786 rv = sw_state_access[unit].dpp.soc.arad.pp.oper_mode.bfd_enable.get(unit, &bfd_is_init); 787 /* Return value ignored: even if the above function failed we must clear the interrupt.*/ 788 (void) rv; 789 790 if (oam_is_init || bfd_is_init) { 791 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, IRQ_CMCx_FIFO_CH_DMA(ch)); 792 rv = sal_dpc(soc_ppd_oam_dma_event_handler, INT_TO_PTR(unit), INT_TO_PTR(SOC_PPC_OAM_DMA_EVENT_TYPE_EVENT), INT_TO_PTR(cmc), INT_TO_PTR(ch), 0); 793 if (rv) 794 { 795 LOG_INFO(BSL_LS_SOC_INTR, 796 (BSL_META_U(unit, 797 "sal_dpc failed to queue soc_ppd_oam_dma_event_handler !!\n"))); 798 799 /* sal_dpc failed. Enable the interrupt */ 800 soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_FIFO_CH_DMA(ch)); 801 } 802 } 803 #endif 804 } else if (SOC_IS_ARADPLUS(unit) && !SOC_IS_JERICHO(unit) && (ch == SOC_MEM_FIFO_DMA_CHANNEL_3)) { 805 #ifdef BCM_PETRA_SUPPORT 806 uint8 oam_is_init=0; 807 uint8 bfd_is_init=0; 808 uint32 rv; 809 810 rv = sw_state_access[unit].dpp.soc.arad.pp.oper_mode.oam_enable.get(unit, &oam_is_init); 811 rv = sw_state_access[unit].dpp.soc.arad.pp.oper_mode.bfd_enable.get(unit, &bfd_is_init); 812 /* Return value ignored: even if the above function failed we must clear the interrupt.*/ 813 (void) rv; 814 815 if (oam_is_init || bfd_is_init) { 816 (void)soc_cmicm_intr0_disable(unit, IRQ_CMCx_FIFO_CH_DMA(ch)); 817 rv = sal_dpc(soc_ppd_oam_dma_event_handler, INT_TO_PTR(unit), INT_TO_PTR(SOC_PPC_OAM_DMA_EVENT_TYPE_EVENT), INT_TO_PTR(cmc), INT_TO_PTR(ch), 0); 818 if (rv) 819 { 820 LOG_INFO(BSL_LS_SOC_INTR, 821 (BSL_META_U(unit, 822 "sal_dpc failed to queue soc_ppd_oam_dma_event_handler !!\n"))); 823 824 /* sal_dpc failed. Enable the interrupt */ 825 soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_FIFO_CH_DMA(ch)); 826 } 827 } 828 #endif 829 830 } else if (SOC_IS_JERICHO(unit) && (vchan == olp_channel)) { 831 #ifdef BCM_PETRA_SUPPORT 832 uint32 rv; 833 834 /* Enable is done in the end of the handler */ 835 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, IRQ_CMCx_FIFO_CH_DMA(ch)); 836 rv = sal_dpc(arad_pp_frwrd_mact_learning_dma_event_handler, INT_TO_PTR(unit), 0, INT_TO_PTR(cmc), INT_TO_PTR(ch), 0); 837 if (rv) 838 { 839 LOG_INFO(BSL_LS_SOC_INTR, 840 (BSL_META_U(unit, 841 "sal_dpc failed to queue arad_pp_frwrd_mact_learning_dma_event_handler !!\n"))); 842 843 /* sal_dpc failed. Enable the interrupt */ 844 soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_FIFO_CH_DMA(ch)); 845 } 846 #endif 847 } 848 else if (SOC_IS_DFE(unit)) 849 { 850 #ifdef BCM_DFE_SUPPORT 851 if (SOC_DFE_CONTROL(unit)->rx_thread_fifo_dma_semaphore != NULL) 852 { 853 (void)soc_cmicm_intr0_disable(unit, IRQ_CMCx_FIFO_CH_DMA(ch)); 854 sal_sem_give(SOC_DFE_CONTROL(unit)->rx_thread_fifo_dma_semaphore); 855 } 856 #endif 857 } else { 858 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, IRQ_CMCx_FIFO_CH_DMA(ch)); 859 860 #ifdef BCM_CMICM_SUPPORT 861 if (soc->fifoDmaMutexs[cmc][ch]) { 862 SOC_CONTROL(unit)->stat.intr_fifo_dma[ch]++; 863 sal_sem_give(soc->fifoDmaIntrs[cmc][ch]); 864 } 865 #endif 866 switch (ch) { 867 case SOC_MEM_FIFO_DMA_CHANNEL_0: 868 #ifdef BCM_TOMAHAWK_SUPPORT 869 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 870 871 if (soc->l2modDmaIntrEnb) { 872 SOC_CONTROL(unit)->stat.intr_fifo_dma[ch]++; 873 sal_sem_give(soc->arl_notify); 874 } 875 break; 876 } 877 #endif /* BCM_TOMAHAWK_SUPPORT */ 878 if (SOC_CONTROL(unit)->ftreportIntrEnb) { 879 SOC_CONTROL(unit)->stat.intr_fifo_dma[ch]++; 880 sal_sem_give(SOC_CONTROL(unit)->ftreportIntr); 881 } else if (SOC_IS_TD2_TT2(unit) && soc->l2modDmaIntrEnb) { 882 /* L2 fifo dma ch = SOC_MEM_FIFO_DMA_CHANNEL_0; */ 883 SOC_CONTROL(unit)->stat.intr_fifo_dma[ch]++; 884 sal_sem_give(soc->arl_notify); 885 } 886 break; 887 case SOC_MEM_FIFO_DMA_CHANNEL_1: 888 #ifdef BCM_TOMAHAWK_SUPPORT 889 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 890 if (soc->ctrEvictDmaIntrEnb) { 891 SOC_CONTROL(unit)->stat.intr_fifo_dma[ch]++; 892 sal_sem_give(soc->ctrEvictIntr); 893 } 894 break; 895 } else 896 #endif /* BCM_TOMAHAWK_SUPPORT */ 897 if (soc->l2modDmaIntrEnb) { 898 SOC_CONTROL(unit)->stat.intr_fifo_dma[ch]++; 899 sal_sem_give(soc->arl_notify); 900 } 901 break; 902 case SOC_MEM_FIFO_DMA_CHANNEL_2: 903 if (SOC_CONTROL(unit)->ipfixIntrEnb) { 904 SOC_CONTROL(unit)->stat.intr_fifo_dma[ch]++; 905 sal_sem_give(SOC_CONTROL(unit)->ipfixIntr); 906 } 907 break; 908 case SOC_MEM_FIFO_DMA_CHANNEL_3: 909 if (SOC_CONTROL(unit)->ipfixIntrEnb) { 910 SOC_CONTROL(unit)->stat.intr_fifo_dma[ch]++; 911 sal_sem_give(SOC_CONTROL(unit)->ipfixIntr); 912 } 913 break; 914 default: 915 LOG_INFO(BSL_LS_SOC_INTR, 916 (BSL_META_U(unit, 917 "Received unallocated fifo dma interrupt !!\n"))); 918 } 919 } 920 } 921 922 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) 923 STATIC void 924 soc_cmicm_chip_func_intr(int unit, uint32 val) 925 { 926 int cmc = SOC_PCI_CMC(unit); 927 uint32 irqStat; 928 #if defined (BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) 929 uint32 irqMask, oldmask; 930 931 oldmask = 0; 932 933 irqMask = SOC_CMCx_IRQ1_MASK(unit,cmc); 934 #endif 935 936 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); 937 938 #ifdef BCM_TRIDENT2_SUPPORT 939 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit)) { 940 uint32 rv; 941 if (irqStat & ~_SOC_TD2_FUNC_INTR_MASK) { 942 (void)soc_cmicm_intr1_disable(unit, irqStat & 943 ~_SOC_TD2_FUNC_INTR_MASK); 944 } 945 946 if (irqStat & _SOC_TD2_FUNC_INTR_MASK) { 947 oldmask = soc_cmicm_intr1_disable(unit, irqMask); 948 949 /* dispatch interrupt */ 950 LOG_INFO(BSL_LS_SOC_INTR, 951 (BSL_META_U(unit, 952 "soc_cmicm_intr type 1 unit %d: dispatch\n"), 953 unit)); 954 955 rv = sal_dpc(soc_td2_process_func_intr, INT_TO_PTR(unit), 956 INT_TO_PTR(oldmask), 0, 0, 0); 957 if (rv) { 958 LOG_ERROR(BSL_LS_SOC_INTR, (BSL_META_U(unit, 959 "sal_dpc failed to queue event handler !!\n"))); 960 /* sal_dpc failed. Enable the interrupt */ 961 soc_cmicm_intr1_enable(unit, irqMask); 962 } 963 } 964 } else 965 #endif /* BCM_TRIDENT2_SUPPORT */ 966 #ifdef BCM_TRIUMPH3_SUPPORT 967 if (SOC_IS_TRIUMPH3(unit)) { 968 uint32 rv; 969 if (soc_feature(unit, soc_feature_esm_correction)) { 970 if (irqStat & ~(_SOC_TR3_FUNC_PARITY_INTR_MASK | 971 _SOC_TR3_ESM_INTR_MASK)) { 972 (void)soc_cmicm_intr1_disable(unit, irqStat & 973 ~(_SOC_TR3_FUNC_PARITY_INTR_MASK | 974 _SOC_TR3_ESM_INTR_MASK)); 975 } 976 977 if (irqStat & (_SOC_TR3_FUNC_PARITY_INTR_MASK | 978 _SOC_TR3_ESM_INTR_MASK)) { 979 oldmask = soc_cmicm_intr1_disable(unit, irqMask); 980 /* dispatch interrupt */ 981 LOG_INFO(BSL_LS_SOC_INTR, 982 (BSL_META_U(unit, 983 "soc_cmicm_intr type 1 unit %d: dispatch\n"), 984 unit)); 985 986 if (irqStat & _SOC_TR3_ESM_INTR_MASK) { 987 sal_sem_give(SOC_CONTROL(unit)->esm_recovery_notify); 988 } 989 rv = sal_dpc(soc_tr3_process_func_intr, INT_TO_PTR(unit), 990 INT_TO_PTR(oldmask), 0, 0, 0); 991 if (rv) { 992 LOG_ERROR(BSL_LS_SOC_INTR, (BSL_META_U(unit, 993 "sal_dpc failed to queue event handler !!\n"))); 994 /* sal_dpc failed. Enable the interrupt */ 995 soc_cmicm_intr1_enable(unit, irqMask); 996 } 997 } 998 } else { 999 if (irqStat & ~_SOC_TR3_FUNC_PARITY_INTR_MASK) { 1000 (void)soc_cmicm_intr1_disable(unit, irqStat & 1001 ~_SOC_TR3_FUNC_PARITY_INTR_MASK); 1002 } 1003 1004 if (irqStat & _SOC_TR3_FUNC_PARITY_INTR_MASK) { 1005 oldmask = soc_cmicm_intr1_disable(unit, irqMask); 1006 1007 /* dispatch interrupt */ 1008 LOG_INFO(BSL_LS_SOC_INTR, 1009 (BSL_META_U(unit, 1010 "soc_cmicm_intr type 1 unit %d: dispatch\n"), 1011 unit)); 1012 1013 rv = sal_dpc(soc_tr3_process_func_intr, INT_TO_PTR(unit), 1014 INT_TO_PTR(oldmask), 0, 0, 0); 1015 if (rv) { 1016 LOG_ERROR(BSL_LS_SOC_INTR, (BSL_META_U(unit, 1017 "sal_dpc failed to queue oam event handler !!\n"))); 1018 /* sal_dpc failed. Enable the interrupt */ 1019 soc_cmicm_intr1_enable(unit, irqMask); 1020 } 1021 } 1022 1023 } 1024 } else 1025 #endif /* BCM_TRIUMPH3_SUPPORT */ 1026 { 1027 LOG_ERROR(BSL_LS_SOC_COMMON, 1028 (BSL_META_U(unit, 1029 "soc_cmicm_intr unit %d: " 1030 "Disabling unhandled interrupt(s): %d\n"), unit, irqStat)); 1031 (void)soc_cmicm_intr1_disable(unit, irqStat); 1032 } 1033 } 1034 #endif /* (BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)*/ 1035 1036 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) 1037 STATIC void 1038 soc_cmicm_intr_link_stat(int unit, uint32 ignored) 1039 { 1040 soc_control_t *soc = SOC_CONTROL(unit); 1041 uint32 rval = 0; 1042 1043 COMPILER_REFERENCE(ignored); 1044 1045 soc_pci_analyzer_trigger(unit); 1046 1047 soc->stat.intr_ls++; 1048 1049 /* Clear interrupt */ 1050 READ_CMIC_MIIM_SCAN_STATUSr(unit, &rval); 1051 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1052 (BSL_META_U(unit, 1053 "Status: 0x%08x\n"), rval)); 1054 WRITE_CMIC_MIIM_CLR_SCAN_STATUSr(unit, rval); 1055 1056 /* Perform user callout, if one is registered */ 1057 1058 if (soc->soc_link_callout != NULL) { 1059 (*soc->soc_link_callout)(unit); 1060 } 1061 } 1062 1063 STATIC void 1064 soc_ser_engine_intr(int unit, uint32 val) 1065 { 1066 int cmc; 1067 uint32 irqMask, irqStat; 1068 1069 cmc = SOC_PCI_CMC(unit); 1070 irqMask = SOC_CMCx_IRQ1_MASK(unit,cmc); 1071 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); 1072 1073 (void)soc_cmicm_intr1_disable(unit, irqMask); 1074 1075 LOG_ERROR(BSL_LS_SOC_COMMON, 1076 (BSL_META_U(unit, 1077 "soc_cmicm_intr unit %d: " 1078 "Disabling unhandled interrupt(s): %d\n"), 1079 unit, irqStat)); 1080 (void)soc_cmicm_intr1_disable(unit, irqStat); 1081 } 1082 1083 STATIC void 1084 soc_cmicm_timesync_intr(int unit, uint32 val) 1085 { 1086 int cmc; 1087 uint32 irqStat; 1088 uint32 irqMask; 1089 1090 cmc = SOC_PCI_CMC(unit); 1091 irqMask = SOC_CMCx_IRQ1_MASK(unit,cmc); 1092 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); 1093 1094 #if defined(BCM_PETRA_SUPPORT) 1095 if (SOC_IS_JERICHO(unit)) { 1096 soc_cmicm_intr1_disable(unit, irqMask); 1097 soc_timesync_intr(unit); 1098 (void)soc_cmicm_intr1_enable(unit, irqMask); 1099 } else 1100 #endif 1101 #if defined(BCM_TIMESYNC_TIME_CAPTURE_SUPPORT) 1102 if (soc_feature(unit, soc_feature_timesync_time_capture)) { 1103 soc_cmicm_intr1_disable(unit, irqMask); 1104 soc_esw_timesync_ts_intr(unit); 1105 (void)soc_cmicm_intr1_enable(unit, irqMask); 1106 } else 1107 #endif 1108 { 1109 LOG_ERROR(BSL_LS_SOC_COMMON, 1110 (BSL_META_U(unit, "soc_cmicm_timesync_intr unit %d: " 1111 "Disabling unhandled interrupt(s): %d\n"), 1112 unit, irqStat)); 1113 (void)soc_cmicm_intr1_disable(unit, irqMask); 1114 } 1115 } 1116 1117 STATIC void 1118 soc_cmicm_parity_intr(int unit, uint32 val) 1119 { 1120 int cmc; 1121 uint32 irqStat; 1122 #if defined(BCM_XGS_SUPPORT) 1123 uint32 irqMask, oldmask; 1124 #endif 1125 1126 cmc = SOC_PCI_CMC(unit); 1127 1128 #if defined(BCM_SABER2_SUPPORT) 1129 if (SOC_IS_SABER2(unit)) { 1130 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); 1131 } else { 1132 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); 1133 } 1134 #else 1135 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); 1136 #endif 1137 1138 #if defined(BCM_XGS_SUPPORT) 1139 #if defined(BCM_SABER2_SUPPORT) 1140 if (SOC_IS_SABER2(unit)) { 1141 irqMask = SOC_CMCx_IRQ3_MASK(unit,cmc); 1142 1143 oldmask = soc_cmicm_intr3_disable(unit, irqMask); 1144 } else { 1145 irqMask = SOC_CMCx_IRQ2_MASK(unit,cmc); 1146 1147 oldmask = soc_cmicm_intr2_disable(unit, irqMask); 1148 } 1149 #else 1150 irqMask = SOC_CMCx_IRQ2_MASK(unit,cmc); 1151 1152 oldmask = soc_cmicm_intr2_disable(unit, irqMask); 1153 #endif 1154 1155 /* dispatch interrupt if we have handler */ 1156 if (soc_ser_parity_error_cmicm_intr(INT_TO_PTR(unit), 0, 1157 INT_TO_PTR(oldmask), 0, 0)) { 1158 LOG_INFO(BSL_LS_SOC_INTR, 1159 (BSL_META_U(unit, 1160 "soc_cmicm_intr type 2 unit %d: dispatch\n"), 1161 unit)); 1162 } else 1163 #endif 1164 { 1165 /* Decoupling OAM interrupt handler from parity interrupt handler */ 1166 #ifdef BCM_TRIUMPH3_SUPPORT 1167 if (SOC_IS_TRIUMPH3(unit)) { 1168 uint32 rv; 1169 rv = sal_dpc((sal_dpc_fn_t)soc_tr3_process_func_intr, INT_TO_PTR(unit), 1170 0, INT_TO_PTR(oldmask), 0, 0); 1171 if (rv) { 1172 LOG_ERROR(BSL_LS_SOC_INTR, (BSL_META_U(unit, 1173 "sal_dpc failed to queue oam event handler !!\n"))); 1174 /* sal_dpc failed. Enable the interrupt */ 1175 soc_cmicm_intr2_enable(unit, irqMask); 1176 } 1177 1178 } else 1179 #endif 1180 { 1181 LOG_ERROR(BSL_LS_SOC_COMMON, 1182 (BSL_META_U(unit, 1183 "soc_cmicm_intr unit %d: " 1184 "Disabling unhandled interrupt(s): %d\n"), 1185 unit, irqStat)); 1186 #if defined(BCM_SABER2_SUPPORT) 1187 if (SOC_IS_SABER2(unit)) { 1188 (void)soc_cmicm_intr3_disable(unit, irqStat); 1189 } else { 1190 (void)soc_cmicm_intr2_disable(unit, irqStat); 1191 } 1192 #else 1193 (void)soc_cmicm_intr2_disable(unit, irqStat); 1194 #endif 1195 } 1196 } 1197 } 1198 1199 STATIC void 1200 soc_cmicdv2_chip_parity_intr(int unit, uint32 val) 1201 { 1202 int cmc; 1203 uint32 irqStat; 1204 #if defined(BCM_XGS_SUPPORT) 1205 uint32 irqMask; 1206 #endif 1207 1208 cmc = SOC_PCI_CMC(unit); 1209 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); 1210 1211 #if defined(BCM_XGS_SUPPORT) 1212 irqMask = SOC_CMCx_IRQ2_MASK(unit,cmc); 1213 1214 soc_cmicm_intr2_disable(unit, irqMask & irqStat); 1215 1216 #if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 1217 if (SOC_IS_MONTEREY(unit) || SOC_IS_TOMAHAWK3(unit)) { 1218 #if defined (INCLUDE_GDPLL) || defined(BCM_TOMAHAWK3_SUPPORT) 1219 uint32 rv; 1220 #endif 1221 /* dispatch interrupt */ 1222 LOG_INFO(BSL_LS_SOC_INTR, 1223 (BSL_META_U(unit, 1224 "soc_cmicm_intr type 3 unit %d: dispatch\n"), 1225 unit)); 1226 1227 switch (val) { 1228 case 24: 1229 #if defined (INCLUDE_GDPLL) || defined(BCM_TOMAHAWK3_SUPPORT) 1230 rv = sal_dpc(soc_nanosync_intr, INT_TO_PTR(unit), 0, 0, 0, 0); 1231 if (rv) { 1232 LOG_ERROR(BSL_LS_SOC_INTR, (BSL_META_U(unit, 1233 "sal_dpc failed to queue oam event handler !!\n"))); 1234 /* sal_dpc failed. Enable the interrupt */ 1235 soc_cmicm_intr2_enable(unit, irqMask); 1236 } 1237 #endif 1238 break; 1239 1240 case 25: 1241 #ifdef INCLUDE_GDPLL 1242 rv = sal_dpc(soc_nanosync_debug_intr, INT_TO_PTR(unit), 0, 0, 0, 0); 1243 if (rv) { 1244 LOG_ERROR(BSL_LS_SOC_INTR, (BSL_META_U(unit, 1245 "sal_dpc failed to queue oam event handler !!\n"))); 1246 /* sal_dpc failed. Enable the interrupt */ 1247 soc_cmicm_intr2_enable(unit, irqMask); 1248 } 1249 #endif 1250 break; 1251 1252 default: 1253 LOG_ERROR(BSL_LS_SOC_COMMON, 1254 (BSL_META_U(unit, "soc_cmicm_intr unit %d: " 1255 "Disabling unhandled interrupt(s): %d\n"), 1256 unit, irqStat)); 1257 (void)soc_cmicm_intr2_disable(unit, irqStat); 1258 } 1259 } else 1260 #endif /*#if defined(BCM_MONTEREY_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)*/ 1261 #endif /* BCM_XGS_SUPPORT */ 1262 { 1263 LOG_ERROR(BSL_LS_SOC_COMMON, 1264 (BSL_META_U(unit, "soc_cmicm_intr unit %d: " 1265 "Disabling unhandled interrupt(s): %d\n"), 1266 unit, irqStat)); 1267 (void)soc_cmicm_intr2_disable(unit, irqStat); 1268 } 1269 } 1270 1271 STATIC void 1272 soc_cmicdv2_parity_intr(int unit, uint32 val) 1273 { 1274 int cmc; 1275 uint32 irqStat; 1276 #if defined(BCM_XGS_SUPPORT) 1277 uint32 irqMask, oldmask; 1278 #endif 1279 1280 cmc = SOC_PCI_CMC(unit); 1281 /* The parity error interrupts are moved to STAT3 for CMICD v2 */ 1282 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); 1283 1284 #if defined(BCM_XGS_SUPPORT) 1285 irqMask = SOC_CMCx_IRQ3_MASK(unit,cmc); 1286 1287 oldmask = soc_cmicm_intr3_disable(unit, irqMask); 1288 1289 #ifdef BCM_TOMAHAWK_SUPPORT 1290 if (SOC_IS_TOMAHAWKX(unit)) { 1291 /* SER interrupts */ 1292 if ((val >= 4 && val <= 16) || 1293 ((val >= 26 && val <= 29) && SOC_IS_TOMAHAWK2(unit))) { 1294 LOG_INFO(BSL_LS_SOC_INTR, 1295 (BSL_META_U(unit, 1296 "soc_cmicm_intr type 3 unit %d: dispatch\n"), unit)); 1297 if (soc_ser_parity_error_cmicm_intr(INT_TO_PTR(unit), 0, 1298 INT_TO_PTR(oldmask), 1299 INT_TO_PTR(3), 1300 INT_TO_PTR(val))) { 1301 1302 } else { 1303 LOG_ERROR(BSL_LS_SOC_COMMON, 1304 (BSL_META_U(unit, 1305 "soc_cmicdv2_intr unit %d: " 1306 "Disabling unhandled interrupt(s): %d\n"), 1307 unit, irqStat)); 1308 (void)soc_cmicm_intr3_disable(unit, irqStat); 1309 } 1310 } else if (val == 2) { /* PVTMON interrupt */ 1311 sal_dpc(soc_tomahawk_temperature_intr, INT_TO_PTR(unit), 1312 0, 0, 0, 0); 1313 } else if (val == 1) { /* L2 MGMT */ 1314 /* dispatch interrupt */ 1315 LOG_INFO(BSL_LS_SOC_INTR, 1316 (BSL_META_U(unit, 1317 "soc_cmicm_intr type 3 unit %d: dispatch\n"), 1318 unit)); 1319 1320 sal_dpc(soc_tomahawk_process_func_intr, INT_TO_PTR(unit), 1321 INT_TO_PTR(oldmask), 0, 0, 0); 1322 } 1323 } else 1324 1325 #endif /* BCM_TOMAHAWK_SUPPORT */ 1326 1327 #ifdef BCM_TRIDENT3_SUPPORT 1328 if (SOC_IS_TRIDENT3X(unit)) { 1329 /* SER interrupts */ 1330 if (val >= 4 && val <= 10) { 1331 LOG_INFO(BSL_LS_SOC_INTR, 1332 (BSL_META_U(unit, 1333 "soc_cmicm_intr type 3 unit %d: dispatch\n"), unit)); 1334 if (soc_ser_parity_error_cmicm_intr(INT_TO_PTR(unit), 0, 1335 INT_TO_PTR(oldmask), 1336 INT_TO_PTR(3), 1337 INT_TO_PTR(val))) { 1338 } else { 1339 LOG_ERROR(BSL_LS_SOC_COMMON, 1340 (BSL_META_U(unit, 1341 "soc_cmicdv2_intr unit %d: " 1342 "Disabling unhandled interrupt(s): %d\n"), 1343 unit, irqStat)); 1344 (void)soc_cmicm_intr3_disable(unit, irqStat); 1345 } 1346 } else if (val == 1) { /* L2 MGMT */ 1347 /* dispatch interrupt */ 1348 LOG_INFO(BSL_LS_SOC_INTR, 1349 (BSL_META_U(unit, 1350 "soc_cmicm_intr type 3 unit %d: dispatch\n"), 1351 unit)); 1352 1353 sal_dpc(soc_trident3_process_func_intr, INT_TO_PTR(unit), 1354 INT_TO_PTR(oldmask), 0, 0, 0); 1355 } 1356 } else 1357 1358 #endif /* BCM_TRIDENT3_SUPPORT */ 1359 1360 #ifdef BCM_APACHE_SUPPORT 1361 if (SOC_IS_APACHE(unit)) { 1362 /* SER interrupts */ 1363 if (val <= 10) { 1364 LOG_INFO(BSL_LS_SOC_INTR, 1365 (BSL_META_U(unit, 1366 "soc_cmicm_intr type 3 unit %d: dispatch\n"), unit)); 1367 if (soc_ser_parity_error_cmicm_intr(INT_TO_PTR(unit), 0, 1368 INT_TO_PTR(oldmask), 1369 INT_TO_PTR(3), 1370 INT_TO_PTR(val))) { 1371 } else { 1372 LOG_ERROR(BSL_LS_SOC_COMMON, 1373 (BSL_META_U(unit, 1374 "soc_cmicdv2_intr unit %d: " 1375 "Disabling unhandled interrupt(s): %d\n"), 1376 unit, irqStat)); 1377 (void)soc_cmicm_intr3_disable(unit, irqStat); 1378 } 1379 } else if (val == 11) { /* TOP(PVTMON,AVS) interrupt */ 1380 #ifdef BCM_MONTEREY_SUPPORT 1381 if (SOC_IS_MONTEREY(unit)) { 1382 sal_dpc(soc_monterey_top_intr, INT_TO_PTR(unit), 1383 0, 0, 0, 0); 1384 } else 1385 #endif 1386 { 1387 sal_dpc(soc_apache_top_intr, INT_TO_PTR(unit), 1388 0, 0, 0, 0); 1389 } 1390 } else if ((val == 13) || (val == 14)) { /* L2 Overflow */ 1391 /* dispatch interrupt */ 1392 LOG_INFO(BSL_LS_SOC_INTR, 1393 (BSL_META_U(unit, 1394 "soc_cmicm_intr type 3 unit %d: dispatch\n"), 1395 unit)); 1396 1397 #ifdef BCM_MONTEREY_SUPPORT 1398 if (SOC_IS_MONTEREY(unit)) { 1399 sal_dpc(soc_monterey_process_func_intr, INT_TO_PTR(unit), 1400 INT_TO_PTR(oldmask), INT_TO_PTR(val), 0, 0); 1401 } else 1402 #endif 1403 { 1404 sal_dpc(soc_apache_process_func_intr, INT_TO_PTR(unit), 1405 INT_TO_PTR(oldmask), INT_TO_PTR(val), 0, 0); 1406 } 1407 } 1408 } else 1409 #endif /* BCM_APACHE_SUPPORT */ 1410 1411 /* dispatch interrupt if we have handler */ 1412 if (soc_ser_parity_error_cmicm_intr(INT_TO_PTR(unit), 0, 1413 INT_TO_PTR(oldmask), INT_TO_PTR(3), INT_TO_PTR(val))) { 1414 LOG_INFO(BSL_LS_SOC_INTR, 1415 (BSL_META_U(unit, 1416 "soc_cmicdv2_intr type 3 unit %d: dispatch\n"), 1417 unit)); 1418 1419 } else 1420 #endif 1421 { 1422 LOG_ERROR(BSL_LS_SOC_COMMON, 1423 (BSL_META_U(unit, 1424 "soc_cmicdv2_intr unit %d: " 1425 "Disabling unhandled interrupt(s): %d\n"), 1426 unit, irqStat)); 1427 1428 (void)soc_cmicm_intr3_disable(unit, irqStat); 1429 } 1430 } 1431 1432 STATIC void 1433 soc_cmicm_block_lo_intr(int unit, uint32 val) 1434 { 1435 uint32 irqStat = 0; 1436 int cmc; 1437 1438 cmc = SOC_PCI_CMC(unit); 1439 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); 1440 1441 { 1442 LOG_ERROR(BSL_LS_SOC_COMMON, 1443 (BSL_META_U(unit, 1444 "soc_cmicm_intr unit %d: " 1445 "Disabling unhandled interrupt(s): %d\n"), 1446 unit, irqStat)); 1447 (void)soc_cmicm_intr3_disable(unit, irqStat); 1448 } 1449 } 1450 1451 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) 1452 STATIC void 1453 soc_cmicdv2_block_intr4(int unit, uint32 val) 1454 { 1455 int cmc; 1456 uint32 irqStat; 1457 #if defined(BCM_XGS_SUPPORT) 1458 uint32 irqMask, oldmask; 1459 #endif 1460 1461 cmc = SOC_PCI_CMC(unit); 1462 /* The parity error interrupts are moved to STAT4 for CMICD v2 */ 1463 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc)); 1464 1465 #if defined(BCM_XGS_SUPPORT) 1466 irqMask = SOC_CMCx_IRQ4_MASK(unit,cmc); 1467 1468 oldmask = soc_cmicm_intr4_disable(unit, irqMask); 1469 1470 #ifdef BCM_MONTEREY_SUPPORT 1471 if (SOC_IS_MONTEREY(unit)) { 1472 #ifdef INCLUDE_XFLOW_MACSEC 1473 if((val == 22) && 1474 (!soc_feature(unit, soc_feature_xflow_macsec_poll_intr))) { 1475 /* MACSEC interrupts */ 1476 sal_dpc(soc_monterey_process_macsec_intr, INT_TO_PTR(unit), 0, 1477 INT_TO_PTR(oldmask), INT_TO_PTR(4), INT_TO_PTR(val)); 1478 } else 1479 #endif 1480 { 1481 /* dispatch PortMacro interrupt if we have handler */ 1482 sal_dpc(soc_monterey_process_pm_intr, INT_TO_PTR(unit), 0, 1483 INT_TO_PTR(oldmask), INT_TO_PTR(4), INT_TO_PTR(val)); 1484 } 1485 } else 1486 #endif 1487 if (soc_ser_parity_error_cmicm_intr(INT_TO_PTR(unit), 0, 1488 INT_TO_PTR(oldmask), INT_TO_PTR(4), INT_TO_PTR(val))) { 1489 LOG_INFO(BSL_LS_SOC_INTR, 1490 (BSL_META_U(unit, 1491 "soc_cmicdv2_intr type 4 unit %d: dispatch\n"), 1492 unit)); 1493 1494 } else 1495 #endif 1496 { 1497 LOG_ERROR(BSL_LS_SOC_COMMON, 1498 (BSL_META_U(unit, 1499 "soc_cmicdv2_intr unit %d: " 1500 "Disabling unhandled interrupt(s): %d\n"), 1501 unit, irqStat)); 1502 1503 (void)soc_cmicm_intr4_disable(unit, irqStat); 1504 } 1505 } 1506 1507 STATIC void 1508 soc_cmicdv2_block_intr5(int unit, uint32 val) 1509 { 1510 int cmc; 1511 uint32 irqStat; 1512 #if defined(BCM_XGS_SUPPORT) 1513 uint32 irqMask, oldmask; 1514 #endif 1515 1516 cmc = SOC_PCI_CMC(unit); 1517 /* The parity error interrupts are moved to STAT5 for CMICD v2 */ 1518 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT5_OFFSET(cmc)); 1519 1520 #if defined(BCM_XGS_SUPPORT) 1521 irqMask = SOC_CMCx_IRQ5_MASK(unit,cmc); 1522 1523 oldmask = soc_cmicm_intr5_disable(unit, irqMask); 1524 1525 /* dispatch interrupt if we have handler */ 1526 if (soc_ser_parity_error_cmicm_intr(INT_TO_PTR(unit), 0, 1527 INT_TO_PTR(oldmask), INT_TO_PTR(5), INT_TO_PTR(val))) { 1528 LOG_INFO(BSL_LS_SOC_INTR, 1529 (BSL_META_U(unit, 1530 "soc_cmicdv2_intr type 5 unit %d: dispatch\n"), 1531 unit)); 1532 1533 } else 1534 #endif 1535 { 1536 LOG_ERROR(BSL_LS_SOC_COMMON, 1537 (BSL_META_U(unit, 1538 "soc_cmicdv2_intr unit %d: " 1539 "Disabling unhandled interrupt(s): %d\n"), 1540 unit, irqStat)); 1541 1542 (void)soc_cmicm_intr5_disable(unit, irqStat); 1543 } 1544 } 1545 1546 STATIC void 1547 soc_cmicdv4_block_intr6(int unit, uint32 val) 1548 { 1549 int cmc; 1550 uint32 irqStat; 1551 #if defined(BCM_XGS_SUPPORT) 1552 uint32 irqMask, oldmask; 1553 #endif 1554 1555 cmc = SOC_PCI_CMC(unit); 1556 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT6_OFFSET(cmc)); 1557 1558 #if defined(BCM_XGS_SUPPORT) 1559 irqMask = SOC_CMCx_IRQ6_MASK(unit,cmc); 1560 oldmask = soc_cmicm_intr6_disable(unit, irqMask); 1561 1562 /* dispatch interrupt if we have handler */ 1563 if (soc_ser_parity_error_cmicm_intr(INT_TO_PTR(unit), 0, 1564 INT_TO_PTR(oldmask), INT_TO_PTR(6), INT_TO_PTR(val))) { 1565 LOG_INFO(BSL_LS_SOC_INTR, 1566 (BSL_META_U(unit, 1567 "soc_cmicdv4_intr type 6 unit %d: dispatch\n"), 1568 unit)); 1569 } else 1570 #endif 1571 { 1572 LOG_ERROR(BSL_LS_SOC_COMMON, 1573 (BSL_META_U(unit, 1574 "soc_cmicdv4_intr unit %d: " 1575 "Disabling unhandled interrupt(s): %d\n"), 1576 unit, irqStat)); 1577 1578 (void)soc_cmicm_intr6_disable(unit, irqStat); 1579 } 1580 } 1581 1582 STATIC void 1583 soc_cmicm_link_stat(int unit, uint32 ignored) 1584 { 1585 soc_control_t *soc = SOC_CONTROL(unit); 1586 1587 COMPILER_REFERENCE(ignored); 1588 1589 soc_pci_analyzer_trigger(unit); 1590 1591 soc->stat.intr_ls++; 1592 1593 /* Clear interrupt */ 1594 1595 soc_pci_write(unit, CMIC_MIIM_CLR_SCAN_STATUS_OFFSET, CLR_LINK_STATUS_CHANGE_MASK); 1596 1597 /* Perform user callout, if one is registered */ 1598 1599 if (soc->soc_link_callout != NULL) { 1600 (*soc->soc_link_callout)(unit); 1601 } 1602 } 1603 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)*/ 1604 1605 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)*/ 1606 1607 /* 1608 * Enable (unmask) or disable (mask) a set of CMIC interrupts. These 1609 * routines should be used instead of manipulating CMIC_IRQ_MASK 1610 * directly, since a read-modify-write is required. The return value is 1611 * the previous mask (can pass mask of 0 to just get the current mask). 1612 * for CMICm use CMIC_CMCx_PCIE_IRQ_MASK0. 1613 */ 1614 1615 uint32 1616 soc_cmicm_cmcx_intr0_enable(int unit, int cmc, uint32 mask) 1617 { 1618 uint32 oldMask; 1619 uint32 newMask; 1620 int s; 1621 1622 s = sal_splhi(); 1623 oldMask = SOC_CMCx_IRQ0_MASK(unit,cmc); 1624 SOC_CMCx_IRQ0_MASK(unit,cmc) |= mask; 1625 newMask = SOC_CMCx_IRQ0_MASK(unit,cmc); 1626 /* In polled mode, the hardware IRQ mask is always zero */ 1627 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1628 newMask = 0; 1629 } 1630 LOG_INFO(BSL_LS_SOC_INTR, 1631 (BSL_META_U(unit, 1632 "soc_cmicm_intr0_enable cmc %d unit %d: mask 0x%8x\n"), 1633 cmc, unit, mask)); 1634 IRQ_MASK0_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), newMask); 1635 sal_spl(s); 1636 return oldMask; 1637 } 1638 1639 uint32 1640 soc_cmicm_cmcx_intr0_disable(int unit, int cmc, uint32 mask) 1641 { 1642 uint32 oldMask; 1643 uint32 newMask; 1644 int s; 1645 1646 s = sal_splhi(); 1647 oldMask = SOC_CMCx_IRQ0_MASK(unit,cmc); 1648 SOC_CMCx_IRQ0_MASK(unit,cmc) &= ~mask; 1649 newMask = SOC_CMCx_IRQ0_MASK(unit,cmc); 1650 /* In polled mode, the hardware IRQ mask is always zero */ 1651 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1652 newMask = 0; 1653 } 1654 LOG_INFO(BSL_LS_SOC_INTR, 1655 (BSL_META_U(unit, 1656 "soc_cmicm_intr0_disable cmc %d unit %d: mask 0x%8x\n"), 1657 cmc, unit, mask)); 1658 IRQ_MASK0_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), newMask); 1659 sal_spl(s); 1660 return oldMask; 1661 } 1662 1663 /* 1664 * Enable (unmask) or disable (mask) a set of CMICM Common / Switch-Specific 1665 * interrupts. These routines should be used instead of manipulating 1666 * CMIC_CMCx_PCIE_IRQ_MASK1 directly, since a read-modify-write is required. 1667 * The return value is the previous mask (can pass mask of 0 to just 1668 * get the current mask) 1669 */ 1670 1671 uint32 1672 soc_cmicm_cmcx_intr1_enable(int unit, int cmc, uint32 mask) 1673 { 1674 uint32 oldMask; 1675 uint32 newMask; 1676 int s; 1677 1678 s = sal_splhi(); 1679 oldMask = SOC_CMCx_IRQ1_MASK(unit,cmc); 1680 SOC_CMCx_IRQ1_MASK(unit,cmc) |= mask; 1681 newMask = SOC_CMCx_IRQ1_MASK(unit,cmc); 1682 /* In polled mode, the hardware IRQ mask is always zero */ 1683 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1684 newMask = 0; 1685 } 1686 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), newMask); 1687 sal_spl(s); 1688 return oldMask; 1689 } 1690 1691 uint32 1692 soc_cmicm_cmcx_intr1_disable(int unit, int cmc, uint32 mask) 1693 { 1694 uint32 oldMask; 1695 uint32 newMask; 1696 int s; 1697 1698 s = sal_splhi(); 1699 oldMask = SOC_CMCx_IRQ1_MASK(unit,cmc); 1700 SOC_CMCx_IRQ1_MASK(unit,cmc) &= ~mask; 1701 newMask = SOC_CMCx_IRQ1_MASK(unit,cmc); 1702 /* In polled mode, the hardware IRQ mask is always zero */ 1703 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1704 newMask = 0; 1705 } 1706 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), newMask); 1707 sal_spl(s); 1708 return oldMask; 1709 } 1710 1711 uint32 1712 soc_cmicm_cmcx_intr2_enable(int unit, int cmc, uint32 mask) 1713 { 1714 uint32 oldMask; 1715 uint32 newMask; 1716 int s; 1717 1718 s = sal_splhi(); 1719 oldMask = SOC_CMCx_IRQ2_MASK(unit,cmc); 1720 SOC_CMCx_IRQ2_MASK(unit,cmc) |= mask; 1721 newMask = SOC_CMCx_IRQ2_MASK(unit,cmc); 1722 /* In polled mode, the hardware IRQ mask is always zero */ 1723 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1724 newMask = 0; 1725 } 1726 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), newMask); 1727 sal_spl(s); 1728 return oldMask; 1729 } 1730 1731 uint32 1732 soc_cmicm_cmcx_intr2_disable(int unit, int cmc, uint32 mask) 1733 { 1734 uint32 oldMask; 1735 uint32 newMask; 1736 int s; 1737 1738 s = sal_splhi(); 1739 oldMask = SOC_CMCx_IRQ2_MASK(unit,cmc); 1740 SOC_CMCx_IRQ2_MASK(unit,cmc) &= ~mask; 1741 newMask = SOC_CMCx_IRQ2_MASK(unit,cmc); 1742 /* In polled mode, the hardware IRQ mask is always zero */ 1743 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1744 newMask = 0; 1745 } 1746 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), newMask); 1747 sal_spl(s); 1748 return oldMask; 1749 } 1750 1751 uint32 1752 soc_cmicm_cmcx_intr3_enable(int unit, int cmc, uint32 mask) 1753 { 1754 uint32 oldMask; 1755 uint32 newMask; 1756 int s; 1757 1758 s = sal_splhi(); 1759 oldMask = SOC_CMCx_IRQ3_MASK(unit,cmc); 1760 SOC_CMCx_IRQ3_MASK(unit,cmc) |= mask; 1761 newMask = SOC_CMCx_IRQ3_MASK(unit,cmc); 1762 /* In polled mode, the hardware IRQ mask is always zero */ 1763 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1764 newMask = 0; 1765 } 1766 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), newMask); 1767 sal_spl(s); 1768 return oldMask; 1769 } 1770 1771 uint32 1772 soc_cmicm_cmcx_intr3_disable(int unit, int cmc, uint32 mask) 1773 { 1774 uint32 oldMask; 1775 uint32 newMask; 1776 int s; 1777 1778 s = sal_splhi(); 1779 oldMask = SOC_CMCx_IRQ3_MASK(unit,cmc); 1780 SOC_CMCx_IRQ3_MASK(unit,cmc) &= ~mask; 1781 newMask = SOC_CMCx_IRQ3_MASK(unit,cmc); 1782 /* In polled mode, the hardware IRQ mask is always zero */ 1783 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1784 newMask = 0; 1785 } 1786 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), newMask); 1787 sal_spl(s); 1788 1789 return oldMask; 1790 } 1791 1792 uint32 1793 soc_cmicm_cmcx_intr4_enable(int unit, int cmc, uint32 mask) 1794 { 1795 uint32 oldMask; 1796 uint32 newMask; 1797 int s; 1798 1799 s = sal_splhi(); 1800 oldMask = SOC_CMCx_IRQ4_MASK(unit,cmc); 1801 SOC_CMCx_IRQ4_MASK(unit,cmc) |= mask; 1802 newMask = SOC_CMCx_IRQ4_MASK(unit,cmc); 1803 /* In polled mode, the hardware IRQ mask is always zero */ 1804 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1805 newMask = 0; 1806 } 1807 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), newMask); 1808 sal_spl(s); 1809 return oldMask; 1810 } 1811 1812 uint32 1813 soc_cmicm_cmcx_intr4_disable(int unit, int cmc, uint32 mask) 1814 { 1815 uint32 oldMask; 1816 uint32 newMask; 1817 int s; 1818 1819 s = sal_splhi(); 1820 oldMask = SOC_CMCx_IRQ4_MASK(unit,cmc); 1821 SOC_CMCx_IRQ4_MASK(unit,cmc) &= ~mask; 1822 newMask = SOC_CMCx_IRQ4_MASK(unit,cmc); 1823 /* In polled mode, the hardware IRQ mask is always zero */ 1824 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1825 newMask = 0; 1826 } 1827 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), newMask); 1828 sal_spl(s); 1829 return oldMask; 1830 } 1831 1832 uint32 1833 soc_cmicm_cmcx_intr5_enable(int unit, int cmc, uint32 mask) 1834 { 1835 uint32 oldMask; 1836 uint32 newMask; 1837 int s; 1838 1839 s = sal_splhi(); 1840 oldMask = SOC_CMCx_IRQ5_MASK(unit,cmc); 1841 SOC_CMCx_IRQ5_MASK(unit,cmc) |= mask; 1842 newMask = SOC_CMCx_IRQ5_MASK(unit,cmc); 1843 /* In polled mode, the hardware IRQ mask is always zero */ 1844 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1845 newMask = 0; 1846 } 1847 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc), newMask); 1848 sal_spl(s); 1849 return oldMask; 1850 } 1851 1852 uint32 1853 soc_cmicm_cmcx_intr5_disable(int unit, int cmc, uint32 mask) 1854 { 1855 uint32 oldMask; 1856 uint32 newMask; 1857 int s; 1858 s = sal_splhi(); 1859 oldMask = SOC_CMCx_IRQ5_MASK(unit,cmc); 1860 SOC_CMCx_IRQ5_MASK(unit,cmc) &= ~mask; 1861 newMask = SOC_CMCx_IRQ5_MASK(unit,cmc); 1862 /* In polled mode, the hardware IRQ mask is always zero */ 1863 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1864 newMask = 0; 1865 } 1866 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc), newMask); 1867 sal_spl(s); 1868 return oldMask; 1869 } 1870 1871 uint32 1872 soc_cmicm_cmcx_intr6_enable(int unit, int cmc, uint32 mask) 1873 { 1874 uint32 oldMask; 1875 uint32 newMask; 1876 int s; 1877 1878 s = sal_splhi(); 1879 oldMask = SOC_CMCx_IRQ6_MASK(unit,cmc); 1880 SOC_CMCx_IRQ6_MASK(unit,cmc) |= mask; 1881 newMask = SOC_CMCx_IRQ6_MASK(unit,cmc); 1882 /* In polled mode, the hardware IRQ mask is always zero */ 1883 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1884 newMask = 0; 1885 } 1886 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc), newMask); 1887 sal_spl(s); 1888 return oldMask; 1889 } 1890 1891 uint32 1892 soc_cmicm_cmcx_intr6_disable(int unit, int cmc, uint32 mask) 1893 { 1894 uint32 oldMask; 1895 uint32 newMask; 1896 int s; 1897 s = sal_splhi(); 1898 1899 oldMask = SOC_CMCx_IRQ6_MASK(unit,cmc); 1900 SOC_CMCx_IRQ6_MASK(unit,cmc) &= ~mask; 1901 newMask = SOC_CMCx_IRQ6_MASK(unit,cmc); 1902 /* In polled mode, the hardware IRQ mask is always zero */ 1903 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 1904 newMask = 0; 1905 } 1906 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc), newMask); 1907 sal_spl(s); 1908 return oldMask; 1909 } 1910 1911 uint32 1912 soc_cmicm_intr0_enable(int unit, uint32 mask) 1913 { 1914 return soc_cmicm_cmcx_intr0_enable(unit, SOC_PCI_CMC(unit), mask); 1915 } 1916 1917 uint32 1918 soc_cmicm_intr0_disable(int unit, uint32 mask) 1919 { 1920 return soc_cmicm_cmcx_intr0_disable(unit, SOC_PCI_CMC(unit), mask); 1921 } 1922 1923 uint32 1924 soc_cmicm_intr1_enable(int unit, uint32 mask) 1925 { 1926 return soc_cmicm_cmcx_intr1_enable(unit, SOC_PCI_CMC(unit), mask); 1927 } 1928 1929 uint32 1930 soc_cmicm_intr1_disable(int unit, uint32 mask) 1931 { 1932 return soc_cmicm_cmcx_intr1_disable(unit, SOC_PCI_CMC(unit), mask); 1933 } 1934 1935 uint32 1936 soc_cmicm_intr2_enable(int unit, uint32 mask) 1937 { 1938 return soc_cmicm_cmcx_intr2_enable(unit, SOC_PCI_CMC(unit), mask); 1939 } 1940 1941 uint32 1942 soc_cmicm_intr2_disable(int unit, uint32 mask) 1943 { 1944 return soc_cmicm_cmcx_intr2_disable(unit, SOC_PCI_CMC(unit), mask); 1945 } 1946 1947 uint32 1948 soc_cmicm_intr3_enable(int unit, uint32 mask) 1949 { 1950 return soc_cmicm_cmcx_intr3_enable(unit, SOC_PCI_CMC(unit), mask); 1951 } 1952 1953 uint32 1954 soc_cmicm_intr3_disable(int unit, uint32 mask) 1955 { 1956 return soc_cmicm_cmcx_intr3_disable(unit, SOC_PCI_CMC(unit), mask); 1957 } 1958 1959 uint32 1960 soc_cmicm_intr4_enable(int unit, uint32 mask) 1961 { 1962 return soc_cmicm_cmcx_intr4_enable(unit, SOC_PCI_CMC(unit), mask); 1963 } 1964 1965 uint32 1966 soc_cmicm_intr4_disable(int unit, uint32 mask) 1967 { 1968 return soc_cmicm_cmcx_intr4_disable(unit, SOC_PCI_CMC(unit), mask); 1969 } 1970 1971 uint32 1972 soc_cmicm_intr5_enable(int unit, uint32 mask) 1973 { 1974 return soc_cmicm_cmcx_intr5_enable(unit, SOC_PCI_CMC(unit), mask); 1975 } 1976 1977 uint32 1978 soc_cmicm_intr5_disable(int unit, uint32 mask) 1979 { 1980 return soc_cmicm_cmcx_intr5_disable(unit, SOC_PCI_CMC(unit), mask); 1981 } 1982 1983 uint32 1984 soc_cmicm_intr6_enable(int unit, uint32 mask) 1985 { 1986 return soc_cmicm_cmcx_intr6_enable(unit, SOC_PCI_CMC(unit), mask); 1987 } 1988 1989 uint32 1990 soc_cmicm_intr6_disable(int unit, uint32 mask) 1991 { 1992 return soc_cmicm_cmcx_intr6_disable(unit, SOC_PCI_CMC(unit), mask); 1993 } 1994 /* 1995 * SOC CMICm Interrupt Service Routine 1996 */ 1997 1998 #define POLL_LIMIT 100000 1999 2000 void 2001 soc_cmicm_intr(void *_unit) 2002 { 2003 soc_control_t *soc; 2004 uint32 irqStat, irqMask; 2005 int unit = PTR_TO_INT(_unit); 2006 int cmc = 0, i = 0; 2007 int poll_limit = POLL_LIMIT; 2008 intr_handler_t *intr_handler = soc_cmicm_intr_handlers; 2009 int arm; 2010 int s; 2011 #ifdef SEPARATE_PKTDMA_INTR_HANDLER 2012 uint32 pktdma_status = 0x7800ff00; 2013 int pktdma_poll_limit = 2; 2014 #endif 2015 2016 #ifdef SAL_SPL_LOCK_ON_IRQ 2017 s = sal_splhi(); 2018 #endif 2019 2020 soc = SOC_CONTROL(unit); 2021 /* 2022 * Our handler is permanently registered in soc_probe(). If our 2023 * unit is not attached yet, it could not have generated this 2024 * interrupt. The interrupt line must be shared by multiple PCI 2025 * cards. Simply ignore the interrupt and let another handler 2026 * process it. 2027 */ 2028 2029 if (soc == NULL || (soc->soc_flags & SOC_F_BUSY) || 2030 !(soc->soc_flags & SOC_F_ATTACHED)) { 2031 #ifdef SAL_SPL_LOCK_ON_IRQ 2032 sal_spl(s); 2033 #endif 2034 return; 2035 } 2036 2037 cmc = SOC_PCI_CMC(unit); 2038 soc->stat.intr++; /* Update count */ 2039 2040 if (SOC_IS_KATANA(unit)) { 2041 intr_handler = soc_cmicm_intr_handlers0_fifo_dma; 2042 } 2043 2044 if (soc_feature(unit, soc_feature_sbusdma)) { 2045 intr_handler = soc_cmicm_intr_handlers0; 2046 } 2047 /* 2048 * Read IRQ Status and IRQ Mask and AND to determine active ints. 2049 * These are re-read each time since either can be changed by ISRs. 2050 */ 2051 for (;;) { 2052 if (soc_feature(unit, soc_feature_cmicm_multi_dma_cmc) && 2053 (SOC_PCI_CMCS_NUM(unit) > 1)) { 2054 for (i = soc->next_int0_cmc; i < soc->next_int0_cmc + SOC_PCI_CMCS_NUM(unit); i++) { 2055 cmc = i % SOC_PCI_CMCS_NUM(unit); 2056 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); 2057 if (irqStat != 0) { 2058 irqMask = SOC_CMCx_IRQ0_MASK(unit, cmc); 2059 irqStat &= irqMask; 2060 if (irqStat != 0) { 2061 #ifdef SEPARATE_PKTDMA_INTR_HANDLER 2062 if (irqStat == (irqStat & pktdma_status)) 2063 { 2064 if (--pktdma_poll_limit == 0) 2065 { 2066 return; 2067 } 2068 /** Bypass to interrupts IRQ_STAT1, IRQ_STAT2... */ 2069 goto check_type1; 2070 } 2071 #endif 2072 goto detected_irq0; 2073 } 2074 } 2075 soc->next_int0_cmc = (cmc + 1) % SOC_PCI_CMCS_NUM(unit); 2076 } 2077 /** re-assign cmc to origin */ 2078 cmc = SOC_PCI_CMC(unit); 2079 goto check_type1; 2080 } else { 2081 cmc = SOC_PCI_CMC(unit); 2082 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); 2083 if (irqStat == 0) { 2084 goto check_type1; /* No pending Interrupts */ 2085 } 2086 irqMask = SOC_CMCx_IRQ0_MASK(unit,cmc); 2087 irqStat &= irqMask; 2088 if (irqStat == 0) { 2089 goto check_type1; 2090 } 2091 #ifdef SEPARATE_PKTDMA_INTR_HANDLER 2092 if (irqStat == (irqStat & pktdma_status)) 2093 { 2094 if (--pktdma_poll_limit == 0) 2095 { 2096 return; 2097 } 2098 /** Bypass to interrupts IRQ_STAT1, IRQ_STAT2... */ 2099 goto check_type1; 2100 } 2101 #endif 2102 2103 } 2104 2105 detected_irq0: 2106 i = 0; 2107 /* 2108 * We may have received an interrupt before all data has been 2109 * posted from the device or intermediate bridge. 2110 * The PCI specification requires that we read a device register 2111 * to make sure pending data is flushed. 2112 */ 2113 soc_pci_read(unit, CMIC_CMCx_SCHAN_CTRL_OFFSET(cmc)); 2114 soc_pci_read(unit, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc)); 2115 2116 for (; intr_handler[i].mask; i++) { 2117 if (irqStat & intr_handler[i].mask) { 2118 2119 /* dispatch interrupt */ 2120 LOG_INFO(BSL_LS_SOC_INTR, 2121 (BSL_META_U(unit, 2122 "soc_cmicm_intr type 0 unit %d: dispatch %s\n"), 2123 unit, intr_handler[i].intr_name)); 2124 2125 (*intr_handler[i].intr_fn) 2126 (unit, cmc * N_DMA_CHAN + intr_handler[i].intr_data); 2127 2128 /* 2129 * Prevent infinite loop in interrupt handler by 2130 * disabling the offending interrupt(s). 2131 */ 2132 /* coverity[dead_error_condition] */ 2133 if (--poll_limit == 0) { 2134 LOG_ERROR(BSL_LS_SOC_COMMON, 2135 (BSL_META_U(unit, 2136 "soc_cmicm_intr unit %d cmc %d: " 2137 "ERROR can't clear type 0 interrupt(s): " 2138 "IRQ=0x%x (disabling 0x%x)\n"), 2139 unit, cmc, irqStat, intr_handler[i].mask)); 2140 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, intr_handler[i].mask); 2141 poll_limit = POLL_LIMIT; 2142 } 2143 2144 /* 2145 * Go back and re-read IRQ status. Start processing 2146 * from scratch since handler may clear more than one 2147 * bit. We don't leave the ISR until all of the bits 2148 * have been cleared and their handlers called. 2149 */ 2150 break; 2151 } 2152 } 2153 } 2154 check_type1: 2155 2156 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) 2157 /* process irq1 (chip_func) */ 2158 if (SOC_IS_JERICHO(unit)) { 2159 SOC_CMCx_IRQ1_MASK(unit,cmc) |= IRQ_CMCx_TIMESYNC_INTR; 2160 } 2161 2162 for (;;) { 2163 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); 2164 if (irqStat == 0) { 2165 goto check_type2; /* No pending Interrupts */ 2166 } 2167 irqMask = SOC_CMCx_IRQ1_MASK(unit,cmc); 2168 irqStat &= irqMask; 2169 if (irqStat == 0) { 2170 goto check_type2; 2171 } 2172 2173 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2174 (BSL_META_U(unit, 2175 "soc_cmicm_intr unit %d: irqStat1 = 0x%x\n"), 2176 unit, irqStat)); 2177 2178 intr_handler = soc_cmicm_intr_handlers1; 2179 poll_limit = POLL_LIMIT; 2180 i = 0; 2181 2182 for (; intr_handler[i].mask; i++) { 2183 if (irqStat & intr_handler[i].mask) { 2184 /* dispatch interrupt */ 2185 LOG_INFO(BSL_LS_SOC_INTR, 2186 (BSL_META_U(unit, 2187 "soc_cmicm_intr type 1 unit %d: dispatch %s\n"), 2188 unit, intr_handler[i].intr_name)); 2189 2190 (*intr_handler[i].intr_fn) 2191 (unit, intr_handler[i].intr_data); 2192 2193 /* coverity[dead_error_condition] */ 2194 if (--poll_limit == 0) { 2195 LOG_ERROR(BSL_LS_SOC_COMMON, 2196 (BSL_META_U(unit, 2197 "soc_cmicm_intr unit %d: " 2198 "ERROR can't clear type 1 interrupt(s): " 2199 "IRQ=0x%x (disabling 0x%x)\n"), 2200 unit, irqStat, intr_handler[i].mask)); 2201 (void)soc_cmicm_intr1_disable(unit, intr_handler[i].mask); 2202 poll_limit = POLL_LIMIT; 2203 } 2204 break; 2205 } 2206 } 2207 2208 /* optimization: don't go back to re-read (PCI transaction) when there is 2209 * only 1 interrupt handled in IRQ1 (for now, this is true) 2210 */ 2211 if (sizeof(soc_cmicm_intr_handlers1)/sizeof(intr_handler_t) == 2) { 2212 break; 2213 } 2214 } 2215 check_type2: 2216 2217 /* process irq2 (parity error) */ 2218 for (;;) { 2219 #if defined(BCM_SABER2_SUPPORT) 2220 if (SOC_IS_SABER2(unit)) { 2221 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); 2222 } else { 2223 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); 2224 } 2225 #else 2226 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); 2227 #endif 2228 if (irqStat == 0) { 2229 goto check_type3; /* No pending Interrupts */ 2230 } 2231 #if defined(BCM_SABER2_SUPPORT) 2232 if (SOC_IS_SABER2(unit)) { 2233 irqMask = SOC_CMCx_IRQ3_MASK(unit,cmc); 2234 } else { 2235 irqMask = SOC_CMCx_IRQ2_MASK(unit,cmc); 2236 } 2237 #else 2238 irqMask = SOC_CMCx_IRQ2_MASK(unit,cmc); 2239 #endif 2240 irqStat &= irqMask; 2241 if (irqStat == 0) { 2242 goto check_type3; 2243 } 2244 2245 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2246 (BSL_META_U(unit, 2247 "soc_cmicm_intr unit %d: irqStat2 = 0x%x\n"), 2248 unit, irqStat)); 2249 2250 if (soc_feature(unit, soc_feature_cmicd_v2)) { 2251 intr_handler = soc_cmicdv2_intr_handlers2; 2252 } else { 2253 intr_handler = soc_cmicm_intr_handlers2; 2254 } 2255 poll_limit = POLL_LIMIT; 2256 i = 0; 2257 2258 for (; intr_handler[i].mask; i++) { 2259 if (irqStat & intr_handler[i].mask) { 2260 /* dispatch interrupt */ 2261 LOG_INFO(BSL_LS_SOC_INTR, 2262 (BSL_META_U(unit, 2263 "soc_cmicm_intr type 2 unit %d: dispatch %s\n"), 2264 unit, intr_handler[i].intr_name)); 2265 2266 (*intr_handler[i].intr_fn) 2267 (unit, intr_handler[i].intr_data); 2268 2269 /* coverity[dead_error_condition] */ 2270 if (--poll_limit == 0) { 2271 LOG_ERROR(BSL_LS_SOC_COMMON, 2272 (BSL_META_U(unit, 2273 "soc_cmicm_intr unit %d: " 2274 "ERROR can't clear type 2 interrupt(s): " 2275 "IRQ=0x%x (disabling 0x%x)\n"), 2276 unit, irqStat, intr_handler[i].mask)); 2277 #if defined(BCM_SABER2_SUPPORT) 2278 if (SOC_IS_SABER2(unit)) { 2279 (void)soc_cmicm_intr3_disable(unit, intr_handler[i].mask); 2280 } else { 2281 (void)soc_cmicm_intr2_disable(unit, intr_handler[i].mask); 2282 } 2283 #else 2284 (void)soc_cmicm_intr2_disable(unit, intr_handler[i].mask); 2285 #endif 2286 poll_limit = POLL_LIMIT; 2287 } 2288 break; 2289 } 2290 } 2291 2292 /* optimization: don't go back to re-read (PCI transaction) when there is 2293 * only 1 interrupt handled in IRQ1 (for now, this is true) 2294 */ 2295 if (sizeof(soc_cmicm_intr_handlers1)/sizeof(intr_handler_t) == 2) { 2296 break; 2297 } 2298 } 2299 check_type3: 2300 2301 if (soc_feature(unit, soc_feature_cmicm_extended_interrupts) && !soc_feature(unit, soc_feature_short_cmic_error)) { 2302 /* this enable processing of IRQ3/4, the sbus slave interrupts */ 2303 for (;;) { 2304 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); 2305 if (irqStat == 0) { 2306 goto check_type4; 2307 } 2308 irqMask = SOC_CMCx_IRQ3_MASK(unit,cmc); 2309 irqStat &= irqMask; 2310 if (irqStat == 0) { 2311 goto check_type4; 2312 } 2313 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2314 (BSL_META_U(unit, 2315 "soc_cmicm_intr unit %d: irqStat3 = 0x%x\n"), 2316 unit, irqStat)); 2317 2318 if (soc_feature(unit, soc_feature_cmicd_v2)) { 2319 intr_handler = soc_cmicdv2_intr_handlers3; 2320 } else { 2321 intr_handler = soc_cmicm_intr_handlers3; 2322 } 2323 poll_limit = POLL_LIMIT; 2324 i = 0; 2325 2326 for (; intr_handler[i].mask; i++) { 2327 if (irqStat & intr_handler[i].mask) { 2328 2329 /* dispatch interrupt */ 2330 LOG_INFO(BSL_LS_SOC_INTR, 2331 (BSL_META_U(unit, 2332 "soc_cmicm_intr type 3 unit %d: dispatch %s\n"), 2333 unit, intr_handler[i].intr_name)); 2334 2335 (*intr_handler[i].intr_fn) 2336 (unit, intr_handler[i].intr_data); 2337 2338 if (--poll_limit == 0) { 2339 LOG_ERROR(BSL_LS_SOC_COMMON, 2340 (BSL_META_U(unit, 2341 "soc_cmicm_intr unit %d: " 2342 "ERROR can't clear type 3 interrupt(s): " 2343 "IRQ=0x%x (disabling 0x%x)\n"), 2344 unit, irqStat, intr_handler[i].mask)); 2345 (void)soc_cmicm_intr3_disable(unit, intr_handler[i].mask); 2346 poll_limit = POLL_LIMIT; 2347 } 2348 2349 /* sbus slave interrupt is per block, assuming that 2350 * handler will only clear interrupt for its own block 2351 * reduce PCI transaction with this assumption 2352 */ 2353 /* break; */ 2354 } 2355 } 2356 } 2357 2358 check_type4: 2359 for (;;) { 2360 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc)); 2361 if (irqStat == 0) { 2362 goto check_type5; 2363 } 2364 irqMask = SOC_CMCx_IRQ4_MASK(unit,cmc); 2365 irqStat &= irqMask; 2366 if (irqStat == 0) { 2367 goto check_type5; 2368 } 2369 2370 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2371 (BSL_META_U(unit, 2372 "soc_cmicm_intr unit %d: irqStat4 = 0x%x\n"), 2373 unit, irqStat)); 2374 2375 if (soc_feature(unit, soc_feature_cmicd_v2)) { 2376 intr_handler = soc_cmicdv2_intr_handlers4; 2377 } else { 2378 intr_handler = soc_cmicm_intr_handlers4; 2379 } 2380 poll_limit = POLL_LIMIT; 2381 i = 0; 2382 2383 for (; intr_handler[i].mask; i++) { 2384 if (irqStat & intr_handler[i].mask) { 2385 2386 /* dispatch interrupt */ 2387 LOG_INFO(BSL_LS_SOC_INTR, 2388 (BSL_META_U(unit, 2389 "soc_cmicm_intr type 4 unit %d: dispatch %s\n"), 2390 unit, intr_handler[i].intr_name)); 2391 2392 (*intr_handler[i].intr_fn) 2393 (unit, intr_handler[i].intr_data); 2394 2395 if (--poll_limit == 0) { 2396 LOG_ERROR(BSL_LS_SOC_COMMON, 2397 (BSL_META_U(unit, 2398 "soc_cmicm_intr unit %d: " 2399 "ERROR can't clear type 4 interrupt(s): " 2400 "IRQ=0x%x (disabling 0x%x)\n"), 2401 unit, irqStat, intr_handler[i].mask)); 2402 (void)soc_cmicm_intr4_disable(unit, intr_handler[i].mask); 2403 poll_limit = POLL_LIMIT; 2404 } 2405 2406 /* sbus slave interrupt is per block, assuming that 2407 * handler will only clear interrupt for its own block 2408 * reduce PCI transaction with this assumption 2409 */ 2410 /* break; */ 2411 } 2412 } 2413 } 2414 2415 check_type5: 2416 if (!soc_feature(unit, soc_feature_cmicd_v2) && 2417 !soc_feature(unit, soc_feature_cmicd_v4)) 2418 goto check_type6; 2419 2420 for (;;) { 2421 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT5_OFFSET(cmc)); 2422 if (irqStat == 0) { 2423 goto check_type6; 2424 } 2425 irqMask = SOC_CMCx_IRQ5_MASK(unit,cmc); 2426 irqStat &= irqMask; 2427 if (irqStat == 0) { 2428 goto check_type6; 2429 } 2430 2431 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2432 (BSL_META_U(unit, 2433 "soc_cmicm_intr unit %d: irqStat5 = 0x%x\n"), 2434 unit, irqStat)); 2435 2436 if (soc_feature(unit, soc_feature_cmicd_v2)) { 2437 intr_handler = soc_cmicdv2_intr_handlers5; 2438 } else { 2439 intr_handler = soc_cmicm_intr_handlers5; 2440 } 2441 poll_limit = POLL_LIMIT; 2442 i = 0; 2443 2444 for (; intr_handler[i].mask; i++) { 2445 if (irqStat & intr_handler[i].mask) { 2446 2447 /* dispatch interrupt */ 2448 LOG_INFO(BSL_LS_SOC_INTR, 2449 (BSL_META_U(unit, 2450 "soc_cmicm_intr type 5 unit %d: dispatch %s\n"), 2451 unit, intr_handler[i].intr_name)); 2452 2453 (*intr_handler[i].intr_fn) 2454 (unit, intr_handler[i].intr_data); 2455 2456 if (--poll_limit == 0) { 2457 LOG_ERROR(BSL_LS_SOC_COMMON, 2458 (BSL_META_U(unit, 2459 "soc_cmicm_intr unit %d: " 2460 "ERROR can't clear type 5 interrupt(s): " 2461 "IRQ=0x%x (disabling 0x%x)\n"), 2462 unit, irqStat, intr_handler[i].mask)); 2463 (void)soc_cmicm_intr5_disable(unit, intr_handler[i].mask); 2464 poll_limit = POLL_LIMIT; 2465 } 2466 2467 /* sbus slave interrupt is per block, assuming that 2468 * handler will only clear interrupt for its own block 2469 * reduce PCI transaction with this assumption 2470 */ 2471 /* break; */ 2472 } 2473 } 2474 } 2475 2476 check_type6: 2477 if (!soc_feature(unit, soc_feature_cmicd_v4)) 2478 goto check_arm_type0; 2479 2480 for (;;) { 2481 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT6_OFFSET(cmc)); 2482 if (irqStat == 0) { 2483 goto check_arm_type0; 2484 } 2485 irqMask = SOC_CMCx_IRQ6_MASK(unit,cmc); 2486 irqStat &= irqMask; 2487 if (irqStat == 0) { 2488 goto check_arm_type0; 2489 } 2490 2491 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2492 (BSL_META_U(unit, 2493 "soc_cmicm_intr unit %d: irqStat6 = 0x%x\n"), 2494 unit, irqStat)); 2495 2496 intr_handler = soc_cmicdv4_intr_handlers6; 2497 poll_limit = POLL_LIMIT; 2498 i = 0; 2499 2500 for (; intr_handler[i].mask; i++) { 2501 if (irqStat & intr_handler[i].mask) { 2502 2503 /* dispatch interrupt */ 2504 LOG_INFO(BSL_LS_SOC_INTR, 2505 (BSL_META_U(unit, 2506 "soc_cmicm_intr type 6 unit %d: dispatch %s\n"), 2507 unit, intr_handler[i].intr_name)); 2508 2509 (*intr_handler[i].intr_fn) 2510 (unit, intr_handler[i].intr_data); 2511 2512 if (--poll_limit == 0) { 2513 LOG_ERROR(BSL_LS_SOC_COMMON, 2514 (BSL_META_U(unit, 2515 "soc_cmicm_intr unit %d: " 2516 "ERROR can't clear type 6 interrupt(s): " 2517 "IRQ=0x%x (disabling 0x%x)\n"), 2518 unit, irqStat, intr_handler[i].mask)); 2519 (void)soc_cmicm_intr6_disable(unit, intr_handler[i].mask); 2520 poll_limit = POLL_LIMIT; 2521 } 2522 2523 /* sbus slave interrupt is per block, assuming that 2524 * handler will only clear interrupt for its own block 2525 * reduce PCI transaction with this assumption 2526 */ 2527 /* break; */ 2528 } 2529 } 2530 } 2531 } 2532 2533 check_arm_type0: 2534 if (soc_feature(unit, soc_feature_cmicm_multi_dma_cmc) && 2535 (SOC_CMCS_NUM(unit) > SOC_PCI_CMCS_NUM(unit))) { 2536 intr_handler = soc_cmicm_intr_handlers0_arm_cmc; 2537 poll_limit = POLL_LIMIT; 2538 2539 for (arm = 0; arm < (SOC_CMCS_NUM(unit) - SOC_PCI_CMCS_NUM(unit)); arm++) { 2540 /* this enable processing of ARM_CMC0/ARM_CMC1 IRQ0 */ 2541 cmc = SOC_ARM_CMC(unit, arm); 2542 2543 for (;;) { 2544 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); 2545 if (irqStat == 0) { 2546 break; /* move to next arm cmc */ 2547 } 2548 irqMask = SOC_CMCx_IRQ0_MASK(unit,cmc); 2549 irqStat &= irqMask; 2550 if (irqStat == 0) { 2551 break; /* move to next arm cmc */ 2552 } 2553 2554 i = 0; 2555 for (; intr_handler[i].mask; i++) { 2556 if (irqStat & intr_handler[i].mask) { 2557 /* dispatch interrupt */ 2558 LOG_INFO(BSL_LS_SOC_INTR, 2559 (BSL_META_U(unit, 2560 "soc_cmicm_intr CMC %d type 0 unit %d: dispatch %s\n"), 2561 unit, cmc, intr_handler[i].intr_name)); 2562 2563 (*intr_handler[i].intr_fn) 2564 (unit, ((cmc<<2) + intr_handler[i].intr_data)); 2565 2566 if (--poll_limit == 0) { 2567 LOG_ERROR(BSL_LS_SOC_COMMON, 2568 (BSL_META_U(unit, 2569 "soc_cmicm_intr unit %d cmc %0d: " 2570 "ERROR can't clear arm type 0 interrupt(s): " 2571 "IRQ=0x%x (disabling 0x%x)\n"), 2572 unit, cmc, irqStat, intr_handler[i].mask)); 2573 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, 2574 intr_handler[i].mask); 2575 poll_limit = POLL_LIMIT; 2576 } 2577 break; 2578 } 2579 } 2580 } 2581 } 2582 } 2583 #else 2584 COMPILER_REFERENCE(arm); 2585 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) */ 2586 2587 if (soc_feature(unit, soc_feature_short_cmic_error)) { 2588 /* Using sal_dpc since there are schan reads in this function 2589 * and schan read cant be done from interrupt context. 2590 * the function soc_cmn_error will be excecuted only after this 2591 * function will end. 2592 */ 2593 sal_dpc(soc_cmn_error, INT_TO_PTR(unit), 0, 0, 0, 0); 2594 } 2595 2596 if (soc->soc_flags & SOC_F_POLLED) { 2597 #ifdef SAL_SPL_LOCK_ON_IRQ 2598 sal_spl(s); 2599 #endif 2600 return; 2601 } 2602 2603 #ifndef SAL_SPL_LOCK_ON_IRQ 2604 s = sal_splhi(); 2605 #endif 2606 2607 for (cmc = 0; cmc < SOC_PCI_CMCS_NUM(unit); cmc++) { 2608 IRQ_MASK0_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), SOC_CMCx_IRQ0_MASK(unit, cmc)); 2609 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) 2610 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), SOC_CMCx_IRQ1_MASK(unit, cmc)); 2611 2612 #if defined(BCM_SABER2_SUPPORT) 2613 if (SOC_IS_SABER2(unit)) { 2614 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), SOC_CMCx_IRQ3_MASK(unit, cmc)); 2615 } else 2616 #endif 2617 { 2618 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), SOC_CMCx_IRQ2_MASK(unit, cmc)); 2619 } 2620 2621 if (soc_feature(unit, soc_feature_extended_cmic_error)) { 2622 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), SOC_CMCx_IRQ3_MASK(unit, cmc)); 2623 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), SOC_CMCx_IRQ4_MASK(unit, cmc)); 2624 if (soc_feature(unit, soc_feature_cmicm_extended_interrupts)) { 2625 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc), SOC_CMCx_IRQ5_MASK(unit, cmc)); 2626 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc), SOC_CMCx_IRQ6_MASK(unit, cmc)); 2627 } 2628 } 2629 if (soc_feature(unit, soc_feature_cmicd_v2)) { 2630 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), SOC_CMCx_IRQ3_MASK(unit, cmc)); 2631 } 2632 if (soc_feature(unit, soc_feature_short_cmic_error)) { 2633 /* When working with this feature other interrupts handling in this reg are done from soc_cmn_error() 2634 * only cmic parity error (bit 0) is handled by this function. 2635 */ 2636 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), SOC_CMCx_IRQ2_MASK(unit, cmc) & 0x1); 2637 } 2638 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) */ 2639 } 2640 2641 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) 2642 /* May need to restore the masks in ARM's CMCs as well */ 2643 if (soc_feature(unit, soc_feature_cmicm_multi_dma_cmc) && 2644 (SOC_CMCS_NUM(unit) > SOC_PCI_CMCS_NUM(unit))) { 2645 int arm; 2646 2647 for (arm = 0; arm < (SOC_CMCS_NUM(unit) - SOC_PCI_CMCS_NUM(unit)); arm++) { 2648 int arm_cmc = SOC_ARM_CMC(unit, arm); 2649 2650 soc_pci_write(unit, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(arm_cmc), SOC_CMCx_IRQ0_MASK(unit, arm_cmc)); 2651 } 2652 } 2653 #endif 2654 2655 sal_spl(s); 2656 } 2657 2658 #ifdef SEPARATE_PKTDMA_INTR_HANDLER 2659 void 2660 soc_cmicm_pktdma_intr(void *_unit) 2661 { 2662 soc_control_t *soc; 2663 uint32 irqStat, irqMask; 2664 int unit = PTR_TO_INT(_unit); 2665 int cmc = 0, i = 0; 2666 int poll_limit = 102400; /* 100K */ 2667 intr_handler_t *intr_handler = soc_cmicm_pktdma_intr_handlers; 2668 uint32 pktdma_status = 0x7800ff00; 2669 2670 #ifdef SAL_SPL_LOCK_ON_IRQ 2671 int s; 2672 s = sal_splhi(); 2673 #endif 2674 2675 soc = SOC_CONTROL(unit); 2676 2677 /* 2678 * Our handler is permanently registered in soc_probe(). If our 2679 * unit is not attached yet, it could not have generated this 2680 * interrupt. The interrupt line must be shared by multiple PCI 2681 * cards. Simply ignore the interrupt and let another handler 2682 * process it. 2683 */ 2684 if (soc == NULL || (soc->soc_flags & SOC_F_BUSY) || 2685 !(soc->soc_flags & SOC_F_ATTACHED)) { 2686 #ifdef SAL_SPL_LOCK_ON_IRQ 2687 sal_spl(s); 2688 #endif 2689 return; 2690 } 2691 2692 cmc = SOC_PCI_CMC(unit); 2693 /* Update count */ 2694 soc->stat.intr++; 2695 2696 if (soc_feature(unit, soc_feature_sbusdma)) { 2697 intr_handler = soc_cmicm_pktdma_intr_handlers0; 2698 } 2699 /* 2700 * Read IRQ Status and IRQ Mask and AND to determine active ints. 2701 * These are re-read each time since either can be changed by ISRs. 2702 */ 2703 for (;;) { 2704 if (soc_feature(unit, soc_feature_cmicm_multi_dma_cmc) && 2705 (SOC_PCI_CMCS_NUM(unit) > 1)) { 2706 for (i = soc->next_int0_cmc; i < soc->next_int0_cmc + SOC_PCI_CMCS_NUM(unit); i++) { 2707 cmc = i % SOC_PCI_CMCS_NUM(unit); 2708 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); 2709 /** Only handle pktdma interrupts */ 2710 irqStat &= pktdma_status; 2711 if (irqStat != 0) { 2712 irqMask = SOC_CMCx_IRQ0_MASK(unit, cmc); 2713 irqStat &= irqMask; 2714 if (irqStat != 0) { 2715 goto detected_irq0; 2716 } 2717 } 2718 soc->next_int0_cmc = (cmc + 1) % SOC_PCI_CMCS_NUM(unit); 2719 } 2720 /** re-assign cmc to origin */ 2721 cmc = SOC_PCI_CMC(unit); 2722 goto exit; 2723 } else { 2724 cmc = SOC_PCI_CMC(unit); 2725 irqStat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); 2726 /** Only handle pktdma interrupts */ 2727 irqStat &= pktdma_status; 2728 if (irqStat == 0) { 2729 goto exit; /* No pending Interrupts */ 2730 } 2731 irqMask = SOC_CMCx_IRQ0_MASK(unit,cmc); 2732 irqStat &= irqMask; 2733 if (irqStat == 0) { 2734 goto exit; 2735 } 2736 } 2737 2738 detected_irq0: 2739 i = 0; 2740 /* 2741 * We may have received an interrupt before all data has been 2742 * posted from the device or intermediate bridge. 2743 * The PCI specification requires that we read a device register 2744 * to make sure pending data is flushed. 2745 */ 2746 soc_pci_read(unit, CMIC_CMCx_SCHAN_CTRL_OFFSET(cmc)); 2747 soc_pci_read(unit, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc)); 2748 2749 for (; intr_handler[i].mask; i++) { 2750 if (irqStat & intr_handler[i].mask) { 2751 2752 /* dispatch interrupt */ 2753 LOG_INFO(BSL_LS_SOC_INTR, 2754 (BSL_META_U(unit, 2755 "soc_cmicm_intr type 0 unit %d: dispatch %s\n"), 2756 unit, intr_handler[i].intr_name)); 2757 2758 (*intr_handler[i].intr_fn) 2759 (unit, cmc * N_DMA_CHAN + intr_handler[i].intr_data); 2760 2761 /* 2762 * Prevent infinite loop in interrupt handler by 2763 * disabling the offending interrupt(s). 2764 */ 2765 /* coverity[dead_error_condition] */ 2766 if (--poll_limit == 0) { 2767 return; 2768 } 2769 /* 2770 * Go back and re-read IRQ status. Start processing 2771 * from scratch since handler may clear more than one 2772 * bit. We don't leave the ISR until all of the bits 2773 * have been cleared and their handlers called. 2774 */ 2775 break; 2776 } 2777 } 2778 } 2779 2780 exit: 2781 2782 if (soc->soc_flags & SOC_F_POLLED) { 2783 #ifdef SAL_SPL_LOCK_ON_IRQ 2784 sal_spl(s); 2785 #endif 2786 return; 2787 } 2788 2789 for (cmc = 0; cmc < SOC_PCI_CMCS_NUM(unit); cmc++) 2790 { 2791 IRQ_MASK0_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), SOC_CMCx_IRQ0_MASK(unit, cmc)); 2792 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), SOC_CMCx_IRQ1_MASK(unit, cmc)); 2793 IRQ_MASKx_SET(unit, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), SOC_CMCx_IRQ2_MASK(unit, cmc)); 2794 } 2795 #ifdef SAL_SPL_LOCK_ON_IRQ 2796 sal_spl(s); 2797 #endif 2798 } 2799 #endif 2800 2801 2802 #ifdef INCLUDE_RCPU 2803 STATIC void 2804 soc_cmicm_rcpu_intr_miim_op(int unit, uint32 ignored) 2805 { 2806 soc_control_t *soc = SOC_CONTROL(unit); 2807 2808 COMPILER_REFERENCE(ignored); 2809 2810 /* Clr Read & Write Stat */ 2811 soc_pci_write(unit, CMIC_RPE_MIIM_CTRL_OFFSET, 0); 2812 2813 soc->stat.intr_mii++; 2814 2815 if (soc->miimIntr) { 2816 sal_sem_give(soc->miimIntr); 2817 } 2818 } 2819 /* 2820 * Enable (unmask) or disable (mask) a set of CMIC RPE interrupts. These 2821 * routines should be used instead of manipulating CMIC_RPE_RCPU_IRQ_MASK 2822 * directly, since a read-modify-write is required. The return value is 2823 * the previous mask (can pass mask of 0 to just get the current mask). 2824 */ 2825 2826 STATIC uint32 2827 soc_cmicm_rcpu_intrx_enable(int unit, uint32 offset, uint32 mask, uint32 *mask_reg) 2828 { 2829 uint32 oldMask; 2830 uint32 newMask; 2831 int s; 2832 s = sal_splhi(); 2833 2834 2835 oldMask = *mask_reg; 2836 *mask_reg |= mask; 2837 newMask = *mask_reg; 2838 /* In polled mode, the hardware IRQ mask is always zero */ 2839 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 2840 newMask = 0; 2841 } 2842 LOG_INFO(BSL_LS_SOC_INTR, 2843 (BSL_META_U(unit, 2844 "soc_cmicm_rcpu_intrx_enable unit %d: mask 0x%8x\n"), unit, mask)); 2845 2846 soc_pci_write(unit, offset, newMask); 2847 2848 sal_spl(s); 2849 return oldMask; 2850 } 2851 2852 STATIC uint32 2853 soc_cmicm_rcpu_intrx_disable(int unit, uint32 offset, uint32 mask, uint32 *mask_reg) 2854 { 2855 uint32 oldMask; 2856 uint32 newMask; 2857 int s; 2858 2859 s = sal_splhi(); 2860 oldMask = *mask_reg; 2861 *mask_reg &= ~mask; 2862 newMask = *mask_reg; 2863 2864 /* In polled mode, the hardware IRQ mask is always zero */ 2865 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 2866 newMask = 0; 2867 } 2868 LOG_INFO(BSL_LS_SOC_INTR, 2869 (BSL_META_U(unit, 2870 "soc_cmicm_rcpu_intrx_disable unit %d: mask 0x%8x\n"), unit, mask)); 2871 soc_pci_write(unit, offset, newMask); 2872 2873 sal_spl(s); 2874 return oldMask; 2875 } 2876 2877 uint32 2878 soc_cmicm_rcpu_intr0_enable(int unit, uint32 mask) 2879 { 2880 return soc_cmicm_rcpu_intrx_enable(unit, CMIC_RPE_RCPU_IRQ_MASK0_OFFSET, 2881 mask, &SOC_RCPU_IRQ0_MASK(unit)); 2882 } 2883 2884 uint32 2885 soc_cmicm_rcpu_intr0_disable(int unit, uint32 mask) 2886 { 2887 return soc_cmicm_rcpu_intrx_disable(unit, CMIC_RPE_RCPU_IRQ_MASK0_OFFSET, 2888 mask, &SOC_RCPU_IRQ0_MASK(unit)); 2889 } 2890 2891 uint32 2892 soc_cmicm_rcpu_intr1_enable(int unit, uint32 mask) 2893 { 2894 return soc_cmicm_rcpu_intrx_enable(unit, CMIC_RPE_RCPU_IRQ_MASK1_OFFSET, 2895 mask, &SOC_RCPU_IRQ1_MASK(unit)); 2896 } 2897 2898 uint32 2899 soc_cmicm_rcpu_intr1_disable(int unit, uint32 mask) 2900 { 2901 return soc_cmicm_rcpu_intrx_disable(unit, CMIC_RPE_RCPU_IRQ_MASK1_OFFSET, 2902 mask, &SOC_RCPU_IRQ1_MASK(unit)); 2903 } 2904 2905 uint32 2906 soc_cmicm_rcpu_intr2_enable(int unit, uint32 mask) 2907 { 2908 return soc_cmicm_rcpu_intrx_enable(unit, CMIC_RPE_RCPU_IRQ_MASK2_OFFSET, 2909 mask, &SOC_RCPU_IRQ2_MASK(unit)); 2910 } 2911 2912 uint32 2913 soc_cmicm_rcpu_intr2_disable(int unit, uint32 mask) 2914 { 2915 return soc_cmicm_rcpu_intrx_disable(unit, CMIC_RPE_RCPU_IRQ_MASK2_OFFSET, 2916 mask, &SOC_RCPU_IRQ2_MASK(unit)); 2917 } 2918 2919 uint32 2920 soc_cmicm_rcpu_intr3_enable(int unit, uint32 mask) 2921 { 2922 return soc_cmicm_rcpu_intrx_enable(unit, CMIC_RPE_RCPU_IRQ_MASK3_OFFSET, 2923 mask, &SOC_RCPU_IRQ3_MASK(unit)); 2924 } 2925 2926 uint32 2927 soc_cmicm_rcpu_intr3_disable(int unit, uint32 mask) 2928 { 2929 return soc_cmicm_rcpu_intrx_disable(unit, CMIC_RPE_RCPU_IRQ_MASK3_OFFSET, 2930 mask, &SOC_RCPU_IRQ3_MASK(unit)); 2931 } 2932 2933 uint32 2934 soc_cmicm_rcpu_intr4_enable(int unit, uint32 mask) 2935 { 2936 return soc_cmicm_rcpu_intrx_enable(unit, CMIC_RPE_RCPU_IRQ_MASK4_OFFSET, 2937 mask, &SOC_RCPU_IRQ4_MASK(unit)); 2938 } 2939 2940 uint32 2941 soc_cmicm_rcpu_intr4_disable(int unit, uint32 mask) 2942 { 2943 return soc_cmicm_rcpu_intrx_disable(unit, CMIC_RPE_RCPU_IRQ_MASK4_OFFSET, 2944 mask, &SOC_RCPU_IRQ4_MASK(unit)); 2945 } 2946 2947 uint32 2948 soc_cmicm_rcpu_cmc0_intr0_enable(int unit, uint32 mask) 2949 { 2950 return soc_cmicm_rcpu_intrx_enable(unit, CMIC_CMC0_RCPU_IRQ_MASK0_OFFSET, 2951 mask, &SOC_RCPU_CMC0_IRQ0_MASK(unit)); 2952 } 2953 2954 uint32 2955 soc_cmicm_rcpu_cmc0_intr0_disable(int unit, uint32 mask) 2956 { 2957 return soc_cmicm_rcpu_intrx_disable(unit, CMIC_CMC0_RCPU_IRQ_MASK0_OFFSET, 2958 mask, &SOC_RCPU_CMC0_IRQ0_MASK(unit)); 2959 } 2960 2961 uint32 2962 soc_cmicm_rcpu_cmc1_intr0_enable(int unit, uint32 mask) 2963 { 2964 return soc_cmicm_rcpu_intrx_enable(unit, CMIC_CMC1_RCPU_IRQ_MASK0_OFFSET, 2965 mask, &SOC_RCPU_CMC1_IRQ0_MASK(unit)); 2966 } 2967 2968 uint32 2969 soc_cmicm_rcpu_cmc1_intr0_disable(int unit, uint32 mask) 2970 { 2971 return soc_cmicm_rcpu_intrx_disable(unit, CMIC_CMC1_RCPU_IRQ_MASK0_OFFSET, 2972 mask, &SOC_RCPU_CMC1_IRQ0_MASK(unit)); 2973 } 2974 2975 uint32 2976 soc_cmicm_rcpu_cmc2_intr0_enable(int unit, uint32 mask) 2977 { 2978 return soc_cmicm_rcpu_intrx_enable(unit, CMIC_CMC2_RCPU_IRQ_MASK0_OFFSET, 2979 mask, &SOC_RCPU_CMC2_IRQ0_MASK(unit)); 2980 } 2981 2982 uint32 2983 soc_cmicm_rcpu_cmc2_intr0_disable(int unit, uint32 mask) 2984 { 2985 return soc_cmicm_rcpu_intrx_disable(unit, CMIC_CMC2_RCPU_IRQ_MASK0_OFFSET, 2986 mask, &SOC_RCPU_CMC2_IRQ0_MASK(unit)); 2987 } 2988 2989 void 2990 soc_cmicm_rcpu_intr(int unit, soc_rcpu_intr_packet_t *intr_pkt) 2991 { 2992 uint32 irqStat, irqMask; 2993 int i = 0; 2994 intr_handler_t *intr_handler = soc_cmicm_rcpu_intr_handlers0; 2995 soc_control_t *soc; 2996 2997 #ifdef SAL_SPL_LOCK_ON_IRQ 2998 int s; 2999 3000 s = sal_splhi(); 3001 #endif 3002 3003 soc = SOC_CONTROL(unit); 3004 3005 /* 3006 * Our handler is permanently registered in soc_probe(). If our 3007 * unit is not attached yet, it could not have generated this 3008 * interrupt. The interrupt line must be shared by multiple PCI 3009 * cards. Simply ignore the interrupt and let another handler 3010 * process it. 3011 */ 3012 if (soc == NULL || (soc->soc_flags & SOC_F_BUSY) || 3013 !(soc->soc_flags & SOC_F_ATTACHED)) { 3014 #ifdef SAL_SPL_LOCK_ON_IRQ 3015 sal_spl(s); 3016 #endif 3017 return; 3018 } 3019 3020 soc->stat.intr++; /* Update count */ 3021 3022 /* 3023 * Read IRQ Status and IRQ Mask and AND to determine active ints. 3024 * These are re-read each time since either can be changed by ISRs. 3025 */ 3026 3027 irqStat = intr_pkt->rcpu_irq0_stat; 3028 if (irqStat == 0) { 3029 goto check_rcpu_type1; /* No pending Interrupts */ 3030 } 3031 irqMask = intr_pkt->rcpu_irq0_mask; 3032 irqStat &= irqMask; 3033 if (irqStat == 0) { 3034 goto check_rcpu_type1; 3035 } 3036 3037 i = 0; 3038 3039 for (; intr_handler[i].mask; i++) { 3040 if (irqStat & intr_handler[i].mask) { 3041 3042 /* dispatch interrupt */ 3043 if (LOG_CHECK(BSL_LS_SOC_RCPU | BSL_INFO) && 3044 LOG_CHECK(BSL_LS_SOC_INTR | BSL_INFO)) { 3045 LOG_CLI((BSL_META_U(unit, 3046 "soc_cmicm_rcpu_intr type 0 unit %d: dispatch %s\n"), 3047 unit, intr_handler[i].intr_name)); 3048 } 3049 3050 (*intr_handler[i].intr_fn)(unit, intr_handler[i].intr_data); 3051 } 3052 } 3053 3054 check_rcpu_type1: 3055 3056 #if defined(BCM_ESW_SUPPORT) 3057 irqStat = intr_pkt->rcpu_irq1_stat; 3058 if (irqStat == 0) { 3059 goto check_rcpu_type2; /* No pending Interrupts */ 3060 } 3061 irqMask = intr_pkt->rcpu_irq1_mask; 3062 irqStat &= irqMask; 3063 if (irqStat == 0) { 3064 goto check_rcpu_type2; 3065 } 3066 3067 intr_handler = soc_cmicm_intr_handlers1; 3068 i = 0; 3069 3070 for (; intr_handler[i].mask; i++) { 3071 if (irqStat & intr_handler[i].mask) { 3072 3073 /* dispatch interrupt, verbose only */ 3074 if (LOG_CHECK(BSL_LS_SOC_RCPU | BSL_INFO) && 3075 LOG_CHECK(BSL_LS_SOC_INTR | BSL_INFO)) { 3076 LOG_CLI((BSL_META_U(unit, 3077 "soc_cmicm_rcpu_intr type 1 unit %d: dispatch %s\n"), 3078 unit, intr_handler[i].intr_name)); 3079 } 3080 } 3081 } 3082 3083 check_rcpu_type2: 3084 3085 irqStat = intr_pkt->rcpu_irq2_stat; 3086 if (irqStat == 0) { 3087 goto check_rcpu_type3; /* No pending Interrupts */ 3088 } 3089 irqMask = intr_pkt->rcpu_irq2_mask; 3090 irqStat &= irqMask; 3091 if (irqStat == 0) { 3092 goto check_rcpu_type2; 3093 } 3094 3095 intr_handler = soc_cmicm_intr_handlers2; 3096 i = 0; 3097 3098 for (; intr_handler[i].mask; i++) { 3099 if (irqStat & intr_handler[i].mask) { 3100 3101 /* dispatch interrupt, verbose only */ 3102 if (LOG_CHECK(BSL_LS_SOC_RCPU | BSL_INFO) && 3103 LOG_CHECK(BSL_LS_SOC_INTR | BSL_INFO)) { 3104 LOG_CLI((BSL_META_U(unit, 3105 "soc_cmicm_rcpu_intr type 2 unit %d: dispatch %s\n"), 3106 unit, intr_handler[i].intr_name)); 3107 } 3108 } 3109 } 3110 3111 check_rcpu_type3: 3112 3113 irqStat = intr_pkt->rcpu_irq3_stat; 3114 if (irqStat == 0) { 3115 goto check_rcpu_type4; /* No pending Interrupts */ 3116 } 3117 irqMask = intr_pkt->rcpu_irq3_mask; 3118 irqStat &= irqMask; 3119 if (irqStat == 0) { 3120 goto check_rcpu_type4; 3121 } 3122 3123 intr_handler = soc_cmicm_intr_handlers3; 3124 i = 0; 3125 3126 for (; intr_handler[i].mask; i++) { 3127 if (irqStat & intr_handler[i].mask) { 3128 3129 /* dispatch interrupt, verbose only */ 3130 if (LOG_CHECK(BSL_LS_SOC_RCPU | BSL_INFO) && 3131 LOG_CHECK(BSL_LS_SOC_INTR | BSL_INFO)) { 3132 LOG_CLI((BSL_META_U(unit, 3133 "soc_cmicm_rcpu_intr type 3 unit %d: dispatch %s\n"), 3134 unit, intr_handler[i].intr_name)); 3135 } 3136 } 3137 } 3138 3139 check_rcpu_type4: 3140 irqStat = intr_pkt->rcpu_irq4_stat; 3141 if (irqStat == 0) { 3142 goto check_rcpu_cmc0; /* No pending Interrupts */ 3143 } 3144 irqMask = intr_pkt->rcpu_irq4_mask; 3145 irqStat &= irqMask; 3146 if (irqStat == 0) { 3147 goto check_rcpu_cmc0; 3148 } 3149 3150 if (soc_feature(unit, soc_feature_cmicd_v2)) { 3151 intr_handler = soc_cmicdv2_intr_handlers4; 3152 } else { 3153 intr_handler = soc_cmicm_intr_handlers4; 3154 } 3155 i = 0; 3156 3157 for (; intr_handler[i].mask; i++) { 3158 if (irqStat & intr_handler[i].mask) { 3159 3160 /* dispatch interrupt, verbose only */ 3161 if (LOG_CHECK(BSL_LS_SOC_RCPU | BSL_INFO) && 3162 LOG_CHECK(BSL_LS_SOC_INTR | BSL_INFO)) { 3163 LOG_CLI((BSL_META_U(unit, 3164 "soc_cmicm_rcpu_intr type 4 unit %d: dispatch %s\n"), 3165 unit, intr_handler[i].intr_name)); 3166 } 3167 } 3168 } 3169 3170 check_rcpu_cmc0: 3171 3172 #endif /* defined(BCM_ESW_SUPPORT) */ 3173 3174 irqStat = intr_pkt->cmc0_irq_stat; 3175 if (irqStat == 0) { 3176 goto rcpu_intr_exit; /* No pending Interrupts */ 3177 } 3178 irqMask = intr_pkt->cmc0_rcpu_irq_mask; 3179 irqStat &= irqMask; 3180 if (irqStat == 0) { 3181 goto rcpu_intr_exit; 3182 } 3183 3184 if (soc_feature(unit, soc_feature_sbusdma)) { 3185 intr_handler = soc_cmicm_intr_handlers0; 3186 } else { 3187 intr_handler = soc_cmicm_intr_handlers; 3188 } 3189 3190 i = 0; 3191 3192 for (; intr_handler[i].mask; i++) { 3193 if (irqStat & intr_handler[i].mask) { 3194 3195 if (LOG_CHECK(BSL_LS_SOC_RCPU | BSL_INFO) && 3196 LOG_CHECK(BSL_LS_SOC_INTR | BSL_INFO)) { 3197 /* dispatch interrupt, verbose only */ 3198 LOG_CLI((BSL_META_U(unit, 3199 "soc_cmicm_rcpu_cmc0_intr type 0 unit %d: dispatch %s\n"), 3200 unit, intr_handler[i].intr_name)); 3201 } 3202 } 3203 } 3204 3205 rcpu_intr_exit: 3206 3207 #ifdef SAL_SPL_LOCK_ON_IRQ 3208 sal_spl(s); 3209 #endif 3210 return; 3211 } 3212 3213 #endif /* INCLUDE_RCPU */ 3214 3215 /* 3216 * Initialize iProc based iHost irq offset 3217 */ 3218 void 3219 soc_cmicm_ihost_irq_offset_set(int unit) 3220 { 3221 soc_cmicm_host_irq_offset[unit] = HOST_IRQ_MASK_OFFSET_DIFF; 3222 } 3223 3224 /* 3225 * Initialize iProc based iHost irq offset 3226 */ 3227 void 3228 soc_cmicm_ihost_irq_offset_reset(int unit) 3229 { 3230 soc_cmicm_host_irq_offset[unit] = 0; 3231 } 3232 3233 #endif /* CMICM Support */