2023-03-08 09:12:59

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v2 0/2] net: dsa: microchip: tc-ets support

changes v2:
- run egress limit configuration on all queue separately. Otherwise
configuration may not apply correctly.

Oleksij Rempel (2):
net: dsa: microchip: add ksz_setup_tc_mode() function
net: dsa: microchip: add ETS Qdisc support for KSZ9477 series

drivers/net/dsa/microchip/ksz_common.c | 205 ++++++++++++++++++++++++-
drivers/net/dsa/microchip/ksz_common.h | 18 ++-
2 files changed, 211 insertions(+), 12 deletions(-)

--
2.30.2



2023-03-08 09:13:02

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v2 1/2] net: dsa: microchip: add ksz_setup_tc_mode() function

Add ksz_setup_tc_mode() to make queue scheduling and shaping
configuration more visible.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/dsa/microchip/ksz_common.c | 20 ++++++++++++--------
drivers/net/dsa/microchip/ksz_common.h | 6 ++----
2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 48e35a1d110e..ae05fe0b0a81 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -32,10 +32,6 @@
#include "ksz9477.h"
#include "lan937x.h"

-#define KSZ_CBS_ENABLE ((MTI_SCHEDULE_STRICT_PRIO << MTI_SCHEDULE_MODE_S) | \
- (MTI_SHAPING_SRP << MTI_SHAPING_S))
-#define KSZ_CBS_DISABLE ((MTI_SCHEDULE_WRR << MTI_SCHEDULE_MODE_S) |\
- (MTI_SHAPING_OFF << MTI_SHAPING_S))
#define MIB_COUNTER_NUM 0x20

struct ksz_stats_raw {
@@ -3119,6 +3115,14 @@ static int cinc_cal(s32 idle_slope, s32 send_slope, u32 *bw)
return 0;
}

+static int ksz_setup_tc_mode(struct ksz_device *dev, int port, u8 scheduler,
+ u8 shaper)
+{
+ return ksz_pwrite8(dev, port, REG_PORT_MTI_QUEUE_CTRL_0,
+ FIELD_PREP(MTI_SCHEDULE_MODE_M, 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)
{
@@ -3138,8 +3142,8 @@ static int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,
return ret;

if (!qopt->enable)
- return ksz_pwrite8(dev, port, REG_PORT_MTI_QUEUE_CTRL_0,
- KSZ_CBS_DISABLE);
+ return ksz_setup_tc_mode(dev, port, MTI_SCHEDULE_WRR,
+ MTI_SHAPING_OFF);

/* High Credit */
ret = ksz_pwrite16(dev, port, REG_PORT_MTI_HI_WATER_MARK,
@@ -3164,8 +3168,8 @@ static int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,
return ret;
}

- return ksz_pwrite8(dev, port, REG_PORT_MTI_QUEUE_CTRL_0,
- KSZ_CBS_ENABLE);
+ return ksz_setup_tc_mode(dev, port, MTI_SCHEDULE_STRICT_PRIO,
+ MTI_SHAPING_SRP);
}

static int ksz_setup_tc(struct dsa_switch *ds, int port,
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 10c732b1cea8..f53834bbe896 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -662,12 +662,10 @@ static inline int is_lan937x(struct ksz_device *dev)

#define REG_PORT_MTI_QUEUE_CTRL_0 0x0914

-#define MTI_SCHEDULE_MODE_M 0x3
-#define MTI_SCHEDULE_MODE_S 6
+#define MTI_SCHEDULE_MODE_M GENMASK(7, 6)
#define MTI_SCHEDULE_STRICT_PRIO 0
#define MTI_SCHEDULE_WRR 2
-#define MTI_SHAPING_M 0x3
-#define MTI_SHAPING_S 4
+#define MTI_SHAPING_M GENMASK(5, 4)
#define MTI_SHAPING_OFF 0
#define MTI_SHAPING_SRP 1
#define MTI_SHAPING_TIME_AWARE 2
--
2.30.2


2023-03-08 09:13:07

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v2 2/2] net: dsa: microchip: add ETS Qdisc support for KSZ9477 series

Add ETS Qdisc support for KSZ9477 of switches. Current implementation is
limited to strict priority mode.

Tested on KSZ8563R with following configuration:
tc qdisc replace dev lan2 root handle 1: ets strict 4 \
priomap 3 3 2 2 1 1 0 0
ip link add link lan2 name v1 type vlan id 1 \
egress-qos-map 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7

and patched iperf3 version:
https://github.com/esnet/iperf/pull/1476
iperf3 -c 172.17.0.1 -b100M -l1472 -t100 -u -R --sock-prio 2

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/dsa/microchip/ksz_common.c | 185 +++++++++++++++++++++++++
drivers/net/dsa/microchip/ksz_common.h | 12 ++
2 files changed, 197 insertions(+)

diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index ae05fe0b0a81..2f9230d3c357 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -3172,12 +3172,197 @@ static int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,
MTI_SHAPING_SRP);
}

