Commit 2e49761e authored by Horatiu Vultur's avatar Horatiu Vultur Committed by David S. Miller
Browse files

net: lan966x: Add support for multiple bridge flags



This patch series extends the current supported bridge flags with the
following flags: BR_FLOOD, BR_BCAST_FLOOD and BR_LEARNING.

Signed-off-by: default avatarHoratiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 963178a0
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -715,8 +715,10 @@ static void lan966x_init(struct lan966x *lan966x)
	/* There are 8 priorities */
	for (i = 0; i < 8; ++i)
		lan_rmw(ANA_FLOODING_FLD_MULTICAST_SET(PGID_MC) |
			ANA_FLOODING_FLD_UNICAST_SET(PGID_UC) |
			ANA_FLOODING_FLD_BROADCAST_SET(PGID_BC),
			ANA_FLOODING_FLD_MULTICAST |
			ANA_FLOODING_FLD_UNICAST |
			ANA_FLOODING_FLD_BROADCAST,
			lan966x, ANA_FLOODING(i));

@@ -768,6 +770,11 @@ static void lan966x_init(struct lan966x *lan966x)
		ANA_PGID_PGID,
		lan966x, ANA_PGID(PGID_MCIPV4));

	/* Unicast to all other ports */
	lan_rmw(GENMASK(lan966x->num_phys_ports - 1, 0),
		ANA_PGID_PGID,
		lan966x, ANA_PGID(PGID_UC));

	/* Broadcast to the CPU port and to other ports */
	lan_rmw(ANA_PGID_PGID_SET(BIT(CPU_PORT) | GENMASK(lan966x->num_phys_ports - 1, 0)),
		ANA_PGID_PGID,
+2 −0
Original line number Diff line number Diff line
@@ -126,6 +126,8 @@ struct lan966x_port {
	u16 vid;
	bool vlan_aware;

	bool learn_ena;

	struct phylink_config phylink_config;
	struct phylink_pcs phylink_pcs;
	struct lan966x_port_config config;
+6 −0
Original line number Diff line number Diff line
@@ -91,6 +91,12 @@ enum lan966x_target {
/*      ANA:ANA:FLOODING */
#define ANA_FLOODING(r)           __REG(TARGET_ANA, 0, 1, 29824, 0, 1, 244, 68, r, 8, 4)

#define ANA_FLOODING_FLD_UNICAST                 GENMASK(17, 12)
#define ANA_FLOODING_FLD_UNICAST_SET(x)\
	FIELD_PREP(ANA_FLOODING_FLD_UNICAST, x)
#define ANA_FLOODING_FLD_UNICAST_GET(x)\
	FIELD_GET(ANA_FLOODING_FLD_UNICAST, x)

#define ANA_FLOODING_FLD_BROADCAST               GENMASK(11, 6)
#define ANA_FLOODING_FLD_BROADCAST_SET(x)\
	FIELD_PREP(ANA_FLOODING_FLD_BROADCAST, x)
+67 −2
Original line number Diff line number Diff line
@@ -25,18 +25,72 @@ static void lan966x_port_set_mcast_flood(struct lan966x_port *port,
		port->lan966x, ANA_PGID(PGID_MC));
}

static void lan966x_port_set_ucast_flood(struct lan966x_port *port,
					 bool enabled)
{
	u32 val = lan_rd(port->lan966x, ANA_PGID(PGID_UC));

	val = ANA_PGID_PGID_GET(val);
	if (enabled)
		val |= BIT(port->chip_port);
	else
		val &= ~BIT(port->chip_port);

	lan_rmw(ANA_PGID_PGID_SET(val),
		ANA_PGID_PGID,
		port->lan966x, ANA_PGID(PGID_UC));
}

static void lan966x_port_set_bcast_flood(struct lan966x_port *port,
					 bool enabled)
{
	u32 val = lan_rd(port->lan966x, ANA_PGID(PGID_BC));

	val = ANA_PGID_PGID_GET(val);
	if (enabled)
		val |= BIT(port->chip_port);
	else
		val &= ~BIT(port->chip_port);

	lan_rmw(ANA_PGID_PGID_SET(val),
		ANA_PGID_PGID,
		port->lan966x, ANA_PGID(PGID_BC));
}

static void lan966x_port_set_learning(struct lan966x_port *port, bool enabled)
{
	lan_rmw(ANA_PORT_CFG_LEARN_ENA_SET(enabled),
		ANA_PORT_CFG_LEARN_ENA,
		port->lan966x, ANA_PORT_CFG(port->chip_port));

	port->learn_ena = enabled;
}

static void lan966x_port_bridge_flags(struct lan966x_port *port,
				      struct switchdev_brport_flags flags)
{
	if (flags.mask & BR_MCAST_FLOOD)
		lan966x_port_set_mcast_flood(port,
					     !!(flags.val & BR_MCAST_FLOOD));

	if (flags.mask & BR_FLOOD)
		lan966x_port_set_ucast_flood(port,
					     !!(flags.val & BR_FLOOD));

	if (flags.mask & BR_BCAST_FLOOD)
		lan966x_port_set_bcast_flood(port,
					     !!(flags.val & BR_BCAST_FLOOD));

	if (flags.mask & BR_LEARNING)
		lan966x_port_set_learning(port,
					  !!(flags.val & BR_LEARNING));
}

static int lan966x_port_pre_bridge_flags(struct lan966x_port *port,
					 struct switchdev_brport_flags flags)
{
	if (flags.mask & ~BR_MCAST_FLOOD)
	if (flags.mask & ~(BR_MCAST_FLOOD | BR_FLOOD | BR_BCAST_FLOOD |
			   BR_LEARNING))
		return -EINVAL;

	return 0;
@@ -65,7 +119,8 @@ static void lan966x_port_stp_state_set(struct lan966x_port *port, u8 state)
	struct lan966x *lan966x = port->lan966x;
	bool learn_ena = false;

	if (state == BR_STATE_FORWARDING || state == BR_STATE_LEARNING)
	if ((state == BR_STATE_FORWARDING || state == BR_STATE_LEARNING) &&
	    port->learn_ena)
		learn_ena = true;

	if (state == BR_STATE_FORWARDING)
@@ -128,6 +183,7 @@ static int lan966x_port_bridge_join(struct lan966x_port *port,
				    struct net_device *bridge,
				    struct netlink_ext_ack *extack)
{
	struct switchdev_brport_flags flags = {0};
	struct lan966x *lan966x = port->lan966x;
	struct net_device *dev = port->dev;
	int err;
@@ -150,14 +206,23 @@ static int lan966x_port_bridge_join(struct lan966x_port *port,

	lan966x->bridge_mask |= BIT(port->chip_port);

	flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD;
	flags.val = flags.mask;
	lan966x_port_bridge_flags(port, flags);

	return 0;
}

static void lan966x_port_bridge_leave(struct lan966x_port *port,
				      struct net_device *bridge)
{
	struct switchdev_brport_flags flags = {0};
	struct lan966x *lan966x = port->lan966x;

	flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD;
	flags.val = flags.mask & ~BR_LEARNING;
	lan966x_port_bridge_flags(port, flags);

	lan966x->bridge_mask &= ~BIT(port->chip_port);

	if (!lan966x->bridge_mask)