.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2008 Marvell Semiconductor |
---|
5 | 6 | * Copyright (c) 2015 CMC Electronics, Inc. |
---|
6 | 7 | * Copyright (c) 2017 Savoir-faire Linux, Inc. |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License as published by |
---|
10 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
11 | | - * (at your option) any later version. |
---|
12 | 8 | */ |
---|
13 | 9 | |
---|
| 10 | +#include <linux/bitfield.h> |
---|
14 | 11 | #include <linux/interrupt.h> |
---|
15 | 12 | #include <linux/irqdomain.h> |
---|
16 | 13 | |
---|
.. | .. |
---|
71 | 68 | |
---|
72 | 69 | static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip) |
---|
73 | 70 | { |
---|
74 | | - return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_VTU_OP, |
---|
75 | | - MV88E6XXX_G1_VTU_OP_BUSY); |
---|
| 71 | + int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY); |
---|
| 72 | + |
---|
| 73 | + return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0); |
---|
76 | 74 | } |
---|
77 | 75 | |
---|
78 | 76 | static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op) |
---|
.. | .. |
---|
338 | 336 | return mv88e6xxx_g1_vtu_vid_read(chip, entry); |
---|
339 | 337 | } |
---|
340 | 338 | |
---|
| 339 | +int 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 | + err = mv88e6185_g1_stu_data_read(chip, entry); |
---|
| 355 | + if (err) |
---|
| 356 | + return err; |
---|
| 357 | + |
---|
| 358 | + /* VTU DBNum[3:0] are located in VTU Operation 3:0 |
---|
| 359 | + * VTU DBNum[5:4] are located in VTU Operation 9:8 |
---|
| 360 | + */ |
---|
| 361 | + err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val); |
---|
| 362 | + if (err) |
---|
| 363 | + return err; |
---|
| 364 | + |
---|
| 365 | + entry->fid = val & 0x000f; |
---|
| 366 | + entry->fid |= (val & 0x0300) >> 4; |
---|
| 367 | + } |
---|
| 368 | + |
---|
| 369 | + return 0; |
---|
| 370 | +} |
---|
| 371 | + |
---|
341 | 372 | int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, |
---|
342 | 373 | struct mv88e6xxx_vtu_entry *entry) |
---|
343 | 374 | { |
---|
.. | .. |
---|
433 | 464 | } |
---|
434 | 465 | |
---|
435 | 466 | return 0; |
---|
| 467 | +} |
---|
| 468 | + |
---|
| 469 | +int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, |
---|
| 470 | + struct mv88e6xxx_vtu_entry *entry) |
---|
| 471 | +{ |
---|
| 472 | + u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE; |
---|
| 473 | + int err; |
---|
| 474 | + |
---|
| 475 | + err = mv88e6xxx_g1_vtu_op_wait(chip); |
---|
| 476 | + if (err) |
---|
| 477 | + return err; |
---|
| 478 | + |
---|
| 479 | + err = mv88e6xxx_g1_vtu_vid_write(chip, entry); |
---|
| 480 | + if (err) |
---|
| 481 | + return err; |
---|
| 482 | + |
---|
| 483 | + if (entry->valid) { |
---|
| 484 | + err = mv88e6185_g1_vtu_data_write(chip, entry); |
---|
| 485 | + if (err) |
---|
| 486 | + return err; |
---|
| 487 | + |
---|
| 488 | + /* VTU DBNum[3:0] are located in VTU Operation 3:0 |
---|
| 489 | + * VTU DBNum[5:4] are located in VTU Operation 9:8 |
---|
| 490 | + */ |
---|
| 491 | + op |= entry->fid & 0x000f; |
---|
| 492 | + op |= (entry->fid & 0x0030) << 4; |
---|
| 493 | + } |
---|
| 494 | + |
---|
| 495 | + return mv88e6xxx_g1_vtu_op(chip, op); |
---|
436 | 496 | } |
---|
437 | 497 | |
---|
438 | 498 | int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, |
---|
.. | .. |
---|
564 | 624 | int err; |
---|
565 | 625 | u16 val; |
---|
566 | 626 | |
---|
567 | | - mutex_lock(&chip->reg_lock); |
---|
| 627 | + mv88e6xxx_reg_lock(chip); |
---|
568 | 628 | |
---|
569 | 629 | err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION); |
---|
570 | 630 | if (err) |
---|
.. | .. |
---|
592 | 652 | chip->ports[spid].vtu_miss_violation++; |
---|
593 | 653 | } |
---|
594 | 654 | |
---|
595 | | - mutex_unlock(&chip->reg_lock); |
---|
| 655 | + mv88e6xxx_reg_unlock(chip); |
---|
596 | 656 | |
---|
597 | 657 | return IRQ_HANDLED; |
---|
598 | 658 | |
---|
599 | 659 | out: |
---|
600 | | - mutex_unlock(&chip->reg_lock); |
---|
| 660 | + mv88e6xxx_reg_unlock(chip); |
---|
601 | 661 | |
---|
602 | 662 | dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n", |
---|
603 | 663 | err); |
---|
.. | .. |
---|
614 | 674 | if (chip->vtu_prob_irq < 0) |
---|
615 | 675 | return chip->vtu_prob_irq; |
---|
616 | 676 | |
---|
| 677 | + snprintf(chip->vtu_prob_irq_name, sizeof(chip->vtu_prob_irq_name), |
---|
| 678 | + "mv88e6xxx-%s-g1-vtu-prob", dev_name(chip->dev)); |
---|
| 679 | + |
---|
617 | 680 | err = request_threaded_irq(chip->vtu_prob_irq, NULL, |
---|
618 | 681 | mv88e6xxx_g1_vtu_prob_irq_thread_fn, |
---|
619 | | - IRQF_ONESHOT, "mv88e6xxx-g1-vtu-prob", |
---|
| 682 | + IRQF_ONESHOT, chip->vtu_prob_irq_name, |
---|
620 | 683 | chip); |
---|
621 | 684 | if (err) |
---|
622 | 685 | irq_dispose_mapping(chip->vtu_prob_irq); |
---|