+static int ksz_disable_egress_rate_limit(struct ksz_device *dev, int port)
+{
+ int queue, ret;
+
+ /* Configuration will not take effect until the last Port Queue X
+ * Egress Limit Control Register is written.
+ */
+ for (queue = 0; queue < dev->info->num_tx_queues; queue++) {
+ ret = ksz_pwrite8(dev, port, KSZ9477_REG_PORT_OUT_RATE_0 + queue,
+ KSZ9477_OUT_RATE_NO_LIMIT);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static 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
+ * highest priority is given to Band 0.
+ */
+ return p->bands - 1 - band;
+}
+
+static int ksz_queue_set_strict(struct ksz_device *dev, int port, int queue)
+{
+ int ret;
+
+ ret = ksz_pwrite32(dev, port, REG_PORT_MTI_QUEUE_INDEX__4, queue);
+ if (ret)
+ return ret;
+
+ return ksz_setup_tc_mode(dev, port, MTI_SCHEDULE_STRICT_PRIO,
+ MTI_SHAPING_OFF);
+}
+
+static int ksz_queue_set_wrr(struct ksz_device *dev, int port, int queue,
+ int weight)
+{
+ int ret;
+
+ ret = ksz_pwrite32(dev, port, REG_PORT_MTI_QUEUE_INDEX__4, queue);
+ if (ret)
+ return ret;
+
+ ret = ksz_setup_tc_mode(dev, port, MTI_SCHEDULE_WRR,
+ MTI_SHAPING_OFF);
+ if (ret)
+ return ret;
+
+ return ksz_pwrite8(dev, port, KSZ9477_PORT_MTI_QUEUE_CTRL_1, weight);
+}
+
+static int ksz_tc_ets_add(struct ksz_device *dev, int port,
+ struct tc_ets_qopt_offload_replace_params *p)
+{
+ int ret, band, tc_prio;
+ u32 queue_map = 0;
+
+ /* In order to ensure proper prioritization, it is necessary to set the
+ * rate limit for the related queue to zero. Otherwise strict priority
+ * or WRR mode will not work. This is a hardware limitation.
+ */
+ ret = ksz_disable_egress_rate_limit(dev, port);
+ if (ret)
+ return ret;
+
+ /* Configure queue scheduling mode for all bands. Currently only strict
+ * prio mode is supported.
+ */
+ for (band = 0; band < p->bands; band++) {
+ int queue = ksz_ets_band_to_queue(p, band);
+
+ ret = ksz_queue_set_strict(dev, port, queue);
+ if (ret)
+ return ret;
+ }
+
+ /* Configure the mapping between traffic classes and queues. Note:
+ * priomap variable support 16 traffic classes, but the chip can handle
+ * only 8 classes.
+ */
+ for (tc_prio = 0; tc_prio < ARRAY_SIZE(p->priomap); tc_prio++) {
+ int queue;
+
+ if (tc_prio > KSZ9477_MAX_TC_PRIO)
+ break;
+
+ queue = ksz_ets_band_to_queue(p, p->priomap[tc_prio]);
+ queue_map |= queue << (tc_prio * KSZ9477_PORT_TC_MAP_S);
+ }
+
+ return ksz_pwrite32(dev, port, KSZ9477_PORT_MRI_TC_MAP__4, queue_map);
+}
+
+static int ksz_tc_ets_del(struct ksz_device *dev, int port)
+{
+ int ret, queue;
+
+ /* To restore the default chip configuration, set all queues to use the
+ * WRR scheduler with a weight of 1.
+ */
+ for (queue = 0; queue < dev->info->num_tx_queues; queue++) {
+ ret = ksz_queue_set_wrr(dev, port, queue,
+ KSZ9477_DEFAULT_WRR_WEIGHT);
+ if (ret)
+ return ret;
+ }
+
+ /* Revert the queue mapping for TC-priority to its default setting on
+ * the chip.
+ */
+ return ksz_pwrite32(dev, port, KSZ9477_PORT_MRI_TC_MAP__4,
+ KSZ9477_DEFAULT_TC_MAP);
+}
+
+static int ksz_tc_ets_validate(struct ksz_device *dev, int port,
+ struct tc_ets_qopt_offload_replace_params *p)
+{
+ int band;
+
+ /* Since it is not feasible to share one port among multiple qdisc,
+ * the user must configure all available queues appropriately.
+ */
+ if (p->bands != dev->info->num_tx_queues) {
+ dev_err(dev->dev, "Not supported amount of bands. It should be %d\n",
+ dev->info->num_tx_queues);
+ return -EOPNOTSUPP;
+ }
+
+ for (band = 0; band < p->bands; ++band) {
+ /* The KSZ switches utilize a weighted round robin configuration
+ * where a certain number of packets can be transmitted from a
+ * queue before the next queue is serviced. For more information
+ * on this, refer to section 5.2.8.4 of the KSZ8565R
+ * documentation on the Port Transmit Queue Control 1 Register.
+ * However, the current ETS Qdisc implementation (as of February
+ * 2023) assigns a weight to each queue based on the number of
+ * bytes or extrapolated bandwidth in percentages. Since this
+ * differs from the KSZ switches' method and we don't want to
+ * fake support by converting bytes to packets, it is better to
+ * return an error instead.
+ */
+ if (p->quanta[band]) {
+ dev_err(dev->dev, "Quanta/weights configuration is not supported.\n");
+ return -EOPNOTSUPP;
+ }
+ }
+
+ return 0;
+}
+
+static int ksz_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 (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 ksz_tc_ets_add(dev, port, &qopt->replace_params);
+ case TC_ETS_DESTROY:
+ return ksz_tc_ets_del(dev, port);
+ case TC_ETS_STATS:
+ case TC_ETS_GRAFT:
+ return -EOPNOTSUPP;
+ }
+
+ return -EOPNOTSUPP;
+}
+
static int ksz_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 ksz_tc_setup_qdisc_ets(ds, port, type_data);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index f53834bbe896..7618a4714e06 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -657,6 +657,15 @@ static inline int is_lan937x(struct ksz_device *dev)
#define KSZ8_LEGAL_PACKET_SIZE 1518
#define KSZ9477_MAX_FRAME_SIZE 9000

