linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Oleksij Rempel <o.rempel@pengutronix.de>
To: Andrew Lunn <andrew@lunn.ch>,
	Vivien Didelot <vivien.didelot@gmail.com>,
	Florian Fainelli <f.fainelli@gmail.com>,
	Vladimir Oltean <olteanv@gmail.com>,
	"David S. Miller" <davem@davemloft.net>,
	Jakub Kicinski <kuba@kernel.org>,
	Russell King <linux@armlinux.org.uk>
Cc: Oleksij Rempel <o.rempel@pengutronix.de>,
	Pengutronix Kernel Team <kernel@pengutronix.de>,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-mips@vger.kernel.org
Subject: [PATCH net-next v1 8/9] net: dsa: qca: ar9331: add STP support
Date: Sat,  3 Apr 2021 13:48:47 +0200	[thread overview]
Message-ID: <20210403114848.30528-9-o.rempel@pengutronix.de> (raw)
In-Reply-To: <20210403114848.30528-1-o.rempel@pengutronix.de>

According to the datasheet, this switch has configurable STP port
states. Suddenly LISTENING and BLOCKING states didn't forwarded packets
to the CPU and linux bridge continuously re enabled ports even if a  loop
was detected. To make it work, I reused bridge functionality to isolate
port in LISTENING and BLOCKING states.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 drivers/net/dsa/qca/ar9331.c | 69 ++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c
index bf9588574205..83b59e771a5f 100644
--- a/drivers/net/dsa/qca/ar9331.c
+++ b/drivers/net/dsa/qca/ar9331.c
@@ -327,6 +327,7 @@ struct ar9331_sw_priv {
 	struct reset_control *sw_reset;
 	struct ar9331_sw_port port[AR9331_SW_PORTS];
 	int cpu_port;
+	u32 isolated_ports;
 };
 
 static struct ar9331_sw_priv *ar9331_sw_port_to_priv(struct ar9331_sw_port *port)
