preemption_cnt.c (11982B)
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 #include <soc/drv.h> 8 #include <bcm/error.h> 9 #include <bcm/types.h> 10 #include <bcm/port.h> 11 #include <bcm_int/esw/preemption_cnt.h> 12 13 #if defined(BCM_GREYHOUND2_SUPPORT) 14 /* for ingress table ING_RX_COUNTERm : 15 * entry 0~127 is for non-preemptable, entry 128~255 is for preemptable packet 16 * so the number of entries is half of table 17 */ 18 #define IGR_COUNTER_ENTRY_NUM (soc_mem_index_count(unit, ING_RX_COUNTERm) >> 1) 19 #define EGR_COUNTER_ENTRY_NUM (soc_mem_index_count(unit, EGR_MFRAME_COUNTERm)) 20 21 /* sw database for ingress counter mode (packet or byte mode) 22 * (need not sw database for egress, because always packet mode) 23 */ 24 STATIC uint32 *igr_counter_mode_non_preempt[SOC_MAX_NUM_DEVICES]; 25 STATIC uint32 *igr_counter_mode_preempt[SOC_MAX_NUM_DEVICES]; 26 27 STATIC int 28 bcmi_gh2_preemption_counter_set(int unit, bcm_port_t local_port, 29 bcm_port_stat_t stat, uint64 val) 30 { 31 int mode = 1; 32 33 if(NULL == igr_counter_mode_non_preempt[unit] || 34 NULL == igr_counter_mode_preempt[unit]) { 35 return BCM_E_INIT; 36 } 37 38 /* check local_port valid */ 39 switch (stat) { 40 case bcmPortStatIngressPackets: 41 case bcmPortStatIngressBytes: 42 case bcmPortStatIngressPreemptPackets: 43 case bcmPortStatIngressPreemptBytes: 44 if (local_port < 0 || local_port >= IGR_COUNTER_ENTRY_NUM) { 45 return BCM_E_PARAM; 46 } 47 break; 48 case bcmPortStatEgressPreemptPackets: 49 case bcmPortStatEgressPackets: 50 case bcmPortStatEgressBytes: 51 case bcmPortStatEgressPreemptBytes: 52 if (local_port < 0 || local_port >= EGR_COUNTER_ENTRY_NUM) { 53 return BCM_E_PARAM; 54 } 55 break; 56 } 57 58 /* set counter */ 59 switch (stat) { 60 case bcmPortStatIngressPackets: 61 case bcmPortStatIngressBytes: 62 BCM_IF_ERROR_RETURN( 63 soc_counter_set( 64 unit, local_port, 65 SOC_COUNTER_NON_DMA_ING_RX_COUNTER_NON_PREEMPTABLE_CNT, 66 0, val)); 67 break; 68 case bcmPortStatIngressPreemptPackets: 69 case bcmPortStatIngressPreemptBytes: 70 BCM_IF_ERROR_RETURN( 71 soc_counter_set( 72 unit, local_port, 73 SOC_COUNTER_NON_DMA_ING_RX_COUNTER_PREEMPTABLE_CNT, 74 0, val)); 75 break; 76 case bcmPortStatEgressPreemptPackets: 77 BCM_IF_ERROR_RETURN( 78 soc_counter_set( 79 unit, local_port, 80 SOC_COUNTER_NON_DMA_EGR_TX_COUNTER_PREEMPTABLE_CNT, 81 0, val)); 82 break; 83 case bcmPortStatEgressPackets: 84 case bcmPortStatEgressBytes: 85 case bcmPortStatEgressPreemptBytes: 86 /* egress: only support preemptable packet mode in GH2 */ 87 return BCM_E_UNAVAIL; 88 } 89 90 /* update counter mode */ 91 switch (stat) { 92 case bcmPortStatIngressPackets: 93 mode = 0; 94 /* fall through */ 95 case bcmPortStatIngressBytes: 96 BCM_IF_ERROR_RETURN( 97 soc_mem_field32_modify( 98 unit, ING_RX_COUNTERm, 99 local_port, 100 COUNT_BYTEf, mode)); 101 BCM_IF_ERROR_RETURN( 102 soc_mem_field32_modify( 103 unit, ING_RX_COUNTERm, 104 IGR_COUNTER_ENTRY_NUM + local_port, 105 COUNT_BYTEf, mode)); 106 igr_counter_mode_non_preempt[unit][local_port] = mode; 107 igr_counter_mode_preempt[unit][local_port] = mode; 108 break; 109 case bcmPortStatIngressPreemptPackets: 110 mode = 0; 111 /* fall through */ 112 case bcmPortStatIngressPreemptBytes: 113 BCM_IF_ERROR_RETURN( 114 soc_mem_field32_modify( 115 unit, ING_RX_COUNTERm, 116 IGR_COUNTER_ENTRY_NUM + local_port, 117 COUNT_BYTEf, mode)); 118 igr_counter_mode_preempt[unit][local_port] = mode; 119 break; 120 default: 121 /* need not update coutner mode for egress in GH2 122 *(because always packet mode) 123 */ 124 break; 125 } 126 return BCM_E_NONE; 127 } 128 129 STATIC int 130 bcmi_gh2_preemption_counter_get(int unit, int sync_mode, bcm_port_t local_port, 131 bcm_port_stat_t stat, uint64 *val) 132 { 133 uint64 local_val; 134 135 if (NULL == val) { 136 return BCM_E_PARAM; 137 } 138 if(NULL == igr_counter_mode_non_preempt[unit] || 139 NULL == igr_counter_mode_preempt[unit]) { 140 return BCM_E_INIT; 141 } 142 143 /* check local_port valid */ 144 switch (stat) { 145 case bcmPortStatIngressPackets: 146 case bcmPortStatIngressBytes: 147 case bcmPortStatIngressPreemptPackets: 148 case bcmPortStatIngressPreemptBytes: 149 if (local_port < 0 || local_port >= IGR_COUNTER_ENTRY_NUM) { 150 return BCM_E_PARAM; 151 } 152 break; 153 case bcmPortStatEgressPreemptPackets: 154 case bcmPortStatEgressPackets: 155 case bcmPortStatEgressBytes: 156 case bcmPortStatEgressPreemptBytes: 157 if (local_port < 0 || local_port >= EGR_COUNTER_ENTRY_NUM) { 158 return BCM_E_PARAM; 159 } 160 break; 161 } 162 163 /* check counter mode first */ 164 switch (stat) { 165 case bcmPortStatIngressPackets: 166 if (0 != igr_counter_mode_non_preempt[unit][local_port]) { 167 return BCM_E_PARAM; 168 } 169 if (0 != igr_counter_mode_preempt[unit][local_port]) { 170 return BCM_E_PARAM; 171 } 172 break; 173 case bcmPortStatIngressBytes: 174 if (1 != igr_counter_mode_non_preempt[unit][local_port]) { 175 return BCM_E_PARAM; 176 } 177 if (1 != igr_counter_mode_preempt[unit][local_port]) { 178 return BCM_E_PARAM; 179 } 180 break; 181 case bcmPortStatIngressPreemptPackets: 182 if (0 != igr_counter_mode_preempt[unit][local_port]) { 183 return BCM_E_PARAM; 184 } 185 break; 186 case bcmPortStatIngressPreemptBytes: 187 if (1 != igr_counter_mode_preempt[unit][local_port]) { 188 return BCM_E_PARAM; 189 } 190 break; 191 case bcmPortStatEgressPreemptPackets: 192 break; 193 case bcmPortStatEgressPackets: 194 case bcmPortStatEgressBytes: 195 case bcmPortStatEgressPreemptBytes: 196 /* egress: only support preemptable packet mode in GH2 */ 197 return BCM_E_UNAVAIL; 198 } 199 200 /* get counter */ 201 COMPILER_64_ZERO(*val); 202 switch (stat) { 203 case bcmPortStatIngressPackets: 204 case bcmPortStatIngressBytes: 205 if (1 == sync_mode) { 206 BCM_IF_ERROR_RETURN( 207 soc_counter_sync_get( 208 unit, local_port, 209 SOC_COUNTER_NON_DMA_ING_RX_COUNTER_NON_PREEMPTABLE_CNT, 210 0, &local_val)); 211 } else { 212 BCM_IF_ERROR_RETURN( 213 soc_counter_get( 214 unit, local_port, 215 SOC_COUNTER_NON_DMA_ING_RX_COUNTER_NON_PREEMPTABLE_CNT, 216 0, &local_val)); 217 } 218 COMPILER_64_ADD_64(*val, local_val); 219 /* fall through */ 220 case bcmPortStatIngressPreemptPackets: 221 case bcmPortStatIngressPreemptBytes: 222 if (1 == sync_mode) { 223 BCM_IF_ERROR_RETURN( 224 soc_counter_sync_get( 225 unit, local_port, 226 SOC_COUNTER_NON_DMA_ING_RX_COUNTER_PREEMPTABLE_CNT, 227 0, &local_val)); 228 } else { 229 BCM_IF_ERROR_RETURN( 230 soc_counter_get( 231 unit, local_port, 232 SOC_COUNTER_NON_DMA_ING_RX_COUNTER_PREEMPTABLE_CNT, 233 0, &local_val)); 234 } 235 COMPILER_64_ADD_64(*val, local_val); 236 break; 237 case bcmPortStatEgressPreemptPackets: 238 if (1 == sync_mode) { 239 BCM_IF_ERROR_RETURN( 240 soc_counter_sync_get( 241 unit, local_port, 242 SOC_COUNTER_NON_DMA_EGR_TX_COUNTER_PREEMPTABLE_CNT, 243 0, &local_val)); 244 } else { 245 BCM_IF_ERROR_RETURN( 246 soc_counter_get( 247 unit, local_port, 248 SOC_COUNTER_NON_DMA_EGR_TX_COUNTER_PREEMPTABLE_CNT, 249 0, &local_val)); 250 } 251 COMPILER_64_ADD_64(*val, local_val); 252 break; 253 default: 254 return BCM_E_INTERNAL; /* should not enter here */ 255 } 256 257 return BCM_E_NONE; 258 } 259 260 STATIC int 261 bcmi_gh2_preemption_counter_clean(int unit) 262 { 263 if(NULL != igr_counter_mode_non_preempt[unit]) { 264 sal_free(igr_counter_mode_non_preempt[unit]); 265 igr_counter_mode_non_preempt[unit] = NULL; 266 } 267 if(NULL != igr_counter_mode_preempt[unit]) { 268 sal_free(igr_counter_mode_preempt[unit]); 269 igr_counter_mode_preempt[unit] = NULL; 270 } 271 return BCM_E_NONE; 272 } 273 274 STATIC int 275 bcmi_gh2_preemption_counter_init(int unit) 276 { 277 int i; 278 uint32 **counter_mode[2]; 279 280 /* prepare sw database for ingress counter mode 281 * entry 0~127 for non-preempt, 128~255 for preempt 282 */ 283 counter_mode[0] = &(igr_counter_mode_non_preempt[unit]); 284 counter_mode[1] = &(igr_counter_mode_preempt[unit]); 285 286 if(NULL != *(counter_mode[0]) || NULL != *(counter_mode[1])) { 287 bcmi_gh2_preemption_counter_clean(unit); 288 } 289 290 for (i = 0; i < 2; i++) { 291 uint8 *dma_buffer = NULL; 292 int alloc_size, j, entry_byte, rv; 293 294 /* alloc sw database */ 295 alloc_size = IGR_COUNTER_ENTRY_NUM * sizeof(uint32); 296 *(counter_mode[i]) = sal_alloc(alloc_size, "igr_counter_mode"); 297 if (NULL == *(counter_mode[i])) { 298 bcmi_gh2_preemption_counter_clean(unit); 299 return BCM_E_MEMORY; 300 } 301 302 /* sync sw database with hw at initial time */ 303 entry_byte = WORDS2BYTES(soc_mem_entry_words(unit, ING_RX_COUNTERm)); 304 alloc_size = IGR_COUNTER_ENTRY_NUM * entry_byte; 305 dma_buffer = soc_cm_salloc(unit, alloc_size, "dma_buffer"); 306 if (NULL == dma_buffer) { 307 bcmi_gh2_preemption_counter_clean(unit); 308 return BCM_E_MEMORY; 309 } 310 rv = soc_mem_read_range(unit, ING_RX_COUNTERm, MEM_BLOCK_ANY, 311 (IGR_COUNTER_ENTRY_NUM * i), 312 (IGR_COUNTER_ENTRY_NUM * (i+1)) -1, 313 dma_buffer); 314 if (SOC_FAILURE(rv)) { 315 bcmi_gh2_preemption_counter_clean(unit); 316 soc_cm_sfree(unit, dma_buffer); 317 return BCM_E_MEMORY; 318 } 319 for (j = 0; j < IGR_COUNTER_ENTRY_NUM; j++) { 320 uint32 mode; 321 322 mode = soc_mem_field32_get(unit, ING_RX_COUNTERm, 323 &dma_buffer[j * entry_byte], 324 COUNT_BYTEf); 325 (*(counter_mode[i]))[j] = mode; 326 } 327 soc_cm_sfree(unit, dma_buffer); 328 } 329 330 return BCM_E_NONE; 331 } 332 333 int 334 bcmi_gh2_preemption_counter_dev_func_init( 335 bcmi_preemption_counte_func_t* dev_func) 336 { 337 dev_func->preemption_counter_init = bcmi_gh2_preemption_counter_init; 338 dev_func->preemption_counter_clean = bcmi_gh2_preemption_counter_clean; 339 dev_func->preemption_counter_get = bcmi_gh2_preemption_counter_get; 340 dev_func->preemption_counter_set = bcmi_gh2_preemption_counter_set; 341 return BCM_E_NONE; 342 } 343 #endif /* BCM_GREYHOUND2_SUPPORT */