+#define KSZ9477_REG_PORT_OUT_RATE_0 0x0420
+#define KSZ9477_OUT_RATE_NO_LIMIT 0
+
+#define KSZ9477_PORT_MRI_TC_MAP__4 0x0808
+#define KSZ9477_DEFAULT_TC_MAP 0x33221100
+
+#define KSZ9477_PORT_TC_MAP_S 4
+#define KSZ9477_MAX_TC_PRIO 7
+
/* CBS related registers */
#define REG_PORT_MTI_QUEUE_INDEX__4 0x0900

@@ -670,6 +679,9 @@ static inline int is_lan937x(struct ksz_device *dev)
#define MTI_SHAPING_SRP 1
#define MTI_SHAPING_TIME_AWARE 2

+#define KSZ9477_PORT_MTI_QUEUE_CTRL_1 0x0915
+#define KSZ9477_DEFAULT_WRR_WEIGHT 1
+
#define REG_PORT_MTI_HI_WATER_MARK 0x0916
#define REG_PORT_MTI_LO_WATER_MARK 0x0918

--
2.30.2


2023-03-08 16:37:54

by Simon Horman

[permalink] [raw]
Subject: Re: [PATCH net-next v2 2/2] net: dsa: microchip: add ETS Qdisc support for KSZ9477 series

On Wed, Mar 08, 2023 at 10:12:37AM +0100, Oleksij Rempel wrote:
> Add ETS Qdisc support for KSZ9477 of switches. Current implementation is
> limited to strict priority mode.
>
> Tested on KSZ8563R with following configuration:
> tc qdisc replace dev lan2 root handle 1: ets strict 4 \
> priomap 3 3 2 2 1 1 0 0
> ip link add link lan2 name v1 type vlan id 1 \
> egress-qos-map 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
>
> and patched iperf3 version:
> https://github.com/esnet/iperf/pull/1476
> iperf3 -c 172.17.0.1 -b100M -l1472 -t100 -u -R --sock-prio 2
>
> Signed-off-by: Oleksij Rempel <[email protected]>

Reviewed-by: Simon Horman <[email protected]>


2023-03-08 16:38:22

by Simon Horman

[permalink] [raw]
Subject: Re: [PATCH net-next v2 1/2] net: dsa: microchip: add ksz_setup_tc_mode() function

On Wed, Mar 08, 2023 at 10:12:36AM +0100, Oleksij Rempel wrote:
> Add ksz_setup_tc_mode() to make queue scheduling and shaping
> configuration more visible.
>
> Signed-off-by: Oleksij Rempel <[email protected]>

