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