Netdev List
 help / color / mirror / Atom feed
From: Vladimir Oltean <vladimir.oltean@nxp.com>
To: netdev@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Jamal Hadi Salim <jhs@mojatatu.com>,
	Cong Wang <xiyou.wangcong@gmail.com>,
	Jiri Pirko <jiri@resnulli.us>,
	Vinicius Costa Gomes <vinicius.gomes@intel.com>,
	Kurt Kanzenbach <kurt@linutronix.de>,
	Gerhard Engleder <gerhard@engleder-embedded.com>,
	Amritha Nambiar <amritha.nambiar@intel.com>,
	Claudiu Manoil <claudiu.manoil@nxp.com>,
	Alexandre Belloni <alexandre.belloni@bootlin.com>,
	UNGLinuxDriver@microchip.com, Andrew Lunn <andrew@lunn.ch>,
	Florian Fainelli <f.fainelli@gmail.com>,
	Ferenc Fejes <ferenc.fejes@ericsson.com>,
	Xiaoliang Yang <xiaoliang.yang_1@nxp.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCH net-next 11/12] net: mscc: ocelot: add support for preemptible traffic classes
Date: Fri, 17 Feb 2023 01:21:25 +0200	[thread overview]
Message-ID: <20230216232126.3402975-12-vladimir.oltean@nxp.com> (raw)
In-Reply-To: <20230216232126.3402975-1-vladimir.oltean@nxp.com>