Reviewed-by: Simon Horman <[email protected]>


2023-03-10 04:01:21

by Arun Ramadoss

[permalink] [raw]
Subject: Re: [PATCH net-next v2 1/2] net: dsa: microchip: add ksz_setup_tc_mode() function

On Wed, 2023-03-08 at 10:12 +0100, Oleksij Rempel wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you
> know the content is safe
>
> Add ksz_setup_tc_mode() to make queue scheduling and shaping
> configuration more visible.
>
> Signed-off-by: Oleksij Rempel <[email protected]>

Acked-by: Arun Ramadoss <[email protected]

2023-03-10 04:22:34

by Arun Ramadoss

[permalink] [raw]
Subject: Re: [PATCH net-next v2 2/2] net: dsa: microchip: add ETS Qdisc support for KSZ9477 series

Hi Oleksij,

> +
> +#define KSZ9477_PORT_MRI_TC_MAP__4 0x0808
> +#define KSZ9477_DEFAULT_TC_MAP 0x33221100

KSZ9477 and KSZ8 switches has 4 queues per port whereas LAN937x has 8
queues. So Default TC MAP for LAN937x will be 0x76543210. Instead of
using this values for all the switch, this value must be derived based
on chip info. Can you consider to add this value in chip_info and use
it in funciton ksz_tc_ets_del based on the switch type, So that the
function will be generic.

> +
> +#define KSZ9477_PORT_TC_MAP_S 4
> +#define KSZ9477_MAX_TC_PRIO 7
> +
> /* CBS related registers */
> #define REG_PORT_MTI_QUEUE_INDEX__4 0x0900
>
> @@ -670,6 +679,9 @@ static inline int is_lan937x(struct ksz_device
> *dev)
> #define MTI_SHAPING_SRP 1
> #define MTI_SHAPING_TIME_AWARE 2
>
> +#define KSZ9477_PORT_MTI_QUEUE_CTRL_1 0x0915
> +#define KSZ9477_DEFAULT_WRR_WEIGHT 1
> +
> #define REG_PORT_MTI_HI_WATER_MARK 0x0916
> #define REG_PORT_MTI_LO_WATER_MARK 0x0918
>
> --
> 2.30.2
>

2023-03-10 04:25:38

by Arun Ramadoss

[permalink] [raw]
Subject: Re: [PATCH net-next v2 1/2] net: dsa: microchip: add ksz_setup_tc_mode() function

On Fri, 2023-03-10 at 04:00 +0000, Arun Ramadoss - I17769 wrote:
> On Wed, 2023-03-08 at 10:12 +0100, Oleksij Rempel wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you
> > know the content is safe
> >
> > Add ksz_setup_tc_mode() to make queue scheduling and shaping
> > configuration more visible.
> >
> > Signed-off-by: Oleksij Rempel <[email protected]>
>
> Acked-by: Arun Ramadoss <[email protected]
>

If the ets command is supported only in KSZ9477 series of switch, do we
need to return Not supported for KSZ87xx/KSZ88xx switch similar to tc
cbs implementation. I could infer from the patch set that, all the
register set are for KSZ9477, so invoking the command in
KSZ87xx/KSZ88xx will have undefined behaviour. Correct me if I am
wrong.

2023-03-10 07:13:39

by Oleksij Rempel

[permalink] [raw]
Subject: Re: [PATCH net-next v2 1/2] net: dsa: microchip: add ksz_setup_tc_mode() function

On Fri, Mar 10, 2023 at 04:22:34AM +0000, [email protected] wrote:
> On Fri, 2023-03-10 at 04:00 +0000, Arun Ramadoss - I17769 wrote:
> > On Wed, 2023-03-08 at 10:12 +0100, Oleksij Rempel wrote:
> > > EXTERNAL EMAIL: Do not click links or open attachments unless you
> > > know the content is safe
> > >
> > > Add ksz_setup_tc_mode() to make queue scheduling and shaping
> > > configuration more visible.
> > >
> > > Signed-off-by: Oleksij Rempel <[email protected]>
> >
> > Acked-by: Arun Ramadoss <[email protected]
> >
>
> If the ets command is supported only in KSZ9477 series of switch, do we
> need to return Not supported for KSZ87xx/KSZ88xx switch similar to tc
> cbs implementation. I could infer from the patch set that, all the
> register set are for KSZ9477, so invoking the command in
> KSZ87xx/KSZ88xx will have undefined behaviour. Correct me if I am
> wrong.

Ack. You are correct.

Regards,
Oleksij
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |