Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'qca8k-cleanup-and-port-isolation'

Matthias Schiffer says:

====================
net: dsa: qca8k: cleanup and port isolation

A small cleanup patch, and basically the same changes that were just
accepted for mt7530 to implement port isolation.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+70 -49
+69 -49
drivers/net/dsa/qca/qca8k-common.c
··· 614 614 qca8k_port_configure_learning(ds, port, learning); 615 615 } 616 616 617 + static int qca8k_update_port_member(struct qca8k_priv *priv, int port, 618 + const struct net_device *bridge_dev, 619 + bool join) 620 + { 621 + bool isolated = !!(priv->port_isolated_map & BIT(port)), other_isolated; 622 + struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp; 623 + u32 port_mask = BIT(dp->cpu_dp->index); 624 + int i, ret; 625 + 626 + for (i = 0; i < QCA8K_NUM_PORTS; i++) { 627 + if (i == port) 628 + continue; 629 + if (dsa_is_cpu_port(priv->ds, i)) 630 + continue; 631 + 632 + other_dp = dsa_to_port(priv->ds, i); 633 + if (!dsa_port_offloads_bridge_dev(other_dp, bridge_dev)) 634 + continue; 635 + 636 + other_isolated = !!(priv->port_isolated_map & BIT(i)); 637 + 638 + /* Add/remove this port to/from the portvlan mask of the other 639 + * ports in the bridge 640 + */ 641 + if (join && !(isolated && other_isolated)) { 642 + port_mask |= BIT(i); 643 + ret = regmap_set_bits(priv->regmap, 644 + QCA8K_PORT_LOOKUP_CTRL(i), 645 + BIT(port)); 646 + } else { 647 + ret = regmap_clear_bits(priv->regmap, 648 + QCA8K_PORT_LOOKUP_CTRL(i), 649 + BIT(port)); 650 + } 651 + 652 + if (ret) 653 + return ret; 654 + } 655 + 656 + /* Add/remove all other ports to/from this port's portvlan mask */ 657 + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), 658 + QCA8K_PORT_LOOKUP_MEMBER, port_mask); 659 + 660 + return ret; 661 + } 662 + 617 663 int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, 618 664 struct switchdev_brport_flags flags, 619 665 struct netlink_ext_ack *extack) 620 666 { 621 - if (flags.mask & ~BR_LEARNING) 667 + if (flags.mask & ~(BR_LEARNING | BR_ISOLATED)) 622 668 return -EINVAL; 623 669 624 670 return 0; ··· 674 628 struct switchdev_brport_flags flags, 675 629 struct netlink_ext_ack *extack) 676 630 { 631 + struct qca8k_priv *priv = ds->priv; 677 632 int ret; 678 633 679 634 if (flags.mask & BR_LEARNING) { 680 635 ret = qca8k_port_configure_learning(ds, port, 681 636 flags.val & BR_LEARNING); 637 + if (ret) 638 + return ret; 639 + } 640 + 641 + if (flags.mask & BR_ISOLATED) { 642 + struct dsa_port *dp = dsa_to_port(ds, port); 643 + struct net_device *bridge_dev = dsa_port_bridge_dev_get(dp); 644 + 645 + if (flags.val & BR_ISOLATED) 646 + priv->port_isolated_map |= BIT(port); 647 + else 648 + priv->port_isolated_map &= ~BIT(port); 649 + 650 + ret = qca8k_update_port_member(priv, port, bridge_dev, true); 682 651 if (ret) 683 652 return ret; 684 653 } ··· 707 646 struct netlink_ext_ack *extack) 708 647 { 709 648 struct qca8k_priv *priv = ds->priv; 710 - int port_mask, cpu_port; 711 - int i, ret; 712 649 713 - cpu_port = dsa_to_port(ds, port)->cpu_dp->index; 714 - port_mask = BIT(cpu_port); 715 - 716 - for (i = 0; i < QCA8K_NUM_PORTS; i++) { 717 - if (dsa_is_cpu_port(ds, i)) 718 - continue; 719 - if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge)) 720 - continue; 721 - /* Add this port to the portvlan mask of the other ports 722 - * in the bridge 723 - */ 724 - ret = regmap_set_bits(priv->regmap, 725 - QCA8K_PORT_LOOKUP_CTRL(i), 726 - BIT(port)); 727 - if (ret) 728 - return ret; 729 - if (i != port) 730 - port_mask |= BIT(i); 731 - } 732 - 733 - /* Add all other ports to this ports portvlan mask */ 734 - ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), 735 - QCA8K_PORT_LOOKUP_MEMBER, port_mask); 736 - 737 - return ret; 650 + return qca8k_update_port_member(priv, port, bridge.dev, true); 738 651 } 739 652 740 653 void qca8k_port_bridge_leave(struct dsa_switch *ds, int port, 741 654 struct dsa_bridge bridge) 742 655 { 743 656 struct qca8k_priv *priv = ds->priv; 744 - int cpu_port, i; 657 + int err; 745 658 746 - cpu_port = dsa_to_port(ds, port)->cpu_dp->index; 747 - 748 - for (i = 0; i < QCA8K_NUM_PORTS; i++) { 749 - if (dsa_is_cpu_port(ds, i)) 750 - continue; 751 - if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge)) 752 - continue; 753 - /* Remove this port to the portvlan mask of the other ports 754 - * in the bridge 755 - */ 756 - regmap_clear_bits(priv->regmap, 757 - QCA8K_PORT_LOOKUP_CTRL(i), 758 - BIT(port)); 759 - } 760 - 761 - /* Set the cpu port to be the only one in the portvlan mask of 762 - * this port 763 - */ 764 - qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), 765 - QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port)); 659 + err = qca8k_update_port_member(priv, port, bridge.dev, false); 660 + if (err) 661 + dev_err(priv->dev, 662 + "Failed to update switch config for bridge leave: %d\n", 663 + err); 766 664 } 767 665 768 666 void qca8k_port_fast_age(struct dsa_switch *ds, int port)
+1
drivers/net/dsa/qca/qca8k.h
··· 451 451 * Bit 1: port enabled. Bit 0: port disabled. 452 452 */ 453 453 u8 port_enabled_map; 454 + u8 port_isolated_map; 454 455 struct qca8k_ports_config ports_config; 455 456 struct regmap *regmap; 456 457 struct mii_bus *bus;