tsn_taf.c (131136B)
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 * Purpose: 8 * Manage chip specific functionality for TSN TAF implementation on GH2. 9 */ 10 11 #include <soc/drv.h> 12 #include <bcm/error.h> 13 #include <bcm/types.h> 14 #include <bcm/tsn.h> 15 #include <bcm_int/esw/port.h> 16 #include <bcm_int/esw/tsn.h> 17 #include <bcm_int/esw/tsn_taf.h> 18 #include <bcm_int/esw_dispatch.h> 19 #include <soc/profile_mem.h> 20 #include <shared/bsl.h> 21 #include <shared/shr_res_bitmap.h> 22 #ifdef BCM_WARM_BOOT_SUPPORT 23 #include <soc/scache.h> 24 #include <bcm_int/esw/switch.h> 25 #endif /* BCM_WARM_BOOT_SUPPORT */ 26 27 #if defined(BCM_TSN_SUPPORT) 28 #define WRITE_PTR(__ptr__, __type__, __data__) \ 29 do { \ 30 *((__type__*)(__ptr__)) = (__data__); \ 31 (__ptr__) += sizeof(__type__); \ 32 } while (0) 33 34 #define WRITE_PTR_RANGE(__ptr__, __size__, __data__) \ 35 do { \ 36 sal_memcpy((__ptr__), (__data__), (__size__)); \ 37 (__ptr__) += (__size__); \ 38 } while (0) 39 40 #define READ_PTR(__ptr__, __type__, __dest__) \ 41 do { \ 42 (__dest__) = *((__type__*)(__ptr__)); \ 43 (__ptr__) += sizeof(__type__); \ 44 } while (0) 45 46 #define READ_PTR_RANGE(__ptr__, __size__, __dest__) \ 47 do { \ 48 sal_memcpy((__dest__), (__ptr__), (__size__)); \ 49 (__ptr__) += (__size__); \ 50 } while (0) 51 52 /* GCLT time interval resolution : 8 ns */ 53 #define TAF_GCLT_TICKS (8) 54 55 /* 56 * taf gate 57 */ 58 #define TAF_GATE_RESERVED_ID (0) 59 STATIC shr_res_bitmap_handle_t taf_gate_bitmap[SOC_MAX_NUM_DEVICES]; 60 STATIC uint32 taf_gate_refcount[SOC_MAX_NUM_DEVICES][BCMI_TSN_TAF_GATE_NUM]; 61 62 /* 63 * taf gate pri map 64 */ 65 #define TAF_GATE_PRI_MAP_PROFILE_OFFSET (0) 66 #define TAF_GATE_PRI_MAP_PROFILE_WIDTH (7) 67 #define TAF_GATE_PRI_MAP_PROFILE_INVALID_ID (0) 68 #define TAF_GATE_PRI_MAP_PROFILE_NUM (1 << TAF_GATE_PRI_MAP_PROFILE_WIDTH) 69 #define TAF_GATE_PRI_MAP_PROFILE_MASK \ 70 (((1 << TAF_GATE_PRI_MAP_PROFILE_WIDTH) - 1) << \ 71 TAF_GATE_PRI_MAP_PROFILE_OFFSET) 72 #define TAF_GATE_PRI_MAP_INTPRI_OFFSET (7) 73 #define TAF_GATE_PRI_MAP_INTPRI_WIDTH (4) 74 #define TAF_GATE_PRI_MAP_INTPRI_NUM (1 << TAF_GATE_PRI_MAP_INTPRI_WIDTH) 75 #define TAF_GATE_PRI_MAP_INTPRI_MASK \ 76 (((1 << TAF_GATE_PRI_MAP_INTPRI_WIDTH) - 1) << \ 77 TAF_GATE_PRI_MAP_INTPRI_OFFSET) 78 #define TAF_GATE_PRI_MAP_PREEMPT_OFFSET (11) 79 #define TAF_GATE_PRI_MAP_PREEMPT_WIDTH (1) 80 #define TAF_GATE_PRI_MAP_PREEMPT_NUM (1 << TAF_GATE_PRI_MAP_PREEMPT_WIDTH) 81 #define TAF_GATE_PRI_MAP_PREEMPT_MASK \ 82 (((1 << TAF_GATE_PRI_MAP_PREEMPT_WIDTH) - 1) << \ 83 TAF_GATE_PRI_MAP_PREEMPT_OFFSET) 84 STATIC const soc_mem_t taf_gate_pri_map_mem = TAF_GATE_ID_LOOKUPm; 85 86 /* 87 * taf max bytes profile 88 */ 89 #define TAF_MAXBYTE_PROFILE_RESERVED_ID (0) 90 #define TAF_MAXBYTE_PROFILE_NUM (4) 91 STATIC shr_res_bitmap_handle_t taf_maxbyte_profile_bitmap 92 [SOC_MAX_NUM_DEVICES] 93 [BCMI_TSN_TAF_GATE_NUM]; 94 STATIC uint32 taf_maxbyte_profile_refcount[SOC_MAX_NUM_DEVICES] 95 [BCMI_TSN_TAF_GATE_NUM] 96 [TAF_MAXBYTE_PROFILE_NUM]; 97 STATIC const soc_field_t taf_maxbyte_profile_field[TAF_MAXBYTE_PROFILE_NUM] 98 = {TAF_GATE_MAXBYTES_0f, TAF_GATE_MAXBYTES_1f, 99 TAF_GATE_MAXBYTES_2f, TAF_GATE_MAXBYTES_3f}; 100 STATIC const soc_mem_t taf_maxbyte_profile_mem = TAF_GATE_CONTROLm; 101 102 /* 103 * taf CosQ profile 104 */ 105 #define TAF_COSQ_INTPRI_OFFSET (0) 106 #define TAF_COSQ_INTPRI_WIDTH (4) 107 #define TAF_COSQ_INTPRI_NUM (1 << TAF_COSQ_INTPRI_WIDTH) 108 #define TAF_COSQ_INTPRI_MASK \ 109 (((1 << TAF_COSQ_INTPRI_WIDTH) - 1) << \ 110 TAF_COSQ_INTPRI_OFFSET) 111 112 #define TAF_COSQ_SELECT_OFFSET (4) 113 #define TAF_COSQ_SELECT_WIDTH (2) 114 #define TAF_COSQ_SELECT_NUM (1 << TAF_COSQ_SELECT_WIDTH) 115 #define TAF_COSQ_SELECT_MASK \ 116 (((1 << TAF_COSQ_SELECT_WIDTH) - 1) << \ 117 TAF_COSQ_SELECT_OFFSET) 118 119 #define TAF_COSQ_PROFILE_RESERVED_ID (0) 120 #define TAF_COSQ_PROFILE_OFFSET (6) 121 #define TAF_COSQ_PROFILE_WIDTH (4) 122 #define TAF_COSQ_PROFILE_NUM (1 << TAF_COSQ_PROFILE_WIDTH) 123 #define TAF_COSQ_PROFILE_MASK \ 124 (((1 << TAF_COSQ_PROFILE_WIDTH) - 1) << \ 125 TAF_COSQ_PROFILE_OFFSET) 126 127 #define TAF_COSQ_HW_INDEX(_profile_id_, _select_, _prio_) \ 128 (((_profile_id_) << TAF_COSQ_PROFILE_OFFSET) | \ 129 ((_select_) << TAF_COSQ_SELECT_OFFSET) | \ 130 ((_prio_) << TAF_COSQ_INTPRI_OFFSET)) 131 132 STATIC shr_res_bitmap_handle_t taf_cosq_profile_bitmap[SOC_MAX_NUM_DEVICES]; 133 STATIC uint32 taf_cosq_profile_refcount[SOC_MAX_NUM_DEVICES] 134 [TAF_COSQ_PROFILE_NUM]; 135 STATIC const soc_mem_t taf_cosq_profile_mem = PORT_COS_MAPm; 136 STATIC const soc_field_t taf_cosq_profile_field = COSf; 137 138 /* 139 * taf schedule profile 140 */ 141 STATIC shr_res_bitmap_handle_t taf_schedule_profile_bitmap 142 [SOC_MAX_NUM_DEVICES]; 143 STATIC bcmi_tsn_taf_profile_t *taf_schedule_profile 144 [SOC_MAX_NUM_DEVICES] 145 [BCMI_TSN_TAF_PROFILE_NUM_MAX]; 146 147 /* 148 * taf schedule timelime 149 */ 150 #define TAF_SCHEDULE_CALENDAR_ENTIRES (16) /* GCLT table size */ 151 #define TAF_SCHEDULE_HW_RESPONSE_TIME (500000) /* 500000 ns */ 152 #define TAF_SCHEDULE_SW_RESPONSE_TIME (1000000000) /* 1000000000 ns */ 153 #define TAF_SCHEDULE_NANOSEC_MAX (1000000000) /* 10^9 */ 154 155 #define TAF_SCHEDULE_SEC_WIDTH (6) /* GH2 only support 6 bit 156 * second value 157 */ 158 #define TAF_SCHEDULE_SEC_MASK ((1 << TAF_SCHEDULE_SEC_WIDTH) - 1) 159 STATIC bcmi_tsn_taf_schedule_entry_t *taf_schedule_timeline 160 [SOC_MAX_NUM_DEVICES] 161 [BCMI_TSN_TAF_GATE_NUM]; 162 STATIC uint8 *taf_schedule_calendar_buf[SOC_MAX_NUM_DEVICES]; 163 STATIC const soc_mem_t taf_schedule_calendar_mem[2][BCMI_TSN_TAF_GATE_NUM] 164 = {{TAF_GATE_CTL_TBL0_P0m, TAF_GATE_CTL_TBL0_P1m, 165 TAF_GATE_CTL_TBL0_P2m, TAF_GATE_CTL_TBL0_P3m, 166 TAF_GATE_CTL_TBL0_P4m, TAF_GATE_CTL_TBL0_P5m, 167 TAF_GATE_CTL_TBL0_P6m, TAF_GATE_CTL_TBL0_P7m, 168 TAF_GATE_CTL_TBL0_P8m, TAF_GATE_CTL_TBL0_P9m, 169 TAF_GATE_CTL_TBL0_P10m, TAF_GATE_CTL_TBL0_P11m, 170 TAF_GATE_CTL_TBL0_P12m, TAF_GATE_CTL_TBL0_P13m, 171 TAF_GATE_CTL_TBL0_P14m, TAF_GATE_CTL_TBL0_P15m, 172 TAF_GATE_CTL_TBL0_P16m, TAF_GATE_CTL_TBL0_P17m, 173 TAF_GATE_CTL_TBL0_P18m, TAF_GATE_CTL_TBL0_P19m, 174 TAF_GATE_CTL_TBL0_P20m, TAF_GATE_CTL_TBL0_P21m, 175 TAF_GATE_CTL_TBL0_P22m, TAF_GATE_CTL_TBL0_P23m, 176 TAF_GATE_CTL_TBL0_P24m, TAF_GATE_CTL_TBL0_P25m, 177 TAF_GATE_CTL_TBL0_P26m, TAF_GATE_CTL_TBL0_P27m, 178 TAF_GATE_CTL_TBL0_P28m, TAF_GATE_CTL_TBL0_P29m, 179 TAF_GATE_CTL_TBL0_P30m, TAF_GATE_CTL_TBL0_P31m, 180 TAF_GATE_CTL_TBL0_P32m, TAF_GATE_CTL_TBL0_P33m, 181 TAF_GATE_CTL_TBL0_P34m, TAF_GATE_CTL_TBL0_P35m, 182 TAF_GATE_CTL_TBL0_P36m, TAF_GATE_CTL_TBL0_P37m, 183 TAF_GATE_CTL_TBL0_P38m, TAF_GATE_CTL_TBL0_P39m, 184 TAF_GATE_CTL_TBL0_P40m, TAF_GATE_CTL_TBL0_P41m, 185 TAF_GATE_CTL_TBL0_P42m, TAF_GATE_CTL_TBL0_P43m, 186 TAF_GATE_CTL_TBL0_P44m, TAF_GATE_CTL_TBL0_P45m, 187 TAF_GATE_CTL_TBL0_P46m, TAF_GATE_CTL_TBL0_P47m, 188 TAF_GATE_CTL_TBL0_P48m, TAF_GATE_CTL_TBL0_P49m, 189 TAF_GATE_CTL_TBL0_P50m, TAF_GATE_CTL_TBL0_P51m, 190 TAF_GATE_CTL_TBL0_P52m, TAF_GATE_CTL_TBL0_P53m, 191 TAF_GATE_CTL_TBL0_P54m, TAF_GATE_CTL_TBL0_P55m, 192 TAF_GATE_CTL_TBL0_P56m, TAF_GATE_CTL_TBL0_P57m, 193 TAF_GATE_CTL_TBL0_P58m, TAF_GATE_CTL_TBL0_P59m, 194 TAF_GATE_CTL_TBL0_P60m, TAF_GATE_CTL_TBL0_P61m, 195 TAF_GATE_CTL_TBL0_P62m, TAF_GATE_CTL_TBL0_P63m, 196 TAF_GATE_CTL_TBL0_P64m, TAF_GATE_CTL_TBL0_P65m, 197 TAF_GATE_CTL_TBL0_P66m, TAF_GATE_CTL_TBL0_P67m, 198 TAF_GATE_CTL_TBL0_P68m, TAF_GATE_CTL_TBL0_P69m, 199 TAF_GATE_CTL_TBL0_P70m, TAF_GATE_CTL_TBL0_P71m, 200 TAF_GATE_CTL_TBL0_P72m, TAF_GATE_CTL_TBL0_P73m, 201 TAF_GATE_CTL_TBL0_P74m, TAF_GATE_CTL_TBL0_P75m, 202 TAF_GATE_CTL_TBL0_P76m, TAF_GATE_CTL_TBL0_P77m, 203 TAF_GATE_CTL_TBL0_P78m, TAF_GATE_CTL_TBL0_P79m, 204 TAF_GATE_CTL_TBL0_P80m, TAF_GATE_CTL_TBL0_P81m, 205 TAF_GATE_CTL_TBL0_P82m, TAF_GATE_CTL_TBL0_P83m, 206 TAF_GATE_CTL_TBL0_P84m, TAF_GATE_CTL_TBL0_P85m, 207 TAF_GATE_CTL_TBL0_P86m, TAF_GATE_CTL_TBL0_P87m, 208 TAF_GATE_CTL_TBL0_P88m, TAF_GATE_CTL_TBL0_P89m, 209 TAF_GATE_CTL_TBL0_P90m, TAF_GATE_CTL_TBL0_P91m, 210 TAF_GATE_CTL_TBL0_P92m, TAF_GATE_CTL_TBL0_P93m, 211 TAF_GATE_CTL_TBL0_P94m, TAF_GATE_CTL_TBL0_P95m, 212 TAF_GATE_CTL_TBL0_P96m, TAF_GATE_CTL_TBL0_P97m, 213 TAF_GATE_CTL_TBL0_P98m, TAF_GATE_CTL_TBL0_P99m, 214 TAF_GATE_CTL_TBL0_P100m, TAF_GATE_CTL_TBL0_P101m, 215 TAF_GATE_CTL_TBL0_P102m, TAF_GATE_CTL_TBL0_P103m, 216 TAF_GATE_CTL_TBL0_P104m, TAF_GATE_CTL_TBL0_P105m, 217 TAF_GATE_CTL_TBL0_P106m, TAF_GATE_CTL_TBL0_P107m, 218 TAF_GATE_CTL_TBL0_P108m, TAF_GATE_CTL_TBL0_P109m, 219 TAF_GATE_CTL_TBL0_P110m, TAF_GATE_CTL_TBL0_P111m, 220 TAF_GATE_CTL_TBL0_P112m, TAF_GATE_CTL_TBL0_P113m, 221 TAF_GATE_CTL_TBL0_P114m, TAF_GATE_CTL_TBL0_P115m, 222 TAF_GATE_CTL_TBL0_P116m, TAF_GATE_CTL_TBL0_P117m, 223 TAF_GATE_CTL_TBL0_P118m, TAF_GATE_CTL_TBL0_P119m, 224 TAF_GATE_CTL_TBL0_P120m, TAF_GATE_CTL_TBL0_P121m, 225 TAF_GATE_CTL_TBL0_P122m, TAF_GATE_CTL_TBL0_P123m, 226 TAF_GATE_CTL_TBL0_P124m, TAF_GATE_CTL_TBL0_P125m, 227 TAF_GATE_CTL_TBL0_P126m, TAF_GATE_CTL_TBL0_P127m}, 228 {TAF_GATE_CTL_TBL1_P0m, TAF_GATE_CTL_TBL1_P1m, 229 TAF_GATE_CTL_TBL1_P2m, TAF_GATE_CTL_TBL1_P3m, 230 TAF_GATE_CTL_TBL1_P4m, TAF_GATE_CTL_TBL1_P5m, 231 TAF_GATE_CTL_TBL1_P6m, TAF_GATE_CTL_TBL1_P7m, 232 TAF_GATE_CTL_TBL1_P8m, TAF_GATE_CTL_TBL1_P9m, 233 TAF_GATE_CTL_TBL1_P10m, TAF_GATE_CTL_TBL1_P11m, 234 TAF_GATE_CTL_TBL1_P12m, TAF_GATE_CTL_TBL1_P13m, 235 TAF_GATE_CTL_TBL1_P14m, TAF_GATE_CTL_TBL1_P15m, 236 TAF_GATE_CTL_TBL1_P16m, TAF_GATE_CTL_TBL1_P17m, 237 TAF_GATE_CTL_TBL1_P18m, TAF_GATE_CTL_TBL1_P19m, 238 TAF_GATE_CTL_TBL1_P20m, TAF_GATE_CTL_TBL1_P21m, 239 TAF_GATE_CTL_TBL1_P22m, TAF_GATE_CTL_TBL1_P23m, 240 TAF_GATE_CTL_TBL1_P24m, TAF_GATE_CTL_TBL1_P25m, 241 TAF_GATE_CTL_TBL1_P26m, TAF_GATE_CTL_TBL1_P27m, 242 TAF_GATE_CTL_TBL1_P28m, TAF_GATE_CTL_TBL1_P29m, 243 TAF_GATE_CTL_TBL1_P30m, TAF_GATE_CTL_TBL1_P31m, 244 TAF_GATE_CTL_TBL1_P32m, TAF_GATE_CTL_TBL1_P33m, 245 TAF_GATE_CTL_TBL1_P34m, TAF_GATE_CTL_TBL1_P35m, 246 TAF_GATE_CTL_TBL1_P36m, TAF_GATE_CTL_TBL1_P37m, 247 TAF_GATE_CTL_TBL1_P38m, TAF_GATE_CTL_TBL1_P39m, 248 TAF_GATE_CTL_TBL1_P40m, TAF_GATE_CTL_TBL1_P41m, 249 TAF_GATE_CTL_TBL1_P42m, TAF_GATE_CTL_TBL1_P43m, 250 TAF_GATE_CTL_TBL1_P44m, TAF_GATE_CTL_TBL1_P45m, 251 TAF_GATE_CTL_TBL1_P46m, TAF_GATE_CTL_TBL1_P47m, 252 TAF_GATE_CTL_TBL1_P48m, TAF_GATE_CTL_TBL1_P49m, 253 TAF_GATE_CTL_TBL1_P50m, TAF_GATE_CTL_TBL1_P51m, 254 TAF_GATE_CTL_TBL1_P52m, TAF_GATE_CTL_TBL1_P53m, 255 TAF_GATE_CTL_TBL1_P54m, TAF_GATE_CTL_TBL1_P55m, 256 TAF_GATE_CTL_TBL1_P56m, TAF_GATE_CTL_TBL1_P57m, 257 TAF_GATE_CTL_TBL1_P58m, TAF_GATE_CTL_TBL1_P59m, 258 TAF_GATE_CTL_TBL1_P60m, TAF_GATE_CTL_TBL1_P61m, 259 TAF_GATE_CTL_TBL1_P62m, TAF_GATE_CTL_TBL1_P63m, 260 TAF_GATE_CTL_TBL1_P64m, TAF_GATE_CTL_TBL1_P65m, 261 TAF_GATE_CTL_TBL1_P66m, TAF_GATE_CTL_TBL1_P67m, 262 TAF_GATE_CTL_TBL1_P68m, TAF_GATE_CTL_TBL1_P69m, 263 TAF_GATE_CTL_TBL1_P70m, TAF_GATE_CTL_TBL1_P71m, 264 TAF_GATE_CTL_TBL1_P72m, TAF_GATE_CTL_TBL1_P73m, 265 TAF_GATE_CTL_TBL1_P74m, TAF_GATE_CTL_TBL1_P75m, 266 TAF_GATE_CTL_TBL1_P76m, TAF_GATE_CTL_TBL1_P77m, 267 TAF_GATE_CTL_TBL1_P78m, TAF_GATE_CTL_TBL1_P79m, 268 TAF_GATE_CTL_TBL1_P80m, TAF_GATE_CTL_TBL1_P81m, 269 TAF_GATE_CTL_TBL1_P82m, TAF_GATE_CTL_TBL1_P83m, 270 TAF_GATE_CTL_TBL1_P84m, TAF_GATE_CTL_TBL1_P85m, 271 TAF_GATE_CTL_TBL1_P86m, TAF_GATE_CTL_TBL1_P87m, 272 TAF_GATE_CTL_TBL1_P88m, TAF_GATE_CTL_TBL1_P89m, 273 TAF_GATE_CTL_TBL1_P90m, TAF_GATE_CTL_TBL1_P91m, 274 TAF_GATE_CTL_TBL1_P92m, TAF_GATE_CTL_TBL1_P93m, 275 TAF_GATE_CTL_TBL1_P94m, TAF_GATE_CTL_TBL1_P95m, 276 TAF_GATE_CTL_TBL1_P96m, TAF_GATE_CTL_TBL1_P97m, 277 TAF_GATE_CTL_TBL1_P98m, TAF_GATE_CTL_TBL1_P99m, 278 TAF_GATE_CTL_TBL1_P100m, TAF_GATE_CTL_TBL1_P101m, 279 TAF_GATE_CTL_TBL1_P102m, TAF_GATE_CTL_TBL1_P103m, 280 TAF_GATE_CTL_TBL1_P104m, TAF_GATE_CTL_TBL1_P105m, 281 TAF_GATE_CTL_TBL1_P106m, TAF_GATE_CTL_TBL1_P107m, 282 TAF_GATE_CTL_TBL1_P108m, TAF_GATE_CTL_TBL1_P109m, 283 TAF_GATE_CTL_TBL1_P110m, TAF_GATE_CTL_TBL1_P111m, 284 TAF_GATE_CTL_TBL1_P112m, TAF_GATE_CTL_TBL1_P113m, 285 TAF_GATE_CTL_TBL1_P114m, TAF_GATE_CTL_TBL1_P115m, 286 TAF_GATE_CTL_TBL1_P116m, TAF_GATE_CTL_TBL1_P117m, 287 TAF_GATE_CTL_TBL1_P118m, TAF_GATE_CTL_TBL1_P119m, 288 TAF_GATE_CTL_TBL1_P120m, TAF_GATE_CTL_TBL1_P121m, 289 TAF_GATE_CTL_TBL1_P122m, TAF_GATE_CTL_TBL1_P123m, 290 TAF_GATE_CTL_TBL1_P124m, TAF_GATE_CTL_TBL1_P125m, 291 TAF_GATE_CTL_TBL1_P126m, TAF_GATE_CTL_TBL1_P127m}}; 292 STATIC const soc_reg_t taf_reg_base_sec[2] = {TAF_BASE_TIME_SEC_0r, 293 TAF_BASE_TIME_SEC_1r}; 294 STATIC const soc_reg_t taf_reg_base_frac[2] = {TAF_BASE_TIME_FRAC_0r, 295 TAF_BASE_TIME_FRAC_1r}; 296 STATIC const soc_reg_t taf_reg_cycle[2] = {TAF_CYCLE_TIME_0r, 297 TAF_CYCLE_TIME_1r}; 298 STATIC const soc_reg_t taf_reg_ext[2] = {TAF_CYCLE_TIME_EXTENSION_0r, 299 TAF_CYCLE_TIME_EXTENSION_1r}; 300 301 /* 302 * taf event handler 303 */ 304 STATIC bcmi_tsn_taf_event_handler_t *taf_event_handler_list 305 [SOC_MAX_NUM_DEVICES] 306 [BCMI_TSN_TAF_GATE_NUM] 307 [bcmTsnTafEventCount]; 308 309 /* 310 * taf hw interrupt info 311 */ 312 #define TAF_INTERRUPT_SUB_FIELD_WIDTH (32) 313 #define TAF_INTERRUPT_SUB_FIELD_NUM \ 314 ((BCMI_TSN_TAF_GATE_NUM + TAF_INTERRUPT_SUB_FIELD_WIDTH - 1)\ 315 / TAF_INTERRUPT_SUB_FIELD_WIDTH) /* ceiling of (128/32) = 4 */ 316 317 typedef enum gh2_taf_interrupt_type_e { 318 TafInterruptSwitchDone = 0, 319 TafInterruptTodWindow = 1, 320 TafInterruptNextCycleTimeError = 2, 321 TafInterruptBaseTimeError = 3, 322 TafInterruptParityError = 4, 323 TafInterruptTblPtrError = 5, 324 TafInterruptCount = 6 325 } gh2_taf_interrupt_type_t; 326 327 typedef struct gh2_taf_interrupt_mapping_s { 328 /* mask field of MEMFAILINTMASKr */ 329 soc_field_t mask_field; 330 /* status field of MEMFAILINTSTATUSr */ 331 soc_field_t status_field; 332 /* clear field of MEMFAILINT_CLRr */ 333 soc_field_t clear_field; 334 /* sub status registers to indicate individual status */ 335 soc_reg_t sub_status_regs[TAF_INTERRUPT_SUB_FIELD_NUM]; 336 /* sub clear registers to clear individual status */ 337 soc_reg_t sub_clear_regs[TAF_INTERRUPT_SUB_FIELD_NUM]; 338 } gh2_taf_interrupt_mapping_t; 339 340 STATIC const 341 gh2_taf_interrupt_mapping_t taf_interrupt_mapping[TafInterruptCount] = { 342 {TAF_TBL_SWITCH_DONE_INTMASKf, 343 TAF_TBL_SWITCH_DONEf, 344 TAF_TBL_SWITCH_DONE_CLRf, 345 {TAF_TBL_SWITCH_DONE_0r, TAF_TBL_SWITCH_DONE_1r, 346 TAF_TBL_SWITCH_DONE_2r, TAF_TBL_SWITCH_DONE_3r}, 347 {TAF_TBL_SWITCH_DONE_CLR_0r, TAF_TBL_SWITCH_DONE_CLR_1r, 348 TAF_TBL_SWITCH_DONE_CLR_2r, TAF_TBL_SWITCH_DONE_CLR_3r}, 349 }, 350 {TAF_TOD_WINDOW_INTERRUPT_INTMASKf, 351 TAF_TOD_WINDOW_INTERRUPTf, 352 TAF_TOD_WINDOW_INTERRUPT_CLRf, 353 {INVALIDr}, 354 {INVALIDr}, 355 }, 356 {TAF_SET_NEXT_CYCLE_TIME_ERROR_INTMASKf, 357 TAF_SET_NEXT_CYCLE_TIME_ERRORf, 358 TAF_SET_NEXT_CYCLE_TIME_ERROR_CLRf, 359 {TAF_SET_NEXT_CYCLE_TIME_ERROR_0r, TAF_SET_NEXT_CYCLE_TIME_ERROR_1r, 360 TAF_SET_NEXT_CYCLE_TIME_ERROR_2r, TAF_SET_NEXT_CYCLE_TIME_ERROR_3r}, 361 {TAF_SET_NEXT_CYCLE_TIME_ERROR_CLR_0r, 362 TAF_SET_NEXT_CYCLE_TIME_ERROR_CLR_1r, 363 TAF_SET_NEXT_CYCLE_TIME_ERROR_CLR_2r, 364 TAF_SET_NEXT_CYCLE_TIME_ERROR_CLR_3r}, 365 }, 366 {TAF_SET_BASE_TIME_ERROR_INTMASKf, 367 TAF_SET_BASE_TIME_ERRORf, 368 TAF_SET_BASE_TIME_ERROR_CLRf, 369 {TAF_SET_BASE_TIME_ERROR_0r, TAF_SET_BASE_TIME_ERROR_1r, 370 TAF_SET_BASE_TIME_ERROR_2r, TAF_SET_BASE_TIME_ERROR_3r}, 371 {TAF_SET_BASE_TIME_ERROR_CLR_0r, TAF_SET_BASE_TIME_ERROR_CLR_1r, 372 TAF_SET_BASE_TIME_ERROR_CLR_2r, TAF_SET_BASE_TIME_ERROR_CLR_3r} 373 }, 374 {TAF_PARITY_ERR_INTMASKf, 375 TAF_PARITY_ERRf, 376 TAF_PARITY_ERR_CLRf, 377 {TAF_PARITY_ERR_VLD_0r, TAF_PARITY_ERR_VLD_1r, 378 TAF_PARITY_ERR_VLD_2r, TAF_PARITY_ERR_VLD_3r}, 379 {TAF_PARITY_ERR_CLR_0r, TAF_PARITY_ERR_CLR_1r, 380 TAF_PARITY_ERR_CLR_2r, TAF_PARITY_ERR_CLR_3r} 381 }, 382 {TAF_CTL_TBL_PTR_ERR_INTMASKf, 383 TAF_CTL_TBL_PTR_ERRf, 384 TAF_CTL_TBL_PTR_ERR_CLRf, 385 {TAF_CTL_TBL_PTR_ERR_0r, TAF_CTL_TBL_PTR_ERR_1r, 386 TAF_CTL_TBL_PTR_ERR_2r, TAF_CTL_TBL_PTR_ERR_3r}, 387 {TAF_CTL_TBL_PTR_ERR_CLR_0r, TAF_CTL_TBL_PTR_ERR_CLR_1r, 388 TAF_CTL_TBL_PTR_ERR_CLR_2r, TAF_CTL_TBL_PTR_ERR_CLR_3r} 389 } 390 }; 391 392 STATIC uint32 taf_interrupt_handling[SOC_MAX_NUM_DEVICES] = {0}; 393 STATIC uint32 taf_interrupt_status[SOC_MAX_NUM_DEVICES]; 394 STATIC uint32 taf_interrupt_substatus[SOC_MAX_NUM_DEVICES] 395 [TafInterruptCount] 396 [TAF_INTERRUPT_SUB_FIELD_NUM]; 397 398 /* TSN TAF Gate stat table contents for GH2 */ 399 STATIC const soc_mem_t taf_gate_cnt_mem[bcmTsnTafGateStatCount] = 400 {TAF_GATE_PASSED_PACKET_COUNTERm, 401 TAF_GATE_DROP_PACKET_COUNTERm}; 402 STATIC const soc_mem_t taf_gate_cnt_field[bcmTsnTafGateStatCount] = 403 {TAF_GATE_PASSED_PKTf, TAF_GATE_DROP_PKTf}; 404 405 /* sw database for taf gate counter */ 406 STATIC uint64 *taf_gate_counter[SOC_MAX_NUM_DEVICES][bcmTsnTafGateStatCount]; 407 STATIC uint8 *taf_gate_counter_dma_buffer[SOC_MAX_NUM_DEVICES] 408 [bcmTsnTafGateStatCount]; 409 410 411 /* 412 * helper macro 413 */ 414 #define ERROR_RETURN_WITH_EXTRA_CLEAN(_op_, _extra_clean_) \ 415 do { \ 416 int _rv_ = (_op_); \ 417 if (BCM_FAILURE(_rv_)) { \ 418 (_extra_clean_); \ 419 return (_rv_); \ 420 } \ 421 } while (0) 422 423 #define TAF_INIT_ERROR_RETURN_WITH_CLEAN(_op_) \ 424 ERROR_RETURN_WITH_EXTRA_CLEAN((_op_), bcmi_gh2_taf_cleanup(unit)) 425 426 /* allocate TAF gate */ 427 STATIC int 428 bcmi_gh2_taf_gate_create(int unit, int flags, int *taf_gate_id) 429 { 430 uint32 shr_flags = 0; 431 432 if (NULL == taf_gate_id) { 433 return BCM_E_PARAM; 434 } 435 436 if (flags & BCM_TSN_TAF_WITH_ID) { 437 shr_flags = SHR_RES_BITMAP_ALLOC_WITH_ID; 438 } 439 440 BCM_IF_ERROR_RETURN( 441 shr_res_bitmap_alloc(taf_gate_bitmap[unit], shr_flags, 442 1, (int *)taf_gate_id)); 443 444 if (*taf_gate_id < 0 || *taf_gate_id >= BCMI_TSN_TAF_GATE_NUM || 445 *taf_gate_id == TAF_GATE_RESERVED_ID) { 446 return BCM_E_INTERNAL; 447 } 448 taf_gate_refcount[unit][*taf_gate_id] = 1; 449 450 return BCM_E_NONE; 451 } 452 453 /* traverse TAF gate */ 454 STATIC int 455 bcmi_gh2_taf_gate_traverse( 456 int unit, 457 bcm_tsn_taf_gate_traverse_cb cb, 458 void *user_data) 459 { 460 int taf_gate_id; 461 462 if (NULL == cb) { 463 return BCM_E_PARAM; 464 } 465 466 for (taf_gate_id = 0; taf_gate_id < BCMI_TSN_TAF_GATE_NUM; taf_gate_id++) { 467 if (TAF_GATE_RESERVED_ID == taf_gate_id) { 468 continue; 469 } 470 if (0 == taf_gate_refcount[unit][taf_gate_id]) { 471 continue; 472 } 473 BCM_IF_ERROR_RETURN(cb(unit, taf_gate_id, user_data)); 474 } 475 476 return BCM_E_NONE; 477 } 478 479 /* free TAF gate */ 480 STATIC int 481 bcmi_gh2_taf_gate_destroy(int unit, int taf_gate_id) 482 { 483 assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM); 484 485 if (taf_gate_refcount[unit][taf_gate_id] == 0) { 486 return BCM_E_NOT_FOUND; 487 } else if (taf_gate_refcount[unit][taf_gate_id] > 1) { 488 return BCM_E_BUSY; 489 } 490 491 BCM_IF_ERROR_RETURN( 492 shr_res_bitmap_free(taf_gate_bitmap[unit], 1, taf_gate_id)); 493 taf_gate_refcount[unit][taf_gate_id] = 0; 494 495 return BCM_E_NONE; 496 } 497 498 /* taf gate id valid check */ 499 STATIC int 500 bcmi_gh2_taf_gate_check( 501 int unit, 502 int taf_gate_id) 503 { 504 if (taf_gate_id < 0 || 505 taf_gate_id == TAF_GATE_RESERVED_ID || 506 taf_gate_id >= BCMI_TSN_TAF_GATE_NUM) { 507 return BCM_E_PARAM; 508 } 509 510 if (taf_gate_refcount[unit][taf_gate_id] == 0) { 511 return BCM_E_NOT_FOUND; 512 } 513 514 return BCM_E_NONE; 515 } 516 517 /* get current time */ 518 STATIC int 519 bcmi_gh2_taf_ptp_time_get( 520 int unit, 521 bcm_ptp_timestamp_t *ret_time) 522 { 523 if (NULL == ret_time) { 524 return BCM_E_PARAM; 525 } 526 527 #if defined(INCLUDE_PTP) 528 if (soc_feature(unit, soc_feature_ptp) || 529 soc_feature(unit, soc_feature_use_local_1588)) { 530 return bcm_esw_ptp_clock_time_get(unit, 0, 0, ret_time); 531 } 532 #endif /* INCLUDE_PTP */ 533 534 return BCM_E_UNAVAIL; 535 } 536 537 /* check if ptp_time_1 > ptp_time_2 538 * note. for speed, caller need to ensure that these pointer are not NULL 539 */ 540 STATIC INLINE int 541 bcmi_gh2_taf_ptp_time_gt( 542 bcm_ptp_timestamp_t *ptp_time_1, 543 bcm_ptp_timestamp_t *ptp_time_2) 544 { 545 if (COMPILER_64_GT(ptp_time_1->seconds, ptp_time_2->seconds)) { 546 return TRUE; 547 } else if (COMPILER_64_EQ(ptp_time_1->seconds, ptp_time_2->seconds)) { 548 if (ptp_time_1->nanoseconds > ptp_time_2->nanoseconds) { 549 return TRUE; 550 } 551 } 552 return FALSE; 553 } 554 555 /* check if ptp_time_1 >= ptp_time_2 556 * note. for speed, caller need to ensure that these pointer are not NULL 557 */ 558 STATIC INLINE int 559 bcmi_gh2_taf_ptp_time_ge( 560 bcm_ptp_timestamp_t *ptp_time_1, 561 bcm_ptp_timestamp_t *ptp_time_2) 562 { 563 if (COMPILER_64_GT(ptp_time_1->seconds, ptp_time_2->seconds)) { 564 return TRUE; 565 } else if (COMPILER_64_EQ(ptp_time_1->seconds, ptp_time_2->seconds)) { 566 if (ptp_time_1->nanoseconds >= ptp_time_2->nanoseconds) { 567 return TRUE; 568 } 569 } 570 return FALSE; 571 } 572 573 /* assign ptp_time_dst as ptp_time_src 574 * note. for speed, caller need to ensure that these pointer are not NULL 575 */ 576 STATIC INLINE void 577 bcmi_gh2_taf_ptp_time_assign( 578 bcm_ptp_timestamp_t *ptp_time_dst, 579 bcm_ptp_timestamp_t *ptp_time_src) 580 { 581 COMPILER_64_COPY(ptp_time_dst->seconds, ptp_time_src->seconds); 582 ptp_time_dst->nanoseconds = ptp_time_src->nanoseconds; 583 } 584 585 /* ptp_time_dst = ptp_time_dst + time_diff(ns) 586 * note. for speed, caller need to ensure that these pointer are not NULL 587 */ 588 STATIC INLINE void 589 bcmi_gh2_taf_ptp_time_add( 590 bcm_ptp_timestamp_t *ptp_time_dst, 591 uint32 time_diff) 592 { 593 ptp_time_dst->nanoseconds += time_diff; 594 if (ptp_time_dst->nanoseconds >= TAF_SCHEDULE_NANOSEC_MAX) { 595 ptp_time_dst->nanoseconds -= TAF_SCHEDULE_NANOSEC_MAX; 596 COMPILER_64_ADD_32(ptp_time_dst->seconds, 1); 597 } 598 } 599 600 /* ptp_time_dst = ptp_time_dst - time_diff(ns) 601 * note. for speed, caller need to ensure that these pointer are not NULL 602 */ 603 STATIC INLINE void 604 bcmi_gh2_taf_ptp_time_sub( 605 bcm_ptp_timestamp_t *ptp_time_dst, 606 uint32 time_diff) 607 { 608 if (ptp_time_dst->nanoseconds >= time_diff) { 609 ptp_time_dst->nanoseconds -= time_diff; 610 } else { 611 ptp_time_dst->nanoseconds += TAF_SCHEDULE_NANOSEC_MAX; 612 ptp_time_dst->nanoseconds -= time_diff; 613 COMPILER_64_SUB_32(ptp_time_dst->seconds, 1); 614 } 615 } 616 617 /* return the ToD (Time of Day) index of the ptp time 618 * note. for speed, caller need to ensure that these pointer are not NULL 619 */ 620 STATIC INLINE void 621 bcmi_gh2_taf_ptp_time_to_tod( 622 bcm_ptp_timestamp_t *ptp_time, uint64 *ret_tod) 623 { 624 /* In GH2, ToD is a 64sec window 625 * ToD 0 : 0 ~ 64sec 626 * ToD 1 : 64 ~ 128sec 627 * .... 628 */ 629 COMPILER_64_COPY(*ret_tod, ptp_time->seconds); 630 COMPILER_64_SHR(*ret_tod, TAF_SCHEDULE_SEC_WIDTH); /* >> 6 */ 631 } 632 633 /* return ptp time of the specfic ToD 634 * note. for speed, caller need to ensure that these pointer are not NULL 635 */ 636 STATIC INLINE void 637 bcmi_gh2_taf_ptp_time_from_tod( 638 uint64 *tod, bcm_ptp_timestamp_t *ret_ptp_time) 639 { 640 ret_ptp_time->nanoseconds = 0; 641 COMPILER_64_COPY(ret_ptp_time->seconds, *tod); 642 COMPILER_64_SHL(ret_ptp_time->seconds, TAF_SCHEDULE_SEC_WIDTH); /* << 6 */ 643 } 644 645 646 647 STATIC int 648 bcmi_gh2_taf_event_register( 649 int unit, 650 int taf_gate, 651 bcm_tsn_taf_event_types_t event_types, 652 bcm_tsn_taf_event_cb cb, 653 void *user_data) 654 { 655 bcm_tsn_taf_event_type_t event_iter; 656 657 if (NULL == cb) { 658 return BCM_E_PARAM; 659 } 660 661 assert(taf_gate >= 0 && taf_gate < BCMI_TSN_TAF_GATE_NUM); 662 663 /* duplicate check */ 664 SHR_BIT_ITER(event_types.w, bcmTsnTafEventCount, event_iter) { 665 bcmi_tsn_taf_event_handler_t *event_handler_iter; 666 667 event_handler_iter = taf_event_handler_list[unit][taf_gate][event_iter]; 668 while (NULL != event_handler_iter) { 669 if (event_handler_iter->cb == cb) { 670 break; 671 } 672 event_handler_iter = event_handler_iter->next; 673 } 674 if (NULL != event_handler_iter) { 675 return BCM_E_EXISTS; 676 } 677 } 678 679 /* insert new event handler at the tail */ 680 SHR_BIT_ITER(event_types.w, bcmTsnTafEventCount, event_iter) { 681 bcmi_tsn_taf_event_handler_t *event_handler_iter; 682 bcmi_tsn_taf_event_handler_t *event_handler_new; 683 684 event_handler_new = sal_alloc(sizeof(bcmi_tsn_taf_event_handler_t), 685 "TAF event handler entry"); 686 if (NULL == event_handler_new) { 687 return BCM_E_MEMORY; 688 } 689 event_handler_new->cb = cb; 690 event_handler_new->user_data = user_data; 691 event_handler_new->next = NULL; 692 693 if (NULL == taf_event_handler_list[unit][taf_gate][event_iter]) { 694 taf_event_handler_list 695 [unit][taf_gate][event_iter] = event_handler_new; 696 } else { 697 event_handler_iter = taf_event_handler_list 698 [unit][taf_gate][event_iter]; 699 while (NULL != event_handler_iter->next) { 700 event_handler_iter = event_handler_iter->next; 701 } 702 event_handler_iter->next = event_handler_new; 703 } 704 } 705 706 return BCM_E_NONE; 707 } 708 709 STATIC int 710 bcmi_gh2_taf_event_unregister( 711 int unit, 712 int taf_gate, 713 bcm_tsn_taf_event_types_t event_types, 714 bcm_tsn_taf_event_cb cb) 715 { 716 bcm_tsn_taf_event_type_t event_iter; 717 int found = 0; 718 719 if (NULL == cb) { 720 return BCM_E_PARAM; 721 } 722 723 assert(taf_gate >= 0 && taf_gate < BCMI_TSN_TAF_GATE_NUM); 724 725 SHR_BIT_ITER(event_types.w, bcmTsnTafEventCount, event_iter) { 726 bcmi_tsn_taf_event_handler_t *event_handler_iter; 727 bcmi_tsn_taf_event_handler_t *event_handler_prev; 728 729 event_handler_prev = NULL; 730 event_handler_iter = taf_event_handler_list[unit][taf_gate][event_iter]; 731 while (NULL != event_handler_iter) { 732 if (event_handler_iter->cb == cb) { 733 break; 734 } 735 event_handler_prev = event_handler_iter; 736 event_handler_iter = event_handler_iter->next; 737 } 738 if (NULL != event_handler_iter) { 739 if (event_handler_iter == taf_event_handler_list 740 [unit][taf_gate][event_iter]) { 741 taf_event_handler_list 742 [unit][taf_gate][event_iter] = event_handler_iter->next; 743 sal_free(event_handler_iter); 744 } else { 745 event_handler_prev->next = event_handler_iter->next; 746 sal_free(event_handler_iter); 747 } 748 found = 1; 749 } 750 } 751 if (1 == found) { 752 return BCM_E_NONE; 753 } else { 754 return BCM_E_NOT_FOUND; 755 } 756 } 757 758 STATIC int 759 bcmi_gh2_taf_event_notify( 760 int unit, 761 int taf_gate, 762 bcm_tsn_taf_event_type_t event_type) 763 { 764 bcmi_tsn_taf_event_handler_t *event_handler_iter; 765 766 if (event_type < 0 || event_type >= bcmTsnTafEventCount) { 767 return BCM_E_PARAM; 768 } 769 assert(taf_gate >= 0 && taf_gate < BCMI_TSN_TAF_GATE_NUM); 770 771 event_handler_iter = taf_event_handler_list[unit][taf_gate][event_type]; 772 while (NULL != event_handler_iter) { 773 BCM_IF_ERROR_RETURN( 774 event_handler_iter->cb(unit, event_type, taf_gate, 775 event_handler_iter->user_data)); 776 event_handler_iter = event_handler_iter->next; 777 } 778 return BCM_E_NONE; 779 } 780 781 /* get taf gate status */ 782 STATIC int 783 bcmi_gh2_taf_gate_status_get( 784 int unit, 785 int taf_gate_id, 786 bcm_tsn_taf_status_t type, 787 uint32 *arg) 788 { 789 uint32 regval; 790 taf_gate_bytes_left_entry_t mem_entry; 791 792 if (NULL == arg) { 793 return BCM_E_PARAM; 794 } 795 796 BCM_IF_ERROR_RETURN( 797 soc_reg32_get(unit, TAF_GSG_STATUSr, REG_PORT_ANY, 798 taf_gate_id, ®val)); 799 800 switch (type) { 801 case bcmTsnTafStatusGateState: 802 *arg = soc_reg_field_get(unit, TAF_GSG_STATUSr, 803 regval, TAF_GATE_STATEf); 804 break; 805 case bcmTsnTafStatusGateStateSet: 806 *arg = soc_reg_field_get(unit, TAF_GSG_STATUSr, 807 regval, GATE_STATE_SELECTf); 808 break; 809 case bcmTsnTafStatusGateCosProfile: 810 *arg = soc_reg_field_get(unit, TAF_GSG_STATUSr, 811 regval, TAF_COS_PROFILEf); 812 break; 813 case bcmTsnTafStatusGateMaxBytesProfile: 814 *arg = soc_reg_field_get(unit, TAF_GSG_STATUSr, 815 regval, TAF_MAXBYTES_SELECTf); 816 break; 817 case bcmTsnTafStatusTickGranularity: 818 *arg = TAF_GCLT_TICKS; 819 break; 820 case bcmTsnTafStatusMaxCalendarEntries: 821 *arg = TAF_SCHEDULE_CALENDAR_ENTIRES; 822 break; 823 case bcmTsnTafStatusGatMaxBytesLeft: 824 SOC_IF_ERROR_RETURN( 825 soc_mem_read(unit, TAF_GATE_BYTES_LEFTm, MEM_BLOCK_ANY, 826 taf_gate_id, &mem_entry)); 827 828 *arg = soc_mem_field32_get(unit, TAF_GATE_BYTES_LEFTm, &mem_entry, 829 GATE_BYTES_LEFTf); 830 break; 831 default: 832 return BCM_E_PARAM; 833 } 834 835 return BCM_E_NONE; 836 } 837 838 /* taf port control set */ 839 STATIC int 840 bcmi_gh2_taf_port_control_set( 841 int unit, 842 bcm_gport_t gport, 843 bcm_tsn_control_t type, 844 uint32 arg) 845 { 846 bcm_port_t port; 847 848 BCM_IF_ERROR_RETURN( 849 _bcm_esw_port_gport_validate(unit, gport, &port)); 850 851 switch (type) { 852 case bcmTsnControlTafEnable: 853 SOC_IF_ERROR_RETURN( 854 soc_mem_field32_modify(unit, PORT_TABm, port, 855 TAF_ENABLEf, arg)); 856 break; 857 case bcmTsnControlTafGatePriMap: 858 SOC_IF_ERROR_RETURN( 859 soc_mem_field32_modify(unit, PORT_TABm, port, 860 TAF_GATE_ID_PROFILEf, arg)); 861 break; 862 case bcmTsnControlTafGatePriMapL2Select: 863 SOC_IF_ERROR_RETURN( 864 soc_mem_field32_modify(unit, PORT_TABm, port, 865 L2_ENTRY_GATE_ID_SELECTf, arg)); 866 break; 867 default: 868 return BCM_E_UNAVAIL; 869 } 870 return BCM_E_NONE; 871 } 872 873 /* taf port control get */ 874 STATIC int 875 bcmi_gh2_taf_port_control_get( 876 int unit, 877 bcm_gport_t gport, 878 bcm_tsn_control_t type, 879 uint32 *arg) 880 { 881 bcm_port_t port; 882 port_tab_entry_t entry; 883 884 if (NULL == arg) { 885 return BCM_E_PARAM; 886 } 887 888 BCM_IF_ERROR_RETURN( 889 _bcm_esw_port_gport_validate(unit, gport, &port)); 890 891 SOC_IF_ERROR_RETURN( 892 soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &entry)); 893 894 switch (type) { 895 case bcmTsnControlTafEnable: 896 *arg = soc_mem_field32_get(unit, PORT_TABm, &entry, 897 TAF_ENABLEf); 898 break; 899 case bcmTsnControlTafGatePriMap: 900 *arg = soc_mem_field32_get(unit, PORT_TABm, &entry, 901 TAF_GATE_ID_PROFILEf); 902 break; 903 case bcmTsnControlTafGatePriMapL2Select: 904 *arg = soc_mem_field32_get(unit, PORT_TABm, &entry, 905 L2_ENTRY_GATE_ID_SELECTf); 906 break; 907 default: 908 return BCM_E_UNAVAIL; 909 } 910 return BCM_E_NONE; 911 } 912 913 914 /* taf gate control set */ 915 STATIC int 916 bcmi_gh2_taf_gate_control_set( 917 int unit, 918 int taf_gate_id, 919 bcm_tsn_taf_control_t type, 920 uint32 arg) 921 { 922 uint32 regval; 923 uint32 field_value; 924 925 switch (type) { 926 case bcmTsnTafControlEnable: 927 BCM_IF_ERROR_RETURN( 928 soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY, 929 taf_gate_id, ®val)); 930 soc_reg_field_set(unit, TAF_CONFIG_0r, ®val, 931 GATE_ENABLEDf, arg); 932 BCM_IF_ERROR_RETURN( 933 soc_reg32_set(unit, TAF_CONFIG_0r, REG_PORT_ANY, 934 taf_gate_id, regval)); 935 break; 936 case bcmTsnTafControlUsePTPTime: 937 BCM_IF_ERROR_RETURN( 938 soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY, 939 taf_gate_id, ®val)); 940 soc_reg_field_set(unit, TAF_CONFIG_0r, ®val, 941 PTP_ACTIVEf, arg); 942 BCM_IF_ERROR_RETURN( 943 soc_reg32_set(unit, TAF_CONFIG_0r, REG_PORT_ANY, 944 taf_gate_id, regval)); 945 break; 946 case bcmTsnTafControlInitGateState: 947 BCM_IF_ERROR_RETURN( 948 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY, 949 taf_gate_id, ®val)); 950 soc_reg_field_set(unit, TAF_CONFIG_2r, ®val, 951 INIT_TAF_GATE_STATEf, arg); 952 BCM_IF_ERROR_RETURN( 953 soc_reg32_set(unit, TAF_CONFIG_2r, REG_PORT_ANY, 954 taf_gate_id, regval)); 955 break; 956 case bcmTsnTafControlInitCosProfile: 957 BCM_IF_ERROR_RETURN( 958 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY, 959 taf_gate_id, ®val)); 960 soc_reg_field_set(unit, TAF_CONFIG_2r, ®val, 961 INIT_TAF_COS_PROFILEf, arg); 962 BCM_IF_ERROR_RETURN( 963 soc_reg32_set(unit, TAF_CONFIG_2r, REG_PORT_ANY, 964 taf_gate_id, regval)); 965 break; 966 case bcmTsnTafControlInitMaxBytesProfile: 967 BCM_IF_ERROR_RETURN( 968 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY, 969 taf_gate_id, ®val)); 970 soc_reg_field_set(unit, TAF_CONFIG_2r, ®val, 971 INIT_TAF_MAXBYTES_SELECTf, arg); 972 BCM_IF_ERROR_RETURN( 973 soc_reg32_set(unit, TAF_CONFIG_2r, REG_PORT_ANY, 974 taf_gate_id, regval)); 975 break; 976 case bcmTsnTafControlErrGateState: 977 BCM_IF_ERROR_RETURN( 978 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY, 979 taf_gate_id, ®val)); 980 soc_reg_field_set(unit, TAF_CONFIG_2r, ®val, 981 ERR_TAF_GATE_STATEf, arg); 982 BCM_IF_ERROR_RETURN( 983 soc_reg32_set(unit, TAF_CONFIG_2r, REG_PORT_ANY, 984 taf_gate_id, regval)); 985 break; 986 case bcmTsnTafControlErrCosProfile: 987 BCM_IF_ERROR_RETURN( 988 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY, 989 taf_gate_id, ®val)); 990 soc_reg_field_set(unit, TAF_CONFIG_2r, ®val, 991 ERR_TAF_COS_PROFILEf, arg); 992 BCM_IF_ERROR_RETURN( 993 soc_reg32_set(unit, TAF_CONFIG_2r, REG_PORT_ANY, 994 taf_gate_id, regval)); 995 break; 996 case bcmTsnTafControlErrMaxByteProfile: 997 BCM_IF_ERROR_RETURN( 998 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY, 999 taf_gate_id, ®val)); 1000 soc_reg_field_set(unit, TAF_CONFIG_2r, ®val, 1001 ERR_TAF_MAXBYTES_SELECTf, arg); 1002 BCM_IF_ERROR_RETURN( 1003 soc_reg32_set(unit, TAF_CONFIG_2r, REG_PORT_ANY, 1004 taf_gate_id, regval)); 1005 break; 1006 case bcmTsnTafControlGateCloseControl: 1007 BCM_IF_ERROR_RETURN( 1008 soc_mem_field32_modify(unit, TAF_GATE_CONTROLm, taf_gate_id, 1009 TAF_GATE_CLOSE_CONTROLf, arg)); 1010 break; 1011 case bcmTsnTafControlBytesLeftCheckEnable: 1012 BCM_IF_ERROR_RETURN( 1013 soc_mem_field32_modify(unit, TAF_GATE_CONTROLm, taf_gate_id, 1014 TAF_MAXBYTE_CHECK_ENABLEf, arg)); 1015 break; 1016 case bcmTsnTafControlGateControlTickInterval: 1017 /* From Arch document, period should be STATIC config and 1018 * not allowed to be changed when TAF is enabled. 1019 */ 1020 BCM_IF_ERROR_RETURN( 1021 soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY, 1022 taf_gate_id, ®val)); 1023 if (soc_reg_field_get(unit, TAF_CONFIG_0r, regval, GATE_ENABLEDf)) { 1024 LOG_ERROR(BSL_LS_BCM_TSN, 1025 (BSL_META("Tick Interval is not allowed " 1026 "to be changed when TAF is enabled.\n"))); 1027 return BCM_E_BUSY; 1028 } 1029 1030 /* Clock Period = (field_value + 1) * 8 nsec */ 1031 if (arg % TAF_GCLT_TICKS != 0) { 1032 return BCM_E_PARAM; 1033 } 1034 field_value = (arg / TAF_GCLT_TICKS) - 1; 1035 1036 SOC_IF_ERROR_RETURN( 1037 soc_reg_field_validate(unit, TAF_GATE_CTRL_PERIODr, 1038 PERIODf, field_value)); 1039 BCM_IF_ERROR_RETURN( 1040 soc_reg32_get(unit, TAF_GATE_CTRL_PERIODr, REG_PORT_ANY, 1041 taf_gate_id, ®val)); 1042 soc_reg_field_set(unit, TAF_GATE_CTRL_PERIODr, ®val, 1043 PERIODf, field_value); 1044 BCM_IF_ERROR_RETURN( 1045 soc_reg32_set(unit, TAF_GATE_CTRL_PERIODr, REG_PORT_ANY, 1046 taf_gate_id, regval)); 1047 break; 1048 default: 1049 return BCM_E_PARAM; 1050 } 1051 1052 return BCM_E_NONE; 1053 } 1054 1055 /* taf gate control get */ 1056 STATIC int 1057 bcmi_gh2_taf_gate_control_get( 1058 int unit, 1059 int taf_gate_id, 1060 bcm_tsn_taf_control_t type, 1061 uint32 *arg) 1062 { 1063 uint32 regval; 1064 taf_gate_control_entry_t mem_entry; 1065 1066 if (NULL == arg) { 1067 return BCM_E_PARAM; 1068 } 1069 1070 switch (type) { 1071 case bcmTsnTafControlEnable: 1072 BCM_IF_ERROR_RETURN( 1073 soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY, 1074 taf_gate_id, ®val)); 1075 *arg = soc_reg_field_get(unit, TAF_CONFIG_0r, 1076 regval, GATE_ENABLEDf); 1077 break; 1078 case bcmTsnTafControlUsePTPTime: 1079 BCM_IF_ERROR_RETURN( 1080 soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY, 1081 taf_gate_id, ®val)); 1082 *arg = soc_reg_field_get(unit, TAF_CONFIG_0r, 1083 regval, PTP_ACTIVEf); 1084 break; 1085 case bcmTsnTafControlInitGateState: 1086 BCM_IF_ERROR_RETURN( 1087 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY, 1088 taf_gate_id, ®val)); 1089 *arg = soc_reg_field_get(unit, TAF_CONFIG_2r, 1090 regval, INIT_TAF_GATE_STATEf); 1091 break; 1092 case bcmTsnTafControlInitCosProfile: 1093 BCM_IF_ERROR_RETURN( 1094 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY, 1095 taf_gate_id, ®val)); 1096 *arg = soc_reg_field_get(unit, TAF_CONFIG_2r, 1097 regval, INIT_TAF_COS_PROFILEf); 1098 break; 1099 case bcmTsnTafControlInitMaxBytesProfile: 1100 BCM_IF_ERROR_RETURN( 1101 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY, 1102 taf_gate_id, ®val)); 1103 *arg = soc_reg_field_get(unit, TAF_CONFIG_2r, 1104 regval, INIT_TAF_MAXBYTES_SELECTf); 1105 break; 1106 case bcmTsnTafControlErrGateState: 1107 BCM_IF_ERROR_RETURN( 1108 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY, 1109 taf_gate_id, ®val)); 1110 *arg = soc_reg_field_get(unit, TAF_CONFIG_2r, 1111 regval, ERR_TAF_GATE_STATEf); 1112 break; 1113 case bcmTsnTafControlErrCosProfile: 1114 BCM_IF_ERROR_RETURN( 1115 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY, 1116 taf_gate_id, ®val)); 1117 *arg = soc_reg_field_get(unit, TAF_CONFIG_2r, 1118 regval, ERR_TAF_COS_PROFILEf); 1119 break; 1120 case bcmTsnTafControlErrMaxByteProfile: 1121 BCM_IF_ERROR_RETURN( 1122 soc_reg32_get(unit, TAF_CONFIG_2r, REG_PORT_ANY, 1123 taf_gate_id, ®val)); 1124 *arg = soc_reg_field_get(unit, TAF_CONFIG_2r, 1125 regval, ERR_TAF_MAXBYTES_SELECTf); 1126 break; 1127 case bcmTsnTafControlGateCloseControl: 1128 BCM_IF_ERROR_RETURN( 1129 soc_mem_read(unit, TAF_GATE_CONTROLm, MEM_BLOCK_ANY, 1130 taf_gate_id, &mem_entry)); 1131 *arg = soc_mem_field32_get(unit, TAF_GATE_CONTROLm, &mem_entry, 1132 TAF_GATE_CLOSE_CONTROLf); 1133 break; 1134 case bcmTsnTafControlBytesLeftCheckEnable: 1135 BCM_IF_ERROR_RETURN( 1136 soc_mem_read(unit, TAF_GATE_CONTROLm, MEM_BLOCK_ANY, 1137 taf_gate_id, &mem_entry)); 1138 *arg = soc_mem_field32_get(unit, TAF_GATE_CONTROLm, &mem_entry, 1139 TAF_MAXBYTE_CHECK_ENABLEf); 1140 break; 1141 case bcmTsnTafControlGateControlTickInterval: 1142 BCM_IF_ERROR_RETURN( 1143 soc_reg32_get(unit, TAF_GATE_CTRL_PERIODr, REG_PORT_ANY, 1144 taf_gate_id, ®val)); 1145 *arg = soc_reg_field_get(unit, TAF_GATE_CTRL_PERIODr, 1146 regval, PERIODf); 1147 *arg = (*arg + 1) * TAF_GCLT_TICKS; 1148 break; 1149 default: 1150 return BCM_E_PARAM; 1151 } 1152 1153 return BCM_E_NONE; 1154 } 1155 1156 /* taf global control set */ 1157 STATIC int 1158 bcmi_gh2_taf_global_control_set( 1159 int unit, 1160 bcm_tsn_taf_control_t type, 1161 uint32 arg) 1162 { 1163 uint32 regval; 1164 1165 switch (type) { 1166 case bcmTsnTafControlTAFPTPLock: 1167 BCM_IF_ERROR_RETURN( 1168 soc_reg32_get(unit, TAF_PTP_LOCKr, REG_PORT_ANY, 1169 0, ®val)); 1170 soc_reg_field_set(unit, TAF_PTP_LOCKr, ®val, 1171 PTP_LOCKf, arg); 1172 BCM_IF_ERROR_RETURN( 1173 soc_reg32_set(unit, TAF_PTP_LOCKr, REG_PORT_ANY, 1174 0, regval)); 1175 break; 1176 default: 1177 return BCM_E_PARAM; 1178 } 1179 1180 return BCM_E_NONE; 1181 } 1182 1183 /* taf global control get */ 1184 STATIC int 1185 bcmi_gh2_taf_global_control_get( 1186 int unit, 1187 bcm_tsn_taf_control_t type, 1188 uint32 *arg) 1189 { 1190 uint32 regval; 1191 1192 if (NULL == arg) { 1193 return BCM_E_PARAM; 1194 } 1195 1196 switch (type) { 1197 case bcmTsnTafControlTAFPTPLock: 1198 BCM_IF_ERROR_RETURN( 1199 soc_reg32_get(unit, TAF_PTP_LOCKr, REG_PORT_ANY, 0, ®val)); 1200 *arg = soc_reg_field_get(unit, TAF_PTP_LOCKr, 1201 regval, PTP_LOCKf); 1202 break; 1203 default: 1204 return BCM_E_PARAM; 1205 } 1206 1207 return BCM_E_NONE; 1208 } 1209 1210 /* get hw index of taf gate pri map 1211 * ex. TAF_GATE_ID_LOOKUP 1212 * Key: PREEMPTABLE_CELL (1 bit) + 1213 * INT_PRI (4 bit) + 1214 * TAF_GATE_ID_PROFILE (7 bit) 1215 * 1216 * TAF_GATE_ID_PROFILE is at LSB, so sw/hw index is the same 1217 */ 1218 int 1219 bcmi_gh2_taf_gate_pri_map_hw_idx_get( 1220 int unit, 1221 uint32 sw_idx, 1222 uint32 *hw_idx) 1223 { 1224 if (NULL == hw_idx || 1225 TAF_GATE_PRI_MAP_PROFILE_NUM <= sw_idx || 1226 TAF_GATE_PRI_MAP_PROFILE_INVALID_ID == sw_idx) { 1227 return BCM_E_PARAM; 1228 } 1229 1230 *hw_idx = sw_idx; 1231 1232 return BCM_E_NONE; 1233 } 1234 1235 /* get sw index of taf gate pri map */ 1236 int 1237 bcmi_gh2_taf_gate_pri_map_sw_idx_get( 1238 int unit, 1239 uint32 hw_idx, 1240 uint32 *sw_idx) 1241 { 1242 if (NULL == sw_idx) { 1243 return BCM_E_PARAM; 1244 } 1245 1246 /* hw index should be located in the range 1~127 */ 1247 if (hw_idx >= TAF_GATE_PRI_MAP_PROFILE_NUM || 1248 hw_idx == TAF_GATE_PRI_MAP_PROFILE_INVALID_ID) { 1249 return BCM_E_PARAM; 1250 } 1251 *sw_idx = hw_idx; 1252 1253 return BCM_E_NONE; 1254 } 1255 1256 1257 /* helper function of bcmi_gh2_taf_gate_pri_map_set */ 1258 STATIC int 1259 bcmi_gh2_taf_gate_pri_map_change( 1260 int unit, 1261 uint32 profile_idx, 1262 uint32 priority, 1263 uint32 preempt, 1264 uint32 new_gate_id) 1265 { 1266 taf_gate_id_lookup_entry_t hw_entry; 1267 uint32 old_gate_id; 1268 uint32 hw_idx; 1269 1270 if (preempt >= TAF_GATE_PRI_MAP_PREEMPT_NUM || 1271 priority >= TAF_GATE_PRI_MAP_INTPRI_NUM || 1272 profile_idx >= TAF_GATE_PRI_MAP_PROFILE_NUM || 1273 profile_idx == TAF_GATE_PRI_MAP_PROFILE_INVALID_ID) { 1274 return BCM_E_PARAM; 1275 } 1276 hw_idx = (preempt << TAF_GATE_PRI_MAP_PREEMPT_OFFSET) | 1277 (priority << TAF_GATE_PRI_MAP_INTPRI_OFFSET) | 1278 (profile_idx << TAF_GATE_PRI_MAP_PROFILE_OFFSET); 1279 1280 BCM_IF_ERROR_RETURN( 1281 soc_mem_read(unit, taf_gate_pri_map_mem, MEM_BLOCK_ANY, 1282 hw_idx, &hw_entry)); 1283 1284 old_gate_id = soc_mem_field32_get(unit, taf_gate_pri_map_mem, 1285 &hw_entry, TAF_GATE_IDf); 1286 1287 /* change to new gate id */ 1288 BCM_IF_ERROR_RETURN( 1289 soc_mem_field32_fit( 1290 unit, taf_gate_pri_map_mem, TAF_GATE_IDf, new_gate_id)); 1291 soc_mem_field32_set( 1292 unit, taf_gate_pri_map_mem, 1293 &hw_entry, TAF_GATE_IDf, new_gate_id); 1294 if (new_gate_id != TAF_GATE_RESERVED_ID) { 1295 taf_gate_refcount[unit][new_gate_id]++; 1296 } 1297 1298 1299 /* de-ref old gate id */ 1300 if (old_gate_id != TAF_GATE_RESERVED_ID) { 1301 taf_gate_refcount[unit][old_gate_id]--; 1302 } 1303 1304 BCM_IF_ERROR_RETURN( 1305 soc_mem_write(unit, taf_gate_pri_map_mem, MEM_BLOCK_ALL, 1306 hw_idx, &hw_entry)); 1307 1308 return BCM_E_NONE; 1309 } 1310 1311 /* helper function of bcmi_gh2_taf_gate_pri_map_get 1312 */ 1313 STATIC int 1314 bcmi_gh2_taf_gate_pri_map_retrieve( 1315 int unit, 1316 uint32 profile_idx, 1317 uint32 priority, 1318 uint32 preempt, 1319 uint32 *output_gate_id) 1320 { 1321 taf_gate_id_lookup_entry_t hw_entry; 1322 uint32 hw_idx; 1323 1324 if (output_gate_id == NULL) { 1325 return BCM_E_PARAM; 1326 } 1327 1328 if (preempt >= TAF_GATE_PRI_MAP_PREEMPT_NUM || 1329 priority >= TAF_GATE_PRI_MAP_INTPRI_NUM || 1330 profile_idx >= TAF_GATE_PRI_MAP_PROFILE_NUM || 1331 profile_idx == TAF_GATE_PRI_MAP_PROFILE_INVALID_ID) { 1332 return BCM_E_PARAM; 1333 } 1334 1335 hw_idx = (preempt << TAF_GATE_PRI_MAP_PREEMPT_OFFSET) | 1336 (priority << TAF_GATE_PRI_MAP_INTPRI_OFFSET) | 1337 (profile_idx << TAF_GATE_PRI_MAP_PROFILE_OFFSET); 1338 1339 BCM_IF_ERROR_RETURN( 1340 soc_mem_read(unit, taf_gate_pri_map_mem, MEM_BLOCK_ANY, 1341 hw_idx, &hw_entry)); 1342 1343 *output_gate_id = soc_mem_field32_get(unit, taf_gate_pri_map_mem, 1344 &hw_entry, TAF_GATE_IDf); 1345 1346 return BCM_E_NONE; 1347 } 1348 1349 1350 /* set taf gate pri map */ 1351 STATIC int 1352 bcmi_gh2_taf_gate_pri_map_set( 1353 int unit, 1354 uint32 sw_idx, 1355 bcm_tsn_pri_map_config_t *config) 1356 { 1357 uint32 hw_idx, prio; 1358 1359 if (NULL == config) { 1360 return BCM_E_PARAM; 1361 } 1362 1363 if (config->num_map_entries != TAF_GATE_PRI_MAP_INTPRI_NUM) { 1364 return BCM_E_PARAM; 1365 } 1366 1367 if (config->map_type != bcmTsnPriMapTypeTafGate) { 1368 return BCM_E_INTERNAL; 1369 } 1370 1371 BCM_IF_ERROR_RETURN( 1372 bcmi_gh2_taf_gate_pri_map_hw_idx_get(unit, sw_idx, &hw_idx)); 1373 1374 1375 /* set config according to the input from user */ 1376 for (prio = 0; prio < TAF_GATE_PRI_MAP_INTPRI_NUM; prio++) { 1377 1378 if (config->map_entries[prio].flags & 1379 BCM_BCM_TSN_PRI_MAP_ENTRY_TAF_GATE_EXPRESS) { 1380 BCM_IF_ERROR_RETURN( 1381 bcmi_gh2_taf_gate_pri_map_change( 1382 unit, hw_idx, prio, 0, 1383 config->map_entries[prio].taf_gate_express)); 1384 } else { 1385 BCM_IF_ERROR_RETURN( 1386 bcmi_gh2_taf_gate_pri_map_change( 1387 unit, hw_idx, prio, 0, 1388 TAF_GATE_RESERVED_ID)); 1389 } 1390 1391 if (config->map_entries[prio].flags & 1392 BCM_BCM_TSN_PRI_MAP_ENTRY_TAF_GATE_PREEMPT) { 1393 BCM_IF_ERROR_RETURN( 1394 bcmi_gh2_taf_gate_pri_map_change( 1395 unit, hw_idx, prio, 1, 1396 config->map_entries[prio].taf_gate_preempt)); 1397 } else { 1398 BCM_IF_ERROR_RETURN( 1399 bcmi_gh2_taf_gate_pri_map_change( 1400 unit, hw_idx, prio, 1, 1401 TAF_GATE_RESERVED_ID)); 1402 } 1403 } 1404 1405 return BCM_E_NONE; 1406 } 1407 1408 /* get taf gate pri map */ 1409 STATIC int 1410 bcmi_gh2_taf_gate_pri_map_get( 1411 int unit, 1412 uint32 sw_idx, 1413 bcm_tsn_pri_map_config_t *config) 1414 { 1415 uint32 hw_indx, prio; 1416 1417 if (NULL == config) { 1418 return BCM_E_PARAM; 1419 } 1420 bcm_tsn_pri_map_config_t_init(config); 1421 1422 BCM_IF_ERROR_RETURN( 1423 bcmi_gh2_taf_gate_pri_map_hw_idx_get(unit, sw_idx, &hw_indx)); 1424 1425 config->map_type = bcmTsnPriMapTypeTafGate; 1426 config->num_map_entries = TAF_GATE_PRI_MAP_INTPRI_NUM; 1427 1428 for (prio = 0; prio < TAF_GATE_PRI_MAP_INTPRI_NUM; prio++) { 1429 uint32 output_gate_id; 1430 1431 config->map_entries[prio].flags = 0; 1432 1433 BCM_IF_ERROR_RETURN( 1434 bcmi_gh2_taf_gate_pri_map_retrieve( 1435 unit, hw_indx, prio, 0, &output_gate_id)); 1436 1437 if (output_gate_id != TAF_GATE_RESERVED_ID) { 1438 config->map_entries[prio].taf_gate_express = output_gate_id; 1439 config->map_entries[prio].flags |= 1440 BCM_BCM_TSN_PRI_MAP_ENTRY_TAF_GATE_EXPRESS; 1441 } else { 1442 config->map_entries[prio].taf_gate_express = -1; 1443 } 1444 1445 BCM_IF_ERROR_RETURN( 1446 bcmi_gh2_taf_gate_pri_map_retrieve( 1447 unit, hw_indx, prio, 1, &output_gate_id)); 1448 1449 if (output_gate_id != TAF_GATE_RESERVED_ID) { 1450 config->map_entries[prio].taf_gate_preempt = output_gate_id; 1451 config->map_entries[prio].flags |= 1452 BCM_BCM_TSN_PRI_MAP_ENTRY_TAF_GATE_PREEMPT; 1453 } else { 1454 config->map_entries[prio].taf_gate_preempt = -1; 1455 } 1456 } 1457 1458 return BCM_E_NONE; 1459 } 1460 1461 /* delete taf gate pri map */ 1462 STATIC int 1463 bcmi_gh2_taf_gate_pri_map_delete( 1464 int unit, 1465 uint32 sw_idx) 1466 { 1467 uint32 hw_idx, prio; 1468 1469 BCM_IF_ERROR_RETURN( 1470 bcmi_gh2_taf_gate_pri_map_hw_idx_get(unit, sw_idx, &hw_idx)); 1471 1472 /* rollback to default gate */ 1473 for (prio = 0; prio < TAF_GATE_PRI_MAP_INTPRI_NUM; prio++) { 1474 BCM_IF_ERROR_RETURN( 1475 bcmi_gh2_taf_gate_pri_map_change( 1476 unit, hw_idx, prio, 0, 1477 TAF_GATE_RESERVED_ID)); 1478 1479 BCM_IF_ERROR_RETURN( 1480 bcmi_gh2_taf_gate_pri_map_change( 1481 unit, hw_idx, prio, 1, 1482 TAF_GATE_RESERVED_ID)); 1483 } 1484 1485 return BCM_E_NONE; 1486 } 1487 1488 /* kick off a new calendar setting into hw 1489 * Note. this function would not modify profile state 1490 */ 1491 STATIC int 1492 bcmi_gh2_taf_calendar_kickoff( 1493 int unit, 1494 int taf_gate_id, 1495 bcmi_tsn_taf_profile_t *profile) 1496 { 1497 uint32 regval, setup_set, i, entry_byte; 1498 soc_mem_t setup_mem; 1499 soc_memacc_t memacc_cos, memacc_interval, memacc_gstate, memacc_maxbyte; 1500 uint32 *entry_ptr; 1501 bcm_tsn_taf_profile_t *calendar; 1502 bcmi_tsn_taf_schedule_entry_t *schedule; 1503 1504 if (NULL == profile) { 1505 return BCM_E_PARAM; 1506 } 1507 assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM); 1508 1509 calendar = &(profile->data); 1510 schedule = profile->schedule; 1511 1512 /* read active set, select another inactive set to setup */ 1513 BCM_IF_ERROR_RETURN( 1514 soc_reg32_get(unit, TAF_CONFIG_1r, REG_PORT_ANY, taf_gate_id, ®val)); 1515 setup_set = soc_reg_field_get(unit, TAF_CONFIG_1r, 1516 regval, ACTIVE_SETf); 1517 setup_set = 1 - setup_set; 1518 1519 /* init mem */ 1520 setup_mem = (setup_set == 1) ? taf_schedule_calendar_mem[1][taf_gate_id] 1521 : taf_schedule_calendar_mem[0][taf_gate_id]; 1522 BCM_IF_ERROR_RETURN( 1523 soc_memacc_init(unit, setup_mem, TIME_INTERVALf, &memacc_interval)); 1524 BCM_IF_ERROR_RETURN( 1525 soc_memacc_init(unit, setup_mem, GATE_STATEf, &memacc_gstate)); 1526 BCM_IF_ERROR_RETURN( 1527 soc_memacc_init(unit, setup_mem, COS_PROFILEf, &memacc_cos)); 1528 BCM_IF_ERROR_RETURN( 1529 soc_memacc_init(unit, setup_mem, MAXBYTES_SELECTf, &memacc_maxbyte)); 1530 1531 /* write calendar */ 1532 entry_byte = WORDS2BYTES(soc_mem_entry_words(unit, setup_mem)); 1533 sal_memset(taf_schedule_calendar_buf[unit], 0, 1534 TAF_SCHEDULE_CALENDAR_ENTIRES * entry_byte); 1535 for (i = 0; i < calendar->num_entries; i++) { 1536 entry_ptr = &(((uint32 *)(taf_schedule_calendar_buf[unit])) 1537 [i * soc_mem_entry_words(unit, setup_mem)]); 1538 if ((calendar->entries)[i].ticks == BCM_TSN_TAF_ENTRY_TICKS_STAY) { 1539 int field_len = soc_mem_field_length(unit, setup_mem, 1540 TIME_INTERVALf); 1541 1542 soc_memacc_field32_set(&memacc_interval, entry_ptr, 1543 (1 << field_len) - 1); 1544 } else { 1545 soc_memacc_field32_set(&memacc_interval, entry_ptr, 1546 calendar->entries[i].ticks); 1547 } 1548 soc_memacc_field32_set(&memacc_gstate, entry_ptr, 1549 calendar->entries[i].state); 1550 soc_memacc_field32_set(&memacc_cos, entry_ptr, 1551 calendar->entries[i].cos_profile); 1552 soc_memacc_field32_set(&memacc_maxbyte, entry_ptr, 1553 calendar->entries[i].maxbyte_profile); 1554 } 1555 1556 BCM_IF_ERROR_RETURN( 1557 soc_mem_write_range(unit, setup_mem, MEM_BLOCK_ALL, 0, 1558 TAF_SCHEDULE_CALENDAR_ENTIRES - 1, 1559 taf_schedule_calendar_buf[unit])); 1560 1561 /* write time related parameter if operated in ptp mode */ 1562 if (NULL != schedule) { 1563 uint32 sec_32 = COMPILER_64_LO(schedule->schedule_time.seconds); 1564 1565 BCM_IF_ERROR_RETURN( 1566 soc_reg32_get(unit, taf_reg_base_sec[setup_set], REG_PORT_ANY, 1567 taf_gate_id, ®val)); 1568 soc_reg_field_set(unit, taf_reg_base_sec[setup_set], ®val, 1569 SECf, sec_32 & TAF_SCHEDULE_SEC_MASK); 1570 BCM_IF_ERROR_RETURN( 1571 soc_reg32_set(unit, taf_reg_base_sec[setup_set], REG_PORT_ANY, 1572 taf_gate_id, regval)); 1573 1574 BCM_IF_ERROR_RETURN( 1575 soc_reg32_get(unit, taf_reg_base_frac[setup_set], REG_PORT_ANY, 1576 taf_gate_id, ®val)); 1577 soc_reg_field_set(unit, taf_reg_base_frac[setup_set], ®val, 1578 FRACTIONf, schedule->schedule_time.nanoseconds); 1579 BCM_IF_ERROR_RETURN( 1580 soc_reg32_set(unit, taf_reg_base_frac[setup_set], REG_PORT_ANY, 1581 taf_gate_id, regval)); 1582 1583 BCM_IF_ERROR_RETURN( 1584 soc_reg32_get(unit, taf_reg_cycle[setup_set], REG_PORT_ANY, 1585 taf_gate_id, ®val)); 1586 soc_reg_field_set(unit, taf_reg_cycle[setup_set], ®val, 1587 CYCLE_TIMEf, calendar->ptp_cycle_time); 1588 BCM_IF_ERROR_RETURN( 1589 soc_reg32_set(unit, taf_reg_cycle[setup_set], REG_PORT_ANY, 1590 taf_gate_id, regval)); 1591 1592 BCM_IF_ERROR_RETURN( 1593 soc_reg32_get(unit, taf_reg_ext[setup_set], REG_PORT_ANY, 1594 taf_gate_id, ®val)); 1595 soc_reg_field_set(unit, taf_reg_ext[setup_set], ®val, 1596 CYCLE_TIME_EXTENSIONf, 1597 calendar->ptp_max_cycle_extension); 1598 BCM_IF_ERROR_RETURN( 1599 soc_reg32_set(unit, taf_reg_ext[setup_set], REG_PORT_ANY, 1600 taf_gate_id, regval)); 1601 1602 } 1603 1604 /* HW detect 0 to 1 change to start switching to new cycles.*/ 1605 BCM_IF_ERROR_RETURN( 1606 soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY, 1607 taf_gate_id, ®val)); 1608 soc_reg_field_set(unit, TAF_CONFIG_0r, ®val, 1609 CONFIG_CHANGEf, 0); 1610 BCM_IF_ERROR_RETURN( 1611 soc_reg32_set(unit, TAF_CONFIG_0r, REG_PORT_ANY, 1612 taf_gate_id, regval)); 1613 1614 BCM_IF_ERROR_RETURN( 1615 soc_reg32_get(unit, TAF_CONFIG_0r, REG_PORT_ANY, 1616 taf_gate_id, ®val)); 1617 soc_reg_field_set(unit, TAF_CONFIG_0r, ®val, 1618 CONFIG_CHANGEf, 1); 1619 BCM_IF_ERROR_RETURN( 1620 soc_reg32_set(unit, TAF_CONFIG_0r, REG_PORT_ANY, 1621 taf_gate_id, regval)); 1622 1623 return BCM_E_NONE; 1624 } 1625 1626 /* check the parameter of calendar */ 1627 STATIC int 1628 bcmi_gh2_taf_calendar_param_check( 1629 int unit, 1630 int taf_gate, 1631 bcm_tsn_taf_profile_t *calendar) 1632 { 1633 int i; 1634 soc_mem_t mem; 1635 1636 if (NULL == calendar) { 1637 return BCM_E_PARAM; 1638 } 1639 1640 if (calendar->num_entries <= 0 || 1641 calendar->num_entries > TAF_SCHEDULE_CALENDAR_ENTIRES) { 1642 return BCM_E_PARAM; 1643 } 1644 1645 if (calendar->entries[0].ticks == BCM_TSN_TAF_ENTRY_TICKS_GO_FIRST) { 1646 return BCM_E_PARAM; 1647 } 1648 1649 assert(taf_gate >= 0 && taf_gate < BCMI_TSN_TAF_GATE_NUM); 1650 1651 mem = taf_schedule_calendar_mem[0][0]; 1652 for (i = 0; i < calendar->num_entries; i++) { 1653 if (calendar->entries[i].ticks != BCM_TSN_TAF_ENTRY_TICKS_STAY) { 1654 BCM_IF_ERROR_RETURN( 1655 soc_mem_field32_fit(unit, mem, TIME_INTERVALf, 1656 calendar->entries[i].ticks)); 1657 } 1658 BCM_IF_ERROR_RETURN( 1659 soc_mem_field32_fit(unit, mem, GATE_STATEf, 1660 calendar->entries[i].state)); 1661 BCM_IF_ERROR_RETURN( 1662 soc_mem_field32_fit(unit, mem, COS_PROFILEf, 1663 calendar->entries[i].cos_profile)); 1664 BCM_IF_ERROR_RETURN( 1665 soc_mem_field32_fit(unit, mem, MAXBYTES_SELECTf, 1666 calendar->entries[i].maxbyte_profile)); 1667 1668 if (0 != calendar->entries[i].cos_profile) { 1669 if (calendar->entries[i].cos_profile >= TAF_COSQ_PROFILE_NUM) { 1670 return BCM_E_PARAM; 1671 } 1672 if (0 == taf_cosq_profile_refcount 1673 [unit][calendar->entries[i].cos_profile]) { 1674 return BCM_E_PARAM; 1675 } 1676 } 1677 1678 if (0 != calendar->entries[i].maxbyte_profile) { 1679 if (calendar->entries[i].maxbyte_profile >= TAF_MAXBYTE_PROFILE_NUM) 1680 { 1681 return BCM_E_PARAM; 1682 } 1683 if (0 == taf_maxbyte_profile_refcount 1684 [unit][taf_gate][calendar->entries[i].maxbyte_profile]) { 1685 return BCM_E_PARAM; 1686 } 1687 } 1688 } 1689 1690 BCM_IF_ERROR_RETURN( 1691 soc_reg_field_validate(unit, TAF_CYCLE_TIME_0r, CYCLE_TIMEf, 1692 calendar->ptp_cycle_time)); 1693 BCM_IF_ERROR_RETURN( 1694 soc_reg_field_validate(unit, TAF_CYCLE_TIME_EXTENSION_0r, 1695 CYCLE_TIME_EXTENSIONf, 1696 calendar->ptp_max_cycle_extension)); 1697 if (calendar->ptp_base_time.nanoseconds >= TAF_SCHEDULE_NANOSEC_MAX) { 1698 return BCM_E_PARAM; 1699 } 1700 return BCM_E_NONE; 1701 } 1702 1703 /* for the profile (maxbyte and CosQ) in calendar, increase the ref_cnt 1704 * Note. this function assume that the profile id is valid. 1705 * the caller need to ensure that 1706 */ 1707 STATIC int 1708 bcmi_gh2_taf_calendar_resource_alloc( 1709 int unit, 1710 int taf_gate, 1711 bcm_tsn_taf_profile_t *calendar) 1712 { 1713 int i; 1714 1715 if (NULL == calendar) { 1716 return BCM_E_PARAM; 1717 } 1718 1719 assert(taf_gate >= 0 && taf_gate < BCMI_TSN_TAF_GATE_NUM); 1720 1721 for (i = 0; i < calendar->num_entries; i++) { 1722 if (0 != calendar->entries[i].cos_profile) { 1723 assert(calendar->entries[i].cos_profile < TAF_COSQ_PROFILE_NUM); 1724 assert(taf_cosq_profile_refcount 1725 [unit][calendar->entries[i].cos_profile] != 0); 1726 taf_cosq_profile_refcount 1727 [unit][calendar->entries[i].cos_profile]++; 1728 } 1729 1730 if (0 != calendar->entries[i].maxbyte_profile) { 1731 assert(calendar->entries[i].maxbyte_profile 1732 < TAF_MAXBYTE_PROFILE_NUM); 1733 assert(taf_maxbyte_profile_refcount 1734 [unit][taf_gate][calendar->entries[i].maxbyte_profile] != 0); 1735 taf_maxbyte_profile_refcount 1736 [unit][taf_gate][calendar->entries[i].maxbyte_profile]++; 1737 } 1738 } 1739 1740 return BCM_E_NONE; 1741 } 1742 1743 /* for the profile (maxbyte and CosQ) in calendar, decrease the ref_cnt 1744 * Note. this function assume that the profile id is valid. 1745 * the caller need to ensure that 1746 */ 1747 STATIC int 1748 bcmi_gh2_taf_calendar_resource_free( 1749 int unit, 1750 int taf_gate, 1751 bcm_tsn_taf_profile_t *calendar) 1752 { 1753 int i; 1754 1755 if (NULL == calendar) { 1756 return BCM_E_PARAM; 1757 } 1758 1759 assert(taf_gate >= 0 && taf_gate < BCMI_TSN_TAF_GATE_NUM); 1760 1761 for (i = 0; i < calendar->num_entries; i++) { 1762 if (0 != calendar->entries[i].cos_profile) { 1763 assert(calendar->entries[i].cos_profile < TAF_COSQ_PROFILE_NUM); 1764 assert(taf_cosq_profile_refcount 1765 [unit][calendar->entries[i].cos_profile] != 0); 1766 taf_cosq_profile_refcount 1767 [unit][calendar->entries[i].cos_profile]--; 1768 } 1769 1770 if (0 != calendar->entries[i].maxbyte_profile) { 1771 assert(calendar->entries[i].maxbyte_profile 1772 < TAF_MAXBYTE_PROFILE_NUM); 1773 assert(taf_maxbyte_profile_refcount 1774 [unit][taf_gate][calendar->entries[i].maxbyte_profile] != 0); 1775 taf_maxbyte_profile_refcount 1776 [unit][taf_gate][calendar->entries[i].maxbyte_profile]--; 1777 } 1778 } 1779 1780 return BCM_E_NONE; 1781 } 1782 1783 /* create a profile according to user's profile */ 1784 STATIC int 1785 bcmi_gh2_taf_calendar_profile_create( 1786 int unit, 1787 bcm_tsn_taf_profile_t *calendar, 1788 bcm_tsn_taf_profile_id_t *ret_pid, 1789 bcmi_tsn_taf_profile_t **ret_profile) 1790 { 1791 int profile_index; 1792 bcmi_tsn_taf_profile_t *new_profile = NULL; 1793 1794 if (NULL == calendar || NULL == ret_profile || NULL == ret_pid) { 1795 return BCM_E_PARAM; 1796 } 1797 1798 BCM_IF_ERROR_RETURN( 1799 shr_res_bitmap_alloc( 1800 taf_schedule_profile_bitmap[unit], 0, 1, &profile_index)); 1801 1802 if (profile_index < 0 || profile_index >= BCMI_TSN_TAF_PROFILE_NUM_MAX) { 1803 return BCM_E_INTERNAL; 1804 } 1805 1806 new_profile = sal_alloc(sizeof(bcmi_tsn_taf_profile_t), "TAF profile"); 1807 if (NULL == new_profile) { 1808 return BCM_E_MEMORY; 1809 } 1810 sal_memset(new_profile, 0, sizeof(bcmi_tsn_taf_profile_t)); 1811 taf_schedule_profile[unit][profile_index] = new_profile; 1812 *ret_profile = new_profile; 1813 *ret_pid = profile_index; 1814 1815 return BCM_E_NONE; 1816 } 1817 1818 /* get profile according to profile id */ 1819 STATIC int 1820 bcmi_gh2_taf_calendar_profile_get( 1821 int unit, 1822 bcm_tsn_taf_profile_id_t profile_id, 1823 bcmi_tsn_taf_profile_t **ret_profile) 1824 { 1825 if (NULL == ret_profile) { 1826 return BCM_E_PARAM; 1827 } 1828 1829 assert(profile_id >= 0 && profile_id < BCMI_TSN_TAF_PROFILE_NUM_MAX); 1830 1831 if (NULL == taf_schedule_profile[unit][profile_id]) { 1832 return BCM_E_NOT_FOUND; 1833 } 1834 1835 *ret_profile = taf_schedule_profile[unit][profile_id]; 1836 return BCM_E_NONE; 1837 } 1838 1839 /* destroy a existing profile */ 1840 STATIC int 1841 bcmi_gh2_taf_calendar_profile_destroy( 1842 int unit, 1843 bcm_tsn_taf_profile_id_t profile_id) 1844 { 1845 assert(profile_id >= 0 && profile_id < BCMI_TSN_TAF_PROFILE_NUM_MAX); 1846 1847 if (NULL == taf_schedule_profile[unit][profile_id]) { 1848 return BCM_E_NOT_FOUND; 1849 } 1850 1851 BCM_IF_ERROR_RETURN( 1852 shr_res_bitmap_free(taf_schedule_profile_bitmap[unit], 1, profile_id)); 1853 sal_free(taf_schedule_profile[unit][profile_id]); 1854 taf_schedule_profile[unit][profile_id] = NULL; 1855 1856 return BCM_E_NONE; 1857 } 1858 1859 /* traverse existing profiles */ 1860 STATIC int 1861 bcmi_gh2_taf_calendar_profile_traverse( 1862 int unit, 1863 int taf_gate, 1864 bcm_tsn_taf_profile_traverse_cb cb, 1865 void *user_data) 1866 { 1867 int i; 1868 1869 if (NULL == cb) { 1870 return BCM_E_PARAM; 1871 } 1872 1873 for (i = 0; i < BCMI_TSN_TAF_PROFILE_NUM_MAX; i++) { 1874 if (NULL != taf_schedule_profile[unit][i] && 1875 taf_schedule_profile[unit][i]->taf_gate == taf_gate) { 1876 BCM_IF_ERROR_RETURN( 1877 cb(unit, taf_gate, i, user_data)); 1878 } 1879 } 1880 1881 return BCM_E_NONE; 1882 } 1883 1884 /* remove a calendar entry from timeline 1885 * Note. we skip check whether entry_remove exitsed in 1886 * taf_schedule_timeline[unit][taf_gate_id] or not. 1887 * ==> The caller need to ensure this. 1888 */ 1889 STATIC int 1890 bcmi_gh2_taf_schedule_remove( 1891 int unit, 1892 int taf_gate_id, 1893 bcmi_tsn_taf_profile_t *profile) 1894 { 1895 bcmi_tsn_taf_schedule_entry_t *entry_remove; 1896 1897 if (NULL == profile) { 1898 return BCM_E_PARAM; 1899 } 1900 assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM); 1901 1902 entry_remove = profile->schedule; 1903 if (NULL == entry_remove) { 1904 return BCM_E_INTERNAL; 1905 } 1906 1907 if (entry_remove->prev != NULL) { 1908 entry_remove->prev->next = entry_remove->next; 1909 } else { 1910 taf_schedule_timeline[unit][taf_gate_id] = entry_remove->next; 1911 } 1912 1913 if (entry_remove->next != NULL) { 1914 entry_remove->next->prev = entry_remove->prev; 1915 } 1916 1917 sal_free(entry_remove); 1918 profile->schedule = NULL; 1919 return BCM_E_NONE; 1920 } 1921 1922 1923 /* check if this profile has already has scheduled in timeline 1924 * (only possible in ptp mode) 1925 */ 1926 STATIC int 1927 bcmi_gh2_taf_schedule_exist( 1928 int unit, 1929 bcmi_tsn_taf_profile_t *profile, 1930 int *ret_is_exist) 1931 { 1932 if (NULL == profile || NULL == ret_is_exist) { 1933 return BCM_E_PARAM; 1934 } else if (NULL == profile->schedule) { 1935 *ret_is_exist = 0; 1936 } else { 1937 *ret_is_exist = 1; 1938 } 1939 1940 return BCM_E_NONE; 1941 } 1942 1943 /* return actual scheduling time 1944 * if this profile has already has been scheduled 1945 */ 1946 STATIC int 1947 bcmi_gh2_taf_schedule_get( 1948 int unit, 1949 bcmi_tsn_taf_profile_t *profile, 1950 bcm_ptp_timestamp_t *ret_schedule_time) 1951 { 1952 if (NULL == profile || NULL == ret_schedule_time) { 1953 return BCM_E_PARAM; 1954 } 1955 1956 if (NULL == profile->schedule) { 1957 return BCM_E_PARAM; 1958 } 1959 1960 bcmi_gh2_taf_ptp_time_assign(ret_schedule_time, 1961 &(profile->schedule->schedule_time)); 1962 1963 return BCM_E_NONE; 1964 } 1965 1966 1967 /* create a new calendar entry and insert it into timeline */ 1968 STATIC int 1969 bcmi_gh2_taf_schedule_insert( 1970 int unit, 1971 int taf_gate_id, 1972 bcm_ptp_timestamp_t *schedule_basetime, 1973 bcmi_tsn_taf_profile_t *profile) 1974 { 1975 bcm_ptp_timestamp_t curr_time; 1976 bcmi_tsn_taf_schedule_entry_t *entry_iter = NULL; 1977 bcmi_tsn_taf_schedule_entry_t *entry_pos = NULL; 1978 bcmi_tsn_taf_schedule_entry_t *entry_tail = NULL; 1979 bcmi_tsn_taf_schedule_entry_t *entry_new = NULL; 1980 1981 if (NULL == profile || NULL == schedule_basetime) { 1982 return BCM_E_PARAM; 1983 } 1984 1985 assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM); 1986 1987 { 1988 BCM_IF_ERROR_RETURN( 1989 bcmi_gh2_taf_ptp_time_get(unit, &curr_time)); 1990 } 1991 1992 if (TRUE == bcmi_gh2_taf_ptp_time_gt(&curr_time, schedule_basetime)) { 1993 return BCM_E_PARAM; 1994 } 1995 1996 /* find the position to insert 1997 * ex. there have already four entry in timeline 1998 * 1999 * basetime 10s 20s 25s 30s 40s 2000 * ----|------------|----------|-----------|-----------|- 2001 * A B C D E 2002 * 2003 * if schedule_basetime = 25s, entry_pos would be D 2004 */ 2005 entry_iter = taf_schedule_timeline[unit][taf_gate_id]; 2006 while (entry_iter != NULL) { 2007 if (TRUE == bcmi_gh2_taf_ptp_time_ge( 2008 schedule_basetime, 2009 &(entry_iter->schedule_time))) { 2010 if (NULL == entry_iter->next) { 2011 entry_tail = entry_iter; 2012 } 2013 entry_iter = entry_iter->next; 2014 } else { 2015 break; /* find out the position */ 2016 } 2017 } 2018 entry_pos = entry_iter; 2019 2020 /* insert new entry */ 2021 entry_new = sal_alloc(sizeof(bcmi_tsn_taf_schedule_entry_t), 2022 "TAF schedule entry"); 2023 if (NULL == entry_new) { 2024 return BCM_E_MEMORY; 2025 } 2026 bcmi_gh2_taf_ptp_time_assign(&(entry_new->schedule_time), 2027 schedule_basetime); 2028 if (NULL == taf_schedule_timeline[unit][taf_gate_id]) { 2029 /* entry_new is a first entry in timline */ 2030 entry_new->prev = NULL; 2031 entry_new->next = NULL; 2032 taf_schedule_timeline[unit][taf_gate_id] = entry_new; 2033 } else { 2034 if (entry_pos == NULL) { 2035 /* insert entry_new at tail */ 2036 entry_new->prev = entry_tail; 2037 entry_new->next = NULL; 2038 entry_tail->next = entry_new; 2039 } else { 2040 /* add entry_new before entry_pos */ 2041 entry_new->prev = entry_pos->prev; 2042 entry_new->next = entry_pos; 2043 if (entry_pos->prev == NULL) { 2044 taf_schedule_timeline[unit][taf_gate_id] = entry_new; 2045 } else { 2046 entry_pos->prev->next = entry_new; 2047 } 2048 entry_pos->prev = entry_new; 2049 } 2050 } 2051 2052 /* remove old schedule if need */ 2053 if (profile->schedule != NULL) { 2054 BCM_IF_ERROR_RETURN( 2055 bcmi_gh2_taf_schedule_remove(unit, taf_gate_id, profile)); 2056 } 2057 2058 /* setup connection */ 2059 entry_new->taf_profile = profile; 2060 profile->schedule = entry_new; 2061 return BCM_E_NONE; 2062 } 2063 2064 /* select a candidate entry from timeline 2065 * which is able to be scheduled as "pending" 2066 * Note. 1. after decide candidate, 2067 * it is possible that it just update its scheduling time 2068 * and not write into hw yet 2069 * 2. this function maybe remove some entries 2070 * and change their state to expired 2071 */ 2072 STATIC int 2073 bcmi_gh2_taf_schedule_pick( 2074 int unit, 2075 int taf_gate_id, 2076 bcmi_tsn_taf_profile_t *active_profile, 2077 bcmi_tsn_taf_profile_t **candidate_profile) 2078 { 2079 bcm_ptp_timestamp_t curr_time; 2080 bcm_ptp_timestamp_t candidate_time; 2081 bcmi_tsn_taf_schedule_entry_t *entry_candidate = NULL; 2082 bcmi_tsn_taf_schedule_entry_t *entry_iter = NULL; 2083 bcmi_tsn_taf_schedule_entry_t *entry_back = NULL; 2084 bcmi_tsn_taf_schedule_entry_t *entry_fore = NULL; 2085 uint32 need_recheck_candicate = FALSE; 2086 uint64 tod_curr; 2087 uint64 tod_candidate; 2088 uint32 okay_to_kick_off = FALSE; 2089 2090 if (NULL == candidate_profile) { 2091 return BCM_E_PARAM; 2092 } 2093 2094 assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM); 2095 2096 /* find candidate 2097 * step 1. according to the current time, traverse backward fisrt 2098 * step 2. if it cannot find anything in step 1, traverse foreward 2099 * 2100 * ex 1. 2101 * 1 2 2102 * --|-------|-------|--- ==> pick entry 2 2103 * curr_time 2104 * 2105 * ex 2. 2106 * 1 2 2107 * ---------|-------|------|- ==> pick entry 1 2108 * curr_time 2109 * ex 3. 2110 * 1 2 3 2111 * --|-------|-------|------|- ==> pick entry 2 2112 * curr_time 2113 */ 2114 2115 2116 { 2117 BCM_IF_ERROR_RETURN( 2118 bcmi_gh2_taf_ptp_time_get(unit, &curr_time)); 2119 } 2120 2121 entry_iter = taf_schedule_timeline[unit][taf_gate_id]; 2122 while (entry_iter != NULL) { 2123 2124 if (TRUE == bcmi_gh2_taf_ptp_time_gt( 2125 &(entry_iter->schedule_time), &curr_time)) { 2126 entry_fore = entry_iter; 2127 entry_back = entry_iter->prev; 2128 break; 2129 } else { 2130 if (NULL == entry_iter->next) { 2131 entry_fore = NULL; 2132 entry_back = entry_iter; 2133 break; 2134 } else { 2135 entry_iter = entry_iter->next; 2136 } 2137 } 2138 } 2139 if (NULL != entry_back) { 2140 entry_candidate = entry_back; 2141 } else { 2142 entry_candidate = entry_fore; 2143 } 2144 2145 if (NULL == entry_candidate) { 2146 /* cannot find out any candidate */ 2147 return BCM_E_NONE; 2148 } 2149 2150 /* Calaulate the actual scheduling time of candidate. 2151 * because of GH2 hw limitaion, maybe we need to delay scheduling time 2152 * [rule] the actual scheduling time needs to be at least 2153 * "2 * old-cycle + hw process + sw process time" 2154 * far away from the current time 2155 * 2156 * After moving scheduling time foreward, 2157 * maybe we needs to select the new candidate 2158 * 2159 * ex. At first, we select entry 2 as a candidate. 2160 * 2161 * 2(c) 3(c) 4(c) 5(c) 2162 * --|-------|-------|------------|-------|-------|------- 2163 * 20s curr_time(30s) 40s 50s 60s 2164 * 2165 * Assume that after calculating, the new scheduling time is at 55s 2166 * Then we need to select entry 4 as new candidate instead. 2167 * And re-calaulate the actual scheduling time of entry 4 2168 * 2169 * 4(c) 5(c) 2170 * --|---------------|--------------------|-------|------- 2171 * curr_time(30s) 50s 60s 2172 * 2173 * remove entry 2 and 3 from timelime (mark their status as expired) 2174 * at the end of this function 2175 */ 2176 need_recheck_candicate = TRUE; 2177 while (TRUE == need_recheck_candicate) { 2178 bcm_ptp_timestamp_t schedule_time_at_least; 2179 2180 bcmi_gh2_taf_ptp_time_assign(&(candidate_time), 2181 &(entry_candidate->schedule_time)); 2182 2183 /* calculate the actual scheduling time of candidate */ 2184 { 2185 BCM_IF_ERROR_RETURN( 2186 bcmi_gh2_taf_ptp_time_get(unit, &curr_time)); 2187 } 2188 2189 LOG_VERBOSE(BSL_LS_BCM_TSN, 2190 (BSL_META("[taf_schedule_pick] curr_time : \ 2191 sec:%d %d, nano:%d\n"), 2192 COMPILER_64_HI(curr_time.seconds), 2193 COMPILER_64_LO(curr_time.seconds), 2194 curr_time.nanoseconds)); 2195 2196 /* schedule_time_at_least = 2197 * curr_time + 2 * old-cycle + hw process + sw process time 2198 */ 2199 bcmi_gh2_taf_ptp_time_assign(&schedule_time_at_least, &curr_time); 2200 if (active_profile != NULL) { 2201 bcmi_gh2_taf_ptp_time_add( 2202 &schedule_time_at_least, 2203 2 * (active_profile->data.ptp_cycle_time)); 2204 } 2205 2206 { 2207 bcmi_gh2_taf_ptp_time_add(&schedule_time_at_least, 2208 TAF_SCHEDULE_HW_RESPONSE_TIME); 2209 bcmi_gh2_taf_ptp_time_add(&schedule_time_at_least, 2210 TAF_SCHEDULE_SW_RESPONSE_TIME); 2211 } 2212 2213 LOG_VERBOSE(BSL_LS_BCM_TSN, 2214 (BSL_META("[taf_schedule_pick] schedule_time_at_least : \ 2215 sec:%d %d, nano:%d\n"), 2216 COMPILER_64_HI(schedule_time_at_least.seconds), 2217 COMPILER_64_LO(schedule_time_at_least.seconds), 2218 schedule_time_at_least.nanoseconds)); 2219 2220 while (TRUE == bcmi_gh2_taf_ptp_time_gt(&schedule_time_at_least, 2221 &candidate_time)) { 2222 /* Add N x new_cycle_time until > schedule_time_at_least */ 2223 bcmi_gh2_taf_ptp_time_add( 2224 &candidate_time, 2225 entry_candidate->taf_profile->data.ptp_cycle_time); 2226 } 2227 2228 LOG_VERBOSE(BSL_LS_BCM_TSN, 2229 (BSL_META("[taf_schedule_pick] candidate_time : \ 2230 sec:%d %d, nano:%d\n"), 2231 COMPILER_64_HI(candidate_time.seconds), 2232 COMPILER_64_LO(candidate_time.seconds), 2233 candidate_time.nanoseconds)); 2234 2235 /* check this new scheduling time would not be larger 2236 * than the next entries 2237 */ 2238 need_recheck_candicate = FALSE; 2239 entry_iter = entry_candidate; 2240 while (NULL != entry_iter) { 2241 if (NULL == entry_iter->next) { 2242 break; 2243 } 2244 if (TRUE == bcmi_gh2_taf_ptp_time_gt( 2245 &candidate_time, 2246 &(entry_iter->next->schedule_time))) { 2247 need_recheck_candicate = TRUE; 2248 entry_iter = entry_iter->next; 2249 } else { 2250 break; 2251 } 2252 } 2253 if (TRUE == need_recheck_candicate) { 2254 entry_candidate = entry_iter; /* new candidate */ 2255 } 2256 } 2257 2258 if (NULL == entry_candidate) { 2259 return BCM_E_INTERNAL; 2260 } 2261 2262 /* for this candidate 2263 * 1. udpate its scheduling time 2264 * 2. kick off this new scheduling time if okay 2265 * [rule] 2266 * 1) need to locate in the same TOD 2267 * 2) actual schedule time need to be 1 old-cycle time 2268 * far away from the boundary of ToD 2269 * ex. 2270 * -----|-----------|-----------|----------- 2271 * 64s ^ 128s ^ 192s 2272 * | | 2273 * candidate cur_time (130s) 2274 * 2275 * Assume that the old cycle time is 100ns 2276 * After calculating in the previous step: 2277 * Case A. the scheduling time is updated to 140s 2278 * ==> it is okay to kick off 2279 * Case B. the scheduling time is updated to 193s 2280 * ==> just update its scheduling time 2281 * delay its kick-off until the next ToD interrupt 2282 */ 2283 okay_to_kick_off = FALSE; 2284 bcmi_gh2_taf_ptp_time_assign( 2285 &(entry_candidate->schedule_time), &candidate_time); 2286 bcmi_gh2_taf_ptp_time_to_tod(&curr_time, &tod_curr); 2287 bcmi_gh2_taf_ptp_time_to_tod(&candidate_time, &tod_candidate); 2288 if (COMPILER_64_EQ(tod_curr, tod_candidate)) { 2289 if (active_profile != NULL) { 2290 bcm_ptp_timestamp_t tod_boundary; 2291 uint64 tod_next; 2292 2293 COMPILER_64_COPY(tod_next, tod_curr); 2294 COMPILER_64_ADD_32(tod_next, 1); 2295 bcmi_gh2_taf_ptp_time_from_tod(&tod_next, &tod_boundary); 2296 bcmi_gh2_taf_ptp_time_sub( 2297 &tod_boundary, 2298 active_profile->data.ptp_cycle_time); 2299 if (TRUE == bcmi_gh2_taf_ptp_time_gt(&tod_boundary, 2300 &candidate_time)) { 2301 okay_to_kick_off = TRUE; 2302 } 2303 } else { 2304 okay_to_kick_off = TRUE; 2305 } 2306 } 2307 if (TRUE == okay_to_kick_off) { 2308 *candidate_profile = entry_candidate->taf_profile; 2309 } else { 2310 *candidate_profile = NULL; 2311 } 2312 2313 LOG_VERBOSE(BSL_LS_BCM_TSN, 2314 (BSL_META("[taf_schedule_pick] okay_to_kick_off : %s\n"), 2315 (TRUE == okay_to_kick_off) ? "Yes" : "No")); 2316 2317 /* 2318 * delete all entries before this candidate from timeline 2319 */ 2320 entry_iter = entry_candidate->prev; 2321 while (NULL != entry_iter) { 2322 bcmi_tsn_taf_schedule_entry_t *entry_prev = entry_iter->prev; 2323 2324 BCM_IF_ERROR_RETURN( 2325 bcmi_gh2_taf_schedule_remove( 2326 unit, taf_gate_id, entry_iter->taf_profile)); 2327 entry_iter->taf_profile->status = bcmTsnTafProfileExpired; 2328 entry_iter = entry_prev; 2329 } 2330 2331 return BCM_E_NONE; 2332 } 2333 2334 /* the 1st function need to be invoked to handle hw interrupt */ 2335 STATIC int 2336 bcmi_gh2_taf_interrupt_handle_start(int unit) 2337 { 2338 uint32 status; 2339 uint32 mask; 2340 gh2_taf_interrupt_type_t iter; 2341 2342 if (1 == taf_interrupt_handling[unit]) { 2343 return BCM_E_INTERNAL; 2344 } 2345 2346 BCM_IF_ERROR_RETURN( 2347 soc_reg32_get(unit, TAF_MEMFAILINTSTATUSr, REG_PORT_ANY, 0, &status)); 2348 2349 BCM_IF_ERROR_RETURN( 2350 soc_reg32_get(unit, TAF_MEMFAILINTMASKr, REG_PORT_ANY, 0, &mask)); 2351 2352 taf_interrupt_status[unit] = status & mask; 2353 2354 for (iter = 0; iter < TafInterruptCount; iter++) { 2355 if (taf_interrupt_mapping[iter].sub_status_regs[0] != INVALIDr) { 2356 int index; 2357 2358 if (soc_reg_field_get( 2359 unit, TAF_MEMFAILINTSTATUSr, taf_interrupt_status[unit], 2360 taf_interrupt_mapping[iter].status_field)) { 2361 2362 for (index = 0; index < TAF_INTERRUPT_SUB_FIELD_NUM; index++) { 2363 BCM_IF_ERROR_RETURN( 2364 soc_reg32_get( 2365 unit, 2366 taf_interrupt_mapping[iter].sub_status_regs[index], 2367 REG_PORT_ANY, 0, 2368 &taf_interrupt_substatus[unit][iter][index])); 2369 } 2370 } else { 2371 for (index = 0; index < TAF_INTERRUPT_SUB_FIELD_NUM; index++) { 2372 taf_interrupt_substatus[unit][iter][index] = 0; 2373 } 2374 } 2375 } 2376 } 2377 2378 taf_interrupt_handling[unit] = 1; 2379 return BCM_E_NONE; 2380 } 2381 2382 /* indicate that whether need to handle Tod window interupt event */ 2383 STATIC int 2384 bcmi_gh2_taf_interrupt_handle_tod(int unit, int *ret_need) 2385 { 2386 if (1 != taf_interrupt_handling[unit]) { 2387 return BCM_E_INTERNAL; 2388 } 2389 if (NULL == ret_need) { 2390 return BCM_E_PARAM; 2391 } 2392 2393 *ret_need = soc_reg_field_get( 2394 unit, TAF_MEMFAILINTSTATUSr, taf_interrupt_status[unit], 2395 taf_interrupt_mapping[TafInterruptTodWindow].status_field); 2396 2397 return BCM_E_NONE; 2398 } 2399 2400 /* indicate that whether need to handle profile switch done event 2401 * ret_need(OUT) : whether to handle profile switch 2402 * ret_bmp_gate(IN/OUT) : return the bitmap of taf_gate need to handle 2403 * bmp_size(IN) : the size of bitmap 2404 */ 2405 STATIC int 2406 bcmi_gh2_taf_interrupt_handle_switch( 2407 int unit, 2408 int *ret_need, 2409 SHR_BITDCL *ret_bmp_gate, 2410 uint32 bmp_size) 2411 { 2412 int index; 2413 2414 if (1 != taf_interrupt_handling[unit]) { 2415 return BCM_E_INTERNAL; 2416 } 2417 if (NULL == ret_need || NULL == ret_bmp_gate) { 2418 return BCM_E_PARAM; 2419 } 2420 if (bmp_size < _SHR_BITDCLSIZE(BCMI_TSN_TAF_GATE_NUM)) { 2421 return BCM_E_PARAM; 2422 } 2423 2424 for (index = 0; index < TAF_INTERRUPT_SUB_FIELD_NUM; index++) { 2425 ret_bmp_gate[index] = 2426 taf_interrupt_substatus[unit][TafInterruptSwitchDone][index]; 2427 } 2428 2429 SHR_BITTEST_RANGE(ret_bmp_gate, 0, BCMI_TSN_TAF_GATE_NUM, *ret_need); 2430 return BCM_E_NONE; 2431 } 2432 2433 /* indicate that whether need to handle profile become error 2434 * ret_need(OUT) : whether to handle profile error 2435 * ret_bmp_gate(IN/OUT) : return the bitmap of taf_gate need to handle 2436 * bmp_size(IN) : the size of bitmap 2437 */ 2438 STATIC int 2439 bcmi_gh2_taf_interrupt_handle_error( 2440 int unit, 2441 int *ret_need, 2442 SHR_BITDCL *ret_bmp_gate, 2443 uint32 bmp_size) 2444 { 2445 int index; 2446 2447 if (1 != taf_interrupt_handling[unit]) { 2448 return BCM_E_INTERNAL; 2449 } 2450 if (NULL == ret_need || NULL == ret_bmp_gate) { 2451 return BCM_E_PARAM; 2452 } 2453 if (bmp_size < _SHR_BITDCLSIZE(BCMI_TSN_TAF_GATE_NUM)) { 2454 return BCM_E_PARAM; 2455 } 2456 2457 for (index = 0; index < TAF_INTERRUPT_SUB_FIELD_NUM; index++) { 2458 ret_bmp_gate[index] = 2459 taf_interrupt_substatus[unit][TafInterruptNextCycleTimeError][index] | 2460 taf_interrupt_substatus[unit][TafInterruptParityError][index] | 2461 taf_interrupt_substatus[unit][TafInterruptTblPtrError][index] | 2462 taf_interrupt_substatus[unit][TafInterruptBaseTimeError][index]; 2463 } 2464 2465 SHR_BITTEST_RANGE(ret_bmp_gate, 0, BCMI_TSN_TAF_GATE_NUM, *ret_need); 2466 return BCM_E_NONE; 2467 } 2468 2469 /* invoke the callback function hooked by the user */ 2470 STATIC int 2471 bcmi_gh2_taf_interrupt_handle_user_cb(int unit) 2472 { 2473 gh2_taf_interrupt_type_t iter; 2474 2475 if (1 != taf_interrupt_handling[unit]) { 2476 return BCM_E_INTERNAL; 2477 } 2478 2479 for (iter = 0; iter < TafInterruptCount; iter++) { 2480 bcm_tsn_taf_event_type_t event; 2481 int i, j; 2482 2483 switch (iter) { 2484 case TafInterruptSwitchDone: 2485 event = bcmTsnTafEventTAFProfileChange; 2486 break; 2487 case TafInterruptNextCycleTimeError: 2488 event = bcmTsnTafEventTAFNextCycleTimeErr; 2489 break; 2490 case TafInterruptBaseTimeError: 2491 event = bcmTsnTafEventTAFBaseTimeErr; 2492 break; 2493 case TafInterruptParityError: 2494 event = bcmTsnTafEventTAFECCErr; 2495 break; 2496 case TafInterruptTblPtrError: 2497 event = bcmTsnTafEventTAFProfilePtrErr; 2498 break; 2499 default: /* user would not register cb for TafInterruptTodWindow */ 2500 continue; 2501 } 2502 if (0 == soc_reg_field_get( 2503 unit, TAF_MEMFAILINTSTATUSr, 2504 taf_interrupt_status[unit], 2505 taf_interrupt_mapping[iter].status_field)) { 2506 continue; 2507 } 2508 for (i = 0; i < TAF_INTERRUPT_SUB_FIELD_NUM; i++) { 2509 for (j = 0; j < TAF_INTERRUPT_SUB_FIELD_WIDTH; j++) { 2510 if (taf_interrupt_substatus[unit][iter][i] & (1 << j)) { 2511 BCM_IF_ERROR_RETURN( 2512 bcmi_gh2_taf_event_notify( 2513 unit, 2514 i * TAF_INTERRUPT_SUB_FIELD_WIDTH + j, 2515 event)); 2516 } 2517 } 2518 } 2519 } 2520 return BCM_E_NONE; 2521 } 2522 2523 /* the last function should be invoked after finish handling */ 2524 STATIC int 2525 bcmi_gh2_taf_interrupt_handle_finish(int unit) 2526 { 2527 gh2_taf_interrupt_type_t iter; 2528 uint32 reg_value; 2529 2530 if (1 != taf_interrupt_handling[unit]) { 2531 return BCM_E_INTERNAL; 2532 } 2533 2534 /* clear interrupt for subfiled */ 2535 for (iter = 0; iter < TafInterruptCount; iter++) { 2536 if (taf_interrupt_mapping[iter].sub_status_regs[0] != INVALIDr) { 2537 int index; 2538 2539 for (index = 0; index < TAF_INTERRUPT_SUB_FIELD_NUM; index++) { 2540 reg_value = taf_interrupt_substatus[unit][iter][index]; 2541 if (0 == reg_value) { 2542 continue; 2543 } 2544 2545 BCM_IF_ERROR_RETURN( 2546 soc_reg32_set( 2547 unit, 2548 taf_interrupt_mapping[iter].sub_clear_regs[index], 2549 REG_PORT_ANY, 0, reg_value)); 2550 } 2551 } 2552 } 2553 2554 /* clear interrupt */ 2555 reg_value = taf_interrupt_status[unit]; 2556 BCM_IF_ERROR_RETURN( 2557 soc_reg32_set(unit, TAF_MEMFAILINT_CLRr, 2558 REG_PORT_ANY, 0, reg_value)); 2559 2560 taf_interrupt_handling[unit] = 0; 2561 return BCM_E_NONE; 2562 } 2563 2564 /* helper function to set maximum bytes */ 2565 STATIC int 2566 _bcmi_gh2_taf_gate_max_bytes_profile_set( 2567 int unit, int taf_gate_id, int profile_id, uint64 max_bytes) 2568 { 2569 taf_gate_control_entry_t mem_entry; 2570 int field_len; 2571 uint64 field_mask64; 2572 uint64 value_mask64; 2573 2574 assert(profile_id >= 0 && profile_id < TAF_MAXBYTE_PROFILE_NUM); 2575 2576 /* check value range */ 2577 field_len = soc_mem_field_length( 2578 unit, taf_maxbyte_profile_mem, 2579 taf_maxbyte_profile_field[profile_id]); 2580 COMPILER_64_SET(field_mask64, 0, 1); 2581 COMPILER_64_SHL(field_mask64, field_len); 2582 COMPILER_64_SUB_32(field_mask64, 1); 2583 2584 COMPILER_64_COPY(value_mask64, max_bytes); 2585 COMPILER_64_AND(value_mask64, field_mask64); 2586 if (COMPILER_64_NE(value_mask64, max_bytes)) { 2587 return BCM_E_PARAM; 2588 } 2589 2590 /* write field */ 2591 BCM_IF_ERROR_RETURN( 2592 soc_mem_read(unit, taf_maxbyte_profile_mem, MEM_BLOCK_ANY, 2593 taf_gate_id, &mem_entry)); 2594 2595 soc_mem_field64_set( 2596 unit, taf_maxbyte_profile_mem, &mem_entry, 2597 taf_maxbyte_profile_field[profile_id], max_bytes); 2598 2599 BCM_IF_ERROR_RETURN( 2600 soc_mem_write(unit, taf_maxbyte_profile_mem, MEM_BLOCK_ALL, 2601 taf_gate_id, &mem_entry)); 2602 2603 return BCM_E_NONE; 2604 } 2605 2606 /* helper function to get maximum bytes */ 2607 STATIC int 2608 _bcmi_gh2_taf_gate_max_bytes_profile_get( 2609 int unit, int taf_gate_id, int profile_id, uint64 *max_bytes) 2610 { 2611 taf_gate_control_entry_t mem_entry; 2612 2613 if (NULL == max_bytes) { 2614 return BCM_E_PARAM; 2615 } 2616 assert(profile_id >= 0 && profile_id < TAF_MAXBYTE_PROFILE_NUM); 2617 2618 BCM_IF_ERROR_RETURN( 2619 soc_mem_read(unit, taf_maxbyte_profile_mem, MEM_BLOCK_ANY, 2620 taf_gate_id, &mem_entry)); 2621 2622 soc_mem_field64_get(unit, taf_maxbyte_profile_mem, &mem_entry, 2623 taf_maxbyte_profile_field[profile_id], max_bytes); 2624 2625 return BCM_E_NONE; 2626 } 2627 2628 /* create profile of maximum bytes */ 2629 STATIC int 2630 bcmi_gh2_taf_gate_max_bytes_profile_create( 2631 int unit, int taf_gate_id, uint64 max_bytes, int *profile_id) 2632 { 2633 if (NULL == profile_id) { 2634 return BCM_E_PARAM; 2635 } 2636 assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM); 2637 2638 BCM_IF_ERROR_RETURN( 2639 shr_res_bitmap_alloc(taf_maxbyte_profile_bitmap[unit][taf_gate_id], 2640 0, 1, profile_id)); 2641 2642 if (*profile_id < 0 || *profile_id >= TAF_MAXBYTE_PROFILE_NUM || 2643 *profile_id == TAF_MAXBYTE_PROFILE_RESERVED_ID) { 2644 return BCM_E_INTERNAL; 2645 } 2646 2647 ERROR_RETURN_WITH_EXTRA_CLEAN( 2648 _bcmi_gh2_taf_gate_max_bytes_profile_set( 2649 unit, taf_gate_id, *profile_id, max_bytes), 2650 shr_res_bitmap_free(taf_maxbyte_profile_bitmap[unit][taf_gate_id], 2651 1, *profile_id)); 2652 2653 taf_maxbyte_profile_refcount[unit][taf_gate_id][*profile_id] = 1; 2654 2655 return BCM_E_NONE; 2656 } 2657 2658 /* set profile of maximum bytes */ 2659 STATIC int 2660 bcmi_gh2_taf_gate_max_bytes_profile_set( 2661 int unit, int taf_gate_id, int profile_id, uint64 max_bytes) 2662 { 2663 if (profile_id < 0 || profile_id >= TAF_MAXBYTE_PROFILE_NUM || 2664 profile_id == TAF_MAXBYTE_PROFILE_RESERVED_ID) { 2665 return BCM_E_PARAM; 2666 } 2667 assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM); 2668 2669 if (taf_maxbyte_profile_refcount[unit][taf_gate_id][profile_id] == 0) { 2670 return BCM_E_PARAM; 2671 } 2672 2673 BCM_IF_ERROR_RETURN( 2674 _bcmi_gh2_taf_gate_max_bytes_profile_set( 2675 unit, taf_gate_id, profile_id, max_bytes)); 2676 2677 return BCM_E_NONE; 2678 } 2679 2680 /* get profile of maximum bytes */ 2681 STATIC int 2682 bcmi_gh2_taf_gate_max_bytes_profile_get( 2683 int unit, int taf_gate_id, int profile_id, uint64 *max_bytes) 2684 { 2685 if (profile_id < 0 || profile_id >= TAF_MAXBYTE_PROFILE_NUM || 2686 profile_id == TAF_MAXBYTE_PROFILE_RESERVED_ID) { 2687 return BCM_E_PARAM; 2688 } 2689 assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM); 2690 2691 if (taf_maxbyte_profile_refcount[unit][taf_gate_id][profile_id] == 0) { 2692 return BCM_E_NOT_FOUND; 2693 } 2694 2695 BCM_IF_ERROR_RETURN( 2696 _bcmi_gh2_taf_gate_max_bytes_profile_get( 2697 unit, taf_gate_id, profile_id, max_bytes)); 2698 2699 return BCM_E_NONE; 2700 } 2701 2702 /* traverse profile of maximum bytes */ 2703 STATIC int 2704 bcmi_gh2_taf_gate_max_bytes_profile_traverse( 2705 int unit, int taf_gate_id, 2706 bcm_tsn_taf_gate_max_bytes_profile_traverse_cb cb, 2707 void *user_data) 2708 { 2709 int profile_id; 2710 2711 if (NULL == cb) { 2712 return BCM_E_PARAM; 2713 } 2714 2715 assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM); 2716 2717 for (profile_id = 0; profile_id < TAF_MAXBYTE_PROFILE_NUM; profile_id++) { 2718 if (TAF_MAXBYTE_PROFILE_RESERVED_ID == profile_id) { 2719 continue; 2720 } 2721 if (taf_maxbyte_profile_refcount[unit][taf_gate_id][profile_id] == 0) { 2722 continue; 2723 } 2724 BCM_IF_ERROR_RETURN( 2725 cb(unit, taf_gate_id, profile_id, user_data)); 2726 } 2727 2728 return BCM_E_NONE; 2729 } 2730 2731 /* destroy profile of maximum bytes */ 2732 STATIC int 2733 bcmi_gh2_taf_gate_max_bytes_profile_destroy( 2734 int unit, int taf_gate_id, int profile_id) 2735 { 2736 if (profile_id < 0 || profile_id >= TAF_MAXBYTE_PROFILE_NUM || 2737 profile_id == TAF_MAXBYTE_PROFILE_RESERVED_ID) { 2738 return BCM_E_PARAM; 2739 } 2740 2741 assert(taf_gate_id >= 0 && taf_gate_id < BCMI_TSN_TAF_GATE_NUM); 2742 2743 if (taf_maxbyte_profile_refcount[unit][taf_gate_id][profile_id] == 0) { 2744 return BCM_E_NOT_FOUND; 2745 } 2746 else if (taf_maxbyte_profile_refcount[unit][taf_gate_id][profile_id] > 1) { 2747 return BCM_E_BUSY; 2748 } 2749 2750 BCM_IF_ERROR_RETURN( 2751 shr_res_bitmap_free(taf_maxbyte_profile_bitmap[unit][taf_gate_id], 2752 1, profile_id)); 2753 taf_maxbyte_profile_refcount[unit][taf_gate_id][profile_id] = 0; 2754 2755 return BCM_E_NONE; 2756 } 2757 2758 /* helper function to set cosq mapping */ 2759 STATIC int 2760 _bcmi_gh2_taf_cosq_profile_set( 2761 int unit, int profile_id, bcm_cos_t prio, bcm_cos_queue_t cosq) 2762 { 2763 int select; 2764 2765 if (profile_id < 0 || profile_id >= TAF_COSQ_PROFILE_NUM || 2766 prio < 0 || prio >= TAF_COSQ_INTPRI_NUM) { 2767 return BCM_E_PARAM; 2768 } 2769 2770 BCM_IF_ERROR_RETURN( 2771 soc_mem_field32_fit(unit, taf_cosq_profile_mem, 2772 taf_cosq_profile_field, cosq)); 2773 2774 for (select = 0; select < TAF_COSQ_SELECT_NUM; select++) { 2775 BCM_IF_ERROR_RETURN( 2776 soc_mem_field32_modify( 2777 unit, taf_cosq_profile_mem, 2778 TAF_COSQ_HW_INDEX(profile_id, select, prio), 2779 taf_cosq_profile_field, cosq)); 2780 } 2781 return BCM_E_NONE; 2782 } 2783 2784 /* helper function to get cosq mapping */ 2785 STATIC int 2786 _bcmi_gh2_taf_cosq_profile_get( 2787 int unit, int profile_id, bcm_cos_t prio, bcm_cos_queue_t *cosq) 2788 { 2789 port_cos_map_entry_t mem_entry; 2790 2791 if (profile_id < 0 || profile_id >= TAF_COSQ_PROFILE_NUM || 2792 prio < 0 || prio >= TAF_COSQ_INTPRI_NUM) { 2793 return BCM_E_PARAM; 2794 } 2795 2796 if (NULL == cosq) { 2797 return BCM_E_PARAM; 2798 } 2799 2800 BCM_IF_ERROR_RETURN( 2801 soc_mem_read(unit, taf_cosq_profile_mem, MEM_BLOCK_ANY, 2802 TAF_COSQ_HW_INDEX(profile_id, 0, prio), 2803 &mem_entry)); 2804 2805 *cosq = soc_mem_field32_get(unit, taf_cosq_profile_mem, &mem_entry, 2806 taf_cosq_profile_field); 2807 return BCM_E_NONE; 2808 } 2809 2810 /* create profile of cosq mapping */ 2811 STATIC int 2812 bcmi_gh2_taf_cosq_mapping_profile_create( 2813 int unit, int *cosq_profile) 2814 { 2815 if (NULL == cosq_profile) { 2816 return BCM_E_PARAM; 2817 } 2818 2819 BCM_IF_ERROR_RETURN( 2820 shr_res_bitmap_alloc(taf_cosq_profile_bitmap[unit], 2821 0, 1, cosq_profile)); 2822 2823 if (*cosq_profile < 0 || *cosq_profile >= TAF_COSQ_PROFILE_NUM || 2824 *cosq_profile == TAF_COSQ_PROFILE_RESERVED_ID) { 2825 return BCM_E_INTERNAL; 2826 } 2827 2828 taf_cosq_profile_refcount[unit][*cosq_profile] = 1; 2829 2830 return BCM_E_NONE; 2831 } 2832 2833 /* set profile of cosq mapping */ 2834 STATIC int 2835 bcmi_gh2_taf_cosq_mapping_profile_set( 2836 int unit, int cosq_profile, bcm_cos_t priority, bcm_cos_queue_t cosq) 2837 { 2838 if (cosq_profile < 0 || cosq_profile >= TAF_COSQ_PROFILE_NUM || 2839 cosq_profile == TAF_COSQ_PROFILE_RESERVED_ID) { 2840 return BCM_E_PARAM; 2841 } 2842 2843 if (taf_cosq_profile_refcount[unit][cosq_profile] == 0) { 2844 return BCM_E_PARAM; 2845 } 2846 2847 BCM_IF_ERROR_RETURN( 2848 _bcmi_gh2_taf_cosq_profile_set( 2849 unit, cosq_profile, priority, cosq)); 2850 2851 return BCM_E_NONE; 2852 } 2853 2854 /* get profile of cosq mapping */ 2855 STATIC int 2856 bcmi_gh2_taf_cosq_mapping_profile_get( 2857 int unit, int cosq_profile, bcm_cos_t priority, bcm_cos_queue_t *cosq) 2858 { 2859 if (cosq_profile < 0 || cosq_profile >= TAF_COSQ_PROFILE_NUM || 2860 cosq_profile == TAF_COSQ_PROFILE_RESERVED_ID) { 2861 return BCM_E_PARAM; 2862 } 2863 2864 if (taf_cosq_profile_refcount[unit][cosq_profile] == 0) { 2865 return BCM_E_NOT_FOUND; 2866 } 2867 2868 BCM_IF_ERROR_RETURN( 2869 _bcmi_gh2_taf_cosq_profile_get( 2870 unit, cosq_profile, priority, cosq)); 2871 2872 return BCM_E_NONE; 2873 } 2874 2875 /* traverse profile of cosq mapping */ 2876 STATIC int 2877 bcmi_gh2_taf_cosq_mapping_profile_traverse( 2878 int unit, 2879 bcm_tsn_taf_cosq_mapping_profile_traverse_cb cb, 2880 void *user_data) 2881 { 2882 int profile_id; 2883 2884 if (NULL == cb) { 2885 return BCM_E_PARAM; 2886 } 2887 2888 for (profile_id = 0; profile_id < TAF_COSQ_PROFILE_NUM; profile_id++) { 2889 if (TAF_COSQ_PROFILE_RESERVED_ID == profile_id) { 2890 continue; 2891 } 2892 if (taf_cosq_profile_refcount[unit][profile_id] == 0) { 2893 continue; 2894 } 2895 BCM_IF_ERROR_RETURN(cb(unit, profile_id, user_data)); 2896 } 2897 2898 return BCM_E_NONE; 2899 } 2900 2901 /* destroy profile of cosq mapping */ 2902 STATIC int 2903 bcmi_gh2_taf_cosq_mapping_profile_destroy( 2904 int unit, int cosq_profile) 2905 { 2906 if (cosq_profile < 0 || cosq_profile >= TAF_COSQ_PROFILE_NUM || 2907 cosq_profile == TAF_COSQ_PROFILE_RESERVED_ID) { 2908 return BCM_E_PARAM; 2909 } 2910 2911 if (taf_cosq_profile_refcount[unit][cosq_profile] == 0) { 2912 return BCM_E_NOT_FOUND; 2913 } else if (taf_cosq_profile_refcount[unit][cosq_profile] > 1) { 2914 return BCM_E_BUSY; 2915 } 2916 2917 BCM_IF_ERROR_RETURN( 2918 shr_res_bitmap_free(taf_cosq_profile_bitmap[unit], 1, cosq_profile)); 2919 taf_cosq_profile_refcount[unit][cosq_profile] = 0; 2920 2921 return BCM_E_NONE; 2922 } 2923 2924 /* 2925 * update flow counter for both hw table and sw database(taf_gate_counter) 2926 * 2927 * if is_write = 0 : read hw data and sync back to sw 2928 * if is_write = 1 : write parameter "write_val" into both sw/hw 2929 */ 2930 STATIC int 2931 bcmi_gh2_taf_gate_stat_counter_update( 2932 int unit, 2933 int taf_gate_id, 2934 bcm_tsn_taf_gate_stat_t stat_type_min, 2935 bcm_tsn_taf_gate_stat_t stat_type_max, 2936 int is_write, 2937 uint64 write_val) 2938 { 2939 bcm_tsn_taf_gate_stat_t stat_type; 2940 2941 if (taf_gate_id < 0 || 2942 taf_gate_id >= BCMI_TSN_TAF_GATE_NUM || 2943 stat_type_min >= bcmTsnTafGateStatCount || 2944 stat_type_max >= bcmTsnTafGateStatCount || 2945 stat_type_min > stat_type_max) { 2946 return BCM_E_PARAM; 2947 } 2948 2949 for (stat_type = stat_type_min; stat_type <= stat_type_max; stat_type++) { 2950 soc_mem_t mem = taf_gate_cnt_mem[stat_type]; 2951 soc_field_t field = taf_gate_cnt_field[stat_type]; 2952 soc_memacc_t memacc_count; 2953 uint64 *update_array_ptr = taf_gate_counter[unit][stat_type]; 2954 uint8 *buffer_ptr = taf_gate_counter_dma_buffer[unit][stat_type]; 2955 uint64 count_mask64; 2956 2957 BCM_IF_ERROR_RETURN( 2958 soc_memacc_init(unit, mem, field, &memacc_count)); 2959 2960 COMPILER_64_SET(count_mask64, 0, 1); 2961 COMPILER_64_SHL(count_mask64, soc_mem_field_length(unit, mem, field)); 2962 COMPILER_64_SUB_32(count_mask64, 1); 2963 2964 if (0 == is_write) { 2965 /* read hw data and sync to sw */ 2966 uint64 hw_count, sw_last_count; 2967 2968 BCM_IF_ERROR_RETURN( 2969 soc_mem_read(unit, mem, MEM_BLOCK_ANY, 2970 taf_gate_id, buffer_ptr)); 2971 soc_memacc_field64_get(&memacc_count, buffer_ptr, &hw_count); 2972 COMPILER_64_COPY(sw_last_count, update_array_ptr[taf_gate_id]); 2973 COMPILER_64_AND(sw_last_count, count_mask64); 2974 2975 if (COMPILER_64_GT(sw_last_count, hw_count)) { 2976 LOG_VERBOSE(BSL_LS_BCM_TSN, 2977 (BSL_META_U(unit, 2978 "Roll over happened\n"))); 2979 LOG_VERBOSE(BSL_LS_BCM_TSN, 2980 (BSL_META_U(unit, 2981 ".Read Packet64 Count: %x:%x\n"), 2982 COMPILER_64_HI(hw_count), 2983 COMPILER_64_LO(hw_count))); 2984 COMPILER_64_ADD_64(hw_count, count_mask64); 2985 COMPILER_64_ADD_32(hw_count, 1); 2986 COMPILER_64_SUB_64(hw_count, sw_last_count); 2987 LOG_VERBOSE(BSL_LS_BCM_TSN, 2988 (BSL_META_U(unit, 2989 ".Diffed 64-Packet Count: %x:%x\n"), 2990 COMPILER_64_HI(hw_count), 2991 COMPILER_64_LO(hw_count))); 2992 } else { 2993 COMPILER_64_SUB_64(hw_count, sw_last_count); 2994 } 2995 2996 /* Add difference (if it is) */ 2997 if (!COMPILER_64_IS_ZERO(hw_count)) { 2998 LOG_VERBOSE(BSL_LS_BCM_TSN, 2999 (BSL_META_U(unit, 3000 "gate id:%d==>" 3001 "Old 64-Packet Count Value%x:%x\t"), 3002 taf_gate_id, 3003 COMPILER_64_HI(update_array_ptr[taf_gate_id]), 3004 COMPILER_64_LO(update_array_ptr[taf_gate_id]))); 3005 COMPILER_64_ADD_64(update_array_ptr[taf_gate_id], hw_count); 3006 LOG_VERBOSE(BSL_LS_BCM_TSN, 3007 (BSL_META_U(unit, 3008 "New 64-Packet Value : %x:%x\n"), 3009 COMPILER_64_HI(update_array_ptr[taf_gate_id]), 3010 COMPILER_64_LO(update_array_ptr[taf_gate_id]))); 3011 } 3012 } else { 3013 /* write hw */ 3014 uint64 write_val_after_mask; 3015 3016 COMPILER_64_COPY(write_val_after_mask, write_val); 3017 COMPILER_64_AND(write_val_after_mask, count_mask64); 3018 if (COMPILER_64_NE(write_val_after_mask, write_val)) { 3019 return BCM_E_PARAM; 3020 } 3021 soc_memacc_field64_set(&memacc_count, buffer_ptr, 3022 write_val_after_mask); 3023 BCM_IF_ERROR_RETURN( 3024 soc_mem_write(unit, mem, MEM_BLOCK_ALL, 3025 taf_gate_id, buffer_ptr)); 3026 3027 /* write sw */ 3028 COMPILER_64_COPY(update_array_ptr[taf_gate_id], write_val); 3029 } 3030 } 3031 3032 return BCM_E_NONE; 3033 } 3034 3035 /* helper function for taf gate counter access */ 3036 STATIC int 3037 bcmi_gh2_taf_gate_stat_counter_access( 3038 int unit, 3039 int taf_gate_id, 3040 uint32 arr_cnt, 3041 bcm_tsn_taf_gate_stat_t *stat_type_arr, 3042 uint64 *stat_value_arr, 3043 bcmi_tsn_stat_counter_action_t action) 3044 { 3045 int arr_idx; 3046 3047 if (NULL == stat_type_arr || NULL == stat_value_arr || 3048 taf_gate_id >= BCMI_TSN_TAF_GATE_NUM || 3049 taf_gate_id < 0) { 3050 return BCM_E_PARAM; 3051 } 3052 3053 for (arr_idx = 0; arr_idx < arr_cnt; arr_idx++) { 3054 int is_write = 0; 3055 3056 if (stat_type_arr[arr_idx] < 0 || 3057 stat_type_arr[arr_idx] >= bcmTsnTafGateStatCount) { 3058 return BCM_E_PARAM; 3059 } 3060 3061 /* update taf gate counter for both hw table and sw database */ 3062 switch (action) { 3063 case bcmiTsnStatCounterActionWrite: 3064 is_write = 1; 3065 /* fall through */ 3066 case bcmiTsnStatCounterActionReadSync: 3067 BCM_IF_ERROR_RETURN( 3068 bcmi_gh2_taf_gate_stat_counter_update( 3069 unit, taf_gate_id, 3070 stat_type_arr[arr_idx], stat_type_arr[arr_idx], 3071 is_write, stat_value_arr[arr_idx])); 3072 break; 3073 case bcmiTsnStatCounterActionRead: 3074 break; 3075 default: 3076 return BCM_E_INTERNAL; 3077 } 3078 3079 /* read sw database if need */ 3080 if (bcmiTsnStatCounterActionWrite != action) { 3081 uint64 *sw_array_ptr = 3082 taf_gate_counter[unit][stat_type_arr[arr_idx]]; 3083 COMPILER_64_COPY(stat_value_arr[arr_idx], 3084 sw_array_ptr[taf_gate_id]); 3085 } 3086 } 3087 3088 return BCM_E_NONE; 3089 } 3090 3091 /* callback for taf gate counter, just need to update the enabled gate */ 3092 STATIC int 3093 bcmi_gh2_taf_gate_stat_counter_sync(int unit, int taf_gate_id) 3094 { 3095 uint64 value_64_zero; 3096 3097 COMPILER_64_ZERO(value_64_zero); 3098 3099 BCM_IF_ERROR_RETURN( 3100 bcmi_gh2_taf_gate_stat_counter_update( 3101 unit, taf_gate_id, 3102 0, bcmTsnTafGateStatCount -1, 0, value_64_zero)); 3103 3104 return BCM_E_NONE; 3105 } 3106 3107 /* cleanup the resource for TAF */ 3108 STATIC int 3109 bcmi_gh2_taf_cleanup(int unit) 3110 { 3111 int i, j; 3112 gh2_taf_interrupt_type_t iter; 3113 bcm_tsn_taf_gate_stat_t stat_type; 3114 3115 /* disable interupt mask */ 3116 for (iter = 0; iter < TafInterruptCount; iter++) { 3117 soc_reg_field32_modify( 3118 unit, TAF_MEMFAILINTMASKr, REG_PORT_ANY, 3119 taf_interrupt_mapping[iter].mask_field, 0); 3120 } 3121 3122 /* taf gate alloc bitmap */ 3123 if (NULL != taf_gate_bitmap[unit]) { 3124 shr_res_bitmap_free(taf_gate_bitmap[unit], 1, 3125 TAF_GATE_RESERVED_ID); 3126 shr_res_bitmap_destroy(taf_gate_bitmap[unit]); 3127 taf_gate_bitmap[unit] = NULL; 3128 } 3129 3130 /* taf calendar */ 3131 if (NULL != taf_schedule_calendar_buf[unit]) { 3132 soc_cm_sfree(unit, taf_schedule_calendar_buf[unit]); 3133 taf_schedule_calendar_buf[unit] = NULL; 3134 } 3135 3136 for (i = 0; i < BCMI_TSN_TAF_GATE_NUM; i++) { 3137 bcmi_tsn_taf_schedule_entry_t *entry_iter = NULL; 3138 bcmi_tsn_taf_schedule_entry_t *entry_next = NULL; 3139 3140 entry_iter = taf_schedule_timeline[unit][i]; 3141 while (entry_iter != NULL) { 3142 entry_next = entry_iter->next; 3143 sal_free(entry_iter); 3144 entry_iter = entry_next; 3145 } 3146 taf_schedule_timeline[unit][i] = NULL; 3147 } 3148 3149 /* taf profile */ 3150 if (NULL != taf_schedule_profile_bitmap[unit]) { 3151 shr_res_bitmap_destroy(taf_schedule_profile_bitmap[unit]); 3152 taf_schedule_profile_bitmap[unit] = NULL; 3153 } 3154 for (i = 0; i < BCMI_TSN_TAF_PROFILE_NUM_MAX; i++) { 3155 if (NULL != taf_schedule_profile[unit][i]) { 3156 sal_free(taf_schedule_profile[unit][i]); 3157 taf_schedule_profile[unit][i] = NULL; 3158 } 3159 } 3160 /* taf event handler */ 3161 for (i = 0; i < BCMI_TSN_TAF_GATE_NUM; i++) { 3162 for (j = 0; j < bcmTsnTafEventCount; j++) { 3163 if (NULL != taf_event_handler_list[unit][i][j]) { 3164 bcmi_tsn_taf_event_handler_t *event_handler_iter; 3165 bcmi_tsn_taf_event_handler_t *event_handler_next; 3166 3167 event_handler_iter = taf_event_handler_list[unit][i][j]; 3168 while (NULL != event_handler_iter) { 3169 event_handler_next = event_handler_iter->next; 3170 sal_free(event_handler_iter); 3171 event_handler_iter = event_handler_next; 3172 } 3173 taf_event_handler_list[unit][i][j] = NULL; 3174 } 3175 } 3176 } 3177 /* taf interrupt handler */ 3178 taf_interrupt_handling[unit] = 0; 3179 3180 /* maxbyte profile */ 3181 for (i = 0; i < BCMI_TSN_TAF_GATE_NUM; i++) { 3182 if (NULL != taf_maxbyte_profile_bitmap[unit][i]) { 3183 shr_res_bitmap_free(taf_maxbyte_profile_bitmap[unit][i], 1, 3184 TAF_MAXBYTE_PROFILE_RESERVED_ID); 3185 shr_res_bitmap_destroy(taf_maxbyte_profile_bitmap[unit][i]); 3186 taf_maxbyte_profile_bitmap[unit][i] = NULL; 3187 } 3188 } 3189 3190 /* cosq profile */ 3191 if (NULL != taf_cosq_profile_bitmap[unit]) { 3192 shr_res_bitmap_free(taf_cosq_profile_bitmap[unit], 1, 3193 TAF_COSQ_PROFILE_RESERVED_ID); 3194 shr_res_bitmap_destroy(taf_cosq_profile_bitmap[unit]); 3195 taf_cosq_profile_bitmap[unit] = NULL; 3196 } 3197 3198 /* gate stat */ 3199 for (stat_type = 0; stat_type < bcmTsnTafGateStatCount; stat_type++) { 3200 if (NULL != taf_gate_counter[unit][stat_type]) { 3201 sal_free(taf_gate_counter[unit][stat_type]); 3202 taf_gate_counter[unit][stat_type] = NULL; 3203 } 3204 if (NULL != taf_gate_counter_dma_buffer[unit][stat_type]) { 3205 soc_cm_sfree(unit, taf_gate_counter_dma_buffer[unit][stat_type]); 3206 taf_gate_counter_dma_buffer[unit][stat_type] = NULL; 3207 } 3208 } 3209 3210 return BCM_E_NONE; 3211 } 3212 3213 /* init the resource for TAF */ 3214 STATIC int 3215 bcmi_gh2_taf_init(int unit) 3216 { 3217 int i, j, entry_count, default_gate, entry_byte, default_profile; 3218 gh2_taf_interrupt_type_t iter; 3219 bcm_tsn_taf_gate_stat_t stat_type; 3220 3221 /* taf gate alloc bitmap */ 3222 default_gate = TAF_GATE_RESERVED_ID; 3223 TAF_INIT_ERROR_RETURN_WITH_CLEAN( 3224 shr_res_bitmap_create(&taf_gate_bitmap[unit], 0, 3225 BCMI_TSN_TAF_GATE_NUM)); 3226 TAF_INIT_ERROR_RETURN_WITH_CLEAN( 3227 shr_res_bitmap_alloc(taf_gate_bitmap[unit], 3228 SHR_RES_BITMAP_ALLOC_WITH_ID, 1, &default_gate)); 3229 for (i = 0; i < BCMI_TSN_TAF_GATE_NUM; i++) { 3230 taf_gate_refcount[unit][i] = 0; 3231 } 3232 3233 /* taf primap */ 3234 entry_count = soc_mem_index_count(unit, taf_gate_pri_map_mem); 3235 if ((TAF_GATE_PRI_MAP_PROFILE_MASK | TAF_GATE_PRI_MAP_INTPRI_MASK | 3236 TAF_GATE_PRI_MAP_PREEMPT_MASK) >= entry_count) { 3237 TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL); 3238 } 3239 3240 /* taf profile */ 3241 TAF_INIT_ERROR_RETURN_WITH_CLEAN( 3242 shr_res_bitmap_create(&taf_schedule_profile_bitmap[unit], 3243 0, BCMI_TSN_TAF_PROFILE_NUM_MAX)); 3244 3245 /* taf calendar */ 3246 entry_byte = WORDS2BYTES( 3247 soc_mem_entry_words(unit, taf_schedule_calendar_mem[0][0])); 3248 taf_schedule_calendar_buf[unit] = 3249 soc_cm_salloc(unit, TAF_SCHEDULE_CALENDAR_ENTIRES * entry_byte, 3250 "taf schedule calendar buffer"); 3251 if (NULL == taf_schedule_calendar_buf[unit]) { 3252 TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL); 3253 } 3254 3255 /* enable interupt mask */ 3256 for (iter = 0; iter < TafInterruptCount; iter++) { 3257 soc_reg_field32_modify( 3258 unit, TAF_MEMFAILINTMASKr, REG_PORT_ANY, 3259 taf_interrupt_mapping[iter].mask_field, 1); 3260 } 3261 3262 /* maxbyte profile */ 3263 default_profile = TAF_MAXBYTE_PROFILE_RESERVED_ID; 3264 for (i = 0; i < BCMI_TSN_TAF_GATE_NUM; i++) { 3265 uint64 default_value; 3266 int field_len; 3267 3268 TAF_INIT_ERROR_RETURN_WITH_CLEAN( 3269 shr_res_bitmap_create(&taf_maxbyte_profile_bitmap[unit][i], 0, 3270 TAF_MAXBYTE_PROFILE_NUM)); 3271 TAF_INIT_ERROR_RETURN_WITH_CLEAN( 3272 shr_res_bitmap_alloc(taf_maxbyte_profile_bitmap[unit][i], 3273 SHR_RES_BITMAP_ALLOC_WITH_ID, 1, 3274 &default_profile)); 3275 for (j = 0; j < TAF_MAXBYTE_PROFILE_NUM; j++) { 3276 taf_maxbyte_profile_refcount[unit][i][j] = 0; 3277 } 3278 3279 /* set default_value to 0xFFFFFFFFF */ 3280 field_len = soc_mem_field_length( 3281 unit, taf_maxbyte_profile_mem, 3282 taf_maxbyte_profile_field[default_profile]); 3283 COMPILER_64_SET(default_value, 0, 1); 3284 COMPILER_64_SHL(default_value, field_len); 3285 COMPILER_64_SUB_32(default_value, 1); 3286 TAF_INIT_ERROR_RETURN_WITH_CLEAN( 3287 _bcmi_gh2_taf_gate_max_bytes_profile_set( 3288 unit, i, default_profile, default_value)); 3289 } 3290 3291 /* cosq profile */ 3292 entry_count = soc_mem_index_count(unit, taf_cosq_profile_mem); 3293 if ((TAF_COSQ_INTPRI_MASK | TAF_COSQ_SELECT_MASK | 3294 TAF_COSQ_PROFILE_MASK) >= entry_count) { 3295 TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL); 3296 } 3297 3298 default_profile = TAF_COSQ_PROFILE_RESERVED_ID; 3299 TAF_INIT_ERROR_RETURN_WITH_CLEAN( 3300 shr_res_bitmap_create(&taf_cosq_profile_bitmap[unit], 0, 3301 TAF_COSQ_PROFILE_NUM)); 3302 TAF_INIT_ERROR_RETURN_WITH_CLEAN( 3303 shr_res_bitmap_alloc(taf_cosq_profile_bitmap[unit], 3304 SHR_RES_BITMAP_ALLOC_WITH_ID, 1, 3305 &default_profile)); 3306 for (i = 0; i < TAF_COSQ_PROFILE_NUM; i++) { 3307 taf_cosq_profile_refcount[unit][i] = 0; 3308 } 3309 3310 /* gate stat */ 3311 for (stat_type = 0; stat_type < bcmTsnTafGateStatCount; stat_type++) { 3312 /* verify memory informaion */ 3313 if (soc_mem_index_count(unit, taf_gate_cnt_mem[stat_type]) 3314 != BCMI_TSN_TAF_GATE_NUM) { 3315 TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL); 3316 } 3317 3318 if (!soc_mem_field_valid(unit, taf_gate_cnt_mem[stat_type], 3319 taf_gate_cnt_field[stat_type])) { 3320 TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL); 3321 } 3322 3323 /* allocate sw database */ 3324 taf_gate_counter[unit][stat_type] = 3325 sal_alloc(BCMI_TSN_TAF_GATE_NUM * sizeof(uint64), 3326 "taf gate counter"); 3327 if (NULL == taf_gate_counter[unit][stat_type]) { 3328 TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY); 3329 } 3330 3331 taf_gate_counter_dma_buffer[unit][stat_type] = 3332 soc_cm_salloc(unit, BCMI_TSN_TAF_GATE_NUM * 3333 WORDS2BYTES( 3334 soc_mem_entry_words(unit, 3335 taf_gate_cnt_mem[stat_type])), 3336 "taf gate counter buffer"); 3337 if (NULL == taf_gate_counter_dma_buffer[unit][stat_type]) { 3338 TAF_INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY); 3339 } 3340 } 3341 3342 return BCM_E_NONE; 3343 } 3344 3345 #if defined(BCM_WARM_BOOT_SUPPORT) 3346 STATIC int 3347 bcmi_gh2_taf_get_scache_size( 3348 int unit, int *size) 3349 { 3350 if (NULL == size) { 3351 return BCM_E_PARAM; 3352 } 3353 3354 *size = 0; 3355 3356 /* taf gate */ 3357 *size += BCMI_TSN_TAF_GATE_NUM * sizeof(uint32); 3358 3359 /* maxbyte profile */ 3360 *size += BCMI_TSN_TAF_GATE_NUM * TAF_MAXBYTE_PROFILE_NUM * sizeof(uint32); 3361 3362 /* cosq profile */ 3363 *size += TAF_COSQ_PROFILE_NUM * sizeof(uint32); 3364 3365 /* taf schedule timelime 3366 * max possible = 3367 * total count (32 bit) + 3368 * profile_max_num * (gate id (32 bit) + count N (32 bit) + 3369 * basetime (96 bit)) 3370 */ 3371 *size += sizeof(uint32); 3372 *size += BCMI_TSN_TAF_PROFILE_NUM_MAX * (sizeof(uint32) * 5); 3373 3374 /* taf schedule profile 3375 * max possible = 3376 * total count (32 bit) + 3377 * profile_max_num * (profile id(32 bit) + taf_gate(32 bit) + 3378 * status(32 bit) + config_change_time(96 bit) + 3379 * data + schedule_index(32 bit)) 3380 */ 3381 *size += sizeof(uint32); 3382 *size += BCMI_TSN_TAF_PROFILE_NUM_MAX * 3383 (sizeof(uint32) * 7 + sizeof(bcm_tsn_taf_profile_t)); 3384 return BCM_E_NONE; 3385 } 3386 3387 3388 /* sync taf info to scache */ 3389 STATIC int 3390 bcmi_gh2_taf_sync( 3391 int unit, uint8 *scache_ptr) 3392 { 3393 int conut_schedule, conut_profile, profile_id, schedule_id; 3394 uint32 gate_id; 3395 bcmi_tsn_taf_schedule_entry_t *schedule_entry_cache 3396 [BCMI_TSN_TAF_PROFILE_NUM_MAX]; 3397 3398 if (NULL == scache_ptr) { 3399 return BCM_E_PARAM; 3400 } 3401 sal_memset(schedule_entry_cache, 0, 3402 BCMI_TSN_TAF_PROFILE_NUM_MAX * 3403 sizeof(bcmi_tsn_taf_schedule_entry_t *)); 3404 3405 /* taf gate */ 3406 WRITE_PTR_RANGE(scache_ptr, BCMI_TSN_TAF_GATE_NUM * sizeof(uint32), 3407 taf_gate_refcount[unit]); 3408 3409 /* maxbyte profile */ 3410 for (gate_id = 0; gate_id < BCMI_TSN_TAF_GATE_NUM; gate_id++) { 3411 WRITE_PTR_RANGE(scache_ptr, TAF_MAXBYTE_PROFILE_NUM * sizeof(uint32), 3412 taf_maxbyte_profile_refcount[unit][gate_id]); 3413 } 3414 3415 /* cosq profile */ 3416 WRITE_PTR_RANGE(scache_ptr, TAF_COSQ_PROFILE_NUM * sizeof(uint32), 3417 taf_cosq_profile_refcount[unit]); 3418 3419 /* taf schedule timelime 3420 * Format : count (32 bit) + 3421 * [ gate id (32 bit) + count N (32 bit) + 3422 * basetime_1(96 bit) + ... + basetime_N(96 bit) ] 3423 * 3424 * ex. gate 1 : basetime_0, basetime_1, basetime_2 3425 * gate 3 : basetime_3 3426 * 3427 * ==> In scache: 3428 * 1 (32 bit) 3 (32 bit) basetime_1(96 bit) basetime_2(96 bit) 3429 * basetime_3(96 bit) 3 (32 bit) 1 (32 bit) basetime_4(96 bit) 3430 * 3431 * BTW, we'll have another cache array to record all schedule entries 3432 */ 3433 conut_schedule = 0; 3434 for (gate_id = 0; gate_id < BCMI_TSN_TAF_GATE_NUM; gate_id++) { 3435 if (NULL != taf_schedule_timeline[unit][gate_id]) { 3436 bcmi_tsn_taf_schedule_entry_t *iter; 3437 3438 iter = taf_schedule_timeline[unit][gate_id]; 3439 while (iter != NULL) { 3440 conut_schedule++; 3441 iter = iter->next; 3442 } 3443 } 3444 } 3445 3446 WRITE_PTR(scache_ptr, uint32, conut_schedule); 3447 schedule_id = 0; 3448 for (gate_id = 0; gate_id < BCMI_TSN_TAF_GATE_NUM; gate_id++) { 3449 if (NULL != taf_schedule_timeline[unit][gate_id]) { 3450 uint32 count_per_gate = 0; 3451 bcmi_tsn_taf_schedule_entry_t *iter; 3452 3453 /* write "gate id" and "count" into scache */ 3454 iter = taf_schedule_timeline[unit][gate_id]; 3455 while (iter != NULL) { 3456 count_per_gate++; 3457 iter = iter->next; 3458 } 3459 3460 WRITE_PTR(scache_ptr, uint32, gate_id); 3461 WRITE_PTR(scache_ptr, uint32, count_per_gate); 3462 3463 /* write each "basetime" into scache */ 3464 iter = taf_schedule_timeline[unit][gate_id]; 3465 while (iter != NULL) { 3466 WRITE_PTR(scache_ptr, uint32, 3467 COMPILER_64_LO(iter->schedule_time.seconds)); 3468 WRITE_PTR(scache_ptr, uint32, 3469 COMPILER_64_HI(iter->schedule_time.seconds)); 3470 WRITE_PTR(scache_ptr, uint32, 3471 iter->schedule_time.nanoseconds); 3472 3473 assert(schedule_id < BCMI_TSN_TAF_PROFILE_NUM_MAX); 3474 schedule_entry_cache[schedule_id++] = iter; 3475 3476 iter = iter->next; 3477 } 3478 } 3479 } 3480 3481 /* taf schedule profile 3482 * Format : count (32 bit) + 3483 * [ profile id (32 bit) + taf_gate (32 bit) + status (32 bit) + 3484 * config_change_time(96 bit) + 3485 * data(bcm_tsn_taf_profile_t) + schedule_entry index (32 bit) ] 3486 * 3487 * ex. profile 0 : schedule = NULL 3488 * profile 1 : schedule = basetime_2 3489 * profile 2 : schedule = basetime_3 3490 * profile 4 : schedule = NULL 3491 * profile 6 : schedule = basetime_1 3492 * profile 7 : schedule = basetime_0 3493 * 3494 * ==> In scache: 3495 * 6 (32 bit) 3496 * 0 (32 bit) taf_gate status data -1(32 bit) 3497 * 1 (32 bit) taf_gate status data 2(32 bit) 3498 * 2 (32 bit) taf_gate status data 3(32 bit) 3499 * 4 (32 bit) taf_gate status data -1(32 bit) 3500 * 6 (32 bit) taf_gate status data 1(32 bit) 3501 * 7 (32 bit) taf_gate status data 0(32 bit) 3502 */ 3503 conut_profile = 0; 3504 for (profile_id = 0; profile_id < BCMI_TSN_TAF_PROFILE_NUM_MAX; 3505 profile_id++) { 3506 if (NULL != taf_schedule_profile[unit][profile_id]) { 3507 conut_profile++; 3508 } 3509 } 3510 3511 WRITE_PTR(scache_ptr, uint32, conut_profile); 3512 3513 for (profile_id = 0; profile_id < BCMI_TSN_TAF_PROFILE_NUM_MAX; 3514 profile_id++) { 3515 bcmi_tsn_taf_profile_t *iter = taf_schedule_profile[unit][profile_id]; 3516 3517 if (NULL == iter) { 3518 continue; 3519 } 3520 3521 WRITE_PTR(scache_ptr, uint32, profile_id); 3522 WRITE_PTR(scache_ptr, uint32, (uint32)(iter->taf_gate)); 3523 WRITE_PTR(scache_ptr, uint32, (uint32)(iter->status)); 3524 WRITE_PTR(scache_ptr, uint32, 3525 COMPILER_64_LO(iter->config_change_time.seconds)); 3526 WRITE_PTR(scache_ptr, uint32, 3527 COMPILER_64_HI(iter->config_change_time.seconds)); 3528 WRITE_PTR(scache_ptr, uint32, 3529 iter->config_change_time.nanoseconds); 3530 WRITE_PTR_RANGE(scache_ptr, sizeof(bcm_tsn_taf_profile_t), 3531 &(iter->data)); 3532 3533 if (NULL == iter->schedule) { 3534 WRITE_PTR(scache_ptr, uint32, (uint32)-1); 3535 } else { 3536 /* search the index */ 3537 int found = -1; 3538 3539 for (schedule_id = 0; schedule_id < conut_schedule; schedule_id++) { 3540 if (schedule_entry_cache[schedule_id] == iter->schedule) { 3541 found = schedule_id; 3542 break; 3543 } 3544 } 3545 if (-1 == found) { 3546 return BCM_E_INTERNAL; /* should not happen */ 3547 } 3548 3549 WRITE_PTR(scache_ptr, uint32, found); 3550 } 3551 } 3552 3553 return BCM_E_NONE; 3554 } 3555 3556 /* restore taf info from scache and hw */ 3557 STATIC int 3558 bcmi_gh2_taf_reload( 3559 int unit, uint8 *scache_ptr) 3560 { 3561 int gate_id, profile_id, entry_index, schedule_id; 3562 uint32 conut_schedule, conut_profile; 3563 bcmi_tsn_taf_schedule_entry_t *schedule_entry_cache 3564 [BCMI_TSN_TAF_PROFILE_NUM_MAX]; 3565 3566 if (NULL == scache_ptr) { 3567 return BCM_E_PARAM; 3568 } 3569 sal_memset(schedule_entry_cache, 0, 3570 BCMI_TSN_TAF_PROFILE_NUM_MAX * 3571 sizeof(bcmi_tsn_taf_schedule_entry_t *)); 3572 3573 /* taf gate */ 3574 READ_PTR_RANGE(scache_ptr, BCMI_TSN_TAF_GATE_NUM * sizeof(uint32), 3575 taf_gate_refcount[unit]); 3576 3577 for (gate_id = 0; gate_id < BCMI_TSN_TAF_GATE_NUM; gate_id++) { 3578 if (taf_gate_refcount[unit][gate_id] != 0) { 3579 BCM_IF_ERROR_RETURN( 3580 shr_res_bitmap_alloc(taf_gate_bitmap[unit], 3581 SHR_RES_BITMAP_ALLOC_WITH_ID, 3582 1, (int *)&gate_id)); 3583 } 3584 } 3585 3586 /* maxbyte profile */ 3587 for (gate_id = 0; gate_id < BCMI_TSN_TAF_GATE_NUM; gate_id++) { 3588 READ_PTR_RANGE(scache_ptr, TAF_MAXBYTE_PROFILE_NUM * sizeof(uint32), 3589 taf_maxbyte_profile_refcount[unit][gate_id]); 3590 3591 for (profile_id = 0; profile_id < TAF_MAXBYTE_PROFILE_NUM; 3592 profile_id++) { 3593 if (taf_maxbyte_profile_refcount[unit][gate_id][profile_id] != 0) { 3594 BCM_IF_ERROR_RETURN( 3595 shr_res_bitmap_alloc( 3596 taf_maxbyte_profile_bitmap[unit][gate_id], 3597 SHR_RES_BITMAP_ALLOC_WITH_ID, 1, (int *)&profile_id)); 3598 } 3599 } 3600 } 3601 3602 /* cosq profile */ 3603 READ_PTR_RANGE(scache_ptr, TAF_COSQ_PROFILE_NUM * sizeof(uint32), 3604 taf_cosq_profile_refcount[unit]); 3605 3606 for (profile_id = 0; profile_id < TAF_COSQ_PROFILE_NUM; profile_id++) { 3607 if (taf_cosq_profile_refcount[unit][profile_id] != 0) { 3608 BCM_IF_ERROR_RETURN( 3609 shr_res_bitmap_alloc(taf_cosq_profile_bitmap[unit], 3610 SHR_RES_BITMAP_ALLOC_WITH_ID, 3611 1, (int *)&profile_id)); 3612 } 3613 } 3614 3615 /* taf schedule timelime 3616 * Format : count (32 bit) + 3617 * [ gate id (32 bit) + count N (32 bit) + 3618 * basetime_1(96 bit) + ... + basetime_N(96 bit) ] 3619 */ 3620 schedule_id = 0; 3621 READ_PTR(scache_ptr, uint32, conut_schedule); 3622 while (schedule_id < conut_schedule) { 3623 int i; 3624 uint32 gate_id, count_per_gate; 3625 uint32 sec_lo, sec_hi; 3626 bcmi_tsn_taf_schedule_entry_t *entry_tail = NULL; 3627 3628 READ_PTR(scache_ptr, uint32, gate_id); 3629 READ_PTR(scache_ptr, uint32, count_per_gate); 3630 entry_tail = taf_schedule_timeline[unit][gate_id]; 3631 3632 for (i = 0; i < count_per_gate; i++) { 3633 bcmi_tsn_taf_schedule_entry_t *entry_new = NULL; 3634 3635 if (schedule_id >= conut_schedule) { 3636 return BCM_E_INTERNAL; /* should not happen */ 3637 } 3638 3639 entry_new = sal_alloc(sizeof(bcmi_tsn_taf_schedule_entry_t), 3640 "TAF schedule entry"); 3641 if (NULL == entry_new) { 3642 return BCM_E_MEMORY; 3643 } 3644 3645 READ_PTR(scache_ptr, uint32, sec_lo); 3646 READ_PTR(scache_ptr, uint32, sec_hi); 3647 READ_PTR(scache_ptr, uint32, entry_new->schedule_time.nanoseconds); 3648 COMPILER_64_SET(entry_new->schedule_time.seconds, sec_hi, sec_lo); 3649 3650 if (NULL == entry_tail) { 3651 /* this the first entry */ 3652 entry_new->prev = NULL; 3653 entry_new->next = NULL; 3654 taf_schedule_timeline[unit][gate_id] = entry_new; 3655 } else { 3656 /* add new entry at the tail */ 3657 entry_tail->next = entry_new; 3658 entry_new->prev = entry_tail; 3659 entry_new->next = NULL; 3660 } 3661 entry_tail = entry_new; 3662 3663 /* cache this new entry, then ready to process the next one */ 3664 schedule_entry_cache[schedule_id] = entry_new; 3665 schedule_id++; 3666 } 3667 } 3668 3669 /* taf schedule profile 3670 * Format : count (32 bit) + 3671 * [ profile id (32 bit) + taf_gate (32 bit) + status (32 bit) + 3672 * config_change_time(96 bit) + 3673 * data(bcm_tsn_taf_profile_t) + schedule_entry index (32 bit) ] 3674 */ 3675 entry_index = 0; 3676 READ_PTR(scache_ptr, uint32, conut_profile); 3677 for (entry_index = 0; entry_index < conut_profile; entry_index++) { 3678 uint32 profile_id; 3679 bcmi_tsn_taf_profile_t *new_profile = NULL; 3680 uint32 sec_lo, sec_hi; 3681 3682 READ_PTR(scache_ptr, uint32, profile_id); 3683 3684 new_profile = sal_alloc(sizeof(bcmi_tsn_taf_profile_t), "TAF profile"); 3685 if (NULL == new_profile) { 3686 return BCM_E_MEMORY; 3687 } 3688 taf_schedule_profile[unit][profile_id] = new_profile; 3689 3690 BCM_IF_ERROR_RETURN( 3691 shr_res_bitmap_alloc( 3692 taf_schedule_profile_bitmap[unit], 3693 SHR_RES_BITMAP_ALLOC_WITH_ID, 1, (int *)&profile_id)); 3694 3695 /* recover taf_gate, status, config_change_time, data */ 3696 READ_PTR(scache_ptr, uint32, new_profile->taf_gate); 3697 READ_PTR(scache_ptr, uint32, new_profile->status); 3698 READ_PTR(scache_ptr, uint32, sec_lo); 3699 READ_PTR(scache_ptr, uint32, sec_hi); 3700 READ_PTR(scache_ptr, uint32, 3701 new_profile->config_change_time.nanoseconds); 3702 COMPILER_64_SET(new_profile->config_change_time.seconds, 3703 sec_hi, sec_lo); 3704 READ_PTR_RANGE(scache_ptr, sizeof(bcm_tsn_taf_profile_t), 3705 &(new_profile->data)); 3706 3707 /* recover schedule entry */ 3708 READ_PTR(scache_ptr, uint32, schedule_id); 3709 if (schedule_id == (uint32)-1) { 3710 new_profile->schedule = NULL; 3711 } else { 3712 if (schedule_id >= conut_schedule) { 3713 return BCM_E_INTERNAL; /* should not happen */ 3714 } 3715 if (NULL == schedule_entry_cache[schedule_id]) { 3716 return BCM_E_INTERNAL; /* should not happen */ 3717 } 3718 new_profile->schedule = schedule_entry_cache[schedule_id]; 3719 new_profile->schedule->taf_profile = new_profile; 3720 } 3721 } 3722 3723 return BCM_E_NONE; 3724 } 3725 #endif /* BCM_WARM_BOOT_SUPPORT */ 3726 3727 3728 /* Per-chip TAF device info */ 3729 STATIC const bcmi_tsn_taf_dev_info_t gh2_taf_devinfo = { 3730 /* function set */ 3731 bcmi_gh2_taf_init, 3732 bcmi_gh2_taf_cleanup, 3733 bcmi_gh2_taf_gate_create, 3734 bcmi_gh2_taf_gate_traverse, 3735 bcmi_gh2_taf_gate_destroy, 3736 bcmi_gh2_taf_gate_check, 3737 bcmi_gh2_taf_gate_status_get, 3738 bcmi_gh2_taf_global_control_get, 3739 bcmi_gh2_taf_global_control_set, 3740 bcmi_gh2_taf_port_control_get, 3741 bcmi_gh2_taf_port_control_set, 3742 bcmi_gh2_taf_gate_control_get, 3743 bcmi_gh2_taf_gate_control_set, 3744 bcmi_gh2_taf_gate_pri_map_set, 3745 bcmi_gh2_taf_gate_pri_map_get, 3746 bcmi_gh2_taf_gate_pri_map_delete, 3747 bcmi_gh2_taf_calendar_param_check, 3748 bcmi_gh2_taf_calendar_resource_alloc, 3749 bcmi_gh2_taf_calendar_resource_free, 3750 bcmi_gh2_taf_calendar_kickoff, 3751 bcmi_gh2_taf_calendar_profile_create, 3752 bcmi_gh2_taf_calendar_profile_get, 3753 bcmi_gh2_taf_calendar_profile_destroy, 3754 bcmi_gh2_taf_calendar_profile_traverse, 3755 bcmi_gh2_taf_schedule_insert, 3756 bcmi_gh2_taf_schedule_remove, 3757 bcmi_gh2_taf_schedule_pick, 3758 bcmi_gh2_taf_schedule_exist, 3759 bcmi_gh2_taf_schedule_get, 3760 bcmi_gh2_taf_event_register, 3761 bcmi_gh2_taf_event_unregister, 3762 bcmi_gh2_taf_event_notify, 3763 bcmi_gh2_taf_interrupt_handle_start, 3764 bcmi_gh2_taf_interrupt_handle_tod, 3765 bcmi_gh2_taf_interrupt_handle_switch, 3766 bcmi_gh2_taf_interrupt_handle_error, 3767 bcmi_gh2_taf_interrupt_handle_user_cb, 3768 bcmi_gh2_taf_interrupt_handle_finish, 3769 bcmi_gh2_taf_gate_max_bytes_profile_create, 3770 bcmi_gh2_taf_gate_max_bytes_profile_set, 3771 bcmi_gh2_taf_gate_max_bytes_profile_get, 3772 bcmi_gh2_taf_gate_max_bytes_profile_destroy, 3773 bcmi_gh2_taf_gate_max_bytes_profile_traverse, 3774 bcmi_gh2_taf_cosq_mapping_profile_create, 3775 bcmi_gh2_taf_cosq_mapping_profile_set, 3776 bcmi_gh2_taf_cosq_mapping_profile_get, 3777 bcmi_gh2_taf_cosq_mapping_profile_destroy, 3778 bcmi_gh2_taf_cosq_mapping_profile_traverse, 3779 bcmi_gh2_taf_gate_stat_counter_sync, 3780 bcmi_gh2_taf_gate_stat_counter_access, 3781 #if defined(BCM_WARM_BOOT_SUPPORT) 3782 bcmi_gh2_taf_get_scache_size, 3783 bcmi_gh2_taf_sync, 3784 bcmi_gh2_taf_reload, 3785 #endif /* BCM_WARM_BOOT_SUPPORT */ 3786 /* data set */ 3787 TAF_GATE_PRI_MAP_PROFILE_NUM, /* exclude invalid index 0 */ 3788 TAF_GATE_PRI_MAP_INTPRI_NUM 3789 }; 3790 3791 /* 3792 * Function: 3793 * bcmi_gh2_taf_info_init 3794 * Description: 3795 * Setup the chip specific info for TAF. 3796 * Parameters: 3797 * unit - (IN) Unit number 3798 * devinfo - (OUT) device info structure. 3799 * Returns: 3800 * BCM_E_XXX 3801 */ 3802 int 3803 bcmi_gh2_taf_info_init( 3804 int unit, 3805 const bcmi_tsn_taf_dev_info_t **devinfo) 3806 { 3807 int rv = BCM_E_NONE; 3808 3809 if (devinfo == NULL) { 3810 return BCM_E_PARAM; 3811 } 3812 3813 /* Return the chip info structure for TSN stat */ 3814 *devinfo = &gh2_taf_devinfo; 3815 3816 return rv; 3817 } 3818 #endif /* BCM_TSN_SUPPORT */