internal_stack.c (10968B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: internal_stack.c 8 * 9 * Purpose: 10 * 11 * Functions: 12 * _bcm_kt_ptp_hw_init 13 * _bcm_ptp_internal_stack_create 14 */ 15 16 #if defined(INCLUDE_PTP) 17 18 #include <soc/defs.h> 19 #include <soc/drv.h> 20 21 #include <sal/core/dpc.h> 22 #include <shared/bsl.h> 23 #include <bcm_int/common/rx.h> 24 #include <bcm/ptp.h> 25 #include <bcm_int/common/ptp.h> 26 #include <bcm/error.h> 27 #include <bcm_int/common/PTP_feature.h> 28 29 /* Global variables */ 30 /* PTP FW version for feature compatibility check */ 31 uint32 ptp_firmware_version = PTP_UC_MIN_VERSION; 32 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) 33 34 #include <soc/uc_msg.h> 35 #include <soc/uc_dbg.h> 36 37 38 /* 39 * Function: 40 * bcm_kt_ptp_hw_init 41 * Purpose: 42 * Initialize the HW for PTP packet processing. 43 * Configure: 44 * - FP rules to copy L2, IPv4, and IPv6 PTP traffic to CPU 45 * - Assign RX DMA channel to PTP CPU COS Queue 46 * - Map RX PTP packets to PTP CPU COS Queue 47 * Parameters: 48 * unit - (IN) Unit number. 49 * Returns: 50 * BCM_E_XXX 51 * Notes: 52 */ 53 STATIC int 54 _bcm_kt_ptp_hw_init(int unit, int uc_num) 55 { 56 int rv = BCM_E_NONE; 57 bcm_rx_chan_t chan_id; 58 int num_cosq = 0; 59 int min_cosq, max_cosq, ptp_cosq; 60 int i; 61 int rx_channel = 1; /* For now, PTP is always on uC by itself, so always use Rx channel 1 */ 62 63 /* 64 * PTP COS Queue 65 * 66 * - The default PTP COS queue. This is set to the highest queue 67 * available within the queue range assigned to the uC where 68 * the PTP application is running. 69 */ 70 71 72 /* Get valid range of COS queues for uC where PTP is loaded */ 73 min_cosq = 0; 74 for (i = 0; i < SOC_CMCS_NUM(unit); i++) { 75 num_cosq = NUM_CPU_ARM_COSQ(unit, i); 76 if (i == uc_num + 1) { 77 break; 78 } 79 min_cosq += num_cosq; 80 } 81 82 max_cosq = min_cosq + num_cosq - 1; 83 84 /* Check that there is at least one COS queue assigned to the CMC */ 85 if (max_cosq < min_cosq) { 86 LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit, 87 "PTP unable to assign COSQ, none are assigned to FW core.\n"))); 88 return BCM_E_CONFIG; 89 } 90 91 /* Get PTP COSq soc property */ 92 ptp_cosq = soc_property_get(unit, spn_PTP_COSQ, max_cosq); 93 94 /* 95 * Assign RX DMA channel to PTP CPU COS Queue 96 * (This is the RX channel to listen on for PTP packets). 97 * 98 * DMA channels (12) are assigned 4 per processor: 99 * (see /src/bcm/common/rx.c) 100 * channels 0..3 --> PCI host 101 * channels 4..7 --> uController 0 102 * chnanels 8..11 --> uController 1 103 * 104 * The uControllers designate the 4 local DMA channels as follows: 105 * local channel 0 --> TX 106 * local channel 1..3 --> RX 107 * 108 * Each uController application needs to use a different 109 * RX DMA channel to listen on. 110 */ 111 chan_id = (BCM_RX_CHANNELS * (SOC_ARM_CMC(unit, uc_num))) + rx_channel; 112 113 if (ptp_cosq != max_cosq) 114 { 115 if ((ptp_cosq < min_cosq) || (ptp_cosq > max_cosq)) { 116 LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit, 117 "PTP COSQ %d is out of bounds for FW core [%d - %d].\n"), 118 ptp_cosq, min_cosq, max_cosq)); 119 120 return BCM_E_RESOURCE; /* Could not find an available COSQ */ 121 } 122 123 rv = _bcm_common_rx_queue_channel_set(unit, ptp_cosq, chan_id); 124 125 if (!BCM_SUCCESS(rv)) { 126 LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit, 127 "PTP unable to assign COSQ %d.\n"), 128 ptp_cosq)); 129 130 return rv; 131 } 132 } 133 else 134 { 135 for (i = max_cosq; i >= min_cosq; i--) { 136 rv = _bcm_common_rx_queue_channel_set(unit, i, chan_id); 137 if (BCM_SUCCESS(rv)) { 138 break; 139 } 140 } 141 142 if (i < min_cosq) { 143 LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit, 144 "PTP unable to assign COSQ from range %d - %d.\n"), 145 min_cosq, max_cosq)); 146 147 return BCM_E_RESOURCE; /* Could not find an available COSQ */ 148 } 149 150 ptp_cosq = i; 151 } 152 153 LOG_VERBOSE(BSL_LS_BCM_PTP, (BSL_META_U(unit, 154 "1588 COSQ for unit %d is %d chan_id: %d\n"), unit, ptp_cosq, chan_id)); 155 156 return rv; 157 } 158 159 160 /* 161 * Function: 162 * _bcm_ptp_internal_stack_create 163 * Purpose: 164 * Create a PTP stack instance 165 * Parameters: 166 * unit - (IN) Unit number. 167 * ptp_info - (IN/OUT) Pointer to an PTP Stack Info structure 168 * Returns: 169 * BCM_E_xxx 170 * Notes: 171 */ 172 int 173 _bcm_ptp_internal_stack_create( 174 int unit, 175 bcm_ptp_stack_info_t *info, 176 bcm_ptp_stack_id_t ptp_id) 177 { 178 _bcm_ptp_info_t *ptp_info_p; 179 _bcm_ptp_stack_info_t *stack_p; 180 mos_msg_data_t start_msg; 181 int timeout_usec = 1900000; 182 int result; 183 int c; 184 int i; 185 int rv; 186 187 /* log storage size is the size of the structure without the placeholder */ 188 /* space for debug->buf, plus the real space for it */ 189 int log_storage_size = sizeof(_bcm_ptp_internal_stack_log_t) - 190 sizeof(stack_p->int_state.log->buf) + BCM_PTP_MAX_LOG; 191 192 SET_PTP_INFO; 193 if (!SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 194 return BCM_E_UNAVAIL; 195 } 196 197 stack_p = &ptp_info_p->stack_info[ptp_id]; 198 199 /* Set up dispatch for internal transport */ 200 stack_p->transport_init = _bcm_ptp_internal_transport_init; 201 stack_p->tx = _bcm_ptp_internal_tx; 202 stack_p->tx_completion = _bcm_ptp_internal_tx_completion; 203 stack_p->rx_free = _bcm_ptp_internal_rx_response_free; 204 stack_p->transport_terminate = _bcm_ptp_internal_transport_terminate; 205 206 /* allocate space for mboxes */ 207 stack_p->int_state.mboxes = soc_cm_salloc(unit, sizeof(_bcm_ptp_internal_stack_mboxes_t), "ptp msg"); 208 209 if (!stack_p->int_state.mboxes) { 210 return BCM_E_MEMORY; 211 } 212 213 /* clear state of message mboxes */ 214 stack_p->int_state.mboxes->num_mboxes = soc_htonl(BCM_PTP_MAX_BUFFERS); 215 stack_p->int_state.mboxes->mbox_size = soc_htonl(sizeof(_bcm_ptp_internal_stack_mbox_t)); 216 stack_p->int_state.mboxes->mbox_offset = soc_htonl((uint8 *)&stack_p->int_state.mboxes->mbox[0] - (uint8 *)stack_p->int_state.mboxes); 217 stack_p->int_state.mboxes->rfu = soc_htonl(0); 218 219 for (i = 0; i < BCM_PTP_MAX_BUFFERS; ++i) { 220 stack_p->int_state.mboxes->mbox[i].status = soc_htonl(MBOX_STATUS_EMPTY); 221 stack_p->int_state.mboxes->mbox[i].clock_num = soc_htonl(0); 222 stack_p->int_state.mboxes->mbox[i].data_len = soc_htonl(0); 223 stack_p->int_state.mboxes->mbox[i].rfu_mbox = soc_htonl(0); 224 } 225 226 /* allocate space for debug log */ 227 stack_p->int_state.log = soc_cm_salloc(unit, log_storage_size, "ptp log"); 228 if (!stack_p->int_state.log) { 229 soc_cm_sfree(unit, stack_p->int_state.mboxes); 230 LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit, 231 "PTP Failed to allocate shared memory\n"))); 232 return BCM_E_MEMORY; 233 } 234 235 /* initialize debug */ 236 stack_p->int_state.log->size = soc_htonl(BCM_PTP_MAX_LOG); 237 stack_p->int_state.log->head = soc_htonl(0); 238 stack_p->int_state.log_tail = 0; 239 240 /* set up the network-byte-order pointers so that CMICm can access the shared memory */ 241 stack_p->int_state.mbox_ptr = soc_htonl(soc_cm_l2p(unit, (void*)stack_p->int_state.mboxes)); 242 stack_p->int_state.log_ptr = soc_htonl(soc_cm_l2p(unit, (void*)stack_p->int_state.log)); 243 244 /* LOG_CLI((BSL_META_U(unit, 245 "DEBUG SPACE: %p\n"), (void *)stack_p->int_state.log->buf)); */ 246 247 /* flush memory on platforms that need it */ 248 soc_cm_sflush(unit, stack_p, sizeof(_bcm_ptp_stack_info_t)); 249 soc_cm_sflush(unit, stack_p->int_state.mboxes, sizeof(_bcm_ptp_internal_stack_mboxes_t)); 250 soc_cm_sflush(unit, stack_p->int_state.log, log_storage_size); 251 252 rv = BCM_E_UNAVAIL; 253 for (c = (SOC_INFO(unit).num_ucs - 1); c >= 0; c--) { 254 LOG_VERBOSE(BSL_LS_BCM_PTP, (BSL_META_U(unit, 255 "Trying PTP on core %d\n"), c)); 256 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtp, 257 "Trying PTP on core %d\n", c)); 258 result = soc_cmic_uc_appl_init(unit, c, 259 MOS_MSG_CLASS_1588, 260 timeout_usec, 261 PTP_SDK_VERSION, PTP_UC_MIN_VERSION, 262 &_bcm_ptp_stack_deinit_callback, INT_TO_PTR(ptp_id)); 263 if (SOC_E_NONE == result){ 264 /* uKernel communications started successfully */ 265 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtp, 266 "PTP -> uKernel communications started successfully\n")); 267 soc_cmic_ucdebug_core_communication_status(unit, 268 CMIC_UC_DBG_PTP_CORE_COMM_SUCCESS); 269 270 start_msg.s.mclass = MOS_MSG_CLASS_1588; 271 start_msg.s.subclass = MOS_MSG_SUBCLASS_MBOX_CONFIG; 272 start_msg.s.len = 0; 273 start_msg.s.data = bcm_htonl(soc_cm_l2p(unit, (void*)&stack_p->int_state)); 274 275 if (BCM_FAILURE(rv = soc_cmic_uc_msg_send(unit, c, &start_msg, timeout_usec))) { 276 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtp, 277 "Error in Initializing PTP application\n")); 278 PTP_ERROR_FUNC("soc_cmic_uc_msg_send()"); 279 } 280 stack_p->int_state.core_num = c; 281 break; 282 } 283 LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit, 284 "No response on core %d\n"), c)); 285 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtp, 286 "No response on core %d\n", c)); 287 } 288 289 if (BCM_FAILURE(rv)) { 290 return rv; 291 } 292 293 soc_cmic_ucdebug_core_communication_status(unit, 294 CMIC_UC_DBG_PTP_STACK_INIT_SUCCESS); 295 296 rv = _bcm_kt_ptp_hw_init(unit, stack_p->int_state.core_num); 297 if (BCM_FAILURE(rv)) { 298 return rv; 299 } 300 301 return rv; 302 } 303 304 /* 305 * Function: 306 * _bcm_ptp_internal_stack_cleanup 307 * Purpose: 308 * Cleans up internal allocations of an internal stack 309 * Parameters: 310 * unit - (IN) Unit number. 311 * ptp_id - (IN) Stack ID 312 * Returns: 313 * BCM_E_xxx 314 * Notes: 315 */ 316 int 317 _bcm_ptp_internal_stack_cleanup( 318 int unit, 319 bcm_ptp_stack_id_t ptp_id) 320 { 321 _bcm_ptp_stack_info_t *stack_p; 322 323 if (!SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 324 return BCM_E_UNAVAIL; 325 } 326 327 if (_bcm_common_ptp_info[unit].memstate != PTP_MEMSTATE_INITIALIZED) { 328 return BCM_E_UNAVAIL; 329 } 330 331 stack_p = &_bcm_common_ptp_info[unit].stack_info[ptp_id]; 332 333 soc_cm_sfree(unit, stack_p->int_state.log); 334 stack_p->int_state.log = NULL; 335 336 soc_cm_sfree(unit, stack_p->int_state.mboxes); 337 stack_p->int_state.mboxes = NULL; 338 339 return BCM_E_NONE; 340 } 341 342 343 #endif /* defined(BCM_PTP_INTERNAL_STACK_SUPPORT) */ 344 #endif /* defined(INCLUDE_PTP) */