@@ -1151,6 +1152,10 @@ static int ar9331_sw_port_bridge_join(struct dsa_switch *ds, int port,
 		if (!dsa_is_user_port(ds, port))
 			continue;
 
+		/* part of the bridge but should be isolated for now */
+		if (priv->isolated_ports & BIT(i))
+			continue;
+
 		val = FIELD_PREP(AR9331_SW_PORT_VLAN_PORT_VID_MEMBER, BIT(port));
 		ret = regmap_set_bits(regmap, AR9331_SW_REG_PORT_VLAN(i), val);
 		if (ret)
@@ -1205,6 +1210,69 @@ static void ar9331_sw_port_bridge_leave(struct dsa_switch *ds, int port,
 	dev_err_ratelimited(priv->dev, "%s: error: %i\n", __func__, ret);
 }
 
+static void ar9331_sw_port_stp_state_set(struct dsa_switch *ds, int port,
+					 u8 state)
+{
+	struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+	struct net_device *br = dsa_to_port(ds, port)->bridge_dev;
+	struct regmap *regmap = priv->regmap;
+	u32 port_ctrl = 0, port_state = 0;
+	bool join = false;
+	int ret;
+
+	/*
+	 * STP hw support is buggy or I didn't understood it. So, it seems to
+	 * be easier to make hand crafted implementation by using bridge
+	 * functionality. Similar implementation can be found on ksz9477 switch
+	 * and may be we need some generic code to so for all related devices
+	 */
+	switch (state) {
+	case BR_STATE_FORWARDING:
+		join = true;
+		fallthrough;
+	case BR_STATE_LEARNING:
+		port_ctrl = AR9331_SW_PORT_CTRL_LEARN_EN;
+		fallthrough;
+	case BR_STATE_LISTENING:
+	case BR_STATE_BLOCKING:
+		port_state = AR9331_SW_PORT_CTRL_PORT_STATE_FORWARD;
+		break;
+	case BR_STATE_DISABLED:
+	default:
+		port_state = AR9331_SW_PORT_CTRL_PORT_STATE_DISABLED;
+		break;
+	}
+
+	port_ctrl |= FIELD_PREP(AR9331_SW_PORT_CTRL_PORT_STATE, port_state);
+
+	ret = regmap_update_bits(regmap, AR9331_SW_REG_PORT_CTRL(port),
+				 AR9331_SW_PORT_CTRL_LEARN_EN |
+				 AR9331_SW_PORT_CTRL_PORT_STATE, port_ctrl);
+	if (ret)
+		goto error;
+
+	if (!dsa_is_user_port(ds, port))
+		return;
+
+	/*
+	 * here we care only about user ports. CPU port do not need this
+	 * configuration
+	 */
+	if (join) {
+		priv->isolated_ports &= ~BIT(port);
+		if (br)
+			ar9331_sw_port_bridge_join(ds, port, br);
+	} else {
+		priv->isolated_ports |= BIT(port);
+		if (br)
+			ar9331_sw_port_bridge_leave(ds, port, br);
+	}
+
+	return;
+error:
+	dev_err_ratelimited(priv->dev, "%s: error: %i\n", __func__, ret);
+}
+
 static const struct dsa_switch_ops ar9331_sw_ops = {
 	.get_tag_protocol	= ar9331_sw_get_tag_protocol,
 	.setup			= ar9331_sw_setup,
@@ -1223,6 +1291,7 @@ static const struct dsa_switch_ops ar9331_sw_ops = {
 	.set_ageing_time	= ar9331_sw_set_ageing_time,
 	.port_bridge_join	= ar9331_sw_port_bridge_join,
 	.port_bridge_leave	= ar9331_sw_port_bridge_leave,
+	.port_stp_state_set	= ar9331_sw_port_stp_state_set,
 };
 
 static irqreturn_t ar9331_sw_irq(int irq, void *data)
-- 
2.29.2


  parent reply	other threads:[~2021-04-03 11:50 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-03 11:48 [PATCH net-next v1 0/9] ar9331: mainline some parts of switch functionality Oleksij Rempel
2021-04-03 11:48 ` [PATCH net-next v1 1/9] net: dsa: add rcv_post call back Oleksij Rempel
2021-04-03 14:05   ` Vladimir Oltean
2021-04-03 23:21     ` Vladimir Oltean
2021-04-04  2:32       ` Florian Fainelli
2021-04-04  5:49       ` Oleksij Rempel
2021-04-04 12:54         ` Vladimir Oltean
2021-04-03 11:48 ` [PATCH net-next v1 2/9] net: dsa: tag_ar9331: detect IGMP and MLD packets Oleksij Rempel
2021-04-03 13:03   ` Vladimir Oltean
2021-04-03 13:26     ` Oleksij Rempel
2021-04-03 13:46       ` Vladimir Oltean
2021-04-03 15:22         ` Oleksij Rempel
2021-04-03 16:38           ` Vladimir Oltean
2021-04-03 14:49   ` Andrew Lunn
2021-04-03 17:14     ` Oleksij Rempel
2021-04-04  0:02       ` Vladimir Oltean
2021-04-04  5:35         ` Oleksij Rempel
2021-04-04 12:58           ` Vladimir Oltean
2021-04-03 11:48 ` [PATCH net-next v1 3/9] net: dsa: qca: ar9331: reorder MDIO write sequence Oleksij Rempel
2021-04-03 14:55   ` Andrew Lunn
2021-04-04  2:17   ` Florian Fainelli
2021-04-03 11:48 ` [PATCH net-next v1 4/9] net: dsa: qca: ar9331: make proper initial port defaults Oleksij Rempel
2021-04-03 15:08   ` Andrew Lunn
2021-04-04  0:16   ` Vladimir Oltean
2021-04-04  6:04     ` Oleksij Rempel
2021-04-03 11:48 ` [PATCH net-next v1 5/9] net: dsa: qca: ar9331: add forwarding database support Oleksij Rempel
2021-04-03 15:25   ` Andrew Lunn
2021-04-03 23:48     ` Vladimir Oltean
2021-04-04  0:46       ` Andrew Lunn
2021-04-03 11:48 ` [PATCH net-next v1 6/9] net: dsa: qca: ar9331: add ageing time support Oleksij Rempel
2021-04-03 15:26   ` Andrew Lunn
2021-04-04  2:20   ` Florian Fainelli
2021-04-03 11:48 ` [PATCH net-next v1 7/9] net: dsa: qca: ar9331: add bridge support Oleksij Rempel
2021-04-03 15:31   ` Andrew Lunn
2021-04-04  2:26   ` Florian Fainelli
2021-04-03 11:48 ` Oleksij Rempel [this message]
2021-04-03 11:48 ` [PATCH net-next v1 9/9] net: dsa: qca: ar9331: add vlan support Oleksij Rempel
2021-04-04  0:36   ` Vladimir Oltean

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210403114848.30528-9-o.rempel@pengutronix.de \
    --to=o.rempel@pengutronix.de \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=f.fainelli@gmail.com \
    --cc=kernel@pengutronix.de \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=netdev@vger.kernel.org \
    --cc=olteanv@gmail.com \
    --cc=vivien.didelot@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).