global1_vtu.c (14629B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support 4 * 5 * Copyright (c) 2008 Marvell Semiconductor 6 * Copyright (c) 2015 CMC Electronics, Inc. 7 * Copyright (c) 2017 Savoir-faire Linux, Inc. 8 */ 9 10#include <linux/bitfield.h> 11#include <linux/interrupt.h> 12#include <linux/irqdomain.h> 13 14#include "chip.h" 15#include "global1.h" 16 17/* Offset 0x02: VTU FID Register */ 18 19static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip, 20 struct mv88e6xxx_vtu_entry *entry) 21{ 22 u16 val; 23 int err; 24 25 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val); 26 if (err) 27 return err; 28 29 entry->fid = val & MV88E6352_G1_VTU_FID_MASK; 30 entry->policy = !!(val & MV88E6352_G1_VTU_FID_VID_POLICY); 31 return 0; 32} 33 34static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip, 35 struct mv88e6xxx_vtu_entry *entry) 36{ 37 u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK; 38 39 if (entry->policy) 40 val |= MV88E6352_G1_VTU_FID_VID_POLICY; 41 42 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val); 43} 44 45/* Offset 0x03: VTU SID Register */ 46 47static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip, u8 *sid) 48{ 49 u16 val; 50 int err; 51 52 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val); 53 if (err) 54 return err; 55 56 *sid = val & MV88E6352_G1_VTU_SID_MASK; 57 58 return 0; 59} 60 61static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip, u8 sid) 62{ 63 u16 val = sid & MV88E6352_G1_VTU_SID_MASK; 64 65 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val); 66} 67 68/* Offset 0x05: VTU Operation Register */ 69 70static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip) 71{ 72 int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY); 73 74 return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0); 75} 76 77static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op) 78{ 79 int err; 80 81 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP, 82 MV88E6XXX_G1_VTU_OP_BUSY | op); 83 if (err) 84 return err; 85 86 return mv88e6xxx_g1_vtu_op_wait(chip); 87} 88 89/* Offset 0x06: VTU VID Register */ 90 91static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip, 92 bool *valid, u16 *vid) 93{ 94 u16 val; 95 int err; 96 97 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val); 98 if (err) 99 return err; 100 101 if (vid) { 102 *vid = val & 0xfff; 103 104 if (val & MV88E6390_G1_VTU_VID_PAGE) 105 *vid |= 0x1000; 106 } 107 108 if (valid) 109 *valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID); 110 111 return 0; 112} 113 114static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip, 115 bool valid, u16 vid) 116{ 117 u16 val = vid & 0xfff; 118 119 if (vid & 0x1000) 120 val |= MV88E6390_G1_VTU_VID_PAGE; 121 122 if (valid) 123 val |= MV88E6XXX_G1_VTU_VID_VALID; 124 125 return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val); 126} 127 128/* Offset 0x07: VTU/STU Data Register 1 129 * Offset 0x08: VTU/STU Data Register 2 130 * Offset 0x09: VTU/STU Data Register 3 131 */ 132static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip, 133 u16 *regs) 134{ 135 int i; 136 137 /* Read all 3 VTU/STU Data registers */ 138 for (i = 0; i < 3; ++i) { 139 u16 *reg = ®s[i]; 140 int err; 141 142 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg); 143 if (err) 144 return err; 145 } 146 147 return 0; 148} 149 150static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip, 151 u8 *member, u8 *state) 152{ 153 u16 regs[3]; 154 int err; 155 int i; 156 157 err = mv88e6185_g1_vtu_stu_data_read(chip, regs); 158 if (err) 159 return err; 160 161 /* Extract MemberTag data */ 162 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { 163 unsigned int member_offset = (i % 4) * 4; 164 unsigned int state_offset = member_offset + 2; 165 166 if (member) 167 member[i] = (regs[i / 4] >> member_offset) & 0x3; 168 169 if (state) 170 state[i] = (regs[i / 4] >> state_offset) & 0x3; 171 } 172 173 return 0; 174} 175 176static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip, 177 u8 *member, u8 *state) 178{ 179 u16 regs[3] = { 0 }; 180 int i; 181 182 /* Insert MemberTag and PortState data */ 183 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { 184 unsigned int member_offset = (i % 4) * 4; 185 unsigned int state_offset = member_offset + 2; 186 187 if (member) 188 regs[i / 4] |= (member[i] & 0x3) << member_offset; 189 190 if (state) 191 regs[i / 4] |= (state[i] & 0x3) << state_offset; 192 } 193 194 /* Write all 3 VTU/STU Data registers */ 195 for (i = 0; i < 3; ++i) { 196 u16 reg = regs[i]; 197 int err; 198 199 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg); 200 if (err) 201 return err; 202 } 203 204 return 0; 205} 206 207static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data) 208{ 209 u16 regs[2]; 210 int i; 211 212 /* Read the 2 VTU/STU Data registers */ 213 for (i = 0; i < 2; ++i) { 214 u16 *reg = ®s[i]; 215 int err; 216 217 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg); 218 if (err) 219 return err; 220 } 221 222 /* Extract data */ 223 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { 224 unsigned int offset = (i % 8) * 2; 225 226 data[i] = (regs[i / 8] >> offset) & 0x3; 227 } 228 229 return 0; 230} 231 232static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data) 233{ 234 u16 regs[2] = { 0 }; 235 int i; 236 237 /* Insert data */ 238 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { 239 unsigned int offset = (i % 8) * 2; 240 241 regs[i / 8] |= (data[i] & 0x3) << offset; 242 } 243 244 /* Write the 2 VTU/STU Data registers */ 245 for (i = 0; i < 2; ++i) { 246 u16 reg = regs[i]; 247 int err; 248 249 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg); 250 if (err) 251 return err; 252 } 253 254 return 0; 255} 256 257/* VLAN Translation Unit Operations */ 258 259int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip, 260 struct mv88e6xxx_vtu_entry *entry) 261{ 262 int err; 263 264 err = mv88e6xxx_g1_vtu_op_wait(chip); 265 if (err) 266 return err; 267 268 /* To get the next higher active VID, the VTU GetNext operation can be 269 * started again without setting the VID registers since it already 270 * contains the last VID. 271 * 272 * To save a few hardware accesses and abstract this to the caller, 273 * write the VID only once, when the entry is given as invalid. 274 */ 275 if (!entry->valid) { 276 err = mv88e6xxx_g1_vtu_vid_write(chip, false, entry->vid); 277 if (err) 278 return err; 279 } 280 281 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT); 282 if (err) 283 return err; 284 285 return mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, &entry->vid); 286} 287 288int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, 289 struct mv88e6xxx_vtu_entry *entry) 290{ 291 u16 val; 292 int err; 293 294 err = mv88e6xxx_g1_vtu_getnext(chip, entry); 295 if (err) 296 return err; 297 298 if (entry->valid) { 299 err = mv88e6185_g1_vtu_data_read(chip, entry->member, entry->state); 300 if (err) 301 return err; 302 303 /* VTU DBNum[3:0] are located in VTU Operation 3:0 304 * VTU DBNum[7:4] ([5:4] for 6250) are located in VTU Operation 11:8 (9:8) 305 */ 306 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val); 307 if (err) 308 return err; 309 310 entry->fid = val & 0x000f; 311 entry->fid |= (val & 0x0f00) >> 4; 312 entry->fid &= mv88e6xxx_num_databases(chip) - 1; 313 } 314 315 return 0; 316} 317 318int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip, 319 struct mv88e6xxx_vtu_entry *entry) 320{ 321 int err; 322 323 /* Fetch VLAN MemberTag data from the VTU */ 324 err = mv88e6xxx_g1_vtu_getnext(chip, entry); 325 if (err) 326 return err; 327 328 if (entry->valid) { 329 err = mv88e6185_g1_vtu_data_read(chip, entry->member, NULL); 330 if (err) 331 return err; 332 333 err = mv88e6xxx_g1_vtu_fid_read(chip, entry); 334 if (err) 335 return err; 336 337 err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid); 338 if (err) 339 return err; 340 } 341 342 return 0; 343} 344 345int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip, 346 struct mv88e6xxx_vtu_entry *entry) 347{ 348 int err; 349 350 /* Fetch VLAN MemberTag data from the VTU */ 351 err = mv88e6xxx_g1_vtu_getnext(chip, entry); 352 if (err) 353 return err; 354 355 if (entry->valid) { 356 err = mv88e6390_g1_vtu_data_read(chip, entry->member); 357 if (err) 358 return err; 359 360 err = mv88e6xxx_g1_vtu_fid_read(chip, entry); 361 if (err) 362 return err; 363 364 err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid); 365 if (err) 366 return err; 367 } 368 369 return 0; 370} 371 372int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, 373 struct mv88e6xxx_vtu_entry *entry) 374{ 375 u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE; 376 int err; 377 378 err = mv88e6xxx_g1_vtu_op_wait(chip); 379 if (err) 380 return err; 381 382 err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid); 383 if (err) 384 return err; 385 386 if (entry->valid) { 387 err = mv88e6185_g1_vtu_data_write(chip, entry->member, entry->state); 388 if (err) 389 return err; 390 391 /* VTU DBNum[3:0] are located in VTU Operation 3:0 392 * VTU DBNum[7:4] are located in VTU Operation 11:8 393 * 394 * For the 6250/6220, the latter are really [5:4] and 395 * 9:8, but in those cases bits 7:6 of entry->fid are 396 * 0 since they have num_databases = 64. 397 */ 398 op |= entry->fid & 0x000f; 399 op |= (entry->fid & 0x00f0) << 4; 400 } 401 402 return mv88e6xxx_g1_vtu_op(chip, op); 403} 404 405int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, 406 struct mv88e6xxx_vtu_entry *entry) 407{ 408 int err; 409 410 err = mv88e6xxx_g1_vtu_op_wait(chip); 411 if (err) 412 return err; 413 414 err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid); 415 if (err) 416 return err; 417 418 if (entry->valid) { 419 /* Write MemberTag data */ 420 err = mv88e6185_g1_vtu_data_write(chip, entry->member, NULL); 421 if (err) 422 return err; 423 424 err = mv88e6xxx_g1_vtu_fid_write(chip, entry); 425 if (err) 426 return err; 427 428 err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid); 429 if (err) 430 return err; 431 } 432 433 /* Load/Purge VTU entry */ 434 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE); 435} 436 437int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, 438 struct mv88e6xxx_vtu_entry *entry) 439{ 440 int err; 441 442 err = mv88e6xxx_g1_vtu_op_wait(chip); 443 if (err) 444 return err; 445 446 err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid); 447 if (err) 448 return err; 449 450 if (entry->valid) { 451 /* Write MemberTag data */ 452 err = mv88e6390_g1_vtu_data_write(chip, entry->member); 453 if (err) 454 return err; 455 456 err = mv88e6xxx_g1_vtu_fid_write(chip, entry); 457 if (err) 458 return err; 459 460 err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid); 461 if (err) 462 return err; 463 } 464 465 /* Load/Purge VTU entry */ 466 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE); 467} 468 469int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip) 470{ 471 int err; 472 473 err = mv88e6xxx_g1_vtu_op_wait(chip); 474 if (err) 475 return err; 476 477 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL); 478} 479 480/* Spanning Tree Unit Operations */ 481 482int mv88e6xxx_g1_stu_getnext(struct mv88e6xxx_chip *chip, 483 struct mv88e6xxx_stu_entry *entry) 484{ 485 int err; 486 487 err = mv88e6xxx_g1_vtu_op_wait(chip); 488 if (err) 489 return err; 490 491 /* To get the next higher active SID, the STU GetNext operation can be 492 * started again without setting the SID registers since it already 493 * contains the last SID. 494 * 495 * To save a few hardware accesses and abstract this to the caller, 496 * write the SID only once, when the entry is given as invalid. 497 */ 498 if (!entry->valid) { 499 err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid); 500 if (err) 501 return err; 502 } 503 504 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT); 505 if (err) 506 return err; 507 508 err = mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, NULL); 509 if (err) 510 return err; 511 512 if (entry->valid) { 513 err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid); 514 if (err) 515 return err; 516 } 517 518 return 0; 519} 520 521int mv88e6352_g1_stu_getnext(struct mv88e6xxx_chip *chip, 522 struct mv88e6xxx_stu_entry *entry) 523{ 524 int err; 525 526 err = mv88e6xxx_g1_stu_getnext(chip, entry); 527 if (err) 528 return err; 529 530 if (!entry->valid) 531 return 0; 532 533 return mv88e6185_g1_vtu_data_read(chip, NULL, entry->state); 534} 535 536int mv88e6390_g1_stu_getnext(struct mv88e6xxx_chip *chip, 537 struct mv88e6xxx_stu_entry *entry) 538{ 539 int err; 540 541 err = mv88e6xxx_g1_stu_getnext(chip, entry); 542 if (err) 543 return err; 544 545 if (!entry->valid) 546 return 0; 547 548 return mv88e6390_g1_vtu_data_read(chip, entry->state); 549} 550 551int mv88e6352_g1_stu_loadpurge(struct mv88e6xxx_chip *chip, 552 struct mv88e6xxx_stu_entry *entry) 553{ 554 int err; 555 556 err = mv88e6xxx_g1_vtu_op_wait(chip); 557 if (err) 558 return err; 559 560 err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0); 561 if (err) 562 return err; 563 564 err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid); 565 if (err) 566 return err; 567 568 if (entry->valid) { 569 err = mv88e6185_g1_vtu_data_write(chip, NULL, entry->state); 570 if (err) 571 return err; 572 } 573 574 /* Load/Purge STU entry */ 575 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE); 576} 577 578int mv88e6390_g1_stu_loadpurge(struct mv88e6xxx_chip *chip, 579 struct mv88e6xxx_stu_entry *entry) 580{ 581 int err; 582 583 err = mv88e6xxx_g1_vtu_op_wait(chip); 584 if (err) 585 return err; 586 587 err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0); 588 if (err) 589 return err; 590 591 err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid); 592 if (err) 593 return err; 594 595 if (entry->valid) { 596 err = mv88e6390_g1_vtu_data_write(chip, entry->state); 597 if (err) 598 return err; 599 } 600 601 /* Load/Purge STU entry */ 602 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE); 603} 604 605/* VTU Violation Management */ 606 607static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id) 608{ 609 struct mv88e6xxx_chip *chip = dev_id; 610 u16 val, vid; 611 int spid; 612 int err; 613 614 mv88e6xxx_reg_lock(chip); 615 616 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION); 617 if (err) 618 goto out; 619 620 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val); 621 if (err) 622 goto out; 623 624 err = mv88e6xxx_g1_vtu_vid_read(chip, NULL, &vid); 625 if (err) 626 goto out; 627 628 spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK; 629 630 if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) { 631 dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n", 632 vid, spid); 633 chip->ports[spid].vtu_member_violation++; 634 } 635 636 if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) { 637 dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n", 638 vid, spid); 639 chip->ports[spid].vtu_miss_violation++; 640 } 641 642 mv88e6xxx_reg_unlock(chip); 643 644 return IRQ_HANDLED; 645 646out: 647 mv88e6xxx_reg_unlock(chip); 648 649 dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n", 650 err); 651 652 return IRQ_HANDLED; 653} 654 655int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip) 656{ 657 int err; 658 659 chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain, 660 MV88E6XXX_G1_STS_IRQ_VTU_PROB); 661 if (chip->vtu_prob_irq < 0) 662 return chip->vtu_prob_irq; 663 664 snprintf(chip->vtu_prob_irq_name, sizeof(chip->vtu_prob_irq_name), 665 "mv88e6xxx-%s-g1-vtu-prob", dev_name(chip->dev)); 666 667 err = request_threaded_irq(chip->vtu_prob_irq, NULL, 668 mv88e6xxx_g1_vtu_prob_irq_thread_fn, 669 IRQF_ONESHOT, chip->vtu_prob_irq_name, 670 chip); 671 if (err) 672 irq_dispose_mapping(chip->vtu_prob_irq); 673 674 return err; 675} 676 677void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip) 678{ 679 free_irq(chip->vtu_prob_irq, chip); 680 irq_dispose_mapping(chip->vtu_prob_irq); 681}