net: dsa: mv88e6xxx: Add support for bridge port locked mode
authorHans Schultz <schultz.hans@gmail.com>
Wed, 23 Feb 2022 10:16:49 +0000 (11:16 +0100)
committerDavid S. Miller <davem@davemloft.net>
Wed, 23 Feb 2022 12:52:34 +0000 (12:52 +0000)
Supporting bridge ports in locked mode using the drop on lock
feature in Marvell mv88e6xxx switchcores is described in the
'88E6096/88E6097/88E6097F Datasheet', sections 4.4.6, 4.4.7 and
5.1.2.1 (Drop on Lock).

This feature is implemented here facilitated by the locked port flag.

Signed-off-by: Hans Schultz <schultz.hans+netdev@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/port.c
drivers/net/dsa/mv88e6xxx/port.h

index 7d5e72c..f737602 100644 (file)
@@ -6103,7 +6103,7 @@ static int mv88e6xxx_port_pre_bridge_flags(struct dsa_switch *ds, int port,
        const struct mv88e6xxx_ops *ops;
 
        if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD |
-                          BR_BCAST_FLOOD))
+                          BR_BCAST_FLOOD | BR_PORT_LOCKED))
                return -EINVAL;
 
        ops = chip->info->ops;
@@ -6161,6 +6161,13 @@ static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port,
                        goto out;
        }
 
+       if (flags.mask & BR_PORT_LOCKED) {
+               bool locked = !!(flags.val & BR_PORT_LOCKED);
+
+               err = mv88e6xxx_port_set_lock(chip, port, locked);
+               if (err)
+                       goto out;
+       }
 out:
        mv88e6xxx_reg_unlock(chip);
 
index ceb4501..d08e3ec 100644 (file)
@@ -1234,6 +1234,35 @@ int mv88e6xxx_port_set_mirror(struct mv88e6xxx_chip *chip, int port,
        return err;
 }
 
+int mv88e6xxx_port_set_lock(struct mv88e6xxx_chip *chip, int port,
+                           bool locked)
+{
+       u16 reg;
+       int err;
+
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
+       if (err)
+               return err;
+
+       reg &= ~MV88E6XXX_PORT_CTL0_SA_FILT_MASK;
+       if (locked)
+               reg |= MV88E6XXX_PORT_CTL0_SA_FILT_DROP_ON_LOCK;
+
+       err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
+       if (err)
+               return err;
+
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR, &reg);
+       if (err)
+               return err;
+
+       reg &= ~MV88E6XXX_PORT_ASSOC_VECTOR_LOCKED_PORT;
+       if (locked)
+               reg |= MV88E6XXX_PORT_ASSOC_VECTOR_LOCKED_PORT;
+
+       return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR, reg);
+}
+
 int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
                                  u16 mode)
 {
index 3a13db2..e0a705d 100644 (file)
 /* Offset 0x04: Port Control Register */
 #define MV88E6XXX_PORT_CTL0                                    0x04
 #define MV88E6XXX_PORT_CTL0_USE_CORE_TAG                       0x8000
-#define MV88E6XXX_PORT_CTL0_DROP_ON_LOCK                       0x4000
+#define MV88E6XXX_PORT_CTL0_SA_FILT_MASK                       0xc000
+#define MV88E6XXX_PORT_CTL0_SA_FILT_DISABLED                   0x0000
+#define MV88E6XXX_PORT_CTL0_SA_FILT_DROP_ON_LOCK               0x4000
+#define MV88E6XXX_PORT_CTL0_SA_FILT_DROP_ON_UNLOCK             0x8000
+#define MV88E6XXX_PORT_CTL0_SA_FILT_DROP_ON_CPU                0xc000
 #define MV88E6XXX_PORT_CTL0_EGRESS_MODE_MASK                   0x3000
 #define MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNMODIFIED             0x0000
 #define MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNTAGGED               0x1000
@@ -370,6 +374,9 @@ int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid);
 int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid);
 int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid);
 
+int mv88e6xxx_port_set_lock(struct mv88e6xxx_chip *chip, int port,
+                           bool locked);
+
 int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
                                  u16 mode);
 int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port);