In order to not transmit (preemptible) frames which will be received by
the link partner as corrupted (because it doesn't support FP), the
hardware requires the driver to program the QSYS_PREEMPTION_CFG_P_QUEUES
register only after the MAC Merge layer becomes active (verification
succeeds, or was disabled).

There are some cases when FP is known (through experimentation) to be
broken. Give priority to FP over cut-through switching, and disable FP
for known broken link modes.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix_vsc9959.c | 13 +++++-
 drivers/net/ethernet/mscc/ocelot.c     |  3 ++
 drivers/net/ethernet/mscc/ocelot.h     |  2 +
 drivers/net/ethernet/mscc/ocelot_mm.c  | 56 ++++++++++++++++++++++++++
 include/soc/mscc/ocelot.h              |  2 +
 5 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 81fcdccacd8b..c6a5cf57dcc6 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1343,6 +1343,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
 				    u32 speed)
 {
 	struct ocelot_port *ocelot_port = ocelot->ports[port];
+	struct ocelot_mm_state *mm = &ocelot->mm[port];
 	u8 tas_speed;
 
 	switch (speed) {
@@ -1374,6 +1375,11 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
 		vsc9959_tas_guard_bands_update(ocelot, port);
 
 	mutex_unlock(&ocelot->tas_lock);
+
+	/* Workaround for hardware bug */
+	mutex_lock(&mm->lock);
+	ocelot_port_update_preemptible_tcs(ocelot, port);
+	mutex_unlock(&mm->lock);
 }
 
 static void vsc9959_new_base_time(struct ocelot *ocelot, ktime_t base_time,
@@ -2519,6 +2525,7 @@ static void vsc9959_cut_through_fwd(struct ocelot *ocelot)
 
 	for (port = 0; port < ocelot->num_phys_ports; port++) {
 		struct ocelot_port *ocelot_port = ocelot->ports[port];
+		struct ocelot_mm_state *mm = &ocelot->mm[port];
 		int min_speed = ocelot_port->speed;
 		unsigned long mask = 0;
 		u32 tmp, val = 0;
@@ -2559,10 +2566,12 @@ static void vsc9959_cut_through_fwd(struct ocelot *ocelot)
 
 		/* Enable cut-through forwarding for all traffic classes that
 		 * don't have oversized dropping enabled, since this check is
-		 * bypassed in cut-through mode.
+		 * bypassed in cut-through mode. Also exclude preemptible
+		 * traffic classes, since these would hang the port for some
+		 * reason, if sent as cut-through.
 		 */
 		if (ocelot_port->speed == min_speed) {
-			val = GENMASK(7, 0);
+			val = GENMASK(7, 0) & ~mm->preemptible_tcs;
 
 			for (tc = 0; tc < OCELOT_NUM_TC; tc++)
 				if (vsc9959_port_qmaxsdu_get(ocelot, port, tc))
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 20557a9c46e6..76a7c25744b9 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2608,6 +2608,7 @@ static void ocelot_port_reset_mqprio(struct ocelot *ocelot, int port)
 	struct net_device *dev = ocelot->ops->port_to_netdev(ocelot, port);
 
 	netdev_reset_tc(dev);
+	ocelot_port_update_fp(ocelot, port, 0);
 }
 
 int ocelot_port_mqprio(struct ocelot *ocelot, int port,
@@ -2642,6 +2643,8 @@ int ocelot_port_mqprio(struct ocelot *ocelot, int port,
 	if (err)
 		goto err_reset_tc;
 
+	ocelot_port_update_fp(ocelot, port, mqprio->preemptible_tcs);
+
 	return 0;
 
 err_reset_tc:
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index e9a0179448bf..fa9b69ba198c 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -110,6 +110,8 @@ int ocelot_stats_init(struct ocelot *ocelot);
 void ocelot_stats_deinit(struct ocelot *ocelot);
 
 int ocelot_mm_init(struct ocelot *ocelot);
+void ocelot_port_update_fp(struct ocelot *ocelot, int port,
+			   unsigned long preemptible_tcs);
 
 extern struct notifier_block ocelot_netdevice_nb;
 extern struct notifier_block ocelot_switchdev_nb;
diff --git a/drivers/net/ethernet/mscc/ocelot_mm.c b/drivers/net/ethernet/mscc/ocelot_mm.c
index 0a8f21ae23f0..21d5656dfc70 100644
--- a/drivers/net/ethernet/mscc/ocelot_mm.c
+++ b/drivers/net/ethernet/mscc/ocelot_mm.c
@@ -49,6 +49,61 @@ static enum ethtool_mm_verify_status ocelot_mm_verify_status(u32 val)
 	}
 }
 
+void ocelot_port_update_preemptible_tcs(struct ocelot *ocelot, int port)
+{
+	struct ocelot_port *ocelot_port = ocelot->ports[port];
+	struct ocelot_mm_state *mm = &ocelot->mm[port];
+	u32 val = 0;
+
+	lockdep_assert_held(&mm->lock);
+
+	/* On NXP LS1028A, when using QSGMII, the port hangs if transmitting
+	 * preemptible frames at any other link speed than gigabit
+	 */
+	if (ocelot_port->phy_mode != PHY_INTERFACE_MODE_QSGMII ||
+	    ocelot_port->speed == SPEED_1000) {
+		/* Only commit preemptible TCs when MAC Merge is active */
+		switch (mm->verify_status) {
+		case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
+		case ETHTOOL_MM_VERIFY_STATUS_DISABLED:
+			val = mm->preemptible_tcs;
+			break;
+		default:
+		}
+	}
+
+	ocelot_rmw_rix(ocelot, QSYS_PREEMPTION_CFG_P_QUEUES(val),
+		       QSYS_PREEMPTION_CFG_P_QUEUES_M,
+		       QSYS_PREEMPTION_CFG, port);
+}
+EXPORT_SYMBOL_GPL(ocelot_port_update_preemptible_tcs);
+
+void ocelot_port_update_fp(struct ocelot *ocelot, int port,
+			   unsigned long preemptible_tcs)
+{
+	struct ocelot_mm_state *mm = &ocelot->mm[port];
+
+	mutex_lock(&mm->lock);
+
+	if (mm->preemptible_tcs == preemptible_tcs)
+		goto out_unlock;
+
+	mm->preemptible_tcs = preemptible_tcs;
+
+	/* Cut through switching doesn't work for preemptible priorities,
+	 * so disable it.
+	 */
+	mutex_lock(&ocelot->fwd_domain_lock);
+	ocelot->ops->cut_through_fwd(ocelot);
+	mutex_unlock(&ocelot->fwd_domain_lock);
+
+	ocelot_port_update_preemptible_tcs(ocelot, port);
+
+out_unlock:
+	mutex_unlock(&mm->lock);
+}
+EXPORT_SYMBOL_GPL(ocelot_port_update_fp);
+
 void ocelot_port_mm_irq(struct ocelot *ocelot, int port)
 {
 	struct ocelot_port *ocelot_port = ocelot->ports[port];
@@ -66,6 +121,7 @@ void ocelot_port_mm_irq(struct ocelot *ocelot, int port)
 			"Port %d MAC Merge verification state %s\n",
 			port, mm_verify_state_to_string(verify_status));
 		mm->verify_status = verify_status;
+		ocelot_port_update_preemptible_tcs(ocelot, port);
 	}
 
 	if (val & DEV_MM_STAT_MM_STATUS_PRMPT_ACTIVE_STICKY) {
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 27ff770a6c53..7ee7a29e7c51 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -748,6 +748,7 @@ struct ocelot_mm_state {
 	struct mutex lock;
 	enum ethtool_mm_verify_status verify_status;
 	bool tx_active;
+	u8 preemptible_tcs;
 };
 
 struct ocelot_port;
@@ -1149,6 +1150,7 @@ int ocelot_port_get_mm(struct ocelot *ocelot, int port,
 		       struct ethtool_mm_state *state);
 int ocelot_port_mqprio(struct ocelot *ocelot, int port,
 		       struct tc_mqprio_qopt_offload *mqprio);
+void ocelot_port_update_preemptible_tcs(struct ocelot *ocelot, int port);
 
 #if IS_ENABLED(CONFIG_BRIDGE_MRP)
 int ocelot_mrp_add(struct ocelot *ocelot, int port,
-- 
2.34.1


  parent reply	other threads:[~2023-02-16 23:23 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-16 23:21 [PATCH net-next 00/12] Add tc-mqprio and tc-taprio support for preemptible traffic classes Vladimir Oltean
2023-02-16 23:21 ` [PATCH net-next 01/12] net: enetc: rename "mqprio" to "qopt" Vladimir Oltean
2023-02-16 23:21 ` [PATCH net-next 02/12] net: mscc: ocelot: add support for mqprio offload Vladimir Oltean
2023-02-16 23:21 ` [PATCH net-next 03/12] net: dsa: felix: act upon the mqprio qopt in taprio offload Vladimir Oltean
2023-02-16 23:21 ` [PATCH net-next 04/12] net: ethtool: fix __ethtool_dev_mm_supported() implementation Vladimir Oltean
2023-02-16 23:21 ` [PATCH net-next 05/12] net: ethtool: create and export ethtool_dev_mm_supported() Vladimir Oltean
2023-02-17 13:00   ` Vladimir Oltean
2023-02-16 23:21 ` [PATCH net-next 06/12] net/sched: mqprio: simplify handling of nlattr portion of TCA_OPTIONS Vladimir Oltean
2023-02-16 23:21 ` [PATCH net-next 07/12] net/sched: mqprio: add extack to mqprio_parse_nlattr() Vladimir Oltean
2023-02-16 23:21 ` [PATCH net-next 08/12] net/sched: mqprio: add an extack message to mqprio_parse_opt() Vladimir Oltean
2023-02-17  7:24   ` Ferenc Fejes
2023-02-20 10:47     ` Vladimir Oltean
2023-02-16 23:21 ` [PATCH net-next 09/12] net/sched: mqprio: allow per-TC user input of FP adminStatus Vladimir Oltean
2023-02-16 23:21 ` [PATCH net-next 10/12] net/sched: taprio: " Vladimir Oltean
2023-02-16 23:21 ` Vladimir Oltean [this message]
2023-02-16 23:21 ` [PATCH net-next 12/12] net: enetc: add support for preemptible traffic classes Vladimir Oltean
2023-02-18 15:20 ` [PATCH net-next 00/12] Add tc-mqprio and tc-taprio " Vladimir Oltean
2023-02-19  9:47   ` Ferenc Fejes
2023-02-19 12:58     ` Vladimir Oltean
2023-02-20  8:11       ` Ferenc Fejes

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=20230216232126.3402975-12-vladimir.oltean@nxp.com \
    --to=vladimir.oltean@nxp.com \
    --cc=UNGLinuxDriver@microchip.com \
    --cc=alexandre.belloni@bootlin.com \
    --cc=amritha.nambiar@intel.com \
    --cc=andrew@lunn.ch \
    --cc=claudiu.manoil@nxp.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=f.fainelli@gmail.com \
    --cc=ferenc.fejes@ericsson.com \
    --cc=gerhard@engleder-embedded.com \
    --cc=jhs@mojatatu.com \
    --cc=jiri@resnulli.us \
    --cc=kuba@kernel.org \
    --cc=kurt@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=vinicius.gomes@intel.com \
    --cc=xiaoliang.yang_1@nxp.com \
    --cc=xiyou.wangcong@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