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