1/* 2 * Copyright (c) 2012, The Linux Foundation. All rights reserved. 3 * Permission to use, copy, modify, and/or distribute this software for 4 * any purpose with or without fee is hereby granted, provided that the 5 * above copyright notice and this permission notice appear in all copies. 6 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 7 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 8 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 9 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 10 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 11 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 12 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 13 */ 14 15 16/** 17 * @defgroup horus_fdb HORUS_FDB 18 * @{ 19 */ 20#include "sw.h" 21#include "hsl.h" 22#include "hsl_dev.h" 23#include "hsl_port_prop.h" 24#include "horus_fdb.h" 25#include "horus_reg.h" 26 27#define ARL_FLUSH_ALL 1 28#define ARL_LOAD_ENTRY 2 29#define ARL_PURGE_ENTRY 3 30#define ARL_FLUSH_ALL_UNLOCK 4 31#define ARL_FLUSH_PORT_UNICAST 5 32#define ARL_NEXT_ENTRY 6 33#define ARL_FIND_ENTRY 7 34 35#define ARL_FIRST_ENTRY 1001 36#define ARL_FLUSH_PORT_NO_STATIC 1002 37#define ARL_FLUSH_PORT_AND_STATIC 1003 38 39static a_bool_t 40horus_fdb_is_zeroaddr(fal_mac_addr_t addr) 41{ 42 a_uint32_t i; 43 44 for (i = 0; i < 6; i++) 45 { 46 if (addr.uc[i]) 47 { 48 return A_FALSE; 49 } 50 } 51 52 return A_TRUE; 53} 54 55static void 56horus_fdb_fill_addr(fal_mac_addr_t addr, a_uint32_t * reg0, a_uint32_t * reg1) 57{ 58 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_ADDR_BYTE0, addr.uc[0], *reg1); 59 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_ADDR_BYTE1, addr.uc[1], *reg1); 60 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_ADDR_BYTE2, addr.uc[2], *reg1); 61 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC1, AT_ADDR_BYTE3, addr.uc[3], *reg1); 62 63 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_ADDR_BYTE4, addr.uc[4], *reg0); 64 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_ADDR_BYTE5, addr.uc[5], *reg0); 65 66 return; 67} 68 69static sw_error_t 70horus_atu_sw_to_hw(a_uint32_t dev_id, const fal_fdb_entry_t * entry, 71 a_uint32_t reg[]) 72{ 73 a_uint32_t port; 74 75 if (A_FALSE == entry->portmap_en) 76 { 77 if (A_TRUE != 78 hsl_port_prop_check(dev_id, entry->port.id, HSL_PP_INCL_CPU)) 79 { 80 return SW_BAD_PARAM; 81 } 82 83 port = 0x1UL << entry->port.id; 84 } 85 else 86 { 87 if (A_FALSE == 88 hsl_mports_prop_check(dev_id, entry->port.map, HSL_PP_INCL_CPU)) 89 { 90 return SW_BAD_PARAM; 91 } 92 93 port = entry->port.map; 94 } 95 96 if (FAL_MAC_CPY_TO_CPU == entry->dacmd) 97 { 98 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, COPY_TO_CPU, 1, reg[2]); 99 } 100 else if (FAL_MAC_RDT_TO_CPU == entry->dacmd) 101 { 102 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, REDRCT_TO_CPU, 1, reg[2]); 103 } 104 else if (FAL_MAC_FRWRD != entry->dacmd) 105 { 106 return SW_NOT_SUPPORTED; 107 } 108 109 if (FAL_MAC_DROP == entry->sacmd) 110 { 111 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, SA_DROP_EN, 1, reg[2]); 112 } 113 else if (FAL_MAC_FRWRD != entry->sacmd) 114 { 115 return SW_NOT_SUPPORTED; 116 } 117 118 if (A_TRUE == entry->leaky_en) 119 { 120 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, LEAKY_EN, 1, reg[2]); 121 } 122 else 123 { 124 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, LEAKY_EN, 0, reg[2]); 125 } 126 127 if (A_TRUE == entry->static_en) 128 { 129 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_STATUS, 15, reg[2]); 130 } 131 else 132 { 133 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_STATUS, 7, reg[2]); 134 } 135 136 if (A_TRUE == entry->mirror_en) 137 { 138 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, MIRROR_EN, 1, reg[2]); 139 } 140 141 if (A_TRUE == entry->clone_en) 142 { 143 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, CLONE_EN, 1, reg[2]); 144 } 145 146 if (A_TRUE == entry->cross_pt_state) 147 { 148 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, CROSS_PT, 1, reg[2]); 149 } 150 151 if (A_TRUE == entry->da_pri_en) 152 { 153 hsl_dev_t *p_dev; 154 155 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_PRI_EN, 1, reg[2]); 156 157 SW_RTN_ON_NULL(p_dev = hsl_dev_ptr_get(dev_id)); 158 159 if (entry->da_queue > (p_dev->nr_queue - 1)) 160 return SW_BAD_PARAM; 161 162 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, AT_PRI, entry->da_queue, reg[2]); 163 } 164 165 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC2, DES_PORT, port, reg[2]); 166 horus_fdb_fill_addr(entry->addr, ®[0], ®[1]); 167 168 return SW_OK; 169} 170 171static void 172horus_atu_hw_to_sw(const a_uint32_t reg[], fal_fdb_entry_t * entry) 173{ 174 a_uint32_t i, data; 175 176 aos_mem_zero(entry, sizeof (fal_fdb_entry_t)); 177 178 entry->dacmd = FAL_MAC_FRWRD; 179 SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, COPY_TO_CPU, data, reg[2]); 180 if (1 == data) 181 { 182 entry->dacmd = FAL_MAC_CPY_TO_CPU; 183 } 184 185 SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, REDRCT_TO_CPU, data, reg[2]); 186 if (1 == data) 187 { 188 entry->dacmd = FAL_MAC_RDT_TO_CPU; 189 } 190 191 entry->sacmd = FAL_MAC_FRWRD; 192 SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, SA_DROP_EN, data, reg[2]); 193 if (1 == data) 194 { 195 entry->sacmd = FAL_MAC_DROP; 196 } 197 198 entry->leaky_en = A_FALSE; 199 SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, LEAKY_EN, data, reg[2]); 200 if (1 == data) 201 { 202 entry->leaky_en = A_TRUE; 203 } 204 205 entry->static_en = A_FALSE; 206 SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, AT_STATUS, data, reg[2]); 207 if (0xf == data) 208 { 209 entry->static_en = A_TRUE; 210 } 211 212 entry->mirror_en = A_FALSE; 213 SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, MIRROR_EN, data, reg[2]); 214 if (1 == data) 215 { 216 entry->mirror_en = A_TRUE; 217 } 218 219 entry->clone_en = A_FALSE; 220 SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, CLONE_EN, data, reg[2]); 221 if (1 == data) 222 { 223 entry->clone_en = A_TRUE; 224 } 225 226 entry->da_pri_en = A_FALSE; 227 SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, AT_PRI_EN, data, reg[2]); 228 if (1 == data) 229 { 230 SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, AT_PRI, data, reg[2]); 231 entry->da_pri_en = A_TRUE; 232 entry->da_queue = data & 0x3; 233 } 234 235 entry->cross_pt_state = A_FALSE; 236 SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, CROSS_PT, data, reg[2]); 237 if (1 == data) 238 { 239 entry->cross_pt_state = A_TRUE; 240 } 241 242 SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, DES_PORT, data, reg[2]); 243 244 entry->portmap_en = A_TRUE; 245 entry->port.map = data; 246 247 for (i = 0; i < 4; i++) 248 { 249 entry->addr.uc[i] = (reg[1] >> ((3 - i) << 3)) & 0xff; 250 } 251 252 for (i = 4; i < 6; i++) 253 { 254 entry->addr.uc[i] = (reg[0] >> ((7 - i) << 3)) & 0xff; 255 } 256 257 return; 258} 259 260static sw_error_t 261horus_fdb_commit(a_uint32_t dev_id, a_uint32_t op) 262{ 263 sw_error_t rv; 264 a_uint32_t busy = 1; 265 a_uint32_t full_vio; 266 a_uint32_t i = 1000; 267 a_uint32_t entry; 268 a_uint32_t hwop = op; 269 270 while (busy && --i) 271 { 272 HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_FUNC0, 0, AT_BUSY, 273 (a_uint8_t *) (&busy), sizeof (a_uint32_t)); 274 SW_RTN_ON_ERROR(rv); 275 aos_udelay(5); 276 } 277 278 if (0 == i) 279 { 280 return SW_BUSY; 281 } 282 283 HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC0, 0, 284 (a_uint8_t *) (&entry), sizeof (a_uint32_t)); 285 SW_RTN_ON_ERROR(rv); 286 287 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_BUSY, 1, entry); 288 289 if (ARL_FLUSH_PORT_AND_STATIC == hwop) 290 { 291 hwop = ARL_FLUSH_PORT_UNICAST; 292 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, FLUSH_ST_EN, 1, entry); 293 } 294 295 if (ARL_FLUSH_PORT_NO_STATIC == hwop) 296 { 297 hwop = ARL_FLUSH_PORT_UNICAST; 298 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, FLUSH_ST_EN, 0, entry); 299 } 300 301 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_FUNC, hwop, entry); 302 303 HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0, 304 (a_uint8_t *) (&entry), sizeof (a_uint32_t)); 305 SW_RTN_ON_ERROR(rv); 306 307 busy = 1; 308 i = 1000; 309 while (busy && --i) 310 { 311 HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_FUNC0, 0, AT_BUSY, 312 (a_uint8_t *) (&busy), sizeof (a_uint32_t)); 313 SW_RTN_ON_ERROR(rv); 314 aos_udelay(5); 315 } 316 317 if (0 == i) 318 { 319 return SW_FAIL; 320 } 321 322 HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_FUNC0, 0, AT_FULL_VIO, 323 (a_uint8_t *) (&full_vio), sizeof (a_uint32_t)); 324 SW_RTN_ON_ERROR(rv); 325 326 if (full_vio) 327 { 328 /* must clear AT_FULL_VOI bit */ 329 entry = 0x1000; 330 HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0, 331 (a_uint8_t *) (&entry), sizeof (a_uint32_t)); 332 SW_RTN_ON_ERROR(rv); 333 334 if (ARL_LOAD_ENTRY == hwop) 335 { 336 return SW_FULL; 337 } 338 else if ((ARL_PURGE_ENTRY == hwop) 339 || (ARL_FLUSH_PORT_UNICAST == hwop)) 340 { 341 return SW_NOT_FOUND; 342 } 343 else 344 { 345 return SW_FAIL; 346 } 347 } 348 349 return SW_OK; 350} 351 352static sw_error_t 353horus_atu_get(a_uint32_t dev_id, fal_fdb_entry_t * entry, a_uint32_t op) 354{ 355 sw_error_t rv; 356 a_uint32_t reg[3] = { 0 }; 357 a_uint32_t status = 0; 358 a_uint32_t hwop = op; 359 360 if ((ARL_NEXT_ENTRY == op) 361 || (ARL_FIND_ENTRY == op)) 362 { 363 horus_fdb_fill_addr(entry->addr, ®[0], ®[1]); 364 } 365 366 HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0, 367 (a_uint8_t *) (®[0]), sizeof (a_uint32_t)); 368 SW_RTN_ON_ERROR(rv); 369 370 HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC1, 0, 371 (a_uint8_t *) (®[1]), sizeof (a_uint32_t)); 372 SW_RTN_ON_ERROR(rv); 373 374 /* set status not zero */ 375 if (ARL_NEXT_ENTRY == op) 376 { 377 reg[2] = 0xf0000; 378 } 379 380 if (ARL_FIRST_ENTRY == op) 381 { 382 hwop = ARL_NEXT_ENTRY; 383 } 384 385 HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC2, 0, 386 (a_uint8_t *) (®[2]), sizeof (a_uint32_t)); 387 SW_RTN_ON_ERROR(rv); 388 389 rv = horus_fdb_commit(dev_id, hwop); 390 SW_RTN_ON_ERROR(rv); 391 392 /* get hardware enrety */ 393 HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC0, 0, 394 (a_uint8_t *) (®[0]), sizeof (a_uint32_t)); 395 396 SW_RTN_ON_ERROR(rv); 397 398 HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC1, 0, 399 (a_uint8_t *) (®[1]), sizeof (a_uint32_t)); 400 401 SW_RTN_ON_ERROR(rv); 402 403 HSL_REG_ENTRY_GET(rv, dev_id, ADDR_TABLE_FUNC2, 0, 404 (a_uint8_t *) (®[2]), sizeof (a_uint32_t)); 405 406 SW_RTN_ON_ERROR(rv); 407 408 SW_GET_FIELD_BY_REG(ADDR_TABLE_FUNC2, AT_STATUS, status, reg[2]); 409 410 horus_atu_hw_to_sw(reg, entry); 411 412 /* If hardware return back with address and status all zero, 413 that means no other next valid entry in fdb table */ 414 if ((A_TRUE == horus_fdb_is_zeroaddr(entry->addr)) 415 && (0 == status)) 416 { 417 if (ARL_NEXT_ENTRY == op) 418 { 419 return SW_NO_MORE; 420 } 421 else if ((ARL_FIND_ENTRY == op) 422 || (ARL_FIRST_ENTRY == op)) 423 { 424 return SW_NOT_FOUND; 425 } 426 else 427 { 428 return SW_FAIL; 429 } 430 } 431 else 432 { 433 return SW_OK; 434 } 435} 436 437static sw_error_t 438_horus_fdb_add(a_uint32_t dev_id, const fal_fdb_entry_t * entry) 439{ 440 sw_error_t rv; 441 a_uint32_t reg[3] = { 0, 0, 0 }; 442 443 HSL_DEV_ID_CHECK(dev_id); 444 445 rv = horus_atu_sw_to_hw(dev_id, entry, reg); 446 SW_RTN_ON_ERROR(rv); 447 448 HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC2, 0, 449 (a_uint8_t *) (®[2]), sizeof (a_uint32_t)); 450 SW_RTN_ON_ERROR(rv); 451 452 HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC1, 0, (a_uint8_t *) (®[1]), 453 sizeof (a_uint32_t)); 454 SW_RTN_ON_ERROR(rv); 455 456 HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0, (a_uint8_t *) (®[0]), 457 sizeof (a_uint32_t)); 458 SW_RTN_ON_ERROR(rv); 459 460 rv = horus_fdb_commit(dev_id, ARL_LOAD_ENTRY); 461 462 return rv; 463} 464 465static sw_error_t 466_horus_fdb_del_all(a_uint32_t dev_id, a_uint32_t flag) 467{ 468 sw_error_t rv; 469 470 HSL_DEV_ID_CHECK(dev_id); 471 472 if (FAL_FDB_DEL_STATIC & flag) 473 { 474 rv = horus_fdb_commit(dev_id, ARL_FLUSH_ALL); 475 } 476 else 477 { 478 rv = horus_fdb_commit(dev_id, ARL_FLUSH_ALL_UNLOCK); 479 } 480 481 return rv; 482} 483 484static sw_error_t 485_horus_fdb_del_by_port(a_uint32_t dev_id, fal_port_t port_id, a_uint32_t flag) 486{ 487 sw_error_t rv; 488 a_uint32_t reg = 0; 489 490 HSL_DEV_ID_CHECK(dev_id); 491 492 if (A_FALSE == hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU)) 493 { 494 return SW_BAD_PARAM; 495 } 496 497 SW_SET_REG_BY_FIELD(ADDR_TABLE_FUNC0, AT_PORT_NUM, port_id, reg); 498 499 HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0, (a_uint8_t *) (®), 500 sizeof (a_uint32_t)); 501 SW_RTN_ON_ERROR(rv); 502 503 if (FAL_FDB_DEL_STATIC & flag) 504 { 505 rv = horus_fdb_commit(dev_id, ARL_FLUSH_PORT_AND_STATIC); 506 } 507 else 508 { 509 rv = horus_fdb_commit(dev_id, ARL_FLUSH_PORT_NO_STATIC); 510 } 511 512 return rv; 513} 514 515static sw_error_t 516_horus_fdb_del_by_mac(a_uint32_t dev_id, const fal_fdb_entry_t * entry) 517{ 518 sw_error_t rv; 519 a_uint32_t reg0 = 0, reg1 = 0; 520 521 HSL_DEV_ID_CHECK(dev_id); 522 523 horus_fdb_fill_addr(entry->addr, ®0, ®1); 524 525 HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC1, 0, (a_uint8_t *) (®1), 526 sizeof (a_uint32_t)); 527 SW_RTN_ON_ERROR(rv); 528 529 HSL_REG_ENTRY_SET(rv, dev_id, ADDR_TABLE_FUNC0, 0, (a_uint8_t *) (®0), 530 sizeof (a_uint32_t)); 531 SW_RTN_ON_ERROR(rv); 532 533 rv = horus_fdb_commit(dev_id, ARL_PURGE_ENTRY); 534 return rv; 535} 536 537static sw_error_t 538_horus_fdb_next(a_uint32_t dev_id, fal_fdb_entry_t * entry) 539{ 540 sw_error_t rv; 541 542 HSL_DEV_ID_CHECK(dev_id); 543 544 rv = horus_atu_get(dev_id, entry, ARL_NEXT_ENTRY); 545 return rv; 546} 547 548static sw_error_t 549_horus_fdb_first(a_uint32_t dev_id, fal_fdb_entry_t * entry) 550{ 551 sw_error_t rv; 552 553 HSL_DEV_ID_CHECK(dev_id); 554 555 rv = horus_atu_get(dev_id, entry, ARL_FIRST_ENTRY); 556 return rv; 557} 558 559static sw_error_t 560_horus_fdb_find(a_uint32_t dev_id, fal_fdb_entry_t * entry) 561{ 562 sw_error_t rv; 563 564 HSL_DEV_ID_CHECK(dev_id); 565 566 rv = horus_atu_get(dev_id, entry, ARL_FIND_ENTRY); 567 return rv; 568} 569 570static sw_error_t 571_horus_fdb_port_learn_set(a_uint32_t dev_id, fal_port_t port_id, 572 a_bool_t enable) 573{ 574 a_uint32_t data; 575 sw_error_t rv; 576 577 HSL_DEV_ID_CHECK(dev_id); 578 579 if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU)) 580 { 581 return SW_BAD_PARAM; 582 } 583 584 if (A_TRUE == enable) 585 { 586 data = 1; 587 } 588 else if (A_FALSE == enable) 589 { 590 data = 0; 591 } 592 else 593 { 594 return SW_BAD_PARAM; 595 } 596 597 HSL_REG_FIELD_SET(rv, dev_id, PORT_CTL, port_id, LEARN_EN, 598 (a_uint8_t *) (&data), sizeof (a_uint32_t)); 599 return rv; 600} 601 602static sw_error_t 603_horus_fdb_port_learn_get(a_uint32_t dev_id, fal_port_t port_id, 604 a_bool_t *enable) 605{ 606 a_uint32_t data; 607 sw_error_t rv; 608 609 HSL_DEV_ID_CHECK(dev_id); 610 611 if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_INCL_CPU)) 612 { 613 return SW_BAD_PARAM; 614 } 615 616 HSL_REG_FIELD_GET(rv, dev_id, PORT_CTL, port_id, LEARN_EN, 617 (a_uint8_t *) (&data), sizeof (a_uint32_t)); 618 SW_RTN_ON_ERROR(rv); 619 620 if (1 == data) 621 { 622 *enable = A_TRUE; 623 } 624 else 625 { 626 *enable = A_FALSE; 627 } 628 629 return SW_OK; 630} 631 632static sw_error_t 633_horus_fdb_age_ctrl_set(a_uint32_t dev_id, a_bool_t enable) 634{ 635 a_uint32_t data; 636 sw_error_t rv; 637 638 HSL_DEV_ID_CHECK(dev_id); 639 640 if (A_TRUE == enable) 641 { 642 data = 1; 643 } 644 else if (A_FALSE == enable) 645 { 646 data = 0; 647 } 648 else 649 { 650 return SW_BAD_PARAM; 651 } 652 653 HSL_REG_FIELD_SET(rv, dev_id, ADDR_TABLE_CTL, 0, AGE_EN, 654 (a_uint8_t *) (&data), sizeof (a_uint32_t)); 655 return rv; 656} 657 658static sw_error_t 659_horus_fdb_age_ctrl_get(a_uint32_t dev_id, a_bool_t *enable) 660{ 661 a_uint32_t data; 662 sw_error_t rv; 663 664 HSL_DEV_ID_CHECK(dev_id); 665 666 HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_CTL, 0, AGE_EN, 667 (a_uint8_t *) (&data), sizeof (a_uint32_t)); 668 SW_RTN_ON_ERROR(rv); 669 670 if (1 == data) 671 { 672 *enable = A_TRUE; 673 } 674 else 675 { 676 *enable = A_FALSE; 677 } 678 679 return SW_OK; 680} 681 682static sw_error_t 683_horus_fdb_age_time_set(a_uint32_t dev_id, a_uint32_t * time) 684{ 685 a_uint32_t data; 686 sw_error_t rv; 687 688 HSL_DEV_ID_CHECK(dev_id); 689 690 if ((65535 * 7 < *time) || (7 > *time)) 691 { 692 return SW_BAD_PARAM; 693 } 694 data = *time / 7; 695 *time = data * 7; 696 HSL_REG_FIELD_SET(rv, dev_id, ADDR_TABLE_CTL, 0, AGE_TIME, 697 (a_uint8_t *) (&data), sizeof (a_uint32_t)); 698 return rv; 699} 700 701static sw_error_t 702_horus_fdb_age_time_get(a_uint32_t dev_id, a_uint32_t *time) 703{ 704 a_uint32_t data; 705 sw_error_t rv; 706 707 HSL_DEV_ID_CHECK(dev_id); 708 709 HSL_REG_FIELD_GET(rv, dev_id, ADDR_TABLE_CTL, 0, AGE_TIME, 710 (a_uint8_t *) (&data), sizeof (a_uint32_t)); 711 SW_RTN_ON_ERROR(rv); 712 713 *time = data * 7; 714 return SW_OK; 715} 716 717/** 718 * @brief Add a Fdb entry 719 * @param[in] dev_id device id 720 * @param[in] entry fdb entry 721 * @return SW_OK or error code 722 */ 723HSL_LOCAL sw_error_t 724horus_fdb_add(a_uint32_t dev_id, const fal_fdb_entry_t * entry) 725{ 726 sw_error_t rv; 727 728 HSL_API_LOCK; 729 rv = _horus_fdb_add(dev_id, entry); 730 HSL_API_UNLOCK; 731 return rv; 732} 733 734/** 735 * @brief Delete all Fdb entries 736 * @details Comments: 737 * If set FAL_FDB_DEL_STATIC bit in flag which means delete all fdb 738 * entries otherwise only delete dynamic entries. 739 * @param[in] dev_id device id 740 * @param[in] flag delete operation option 741 * @return SW_OK or error code 742 */ 743HSL_LOCAL sw_error_t 744horus_fdb_del_all(a_uint32_t dev_id, a_uint32_t flag) 745{ 746 sw_error_t rv; 747 748 HSL_API_LOCK; 749 rv = _horus_fdb_del_all(dev_id, flag); 750 HSL_API_UNLOCK; 751 return rv; 752} 753 754/** 755 * @brief Delete Fdb entries on a particular port 756 * @details Comments: 757 * If set FAL_FDB_DEL_STATIC bit in flag which means delete all fdb 758 * entries otherwise only delete dynamic entries. 759 * @param[in] dev_id device id 760 * @param[in] port_id port id 761 * @param[in] flag delete operation option 762 * @return SW_OK or error code 763 */ 764HSL_LOCAL sw_error_t 765horus_fdb_del_by_port(a_uint32_t dev_id, fal_port_t port_id, a_uint32_t flag) 766{ 767 sw_error_t rv; 768 769 HSL_API_LOCK; 770 rv = _horus_fdb_del_by_port(dev_id, port_id, flag); 771 HSL_API_UNLOCK; 772 return rv; 773} 774 775/** 776 * @brief Delete a particular Fdb entry through mac address 777 * @details Comments: 778 * Only addr field in entry is meaning. For IVL learning vid or fid field 779 * also is meaning. 780 * @param[in] dev_id device id 781 * @param[in] entry fdb entry 782 * @return SW_OK or error code 783 */ 784HSL_LOCAL sw_error_t 785horus_fdb_del_by_mac(a_uint32_t dev_id, const fal_fdb_entry_t * entry) 786{ 787 sw_error_t rv; 788 789 HSL_API_LOCK; 790 rv = _horus_fdb_del_by_mac(dev_id, entry); 791 HSL_API_UNLOCK; 792 return rv; 793} 794 795/** 796 * @brief Get next Fdb entry from particular device 797 * @details Comments: 798 * For input parameter only addr field in entry is meaning. 799 * @param[in] dev_id device id 800 * @param entry fdb entry 801 * @return SW_OK or error code 802 */ 803HSL_LOCAL sw_error_t 804horus_fdb_next(a_uint32_t dev_id, fal_fdb_entry_t * entry) 805{ 806 sw_error_t rv; 807 808 HSL_API_LOCK; 809 rv = _horus_fdb_next(dev_id, entry); 810 HSL_API_UNLOCK; 811 return rv; 812} 813 814/** 815 * @brief Get first Fdb entry from particular device 816 * @param[in] dev_id device id 817 * @param[out] entry fdb entry 818 * @return SW_OK or error code 819 */ 820HSL_LOCAL sw_error_t 821horus_fdb_first(a_uint32_t dev_id, fal_fdb_entry_t * entry) 822{ 823 sw_error_t rv; 824 825 HSL_API_LOCK; 826 rv = _horus_fdb_first(dev_id, entry); 827 HSL_API_UNLOCK; 828 return rv; 829} 830 831/** 832 * @brief Find a particular Fdb entry from device through mac address. 833 * @details Comments: 834 For input parameter only addr field in entry is meaning. 835 * @param[in] dev_id device id 836 * @param[in] entry fdb entry 837 * @param[out] entry fdb entry 838 * @return SW_OK or error code 839 */ 840HSL_LOCAL sw_error_t 841horus_fdb_find(a_uint32_t dev_id, fal_fdb_entry_t * entry) 842{ 843 sw_error_t rv; 844 845 HSL_API_LOCK; 846 rv = _horus_fdb_find(dev_id, entry); 847 HSL_API_UNLOCK; 848 return rv; 849} 850 851/** 852 * @brief Set dynamic address learning status on a particular port. 853 * @details Comments: 854 * This operation will enable or disable dynamic address learning 855 * feature on a particular port. 856 * @param[in] dev_id device id 857 * @param[in] port_id port id 858 * @param[in] enable enable or disable 859 * @return SW_OK or error code 860 */ 861HSL_LOCAL sw_error_t 862horus_fdb_port_learn_set(a_uint32_t dev_id, fal_port_t port_id, 863 a_bool_t enable) 864{ 865 sw_error_t rv; 866 867 HSL_API_LOCK; 868 rv = _horus_fdb_port_learn_set(dev_id, port_id, enable); 869 HSL_API_UNLOCK; 870 return rv; 871} 872 873/** 874 * @brief Get dynamic address learning status on a particular port. 875 * @param[in] dev_id device id 876 * @param[in] port_id port id 877 * @param[out] enable A_TRUE or A_FALSE 878 * @return SW_OK or error code 879 */ 880HSL_LOCAL sw_error_t 881horus_fdb_port_learn_get(a_uint32_t dev_id, fal_port_t port_id, 882 a_bool_t *enable) 883{ 884 sw_error_t rv; 885 886 HSL_API_LOCK; 887 rv = _horus_fdb_port_learn_get(dev_id, port_id, enable); 888 HSL_API_UNLOCK; 889 return rv; 890} 891 892/** 893 * @brief Set dynamic address aging status on particular device. 894 * @details Comments: 895 * This operation will enable or disable dynamic address aging 896 * feature on particular device. 897 * @param[in] dev_id device id 898 * @param[in] enable enable or disable 899 * @return SW_OK or error code 900 */ 901HSL_LOCAL sw_error_t 902horus_fdb_age_ctrl_set(a_uint32_t dev_id, a_bool_t enable) 903{ 904 sw_error_t rv; 905 906 HSL_API_LOCK; 907 rv = _horus_fdb_age_ctrl_set(dev_id, enable); 908 HSL_API_UNLOCK; 909 return rv; 910} 911 912/** 913 * @brief Get dynamic address aging status on particular device. 914 * @param[in] dev_id device id 915 * @param[in] enable enable or disable 916 * @return SW_OK or error code 917 */ 918HSL_LOCAL sw_error_t 919horus_fdb_age_ctrl_get(a_uint32_t dev_id, a_bool_t *enable) 920{ 921 sw_error_t rv; 922 923 HSL_API_LOCK; 924 rv = _horus_fdb_age_ctrl_get(dev_id, enable); 925 HSL_API_UNLOCK; 926 return rv; 927} 928 929/** 930 * @brief Set dynamic address aging time on a particular device. 931 * @details Comments: 932 * This operation will set dynamic address aging time on a particular device. 933 * The unit of time is second. Because different device has differnet 934 * hardware granularity function will return actual time in hardware. 935 * @param[in] dev_id device id 936 * @param time aging time 937 * @return SW_OK or error code 938 */ 939HSL_LOCAL sw_error_t 940horus_fdb_age_time_set(a_uint32_t dev_id, a_uint32_t * time) 941{ 942 sw_error_t rv; 943 944 HSL_API_LOCK; 945 rv = _horus_fdb_age_time_set(dev_id, time); 946 HSL_API_UNLOCK; 947 return rv; 948} 949 950/** 951 * @brief Get dynamic address aging time on a particular device. 952 * @param[in] dev_id device id 953 * @param[out] time aging time 954 * @return SW_OK or error code 955 */ 956HSL_LOCAL sw_error_t 957horus_fdb_age_time_get(a_uint32_t dev_id, a_uint32_t *time) 958{ 959 sw_error_t rv; 960 961 HSL_API_LOCK; 962 rv = _horus_fdb_age_time_get(dev_id, time); 963 HSL_API_UNLOCK; 964 return rv; 965} 966 967sw_error_t 968horus_fdb_init(a_uint32_t dev_id) 969{ 970 HSL_DEV_ID_CHECK(dev_id); 971 972#ifndef HSL_STANDALONG 973 { 974 hsl_api_t *p_api; 975 976 SW_RTN_ON_NULL(p_api = hsl_api_ptr_get(dev_id)); 977 978 p_api->fdb_add = horus_fdb_add; 979 p_api->fdb_del_all = horus_fdb_del_all; 980 p_api->fdb_del_by_port = horus_fdb_del_by_port; 981 p_api->fdb_del_by_mac = horus_fdb_del_by_mac; 982 p_api->fdb_first = horus_fdb_first; 983 p_api->fdb_next = horus_fdb_next; 984 p_api->fdb_find = horus_fdb_find; 985 p_api->port_learn_set = horus_fdb_port_learn_set; 986 p_api->port_learn_get = horus_fdb_port_learn_get; 987 p_api->age_ctrl_set = horus_fdb_age_ctrl_set; 988 p_api->age_ctrl_get = horus_fdb_age_ctrl_get; 989 p_api->age_time_set = horus_fdb_age_time_set; 990 p_api->age_time_get = horus_fdb_age_time_get; 991 } 992#endif 993 994 return SW_OK; 995} 996 997/** 998 * @} 999 */ 1000