1 /* 2 * Texas Instruments 3-Port Ethernet Switch Address Lookup Engine 3 * 4 * Copyright (C) 2012 Texas Instruments 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation version 2. 9 * 10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 11 * kind, whether express or implied; without even the implied warranty 12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 #include <linux/kernel.h> 16 #include <linux/platform_device.h> 17 #include <linux/seq_file.h> 18 #include <linux/slab.h> 19 #include <linux/err.h> 20 #include <linux/io.h> 21 #include <linux/stat.h> 22 #include <linux/sysfs.h> 23 #include <linux/etherdevice.h> 24 25 #include "cpsw_ale.h" 26 27 #define BITMASK(bits) (BIT(bits) - 1) 28 #define ALE_ENTRY_BITS 68 29 #define ALE_ENTRY_WORDS DIV_ROUND_UP(ALE_ENTRY_BITS, 32) 30 31 #define ALE_VERSION_MAJOR(rev) ((rev >> 8) & 0xff) 32 #define ALE_VERSION_MINOR(rev) (rev & 0xff) 33 34 /* ALE Registers */ 35 #define ALE_IDVER 0x00 36 #define ALE_CONTROL 0x08 37 #define ALE_PRESCALE 0x10 38 #define ALE_UNKNOWNVLAN 0x18 39 #define ALE_TABLE_CONTROL 0x20 40 #define ALE_TABLE 0x34 41 #define ALE_PORTCTL 0x40 42 43 #define ALE_TABLE_WRITE BIT(31) 44 45 #define ALE_TYPE_FREE 0 46 #define ALE_TYPE_ADDR 1 47 #define ALE_TYPE_VLAN 2 48 #define ALE_TYPE_VLAN_ADDR 3 49 50 #define ALE_UCAST_PERSISTANT 0 51 #define ALE_UCAST_UNTOUCHED 1 52 #define ALE_UCAST_OUI 2 53 #define ALE_UCAST_TOUCHED 3 54 55 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits) 56 { 57 int idx; 58 59 idx = start / 32; 60 start -= idx * 32; 61 idx = 2 - idx; /* flip */ 62 return (ale_entry[idx] >> start) & BITMASK(bits); 63 } 64 65 static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits, 66 u32 value) 67 { 68 int idx; 69 70 value &= BITMASK(bits); 71 idx = start / 32; 72 start -= idx * 32; 73 idx = 2 - idx; /* flip */ 74 ale_entry[idx] &= ~(BITMASK(bits) << start); 75 ale_entry[idx] |= (value << start); 76 } 77 78 #define DEFINE_ALE_FIELD(name, start, bits) \ 79 static inline int cpsw_ale_get_##name(u32 *ale_entry) \ 80 { \ 81 return cpsw_ale_get_field(ale_entry, start, bits); \ 82 } \ 83 static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value) \ 84 { \ 85 cpsw_ale_set_field(ale_entry, start, bits, value); \ 86 } 87 88 DEFINE_ALE_FIELD(entry_type, 60, 2) 89 DEFINE_ALE_FIELD(vlan_id, 48, 12) 90 DEFINE_ALE_FIELD(mcast_state, 62, 2) 91 DEFINE_ALE_FIELD(port_mask, 66, 3) 92 DEFINE_ALE_FIELD(super, 65, 1) 93 DEFINE_ALE_FIELD(ucast_type, 62, 2) 94 DEFINE_ALE_FIELD(port_num, 66, 2) 95 DEFINE_ALE_FIELD(blocked, 65, 1) 96 DEFINE_ALE_FIELD(secure, 64, 1) 97 DEFINE_ALE_FIELD(vlan_untag_force, 24, 3) 98 DEFINE_ALE_FIELD(vlan_reg_mcast, 16, 3) 99 DEFINE_ALE_FIELD(vlan_unreg_mcast, 8, 3) 100 DEFINE_ALE_FIELD(vlan_member_list, 0, 3) 101 DEFINE_ALE_FIELD(mcast, 40, 1) 102 103 /* The MAC address field in the ALE entry cannot be macroized as above */ 104 static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr) 105 { 106 int i; 107 108 for (i = 0; i < 6; i++) 109 addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8); 110 } 111 112 static inline void cpsw_ale_set_addr(u32 *ale_entry, u8 *addr) 113 { 114 int i; 115 116 for (i = 0; i < 6; i++) 117 cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]); 118 } 119 120 static int cpsw_ale_read(struct cpsw_ale *ale, int idx, u32 *ale_entry) 121 { 122 int i; 123 124 WARN_ON(idx > ale->params.ale_entries); 125 126 __raw_writel(idx, ale->params.ale_regs + ALE_TABLE_CONTROL); 127 128 for (i = 0; i < ALE_ENTRY_WORDS; i++) 129 ale_entry[i] = __raw_readl(ale->params.ale_regs + 130 ALE_TABLE + 4 * i); 131 132 return idx; 133 } 134 135 static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry) 136 { 137 int i; 138 139 WARN_ON(idx > ale->params.ale_entries); 140 141 for (i = 0; i < ALE_ENTRY_WORDS; i++) 142 __raw_writel(ale_entry[i], ale->params.ale_regs + 143 ALE_TABLE + 4 * i); 144 145 __raw_writel(idx | ALE_TABLE_WRITE, ale->params.ale_regs + 146 ALE_TABLE_CONTROL); 147 148 return idx; 149 } 150 151 static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr) 152 { 153 u32 ale_entry[ALE_ENTRY_WORDS]; 154 int type, idx; 155 156 for (idx = 0; idx < ale->params.ale_entries; idx++) { 157 u8 entry_addr[6]; 158 159 cpsw_ale_read(ale, idx, ale_entry); 160 type = cpsw_ale_get_entry_type(ale_entry); 161 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR) 162 continue; 163 cpsw_ale_get_addr(ale_entry, entry_addr); 164 if (memcmp(entry_addr, addr, 6) == 0) 165 return idx; 166 } 167 return -ENOENT; 168 } 169 170 static int cpsw_ale_match_free(struct cpsw_ale *ale) 171 { 172 u32 ale_entry[ALE_ENTRY_WORDS]; 173 int type, idx; 174 175 for (idx = 0; idx < ale->params.ale_entries; idx++) { 176 cpsw_ale_read(ale, idx, ale_entry); 177 type = cpsw_ale_get_entry_type(ale_entry); 178 if (type == ALE_TYPE_FREE) 179 return idx; 180 } 181 return -ENOENT; 182 } 183 184 static int cpsw_ale_find_ageable(struct cpsw_ale *ale) 185 { 186 u32 ale_entry[ALE_ENTRY_WORDS]; 187 int type, idx; 188 189 for (idx = 0; idx < ale->params.ale_entries; idx++) { 190 cpsw_ale_read(ale, idx, ale_entry); 191 type = cpsw_ale_get_entry_type(ale_entry); 192 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR) 193 continue; 194 if (cpsw_ale_get_mcast(ale_entry)) 195 continue; 196 type = cpsw_ale_get_ucast_type(ale_entry); 197 if (type != ALE_UCAST_PERSISTANT && 198 type != ALE_UCAST_OUI) 199 return idx; 200 } 201 return -ENOENT; 202 } 203 204 static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry, 205 int port_mask) 206 { 207 int mask; 208 209 mask = cpsw_ale_get_port_mask(ale_entry); 210 if ((mask & port_mask) == 0) 211 return; /* ports dont intersect, not interested */ 212 mask &= ~port_mask; 213 214 /* free if only remaining port is host port */ 215 if (mask) 216 cpsw_ale_set_port_mask(ale_entry, mask); 217 else 218 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); 219 } 220 221 int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask) 222 { 223 u32 ale_entry[ALE_ENTRY_WORDS]; 224 int ret, idx; 225 226 for (idx = 0; idx < ale->params.ale_entries; idx++) { 227 cpsw_ale_read(ale, idx, ale_entry); 228 ret = cpsw_ale_get_entry_type(ale_entry); 229 if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR) 230 continue; 231 232 if (cpsw_ale_get_mcast(ale_entry)) { 233 u8 addr[6]; 234 235 cpsw_ale_get_addr(ale_entry, addr); 236 if (!is_broadcast_ether_addr(addr)) 237 cpsw_ale_flush_mcast(ale, ale_entry, port_mask); 238 } 239 240 cpsw_ale_write(ale, idx, ale_entry); 241 } 242 return 0; 243 } 244 245 static void cpsw_ale_flush_ucast(struct cpsw_ale *ale, u32 *ale_entry, 246 int port_mask) 247 { 248 int port; 249 250 port = cpsw_ale_get_port_num(ale_entry); 251 if ((BIT(port) & port_mask) == 0) 252 return; /* ports dont intersect, not interested */ 253 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); 254 } 255 256 int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask) 257 { 258 u32 ale_entry[ALE_ENTRY_WORDS]; 259 int ret, idx; 260 261 for (idx = 0; idx < ale->params.ale_entries; idx++) { 262 cpsw_ale_read(ale, idx, ale_entry); 263 ret = cpsw_ale_get_entry_type(ale_entry); 264 if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR) 265 continue; 266 267 if (cpsw_ale_get_mcast(ale_entry)) 268 cpsw_ale_flush_mcast(ale, ale_entry, port_mask); 269 else 270 cpsw_ale_flush_ucast(ale, ale_entry, port_mask); 271 272 cpsw_ale_write(ale, idx, ale_entry); 273 } 274 return 0; 275 } 276 277 int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags) 278 { 279 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; 280 int idx; 281 282 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR); 283 cpsw_ale_set_addr(ale_entry, addr); 284 cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT); 285 cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0); 286 cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0); 287 cpsw_ale_set_port_num(ale_entry, port); 288 289 idx = cpsw_ale_match_addr(ale, addr); 290 if (idx < 0) 291 idx = cpsw_ale_match_free(ale); 292 if (idx < 0) 293 idx = cpsw_ale_find_ageable(ale); 294 if (idx < 0) 295 return -ENOMEM; 296 297 cpsw_ale_write(ale, idx, ale_entry); 298 return 0; 299 } 300 301 int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port) 302 { 303 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; 304 int idx; 305 306 idx = cpsw_ale_match_addr(ale, addr); 307 if (idx < 0) 308 return -ENOENT; 309 310 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); 311 cpsw_ale_write(ale, idx, ale_entry); 312 return 0; 313 } 314 315 int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask, 316 int super, int mcast_state) 317 { 318 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; 319 int idx, mask; 320 321 idx = cpsw_ale_match_addr(ale, addr); 322 if (idx >= 0) 323 cpsw_ale_read(ale, idx, ale_entry); 324 325 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR); 326 cpsw_ale_set_addr(ale_entry, addr); 327 cpsw_ale_set_super(ale_entry, super); 328 cpsw_ale_set_mcast_state(ale_entry, mcast_state); 329 330 mask = cpsw_ale_get_port_mask(ale_entry); 331 port_mask |= mask; 332 cpsw_ale_set_port_mask(ale_entry, port_mask); 333 334 if (idx < 0) 335 idx = cpsw_ale_match_free(ale); 336 if (idx < 0) 337 idx = cpsw_ale_find_ageable(ale); 338 if (idx < 0) 339 return -ENOMEM; 340 341 cpsw_ale_write(ale, idx, ale_entry); 342 return 0; 343 } 344 345 int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask) 346 { 347 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; 348 int idx; 349 350 idx = cpsw_ale_match_addr(ale, addr); 351 if (idx < 0) 352 return -EINVAL; 353 354 cpsw_ale_read(ale, idx, ale_entry); 355 356 if (port_mask) 357 cpsw_ale_set_port_mask(ale_entry, port_mask); 358 else 359 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); 360 361 cpsw_ale_write(ale, idx, ale_entry); 362 return 0; 363 } 364 365 struct ale_control_info { 366 const char *name; 367 int offset, port_offset; 368 int shift, port_shift; 369 int bits; 370 }; 371 372 static const struct ale_control_info ale_controls[ALE_NUM_CONTROLS] = { 373 [ALE_ENABLE] = { 374 .name = "enable", 375 .offset = ALE_CONTROL, 376 .port_offset = 0, 377 .shift = 31, 378 .port_shift = 0, 379 .bits = 1, 380 }, 381 [ALE_CLEAR] = { 382 .name = "clear", 383 .offset = ALE_CONTROL, 384 .port_offset = 0, 385 .shift = 30, 386 .port_shift = 0, 387 .bits = 1, 388 }, 389 [ALE_AGEOUT] = { 390 .name = "ageout", 391 .offset = ALE_CONTROL, 392 .port_offset = 0, 393 .shift = 29, 394 .port_shift = 0, 395 .bits = 1, 396 }, 397 [ALE_VLAN_NOLEARN] = { 398 .name = "vlan_nolearn", 399 .offset = ALE_CONTROL, 400 .port_offset = 0, 401 .shift = 7, 402 .port_shift = 0, 403 .bits = 1, 404 }, 405 [ALE_NO_PORT_VLAN] = { 406 .name = "no_port_vlan", 407 .offset = ALE_CONTROL, 408 .port_offset = 0, 409 .shift = 6, 410 .port_shift = 0, 411 .bits = 1, 412 }, 413 [ALE_OUI_DENY] = { 414 .name = "oui_deny", 415 .offset = ALE_CONTROL, 416 .port_offset = 0, 417 .shift = 5, 418 .port_shift = 0, 419 .bits = 1, 420 }, 421 [ALE_BYPASS] = { 422 .name = "bypass", 423 .offset = ALE_CONTROL, 424 .port_offset = 0, 425 .shift = 4, 426 .port_shift = 0, 427 .bits = 1, 428 }, 429 [ALE_RATE_LIMIT_TX] = { 430 .name = "rate_limit_tx", 431 .offset = ALE_CONTROL, 432 .port_offset = 0, 433 .shift = 3, 434 .port_shift = 0, 435 .bits = 1, 436 }, 437 [ALE_VLAN_AWARE] = { 438 .name = "vlan_aware", 439 .offset = ALE_CONTROL, 440 .port_offset = 0, 441 .shift = 2, 442 .port_shift = 0, 443 .bits = 1, 444 }, 445 [ALE_AUTH_ENABLE] = { 446 .name = "auth_enable", 447 .offset = ALE_CONTROL, 448 .port_offset = 0, 449 .shift = 1, 450 .port_shift = 0, 451 .bits = 1, 452 }, 453 [ALE_RATE_LIMIT] = { 454 .name = "rate_limit", 455 .offset = ALE_CONTROL, 456 .port_offset = 0, 457 .shift = 0, 458 .port_shift = 0, 459 .bits = 1, 460 }, 461 [ALE_PORT_STATE] = { 462 .name = "port_state", 463 .offset = ALE_PORTCTL, 464 .port_offset = 4, 465 .shift = 0, 466 .port_shift = 0, 467 .bits = 2, 468 }, 469 [ALE_PORT_DROP_UNTAGGED] = { 470 .name = "drop_untagged", 471 .offset = ALE_PORTCTL, 472 .port_offset = 4, 473 .shift = 2, 474 .port_shift = 0, 475 .bits = 1, 476 }, 477 [ALE_PORT_DROP_UNKNOWN_VLAN] = { 478 .name = "drop_unknown", 479 .offset = ALE_PORTCTL, 480 .port_offset = 4, 481 .shift = 3, 482 .port_shift = 0, 483 .bits = 1, 484 }, 485 [ALE_PORT_NOLEARN] = { 486 .name = "nolearn", 487 .offset = ALE_PORTCTL, 488 .port_offset = 4, 489 .shift = 4, 490 .port_shift = 0, 491 .bits = 1, 492 }, 493 [ALE_PORT_MCAST_LIMIT] = { 494 .name = "mcast_limit", 495 .offset = ALE_PORTCTL, 496 .port_offset = 4, 497 .shift = 16, 498 .port_shift = 0, 499 .bits = 8, 500 }, 501 [ALE_PORT_BCAST_LIMIT] = { 502 .name = "bcast_limit", 503 .offset = ALE_PORTCTL, 504 .port_offset = 4, 505 .shift = 24, 506 .port_shift = 0, 507 .bits = 8, 508 }, 509 [ALE_PORT_UNKNOWN_VLAN_MEMBER] = { 510 .name = "unknown_vlan_member", 511 .offset = ALE_UNKNOWNVLAN, 512 .port_offset = 0, 513 .shift = 0, 514 .port_shift = 0, 515 .bits = 6, 516 }, 517 [ALE_PORT_UNKNOWN_MCAST_FLOOD] = { 518 .name = "unknown_mcast_flood", 519 .offset = ALE_UNKNOWNVLAN, 520 .port_offset = 0, 521 .shift = 8, 522 .port_shift = 0, 523 .bits = 6, 524 }, 525 [ALE_PORT_UNKNOWN_REG_MCAST_FLOOD] = { 526 .name = "unknown_reg_flood", 527 .offset = ALE_UNKNOWNVLAN, 528 .port_offset = 0, 529 .shift = 16, 530 .port_shift = 0, 531 .bits = 6, 532 }, 533 [ALE_PORT_UNTAGGED_EGRESS] = { 534 .name = "untagged_egress", 535 .offset = ALE_UNKNOWNVLAN, 536 .port_offset = 0, 537 .shift = 24, 538 .port_shift = 0, 539 .bits = 6, 540 }, 541 }; 542 543 int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control, 544 int value) 545 { 546 const struct ale_control_info *info; 547 int offset, shift; 548 u32 tmp, mask; 549 550 if (control < 0 || control >= ARRAY_SIZE(ale_controls)) 551 return -EINVAL; 552 553 info = &ale_controls[control]; 554 if (info->port_offset == 0 && info->port_shift == 0) 555 port = 0; /* global, port is a dont care */ 556 557 if (port < 0 || port > ale->params.ale_ports) 558 return -EINVAL; 559 560 mask = BITMASK(info->bits); 561 if (value & ~mask) 562 return -EINVAL; 563 564 offset = info->offset + (port * info->port_offset); 565 shift = info->shift + (port * info->port_shift); 566 567 tmp = __raw_readl(ale->params.ale_regs + offset); 568 tmp = (tmp & ~(mask << shift)) | (value << shift); 569 __raw_writel(tmp, ale->params.ale_regs + offset); 570 571 return 0; 572 } 573 574 int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control) 575 { 576 const struct ale_control_info *info; 577 int offset, shift; 578 u32 tmp; 579 580 if (control < 0 || control >= ARRAY_SIZE(ale_controls)) 581 return -EINVAL; 582 583 info = &ale_controls[control]; 584 if (info->port_offset == 0 && info->port_shift == 0) 585 port = 0; /* global, port is a dont care */ 586 587 if (port < 0 || port > ale->params.ale_ports) 588 return -EINVAL; 589 590 offset = info->offset + (port * info->port_offset); 591 shift = info->shift + (port * info->port_shift); 592 593 tmp = __raw_readl(ale->params.ale_regs + offset) >> shift; 594 return tmp & BITMASK(info->bits); 595 } 596 597 static void cpsw_ale_timer(unsigned long arg) 598 { 599 struct cpsw_ale *ale = (struct cpsw_ale *)arg; 600 601 cpsw_ale_control_set(ale, 0, ALE_AGEOUT, 1); 602 603 if (ale->ageout) { 604 ale->timer.expires = jiffies + ale->ageout; 605 add_timer(&ale->timer); 606 } 607 } 608 609 int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout) 610 { 611 del_timer_sync(&ale->timer); 612 ale->ageout = ageout * HZ; 613 if (ale->ageout) { 614 ale->timer.expires = jiffies + ale->ageout; 615 add_timer(&ale->timer); 616 } 617 return 0; 618 } 619 620 void cpsw_ale_start(struct cpsw_ale *ale) 621 { 622 u32 rev; 623 624 rev = __raw_readl(ale->params.ale_regs + ALE_IDVER); 625 dev_dbg(ale->params.dev, "initialized cpsw ale revision %d.%d\n", 626 ALE_VERSION_MAJOR(rev), ALE_VERSION_MINOR(rev)); 627 cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1); 628 cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1); 629 630 init_timer(&ale->timer); 631 ale->timer.data = (unsigned long)ale; 632 ale->timer.function = cpsw_ale_timer; 633 if (ale->ageout) { 634 ale->timer.expires = jiffies + ale->ageout; 635 add_timer(&ale->timer); 636 } 637 } 638 639 void cpsw_ale_stop(struct cpsw_ale *ale) 640 { 641 del_timer_sync(&ale->timer); 642 } 643 644 struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params) 645 { 646 struct cpsw_ale *ale; 647 648 ale = kzalloc(sizeof(*ale), GFP_KERNEL); 649 if (!ale) 650 return NULL; 651 652 ale->params = *params; 653 ale->ageout = ale->params.ale_ageout * HZ; 654 655 return ale; 656 } 657 658 int cpsw_ale_destroy(struct cpsw_ale *ale) 659 { 660 if (!ale) 661 return -EINVAL; 662 cpsw_ale_stop(ale); 663 cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0); 664 kfree(ale); 665 return 0; 666 } 667