Shad Ansari | 2f7f9be | 2017-06-07 13:34:53 -0700 | [diff] [blame^] | 1 | /****************************************************************************** |
| 2 | * |
| 3 | * <:copyright-BRCM:2016:DUAL/GPL:standard |
| 4 | * |
| 5 | * Copyright (c) 2016 Broadcom |
| 6 | * All Rights Reserved |
| 7 | * |
| 8 | * Unless you and Broadcom execute a separate written software license |
| 9 | * agreement governing use of this software, this software is licensed |
| 10 | * to you under the terms of the GNU General Public License version 2 |
| 11 | * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, |
| 12 | * with the following added to such license: |
| 13 | * |
| 14 | * As a special exception, the copyright holders of this software give |
| 15 | * you permission to link this software with independent modules, and |
| 16 | * to copy and distribute the resulting executable under terms of your |
| 17 | * choice, provided that you also meet, for each linked independent |
| 18 | * module, the terms and conditions of the license of that module. |
| 19 | * An independent module is a module which is not derived from this |
| 20 | * software. The special exception does not apply to any modifications |
| 21 | * of the software. |
| 22 | * |
| 23 | * Not withstanding the above, under no circumstances may you combine |
| 24 | * this software in any way with any other Broadcom software provided |
| 25 | * under a license other than the GPL, without Broadcom's express prior |
| 26 | * written consent. |
| 27 | * |
| 28 | * :> |
| 29 | * |
| 30 | *****************************************************************************/ |
| 31 | |
| 32 | #include <bcm_dev_log.h> |
| 33 | #include <bcmolt_math.h> |
| 34 | #include "bcm_topo.h" |
| 35 | |
| 36 | #define BCM_TOPO_MAX_LINE_SIZE 256 |
| 37 | #define BCM_TOPO_MAX_NNI_DEVICES 1 |
| 38 | |
| 39 | uint32_t g_max_nni_ports[BCM_TOPO_MAX_NNI_DEVICES] = {BCM_TOPO_MAX_NNI_PORTS}; |
| 40 | |
| 41 | typedef struct bcm_topo_dev_context_t bcm_topo_dev_context_t; |
| 42 | |
| 43 | typedef struct |
| 44 | { |
| 45 | bcm_topo_dev_context_t *dev; /* Back pointer to the physical device this PON belongs to */ |
| 46 | bcmos_bool is_initialized; |
| 47 | uint32_t pon_id; |
| 48 | uint32_t logical_pon; |
| 49 | bcm_topo_pon_mode pon_mode; |
| 50 | uint32_t max_num_of_onus; |
| 51 | void *contexts[BCM_TOPO_PON_CONTEXT_ID__NUM_OF]; /* User context - 1 entry per user */ |
| 52 | } bcm_topo_pon_context_t; |
| 53 | |
| 54 | struct bcm_topo_dev_context_t |
| 55 | { |
| 56 | bcm_topo_pon_mode pon_mode; /* Currently we do not allow more than one PON mode per device (e.g: GPONx8 + XGPONx4) */ |
| 57 | bcmos_bool is_initialized; |
| 58 | uint32_t device_id; |
| 59 | uint32_t max_num_of_pons; |
| 60 | bcm_topo_pon_context_t pons[BCM_TOPO_MAX_NUM_OF_PONS_PER_DEV]; |
| 61 | }; |
| 62 | |
| 63 | typedef struct |
| 64 | { |
| 65 | bcmos_bool is_initialized; |
| 66 | bcm_topo_dev_context_t devs[BCM_TOPO_MAX_NUM_OF_DEVS]; |
| 67 | bcm_topo_pon_context_t *logical_pon2physical_pon[BCM_TOPO_MAX_NUM_OF_LOGICAL_PONS]; |
| 68 | } bcm_topo_context_t; |
| 69 | |
| 70 | static bcm_topo_context_t bcm_topo_context; |
| 71 | |
| 72 | #ifdef ENABLE_LOG |
| 73 | static dev_log_id topo_log_id = DEV_LOG_INVALID_ID; |
| 74 | #endif |
| 75 | |
| 76 | static int2str_t pon_mode2str[] = |
| 77 | { |
| 78 | {BCM_TOPO_PON_MODE_GPON, "gpon"}, |
| 79 | {BCM_TOPO_PON_MODE_XGPON, "xgpon"}, |
| 80 | {BCM_TOPO_PON_MODE_XGS, "xgs"}, |
| 81 | {BCM_TOPO_PON_MODE_EPON_TDMA, "epon_tdma"}, |
| 82 | {BCM_TOPO_PON_MODE_EPON_1G, "epon_1g"}, |
| 83 | {BCM_TOPO_PON_MODE_EPON_10G, "epon_10g"}, |
| 84 | {-1}, |
| 85 | }; |
| 86 | |
| 87 | static int2int_t pon_mode2max_num_of_pons[] = |
| 88 | { |
| 89 | {BCM_TOPO_PON_MODE_GPON, 16}, |
| 90 | {BCM_TOPO_PON_MODE_XGPON, 8}, |
| 91 | {BCM_TOPO_PON_MODE_XGS, 2}, |
| 92 | {BCM_TOPO_PON_MODE_EPON_TDMA, 8}, |
| 93 | {BCM_TOPO_PON_MODE_EPON_1G, 16}, |
| 94 | {BCM_TOPO_PON_MODE_EPON_10G, 8}, |
| 95 | {-1}, |
| 96 | }; |
| 97 | |
| 98 | const char *bcm_topo_dev_get_pon_mode_str(bcmolt_devid device_id) |
| 99 | { |
| 100 | return int2str(pon_mode2str, bcm_topo_context.devs[device_id].pon_mode); |
| 101 | } |
| 102 | |
| 103 | int bcm_topo_dev_get_max_pon(bcmolt_devid device_id) |
| 104 | { |
| 105 | return int2int(pon_mode2max_num_of_pons, bcm_topo_context.devs[device_id].pon_mode); |
| 106 | } |
| 107 | |
| 108 | bcm_topo_pon_mode bcm_topo_pon_get_pon_mode(uint32_t pon) |
| 109 | { |
| 110 | bcmolt_devid device_id; |
| 111 | uint32_t physical_pon; |
| 112 | bcmos_errno rc; |
| 113 | |
| 114 | rc = bcm_topo_pon_get_logical2physical(pon, &device_id, &physical_pon); |
| 115 | if (rc != BCM_ERR_OK) |
| 116 | return BCM_TOPO_PON_MODE_INVALID; |
| 117 | |
| 118 | return bcm_topo_context.devs[device_id].pons[physical_pon].pon_mode; |
| 119 | } |
| 120 | |
| 121 | bcm_topo_pon_family bcm_topo_pon_get_pon_family(uint32_t pon) |
| 122 | { |
| 123 | switch (bcm_topo_pon_get_pon_mode(pon)) |
| 124 | { |
| 125 | case BCM_TOPO_PON_MODE_GPON: |
| 126 | case BCM_TOPO_PON_MODE_XGPON: |
| 127 | case BCM_TOPO_PON_MODE_XGS: |
| 128 | return BCM_TOPO_PON_FAMILY_GPON; |
| 129 | case BCM_TOPO_PON_MODE_EPON_TDMA: |
| 130 | case BCM_TOPO_PON_MODE_EPON_1G: |
| 131 | case BCM_TOPO_PON_MODE_EPON_10G: |
| 132 | return BCM_TOPO_PON_FAMILY_EPON; |
| 133 | default: |
| 134 | return BCM_TOPO_PON_FAMILY_INVALID; |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | bcm_topo_pon_sub_family bcm_topo_pon_get_pon_sub_family(uint32_t pon) |
| 139 | { |
| 140 | switch (bcm_topo_pon_get_pon_mode(pon)) |
| 141 | { |
| 142 | case BCM_TOPO_PON_MODE_GPON: |
| 143 | return BCM_TOPO_PON_SUB_FAMILY_GPON; |
| 144 | case BCM_TOPO_PON_MODE_XGPON: |
| 145 | case BCM_TOPO_PON_MODE_XGS: |
| 146 | return BCM_TOPO_PON_SUB_FAMILY_XGPON; |
| 147 | case BCM_TOPO_PON_MODE_EPON_TDMA: |
| 148 | case BCM_TOPO_PON_MODE_EPON_1G: |
| 149 | case BCM_TOPO_PON_MODE_EPON_10G: |
| 150 | return BCM_TOPO_PON_SUB_FAMILY_EPON; |
| 151 | default: |
| 152 | return BCM_TOPO_PON_SUB_FAMILY_INVALID; |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | uint32_t bcm_topo_pon_get_max_num_of_onus(uint32_t pon) |
| 157 | { |
| 158 | bcmolt_devid device_id; |
| 159 | uint32_t physical_pon; |
| 160 | bcmos_errno rc; |
| 161 | |
| 162 | rc = bcm_topo_pon_get_logical2physical(pon, &device_id, &physical_pon); |
| 163 | if (rc != BCM_ERR_OK) |
| 164 | return BCM_TOPO_ERR_INVALID; |
| 165 | |
| 166 | return bcm_topo_context.devs[device_id].pons[physical_pon].max_num_of_onus; |
| 167 | } |
| 168 | |
| 169 | bcmos_bool bcm_topo_pon_is_valid(uint32_t pon) |
| 170 | { |
| 171 | bcmolt_devid device_id; |
| 172 | uint32_t physical_pon; |
| 173 | |
| 174 | if (bcm_topo_pon_get_logical2physical(pon, &device_id, &physical_pon) != BCM_ERR_OK) |
| 175 | return BCMOS_FALSE; |
| 176 | |
| 177 | return BCMOS_TRUE; |
| 178 | } |
| 179 | |
| 180 | bcmolt_devid bcm_topo_dev_get_next(bcmolt_devid device_id) |
| 181 | { |
| 182 | if (device_id == BCM_TOPO_DEV_INVALID) |
| 183 | device_id = 0; |
| 184 | else |
| 185 | device_id++; |
| 186 | |
| 187 | for (; device_id < BCM_TOPO_MAX_NUM_OF_DEVS && !bcm_topo_context.devs[device_id].is_initialized; device_id++); |
| 188 | |
| 189 | return device_id == BCM_TOPO_MAX_NUM_OF_DEVS ? BCM_TOPO_DEV_INVALID : device_id; |
| 190 | } |
| 191 | |
| 192 | uint32_t bcm_topo_pon_get_next(bcmolt_devid device_id, uint32_t pon) |
| 193 | { |
| 194 | uint32_t physical_pon; |
| 195 | bcmos_errno rc; |
| 196 | |
| 197 | if (device_id >= BCM_TOPO_MAX_NUM_OF_DEVS) |
| 198 | { |
| 199 | BCM_LOG(ERROR, topo_log_id, "Device ID must be in the range 0 .. %u\n", BCM_TOPO_MAX_NUM_OF_DEVS - 1); |
| 200 | return BCM_TOPO_PON_INVALID; |
| 201 | } |
| 202 | |
| 203 | if (pon == BCM_TOPO_PON_INVALID) |
| 204 | physical_pon = 0; |
| 205 | else |
| 206 | { |
| 207 | bcmolt_devid dummy; |
| 208 | |
| 209 | rc = bcm_topo_pon_get_logical2physical(pon, &dummy, &physical_pon); |
| 210 | if (rc != BCM_ERR_OK) |
| 211 | { |
| 212 | return BCM_TOPO_PON_INVALID; |
| 213 | } |
| 214 | else |
| 215 | { |
| 216 | physical_pon++; |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | if (physical_pon < bcm_topo_context.devs[device_id].max_num_of_pons) |
| 221 | { |
| 222 | rc = bcm_topo_pon_get_physical2logical(device_id, physical_pon, &pon); |
| 223 | if (rc != BCM_ERR_OK) |
| 224 | { |
| 225 | return BCM_TOPO_PON_INVALID; |
| 226 | } |
| 227 | else |
| 228 | { |
| 229 | return pon; |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | return BCM_TOPO_PON_INVALID; |
| 234 | } |
| 235 | |
| 236 | bcmos_errno bcm_topo_pon_get_logical2physical(uint32_t logical_pon, bcmolt_devid *device_id, uint32_t *physical_pon) |
| 237 | { |
| 238 | if (logical_pon >= BCM_TOPO_MAX_NUM_OF_LOGICAL_PONS) |
| 239 | { |
| 240 | BCM_LOG(ERROR, topo_log_id, "Logical PON ID must be in the range 0 .. %u\n", BCM_TOPO_MAX_NUM_OF_LOGICAL_PONS - 1); |
| 241 | return BCM_ERR_RANGE; |
| 242 | } |
| 243 | |
| 244 | if (!bcm_topo_context.logical_pon2physical_pon[logical_pon]) |
| 245 | { |
| 246 | BCM_LOG(ERROR, topo_log_id, "Logical PON=%u was not associated with a physical PON\n", logical_pon); |
| 247 | return BCM_ERR_RANGE; |
| 248 | } |
| 249 | |
| 250 | *physical_pon = bcm_topo_context.logical_pon2physical_pon[logical_pon]->pon_id; |
| 251 | *device_id = bcm_topo_context.logical_pon2physical_pon[logical_pon]->dev->device_id; |
| 252 | |
| 253 | return BCM_ERR_OK; |
| 254 | } |
| 255 | |
| 256 | bcmos_errno bcm_topo_pon_get_physical2logical(bcmolt_devid device_id, uint32_t physical_pon, uint32_t *logical_pon) |
| 257 | { |
| 258 | if (device_id >= BCM_TOPO_MAX_NUM_OF_DEVS) |
| 259 | { |
| 260 | BCM_LOG(ERROR, topo_log_id, "Device ID must be in the range 0 .. %u\n", BCM_TOPO_MAX_NUM_OF_DEVS - 1); |
| 261 | return BCM_ERR_RANGE; |
| 262 | } |
| 263 | |
| 264 | if (physical_pon >= bcm_topo_context.devs[device_id].max_num_of_pons) |
| 265 | { |
| 266 | BCM_LOG(ERROR, topo_log_id, "Physical PON ID must be in the range 0 .. %u\n", bcm_topo_context.devs[device_id].max_num_of_pons - 1); |
| 267 | return BCM_ERR_RANGE; |
| 268 | } |
| 269 | |
| 270 | if (bcm_topo_context.devs[device_id].pons[physical_pon].logical_pon == BCM_TOPO_PON_INVALID) |
| 271 | { |
| 272 | BCM_LOG(ERROR, topo_log_id, "Physical PON=%u on device=%u was not associated with a logical PON\n", physical_pon, device_id); |
| 273 | return BCM_ERR_RANGE; |
| 274 | } |
| 275 | |
| 276 | *logical_pon = bcm_topo_context.devs[device_id].pons[physical_pon].logical_pon; |
| 277 | |
| 278 | return BCM_ERR_OK; |
| 279 | } |
| 280 | |
| 281 | bcmos_errno bcm_topo_pon_set_context(uint32_t pon, bcm_topo_pon_context_id pon_context_id, void *context) |
| 282 | { |
| 283 | bcmolt_devid device_id; |
| 284 | uint32_t physical_pon; |
| 285 | bcmos_errno rc; |
| 286 | |
| 287 | if (pon_context_id >= BCM_TOPO_PON_CONTEXT_ID__NUM_OF) |
| 288 | { |
| 289 | BCM_LOG(ERROR, topo_log_id, "Invalid PON context ID\n"); |
| 290 | return BCM_ERR_RANGE; |
| 291 | } |
| 292 | |
| 293 | rc = bcm_topo_pon_get_logical2physical(pon, &device_id, &physical_pon); |
| 294 | if (rc != BCM_ERR_OK) |
| 295 | return rc; |
| 296 | |
| 297 | bcm_topo_context.devs[device_id].pons[physical_pon].contexts[pon_context_id] = context; |
| 298 | |
| 299 | return BCM_ERR_OK; |
| 300 | } |
| 301 | |
| 302 | void *bcm_topo_pon_get_context(uint32_t pon, bcm_topo_pon_context_id pon_context_id) |
| 303 | { |
| 304 | bcmolt_devid device_id; |
| 305 | uint32_t physical_pon; |
| 306 | bcmos_errno rc; |
| 307 | |
| 308 | if (pon_context_id >= BCM_TOPO_PON_CONTEXT_ID__NUM_OF) |
| 309 | { |
| 310 | BCM_LOG(ERROR, topo_log_id, "Invalid PON context ID\n"); |
| 311 | return NULL; |
| 312 | } |
| 313 | |
| 314 | rc = bcm_topo_pon_get_logical2physical(pon, &device_id, &physical_pon); |
| 315 | if (rc != BCM_ERR_OK) |
| 316 | return NULL; |
| 317 | |
| 318 | return bcm_topo_context.devs[device_id].pons[physical_pon].contexts[pon_context_id]; |
| 319 | } |
| 320 | |
| 321 | static void bcm_topo_init_context(void) |
| 322 | { |
| 323 | uint32_t device_id; |
| 324 | |
| 325 | for (device_id = 0; device_id < BCM_TOPO_MAX_NUM_OF_DEVS; device_id++) |
| 326 | { |
| 327 | bcm_topo_dev_context_t *dev; |
| 328 | uint32_t pon_id; |
| 329 | |
| 330 | dev = &bcm_topo_context.devs[device_id]; |
| 331 | dev->device_id = device_id; |
| 332 | dev->pon_mode = BCM_TOPO_PON_MODE_INVALID; |
| 333 | for (pon_id = 0; pon_id < BCM_TOPO_MAX_NUM_OF_PONS_PER_DEV; pon_id++) |
| 334 | { |
| 335 | bcm_topo_pon_context_t *pon; |
| 336 | |
| 337 | pon = &dev->pons[pon_id]; |
| 338 | pon->dev = dev; |
| 339 | pon->pon_id = pon_id; |
| 340 | pon->pon_mode = BCM_TOPO_PON_MODE_INVALID; |
| 341 | pon->logical_pon = BCM_TOPO_PON_INVALID; |
| 342 | } |
| 343 | } |
| 344 | } |
| 345 | |
| 346 | static bcmos_errno bcm_topo_init_line_parse(const char *line, const char *filename, uint32_t line_num, bcmos_bool *is_skipped, uint32_t *logical_pon, bcm_topo_pon_mode *pon_mode, |
| 347 | uint32_t *device_id, uint32_t *physical_pon) |
| 348 | { |
| 349 | int rc; |
| 350 | char logical_pon_str[BCM_TOPO_MAX_LINE_SIZE]; |
| 351 | char pon_mode_str[BCM_TOPO_MAX_LINE_SIZE]; |
| 352 | char device_id_str[BCM_TOPO_MAX_LINE_SIZE]; |
| 353 | char physical_pon_str[BCM_TOPO_MAX_LINE_SIZE]; |
| 354 | int2str_t *p; |
| 355 | |
| 356 | /* Skip blank lines and comments. */ |
| 357 | if (!*line || *line == '\n' || *line == '#') |
| 358 | { |
| 359 | *is_skipped = BCMOS_TRUE; |
| 360 | return BCM_ERR_OK; |
| 361 | } |
| 362 | |
| 363 | *is_skipped = BCMOS_FALSE; |
| 364 | |
| 365 | /* Read the tokens separated by commas. */ |
| 366 | rc = sscanf(line, "%[^,],%*[ ]%[^,],%[^,],%[^\n]", logical_pon_str, pon_mode_str, device_id_str, physical_pon_str); |
| 367 | if (rc < 4) |
| 368 | { |
| 369 | BCM_LOG(ERROR, topo_log_id, "Error parsing line %s:%u (rc=%u)\n", filename, line_num, rc); |
| 370 | return BCM_ERR_PARSE; |
| 371 | } |
| 372 | |
| 373 | if (sscanf(logical_pon_str, "%u", logical_pon) < 1) |
| 374 | { |
| 375 | BCM_LOG(ERROR, topo_log_id, "Error parsing line %s:%u (rc=%u)\n", filename, line_num, rc); |
| 376 | return BCM_ERR_PARSE; |
| 377 | } |
| 378 | |
| 379 | if (sscanf(device_id_str, "%u", device_id) < 1) |
| 380 | { |
| 381 | BCM_LOG(ERROR, topo_log_id, "Error parsing line %s:%u (rc=%u)\n", filename, line_num, rc); |
| 382 | return BCM_ERR_PARSE; |
| 383 | } |
| 384 | |
| 385 | if (sscanf(physical_pon_str, "%u", physical_pon) < 1) |
| 386 | { |
| 387 | BCM_LOG(ERROR, topo_log_id, "Error parsing line %s:%u (rc=%u)\n", filename, line_num, rc); |
| 388 | return BCM_ERR_PARSE; |
| 389 | } |
| 390 | |
| 391 | BCM_LOG(INFO, topo_log_id, "Map Logical PON ID=%u -> (Physical Device ID=%u, Physical Pon ID=%u, PON mode='%s')\n", *logical_pon, *device_id, *physical_pon, pon_mode_str); |
| 392 | |
| 393 | for (p = pon_mode2str; p->from != -1 && strcmp(pon_mode_str, p->to); p++); |
| 394 | |
| 395 | if (p->from == -1) |
| 396 | { |
| 397 | BCM_LOG(ERROR, topo_log_id, "Error parsing PON mode at %s:%u\n", filename, line_num); |
| 398 | return BCM_ERR_PARSE; |
| 399 | } |
| 400 | |
| 401 | *pon_mode = p->from; |
| 402 | |
| 403 | return BCM_ERR_OK; |
| 404 | } |
| 405 | |
| 406 | static void bcm_topo_init_dev(bcm_topo_dev_context_t *dev, bcm_topo_pon_mode pon_mode) |
| 407 | { |
| 408 | dev->pon_mode = pon_mode; |
| 409 | dev->max_num_of_pons = int2int(pon_mode2max_num_of_pons, pon_mode); |
| 410 | } |
| 411 | |
| 412 | static void bcm_topo_init_pon(bcm_topo_pon_context_t *pon, bcm_topo_pon_mode pon_mode) |
| 413 | { |
| 414 | pon->pon_mode = pon_mode; |
| 415 | switch (pon_mode) |
| 416 | { |
| 417 | case BCM_TOPO_PON_MODE_GPON: |
| 418 | pon->max_num_of_onus = 128; |
| 419 | break; |
| 420 | case BCM_TOPO_PON_MODE_XGPON: |
| 421 | case BCM_TOPO_PON_MODE_XGS: |
| 422 | pon->max_num_of_onus = 256; |
| 423 | break; |
| 424 | case BCM_TOPO_PON_MODE_EPON_TDMA: |
| 425 | case BCM_TOPO_PON_MODE_EPON_1G: |
| 426 | case BCM_TOPO_PON_MODE_EPON_10G: |
| 427 | pon->max_num_of_onus = 0; /* There is no "ONU" in EPON, but LLIDs. */ |
| 428 | break; |
| 429 | default: |
| 430 | break; |
| 431 | } |
| 432 | } |
| 433 | |
| 434 | static bcmos_errno bcm_topo_init_by_file(FILE *fp, const char *filename) |
| 435 | { |
| 436 | char line[BCM_TOPO_MAX_LINE_SIZE]; |
| 437 | uint32_t line_num; |
| 438 | |
| 439 | /* Read next line. */ |
| 440 | line_num = 1; |
| 441 | while (fgets(line, sizeof(line), fp)) |
| 442 | { |
| 443 | bcmos_bool is_skipped; |
| 444 | uint32_t logical_pon, device_id, physical_pon; |
| 445 | bcm_topo_pon_mode pon_mode; |
| 446 | bcm_topo_dev_context_t *dev; |
| 447 | bcm_topo_pon_context_t *pon; |
| 448 | |
| 449 | if (bcm_topo_init_line_parse(line, filename, line_num, &is_skipped, &logical_pon, &pon_mode, &device_id, &physical_pon) != BCM_ERR_OK) |
| 450 | return BCM_ERR_PARSE; |
| 451 | |
| 452 | if (is_skipped) |
| 453 | { |
| 454 | line_num++; |
| 455 | continue; |
| 456 | } |
| 457 | |
| 458 | if (logical_pon >= BCM_TOPO_MAX_NUM_OF_LOGICAL_PONS) |
| 459 | { |
| 460 | BCM_LOG(ERROR, topo_log_id, "Logical PON ID at %s:%u must be in the range 0 .. %u\n", filename, line_num, BCM_TOPO_MAX_NUM_OF_LOGICAL_PONS - 1); |
| 461 | return BCM_ERR_RANGE; |
| 462 | } |
| 463 | |
| 464 | if (bcm_topo_context.logical_pon2physical_pon[logical_pon]) |
| 465 | { |
| 466 | BCM_LOG(ERROR, topo_log_id, "Logical PON ID at %s:%u has already been set before\n", filename, line_num); |
| 467 | return BCM_ERR_ALREADY; |
| 468 | } |
| 469 | |
| 470 | if (device_id >= BCM_TOPO_MAX_NUM_OF_DEVS) |
| 471 | { |
| 472 | BCM_LOG(ERROR, topo_log_id, "Physical device ID at %s:%u must be in the range 0 .. %u\n", filename, line_num, BCM_TOPO_MAX_NUM_OF_DEVS - 1); |
| 473 | return BCM_ERR_RANGE; |
| 474 | } |
| 475 | |
| 476 | dev = &bcm_topo_context.devs[device_id]; |
| 477 | if (!dev->is_initialized) |
| 478 | { |
| 479 | bcm_topo_init_dev(dev, pon_mode); |
| 480 | dev->is_initialized = BCMOS_TRUE; |
| 481 | } |
| 482 | else if (dev->pon_mode != pon_mode) |
| 483 | { |
| 484 | BCM_LOG(ERROR, topo_log_id, "PON mode at %s:%u conflicts with PON mode='%s' that has already been set for this device\n", filename, line_num, |
| 485 | int2str(pon_mode2str, dev->pon_mode)); |
| 486 | return BCM_ERR_NOT_SUPPORTED; |
| 487 | } |
| 488 | |
| 489 | if (physical_pon >= dev->max_num_of_pons) |
| 490 | { |
| 491 | BCM_LOG(ERROR, topo_log_id, "Physical PON ID at %s:%u must be in the range 0 .. %u\n", filename, line_num, dev->max_num_of_pons - 1); |
| 492 | return BCM_ERR_RANGE; |
| 493 | } |
| 494 | |
| 495 | pon = &bcm_topo_context.devs[device_id].pons[physical_pon]; |
| 496 | if (!pon->is_initialized) |
| 497 | { |
| 498 | bcm_topo_init_pon(pon, pon_mode); |
| 499 | pon->is_initialized = BCMOS_TRUE; |
| 500 | } |
| 501 | else |
| 502 | { |
| 503 | BCM_LOG(ERROR, topo_log_id, "Physical PON ID at %s:%u has already been set before\n", filename, line_num); |
| 504 | return BCM_ERR_ALREADY; |
| 505 | } |
| 506 | |
| 507 | bcm_topo_context.logical_pon2physical_pon[logical_pon] = &bcm_topo_context.devs[device_id].pons[physical_pon]; |
| 508 | bcm_topo_context.devs[device_id].pons[physical_pon].logical_pon = logical_pon; |
| 509 | |
| 510 | line_num++; |
| 511 | } |
| 512 | |
| 513 | return BCM_ERR_OK; |
| 514 | } |
| 515 | |
| 516 | static bcmos_errno bcm_topo_init_by_args(bcm_topo_params *params) |
| 517 | { |
| 518 | uint32_t device_id; |
| 519 | uint32_t max_num_of_pons_per_dev; |
| 520 | |
| 521 | if (params->num_of_devs > BCM_TOPO_MAX_NUM_OF_DEVS) |
| 522 | { |
| 523 | BCM_LOG(ERROR, topo_log_id, "Number of devices must be in the range 0 .. %u\n", BCM_TOPO_MAX_NUM_OF_DEVS); |
| 524 | return BCM_ERR_RANGE; |
| 525 | } |
| 526 | |
| 527 | max_num_of_pons_per_dev = int2int(pon_mode2max_num_of_pons, params->pon_mode); |
| 528 | |
| 529 | if (params->num_of_pons_per_dev > max_num_of_pons_per_dev) |
| 530 | { |
| 531 | BCM_LOG(ERROR, topo_log_id, "Number of PONs per device for PON mode '%s' must be in the range 0 .. %u\n", int2str(pon_mode2str, params->pon_mode), BCM_TOPO_MAX_NUM_OF_DEVS); |
| 532 | return BCM_ERR_RANGE; |
| 533 | } |
| 534 | |
| 535 | for (device_id = 0; device_id < params->num_of_devs; device_id++) |
| 536 | { |
| 537 | uint32_t physical_pon; |
| 538 | bcm_topo_dev_context_t *dev; |
| 539 | bcm_topo_pon_context_t *pon; |
| 540 | |
| 541 | dev = &bcm_topo_context.devs[device_id]; |
| 542 | bcm_topo_init_dev(dev, params->pon_mode); |
| 543 | dev->is_initialized = BCMOS_TRUE; |
| 544 | |
| 545 | for (physical_pon = 0; physical_pon < params->num_of_pons_per_dev; physical_pon++) |
| 546 | { |
| 547 | uint32_t logical_pon; |
| 548 | |
| 549 | logical_pon = (device_id * params->num_of_pons_per_dev) + physical_pon; |
| 550 | |
| 551 | BCM_LOG(INFO, topo_log_id, "Map Logical PON ID=%u -> (Physical Device ID=%u, Physical pon ID=%u, PON mode='%s')\n", logical_pon, device_id, physical_pon, |
| 552 | int2str(pon_mode2str, params->pon_mode)); |
| 553 | |
| 554 | pon = &bcm_topo_context.devs[device_id].pons[physical_pon]; |
| 555 | bcm_topo_init_pon(pon, params->pon_mode); |
| 556 | pon->is_initialized = BCMOS_TRUE; |
| 557 | |
| 558 | bcm_topo_context.logical_pon2physical_pon[logical_pon] = &bcm_topo_context.devs[device_id].pons[physical_pon]; |
| 559 | bcm_topo_context.devs[device_id].pons[physical_pon].logical_pon = logical_pon; |
| 560 | } |
| 561 | } |
| 562 | |
| 563 | return BCM_ERR_OK; |
| 564 | } |
| 565 | |
| 566 | bcmos_errno bcm_topo_init(bcm_topo_params *params, const char *topo_filename) |
| 567 | { |
| 568 | bcmos_errno ret; |
| 569 | FILE *topo_fp; |
| 570 | |
| 571 | #ifdef ENABLE_LOG |
| 572 | if (topo_log_id == DEV_LOG_INVALID_ID) |
| 573 | { |
| 574 | topo_log_id = bcm_dev_log_id_register("TOPOLOGY", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH); |
| 575 | BUG_ON(topo_log_id == DEV_LOG_INVALID_ID); |
| 576 | } |
| 577 | #endif |
| 578 | |
| 579 | bcm_topo_init_context(); |
| 580 | |
| 581 | topo_fp = fopen(topo_filename, "r"); |
| 582 | if (topo_fp) |
| 583 | { |
| 584 | BCM_LOG(INFO, topo_log_id, "Topology is taken from file\n"); |
| 585 | ret = bcm_topo_init_by_file(topo_fp, topo_filename); |
| 586 | fclose(topo_fp); |
| 587 | } |
| 588 | else if (params) |
| 589 | { |
| 590 | BCM_LOG(INFO, topo_log_id, "Topology is taken from arguments\n"); |
| 591 | ret = bcm_topo_init_by_args(params); |
| 592 | } |
| 593 | else |
| 594 | { |
| 595 | BCM_LOG(INFO, topo_log_id, "At least one of topo_fp and params must be specified and exist\n"); |
| 596 | ret = BCM_ERR_PARM; |
| 597 | } |
| 598 | |
| 599 | if (ret != BCM_ERR_OK) |
| 600 | goto exit; |
| 601 | |
| 602 | bcm_topo_context.is_initialized = BCMOS_TRUE; |
| 603 | |
| 604 | ret = BCM_ERR_OK; |
| 605 | |
| 606 | exit: |
| 607 | return ret; |
| 608 | } |
| 609 | |
| 610 | bcmos_bool bcm_topo_is_initialized(void) |
| 611 | { |
| 612 | return bcm_topo_context.is_initialized; |
| 613 | } |
| 614 | |
| 615 | bcmos_bool bcm_topo_dev_set_max_nni(bcmolt_devid device_id, uint32_t num_nni_ports) |
| 616 | { |
| 617 | if(device_id >= BCM_TOPO_MAX_NNI_DEVICES) |
| 618 | { |
| 619 | return BCM_ERR_PARM; |
| 620 | } |
| 621 | /* make sure the max number does not exceed the allocated resrouce */ |
| 622 | if( num_nni_ports > BCM_TOPO_MAX_NNI_PORTS) |
| 623 | { |
| 624 | return BCM_ERR_PARM; |
| 625 | } |
| 626 | g_max_nni_ports[device_id] = num_nni_ports; |
| 627 | |
| 628 | return BCMOS_TRUE; |
| 629 | } |
| 630 | |
| 631 | bcmos_bool bcm_topo_dev_get_max_nni(bcmolt_devid device_id, uint32_t *p_num_nni_ports) |
| 632 | { |
| 633 | if(device_id >= BCM_TOPO_MAX_NNI_DEVICES) |
| 634 | { |
| 635 | return BCM_ERR_PARM; |
| 636 | } |
| 637 | *p_num_nni_ports = g_max_nni_ports[device_id]; |
| 638 | |
| 639 | return BCMOS_TRUE; |
| 640 | } |
| 641 | |
| 642 | bcmos_bool bcm_topo_nni_is_valid(uint32_t nni) |
| 643 | { |
| 644 | |
| 645 | if (nni >= g_max_nni_ports[0]) |
| 646 | return BCMOS_FALSE; |
| 647 | |
| 648 | return BCMOS_TRUE; |
| 649 | } |
| 650 | |