From: "Bastien Curutchet (Schneider Electric)" <bastien.curutchet@bootlin.com>
To: Woojung Huh <woojung.huh@microchip.com>,
UNGLinuxDriver@microchip.com, Andrew Lunn <andrew@lunn.ch>,
Vladimir Oltean <olteanv@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>,
Russell King <linux@armlinux.org.uk>
Cc: "Pascal Eberhard" <pascal.eberhard@se.com>,
"Miquèl Raynal" <miquel.raynal@bootlin.com>,
"Thomas Petazzoni" <thomas.petazzoni@bootlin.com>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
"Bastien Curutchet (Schneider Electric)"
<bastien.curutchet@bootlin.com>
Subject: [PATCH net-next 07/10] net: dsa: microchip: handle KSZ8-specific tc setup in ksz8.c
Date: Thu, 02 Jul 2026 11:07:29 +0200 [thread overview]
Message-ID: <20260702-clean-ksz-4th-v1-7-93441e695fa4@bootlin.com> (raw)
In-Reply-To: <20260702-clean-ksz-4th-v1-0-93441e695fa4@bootlin.com>
The setup of QDISC_ETS isn't the same for the KSZ8 switches than for
the other switches. It leads to is_ksz8() branches in the common code.
Move the KSZ8-specific portions into ksz8.c by creating two setup_tc()
functions, one dedicated to the KSZ87xx family that only handles the
TC_SETUP_QDISC_CBS case, one for the rest of the KSZ8 that handles both
TC_SETUP_QDISC_CBS and TC_SETUP_QDISC_ETS cases.
It remains some is_kszXXXX() branches because inside the ksz88xx family,
only the ksz88x3 switches support QDISC_ETS.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 159 ++++++++++++++++++++++++++++++++-
drivers/net/dsa/microchip/ksz_common.c | 124 ++-----------------------
drivers/net/dsa/microchip/ksz_common.h | 7 ++
3 files changed, 171 insertions(+), 119 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index ad7c7a6e1d31..472cc62ea747 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -1782,6 +1782,159 @@ static void ksz8_port_mirror_del(struct dsa_switch *ds, int port,
PORT_MIRROR_SNIFFER, false);
}
+static u8 ksz8463_tc_ctrl(int port, int queue)
+{
+ u8 reg;
+
+ reg = 0xC8 + port * 4;
+ reg += ((3 - queue) / 2) * 2;
+ reg++;
+ reg -= (queue & 1);
+ return reg;
+}
+
+/**
+ * ksz88x3_tc_ets_add - Configure ETS (Enhanced Transmission Selection)
+ * for a port on KSZ88x3 switch
+ * @dev: Pointer to the KSZ switch device structure
+ * @port: Port number to configure
+ * @p: Pointer to offload replace parameters describing ETS bands and mapping
+ *
+ * The KSZ88x3 supports two scheduling modes: Strict Priority and
+ * Weighted Fair Queuing (WFQ). Both modes have fixed behavior:
+ * - No configurable queue-to-priority mapping
+ * - No weight adjustment in WFQ mode
+ *
+ * This function configures the switch to use strict priority mode by
+ * clearing the WFQ enable bit for all queues associated with ETS bands.
+ * If strict priority is not explicitly requested, the switch will default
+ * to WFQ mode.
+ *
+ * Return: 0 on success, or a negative error code on failure
+ */
+static int ksz88x3_tc_ets_add(struct ksz_device *dev, int port,
+ struct tc_ets_qopt_offload_replace_params *p)
+{
+ int ret, band;
+
+ /* Only strict priority mode is supported for now.
+ * WFQ is implicitly enabled when strict mode is disabled.
+ */
+ for (band = 0; band < p->bands; band++) {
+ int queue = ksz_ets_band_to_queue(p, band);
+ u8 reg;
+
+ /* Calculate TXQ Split Control register address for this
+ * port/queue
+ */
+ reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);
+ if (ksz_is_ksz8463(dev))
+ reg = ksz8463_tc_ctrl(port, queue);
+
+ /* Clear WFQ enable bit to select strict priority scheduling */
+ ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE, 0);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ksz88x3_tc_ets_del - Reset ETS (Enhanced Transmission Selection) config
+ * for a port on KSZ88x3 switch
+ * @dev: Pointer to the KSZ switch device structure
+ * @port: Port number to reset
+ *
+ * The KSZ88x3 supports only fixed scheduling modes: Strict Priority or
+ * Weighted Fair Queuing (WFQ), with no reconfiguration of weights or
+ * queue mapping. This function resets the port’s scheduling mode to
+ * the default, which is WFQ, by enabling the WFQ bit for all queues.
+ *
+ * Return: 0 on success, or a negative error code on failure
+ */
+static int ksz88x3_tc_ets_del(struct ksz_device *dev, int port)
+{
+ int ret, queue;
+
+ /* Iterate over all transmit queues for this port */
+ for (queue = 0; queue < dev->info->num_tx_queues; queue++) {
+ u8 reg;
+
+ /* Calculate TXQ Split Control register address for this
+ * port/queue
+ */
+ reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);
+ if (ksz_is_ksz8463(dev))
+ reg = ksz8463_tc_ctrl(port, queue);
+
+ /* Set WFQ enable bit to revert back to default scheduling
+ * mode
+ */
+ ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE,
+ KSZ8873_TXQ_WFQ_ENABLE);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ksz8_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,
+ struct tc_ets_qopt_offload *qopt)
+{
+ struct ksz_device *dev = ds->priv;
+ int ret;
+
+ if (!(ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)))
+ return -EOPNOTSUPP;
+
+ if (qopt->parent != TC_H_ROOT) {
+ dev_err(dev->dev, "Parent should be \"root\"\n");
+ return -EOPNOTSUPP;
+ }
+
+ switch (qopt->command) {
+ case TC_ETS_REPLACE:
+ ret = ksz_tc_ets_validate(dev, port, &qopt->replace_params);
+ if (ret)
+ return ret;
+
+ return ksz88x3_tc_ets_add(dev, port, &qopt->replace_params);
+ case TC_ETS_DESTROY:
+ return ksz88x3_tc_ets_del(dev, port);
+ case TC_ETS_STATS:
+ case TC_ETS_GRAFT:
+ return -EOPNOTSUPP;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static int ksz87xx_setup_tc(struct dsa_switch *ds, int port,
+ enum tc_setup_type type, void *type_data)
+{
+ switch (type) {
+ case TC_SETUP_QDISC_CBS:
+ return ksz_setup_tc_cbs(ds, port, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int ksz8_setup_tc(struct dsa_switch *ds, int port,
+ enum tc_setup_type type, void *type_data)
+{
+ switch (type) {
+ case TC_SETUP_QDISC_CBS:
+ return ksz_setup_tc_cbs(ds, port, type_data);
+ case TC_SETUP_QDISC_ETS:
+ return ksz8_tc_setup_qdisc_ets(ds, port, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static void ksz8795_cpu_interface_select(struct ksz_device *dev, int port)
{
struct ksz_port *p = &dev->ports[port];
@@ -2645,7 +2798,7 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
.port_hwtstamp_set = ksz_hwtstamp_set,
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
- .port_setup_tc = ksz_setup_tc,
+ .port_setup_tc = ksz8_setup_tc,
.port_get_default_prio = ksz_port_get_default_prio,
.port_set_default_prio = ksz_port_set_default_prio,
.port_get_dscp_prio = ksz_port_get_dscp_prio,
@@ -2695,7 +2848,7 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {
.port_hwtstamp_set = ksz_hwtstamp_set,
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
- .port_setup_tc = ksz_setup_tc,
+ .port_setup_tc = ksz87xx_setup_tc,
.port_get_default_prio = ksz_port_get_default_prio,
.port_set_default_prio = ksz_port_set_default_prio,
.port_get_dscp_prio = ksz_port_get_dscp_prio,
@@ -2748,7 +2901,7 @@ const struct dsa_switch_ops ksz88xx_switch_ops = {
.port_hwtstamp_set = ksz_hwtstamp_set,
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
- .port_setup_tc = ksz_setup_tc,
+ .port_setup_tc = ksz8_setup_tc,
.port_get_default_prio = ksz_port_get_default_prio,
.port_set_default_prio = ksz_port_set_default_prio,
.port_get_dscp_prio = ksz_port_get_dscp_prio,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index b54aea92b67d..2846041d97a5 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -3097,8 +3097,8 @@ static int ksz_setup_tc_mode(struct ksz_device *dev, int port, u8 scheduler,
FIELD_PREP(MTI_SHAPING_M, shaper));
}
-static int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,
- struct tc_cbs_qopt_offload *qopt)
+int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,
+ struct tc_cbs_qopt_offload *qopt)
{
struct ksz_device *dev = ds->priv;
int ret;
@@ -3163,8 +3163,8 @@ static int ksz_disable_egress_rate_limit(struct ksz_device *dev, int port)
return 0;
}
-static int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,
- int band)
+int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,
+ int band)
{
/* Compared to queues, bands prioritize packets differently. In strict
* priority mode, the lowest priority is assigned to Queue 0 while the
@@ -3173,104 +3173,6 @@ static int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,
return p->bands - 1 - band;
}
-static u8 ksz8463_tc_ctrl(int port, int queue)
-{
- u8 reg;
-
- reg = 0xC8 + port * 4;
- reg += ((3 - queue) / 2) * 2;
- reg++;
- reg -= (queue & 1);
- return reg;
-}
-
-/**
- * ksz88x3_tc_ets_add - Configure ETS (Enhanced Transmission Selection)
- * for a port on KSZ88x3 switch
- * @dev: Pointer to the KSZ switch device structure
- * @port: Port number to configure
- * @p: Pointer to offload replace parameters describing ETS bands and mapping
- *
- * The KSZ88x3 supports two scheduling modes: Strict Priority and
- * Weighted Fair Queuing (WFQ). Both modes have fixed behavior:
- * - No configurable queue-to-priority mapping
- * - No weight adjustment in WFQ mode
- *
- * This function configures the switch to use strict priority mode by
- * clearing the WFQ enable bit for all queues associated with ETS bands.
- * If strict priority is not explicitly requested, the switch will default
- * to WFQ mode.
- *
- * Return: 0 on success, or a negative error code on failure
- */
-static int ksz88x3_tc_ets_add(struct ksz_device *dev, int port,
- struct tc_ets_qopt_offload_replace_params *p)
-{
- int ret, band;
-
- /* Only strict priority mode is supported for now.
- * WFQ is implicitly enabled when strict mode is disabled.
- */
- for (band = 0; band < p->bands; band++) {
- int queue = ksz_ets_band_to_queue(p, band);
- u8 reg;
-
- /* Calculate TXQ Split Control register address for this
- * port/queue
- */
- reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);
- if (ksz_is_ksz8463(dev))
- reg = ksz8463_tc_ctrl(port, queue);
-
- /* Clear WFQ enable bit to select strict priority scheduling */
- ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE, 0);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-/**
- * ksz88x3_tc_ets_del - Reset ETS (Enhanced Transmission Selection) config
- * for a port on KSZ88x3 switch
- * @dev: Pointer to the KSZ switch device structure
- * @port: Port number to reset
- *
- * The KSZ88x3 supports only fixed scheduling modes: Strict Priority or
- * Weighted Fair Queuing (WFQ), with no reconfiguration of weights or
- * queue mapping. This function resets the port’s scheduling mode to
- * the default, which is WFQ, by enabling the WFQ bit for all queues.
- *
- * Return: 0 on success, or a negative error code on failure
- */
-static int ksz88x3_tc_ets_del(struct ksz_device *dev, int port)
-{
- int ret, queue;
-
- /* Iterate over all transmit queues for this port */
- for (queue = 0; queue < dev->info->num_tx_queues; queue++) {
- u8 reg;
-
- /* Calculate TXQ Split Control register address for this
- * port/queue
- */
- reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);
- if (ksz_is_ksz8463(dev))
- reg = ksz8463_tc_ctrl(port, queue);
-
- /* Set WFQ enable bit to revert back to default scheduling
- * mode
- */
- ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE,
- KSZ8873_TXQ_WFQ_ENABLE);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
static int ksz_queue_set_strict(struct ksz_device *dev, int port, int queue)
{
int ret;
@@ -3363,8 +3265,8 @@ static int ksz_tc_ets_del(struct ksz_device *dev, int port)
return ksz9477_set_default_prio_queue_mapping(dev, port);
}
-static int ksz_tc_ets_validate(struct ksz_device *dev, int port,
- struct tc_ets_qopt_offload_replace_params *p)
+int ksz_tc_ets_validate(struct ksz_device *dev, int port,
+ struct tc_ets_qopt_offload_replace_params *p)
{
int band;
@@ -3405,9 +3307,6 @@ static int ksz_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,
struct ksz_device *dev = ds->priv;
int ret;
- if (is_ksz8(dev) && !(ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)))
- return -EOPNOTSUPP;
-
if (qopt->parent != TC_H_ROOT) {
dev_err(dev->dev, "Parent should be \"root\"\n");
return -EOPNOTSUPP;
@@ -3419,16 +3318,9 @@ static int ksz_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,
if (ret)
return ret;
- if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))
- return ksz88x3_tc_ets_add(dev, port,
- &qopt->replace_params);
- else
- return ksz_tc_ets_add(dev, port, &qopt->replace_params);
+ return ksz_tc_ets_add(dev, port, &qopt->replace_params);
case TC_ETS_DESTROY:
- if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))
- return ksz88x3_tc_ets_del(dev, port);
- else
- return ksz_tc_ets_del(dev, port);
+ return ksz_tc_ets_del(dev, port);
case TC_ETS_STATS:
case TC_ETS_GRAFT:
return -EOPNOTSUPP;
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 245329b6e0e9..7aa4a69d06ef 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -14,6 +14,7 @@
#include <linux/phy.h>
#include <linux/regmap.h>
#include <net/dsa.h>
+#include <net/pkt_cls.h>
#include <linux/irq.h>
#include <linux/platform_data/microchip-ksz.h>
@@ -481,6 +482,12 @@ void ksz_phylink_mac_link_down(struct phylink_config *config,
int ksz_set_mac_eee(struct dsa_switch *ds, int port,
struct ethtool_keee *e);
+int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,
+ int band);
+int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,
+ struct tc_cbs_qopt_offload *qopt);
+int ksz_tc_ets_validate(struct ksz_device *dev, int port,
+ struct tc_ets_qopt_offload_replace_params *p);
int ksz_setup_tc(struct dsa_switch *ds, int port,
enum tc_setup_type type, void *type_data);
--
2.54.0
next prev parent reply other threads:[~2026-07-02 9:07 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-02 9:07 [PATCH net-next 00/10] net: dsa: microchip: move non-common function out of ksz_common.c Bastien Curutchet
2026-07-02 9:07 ` [PATCH net-next 01/10] net: dsa: microchip: split ksz8_change_mtu() Bastien Curutchet
2026-07-02 9:07 ` [PATCH net-next 02/10] net: dsa: microchip: split port_max_mtu() implementation Bastien Curutchet
2026-07-02 9:07 ` [PATCH net-next 03/10] net: dsa: microchip: make ksz_is_port_mac_global_usable() static Bastien Curutchet (Schneider Electric)
2026-07-02 9:07 ` [PATCH net-next 04/10] net: dsa: microchip: move ksz88xx stats handling in ksz8.c Bastien Curutchet (Schneider Electric)
2026-07-02 9:07 ` [PATCH net-next 05/10] net: dsa: microchip: move ksz_get_gbit() and ksz_get_xmii() to ksz9477.c Bastien Curutchet (Schneider Electric)
2026-07-02 9:07 ` [PATCH net-next 06/10] net: dsa: microchip: move KSZ9477 errata handling " Bastien Curutchet (Schneider Electric)
2026-07-02 9:07 ` Bastien Curutchet (Schneider Electric) [this message]
2026-07-02 9:07 ` [PATCH net-next 08/10] net: dsa: microchip: move ksz9477_set_default_prio_queue_mapping() " Bastien Curutchet (Schneider Electric)
2026-07-02 9:07 ` [PATCH net-next 09/10] net: dsa: microchip: rename ksz9477_drive_strength_write() Bastien Curutchet (Schneider Electric)
2026-07-02 9:07 ` [PATCH net-next 10/10] net: dsa: microchip: move the drive strength config out of the common section Bastien Curutchet (Schneider Electric)
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=20260702-clean-ksz-4th-v1-7-93441e695fa4@bootlin.com \
--to=bastien.curutchet@bootlin.com \
--cc=UNGLinuxDriver@microchip.com \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=miquel.raynal@bootlin.com \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=pabeni@redhat.com \
--cc=pascal.eberhard@se.com \
--cc=thomas.petazzoni@bootlin.com \
--cc=woojung.huh@microchip.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