[PATCH net-next] rtase: Add ndo_setup_tc support for CBS offload in traffic control setup

Justin Lai posted 1 patch 9 months, 1 week ago
There is a newer version of this series
drivers/net/ethernet/realtek/rtase/rtase.h    | 15 ++++++
.../net/ethernet/realtek/rtase/rtase_main.c   | 49 +++++++++++++++++++
2 files changed, 64 insertions(+)
[PATCH net-next] rtase: Add ndo_setup_tc support for CBS offload in traffic control setup
Posted by Justin Lai 9 months, 1 week ago
Add support for ndo_setup_tc to enable CBS offload functionality as
part of traffic control configuration for network devices.

Signed-off-by: Justin Lai <justinlai0215@realtek.com>
---
 drivers/net/ethernet/realtek/rtase/rtase.h    | 15 ++++++
 .../net/ethernet/realtek/rtase/rtase_main.c   | 49 +++++++++++++++++++
 2 files changed, 64 insertions(+)

diff --git a/drivers/net/ethernet/realtek/rtase/rtase.h b/drivers/net/ethernet/realtek/rtase/rtase.h
index 2bbfcad613ab..498cfe4d0cac 100644
--- a/drivers/net/ethernet/realtek/rtase/rtase.h
+++ b/drivers/net/ethernet/realtek/rtase/rtase.h
@@ -170,6 +170,7 @@ enum rtase_registers {
 #define RTASE_TC_MODE_MASK GENMASK(11, 10)
 
 	RTASE_TOKSEL      = 0x2046,
+	RTASE_TXQCRDT_0   = 0x2500,
 	RTASE_RFIFONFULL  = 0x4406,
 	RTASE_INT_MITI_TX = 0x0A00,
 	RTASE_INT_MITI_RX = 0x0A80,
@@ -259,6 +260,12 @@ union rtase_rx_desc {
 #define RTASE_VLAN_TAG_MASK     GENMASK(15, 0)
 #define RTASE_RX_PKT_SIZE_MASK  GENMASK(13, 0)
 
+/* txqos hardware definitions */
+#define RTASE_1T_CLOCK            64
+#define RTASE_1T_POWER            10000000
+#define RTASE_IDLESLOPE_INT_SHIFT 25
+#define RTASE_IDLESLOPE_INT_MASK  GENMASK(31, 25)
+
 #define RTASE_IVEC_NAME_SIZE (IFNAMSIZ + 10)
 
 struct rtase_int_vector {
@@ -294,6 +301,13 @@ struct rtase_ring {
 	u64 alloc_fail;
 };
 
+struct rtase_txqos {
+	int hicredit;
+	int locredit;
+	int idleslope;
+	int sendslope;
+};
+
 struct rtase_stats {
 	u64 tx_dropped;
 	u64 rx_dropped;
@@ -313,6 +327,7 @@ struct rtase_private {
 
 	struct page_pool *page_pool;
 	struct rtase_ring tx_ring[RTASE_NUM_TX_QUEUE];
+	struct rtase_txqos tx_qos[RTASE_NUM_TX_QUEUE];
 	struct rtase_ring rx_ring[RTASE_NUM_RX_QUEUE];
 	struct rtase_counters *tally_vaddr;
 	dma_addr_t tally_paddr;
diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c
index 2aacc1996796..2a61cd192026 100644
--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
+++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
@@ -1661,6 +1661,54 @@ static void rtase_get_stats64(struct net_device *dev,
 	stats->rx_length_errors = tp->stats.rx_length_errors;
 }
 
+static void rtase_set_hw_cbs(const struct rtase_private *tp, u32 queue)
+{
+	u32 idle = tp->tx_qos[queue].idleslope * RTASE_1T_CLOCK;
+	u32 val, i;
+
+	val = u32_encode_bits(idle / RTASE_1T_POWER, RTASE_IDLESLOPE_INT_MASK);
+	idle %= RTASE_1T_POWER;
+
+	for (i = 1; i <= RTASE_IDLESLOPE_INT_SHIFT; i++) {
+		idle *= 2;
+		if ((idle / RTASE_1T_POWER) == 1)
+			val |= BIT(RTASE_IDLESLOPE_INT_SHIFT - i);
+
+		idle %= RTASE_1T_POWER;
+	}
+
+	rtase_w32(tp, RTASE_TXQCRDT_0 + queue * 4, val);
+}
+
+static void rtase_setup_tc_cbs(struct rtase_private *tp,
+			       const struct tc_cbs_qopt_offload *qopt)
+{
+	u32 queue = qopt->queue;
+
+	tp->tx_qos[queue].hicredit = qopt->hicredit;
+	tp->tx_qos[queue].locredit = qopt->locredit;
+	tp->tx_qos[queue].idleslope = qopt->idleslope;
+	tp->tx_qos[queue].sendslope = qopt->sendslope;
+
+	rtase_set_hw_cbs(tp, queue);
+}
+
+static int rtase_setup_tc(struct net_device *dev, enum tc_setup_type type,
+			  void *type_data)
+{
+	struct rtase_private *tp = netdev_priv(dev);
+
+	switch (type) {
+	case TC_SETUP_QDISC_CBS:
+		rtase_setup_tc_cbs(tp, type_data);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
 static netdev_features_t rtase_fix_features(struct net_device *dev,
 					    netdev_features_t features)
 {
@@ -1696,6 +1744,7 @@ static const struct net_device_ops rtase_netdev_ops = {
 	.ndo_change_mtu = rtase_change_mtu,
 	.ndo_tx_timeout = rtase_tx_timeout,
 	.ndo_get_stats64 = rtase_get_stats64,
+	.ndo_setup_tc = rtase_setup_tc,
 	.ndo_fix_features = rtase_fix_features,
 	.ndo_set_features = rtase_set_features,
 };
-- 
2.34.1
Re: [PATCH net-next] rtase: Add ndo_setup_tc support for CBS offload in traffic control setup
Posted by Simon Horman 9 months ago
On Fri, Mar 14, 2025 at 05:40:21PM +0800, Justin Lai wrote:
> Add support for ndo_setup_tc to enable CBS offload functionality as
> part of traffic control configuration for network devices.
> 
> Signed-off-by: Justin Lai <justinlai0215@realtek.com>

...

> diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c
> index 2aacc1996796..2a61cd192026 100644
> --- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
> +++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
> @@ -1661,6 +1661,54 @@ static void rtase_get_stats64(struct net_device *dev,
>  	stats->rx_length_errors = tp->stats.rx_length_errors;
>  }
>  
> +static void rtase_set_hw_cbs(const struct rtase_private *tp, u32 queue)
> +{
> +	u32 idle = tp->tx_qos[queue].idleslope * RTASE_1T_CLOCK;
> +	u32 val, i;
> +
> +	val = u32_encode_bits(idle / RTASE_1T_POWER, RTASE_IDLESLOPE_INT_MASK);
> +	idle %= RTASE_1T_POWER;
> +
> +	for (i = 1; i <= RTASE_IDLESLOPE_INT_SHIFT; i++) {
> +		idle *= 2;
> +		if ((idle / RTASE_1T_POWER) == 1)
> +			val |= BIT(RTASE_IDLESLOPE_INT_SHIFT - i);
> +
> +		idle %= RTASE_1T_POWER;
> +	}
> +
> +	rtase_w32(tp, RTASE_TXQCRDT_0 + queue * 4, val);
> +}
> +
> +static void rtase_setup_tc_cbs(struct rtase_private *tp,
> +			       const struct tc_cbs_qopt_offload *qopt)
> +{
> +	u32 queue = qopt->queue;

Hi Justin,

Does queue need to be checked somewhere to make sure it is in range?

> +
> +	tp->tx_qos[queue].hicredit = qopt->hicredit;
> +	tp->tx_qos[queue].locredit = qopt->locredit;
> +	tp->tx_qos[queue].idleslope = qopt->idleslope;
> +	tp->tx_qos[queue].sendslope = qopt->sendslope;

Does qopt->enable need to be honoured in order to allow
the offload to be both enabled and disabled?

> +
> +	rtase_set_hw_cbs(tp, queue);
> +}
> +
> +static int rtase_setup_tc(struct net_device *dev, enum tc_setup_type type,
> +			  void *type_data)
> +{
> +	struct rtase_private *tp = netdev_priv(dev);
> +
> +	switch (type) {
> +	case TC_SETUP_QDISC_CBS:
> +		rtase_setup_tc_cbs(tp, type_data);
> +		break;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +
> +	return 0;
> +}
> +
>  static netdev_features_t rtase_fix_features(struct net_device *dev,
>  					    netdev_features_t features)
>  {

...
RE: [PATCH net-next] rtase: Add ndo_setup_tc support for CBS offload in traffic control setup
Posted by Justin Lai 9 months ago
> On Fri, Mar 14, 2025 at 05:40:21PM +0800, Justin Lai wrote:
> > Add support for ndo_setup_tc to enable CBS offload functionality as
> > part of traffic control configuration for network devices.
> >
> > Signed-off-by: Justin Lai <justinlai0215@realtek.com>
> 
> ...
> 
> > diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > b/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > index 2aacc1996796..2a61cd192026 100644
> > --- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > +++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > @@ -1661,6 +1661,54 @@ static void rtase_get_stats64(struct net_device
> *dev,
> >       stats->rx_length_errors = tp->stats.rx_length_errors;  }
> >
> > +static void rtase_set_hw_cbs(const struct rtase_private *tp, u32
> > +queue) {
> > +     u32 idle = tp->tx_qos[queue].idleslope * RTASE_1T_CLOCK;
> > +     u32 val, i;
> > +
> > +     val = u32_encode_bits(idle / RTASE_1T_POWER,
> RTASE_IDLESLOPE_INT_MASK);
> > +     idle %= RTASE_1T_POWER;
> > +
> > +     for (i = 1; i <= RTASE_IDLESLOPE_INT_SHIFT; i++) {
> > +             idle *= 2;
> > +             if ((idle / RTASE_1T_POWER) == 1)
> > +                     val |= BIT(RTASE_IDLESLOPE_INT_SHIFT - i);
> > +
> > +             idle %= RTASE_1T_POWER;
> > +     }
> > +
> > +     rtase_w32(tp, RTASE_TXQCRDT_0 + queue * 4, val); }
> > +
> > +static void rtase_setup_tc_cbs(struct rtase_private *tp,
> > +                            const struct tc_cbs_qopt_offload *qopt) {
> > +     u32 queue = qopt->queue;
> 
> Hi Justin,
> 
> Does queue need to be checked somewhere to make sure it is in range?

Hi Simon,

Thank you for your response. I will add a check to ensure that the
queue is within the specified range.
> 
> > +
> > +     tp->tx_qos[queue].hicredit = qopt->hicredit;
> > +     tp->tx_qos[queue].locredit = qopt->locredit;
> > +     tp->tx_qos[queue].idleslope = qopt->idleslope;
> > +     tp->tx_qos[queue].sendslope = qopt->sendslope;
> 
> Does qopt->enable need to be honoured in order to allow the offload to be
> both enabled and disabled?
> 
Thank you for your suggestion. I will add a check for qopt->enable and
handle it appropriately.

> > +
> > +     rtase_set_hw_cbs(tp, queue);
> > +}
> > +
> > +static int rtase_setup_tc(struct net_device *dev, enum tc_setup_type type,
> > +                       void *type_data) {
> > +     struct rtase_private *tp = netdev_priv(dev);
> > +
> > +     switch (type) {
> > +     case TC_SETUP_QDISC_CBS:
> > +             rtase_setup_tc_cbs(tp, type_data);
> > +             break;
> > +     default:
> > +             return -EOPNOTSUPP;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> >  static netdev_features_t rtase_fix_features(struct net_device *dev,
> >                                           netdev_features_t
> features)
> > {
> 
> ...
RE: [PATCH net-next] rtase: Add ndo_setup_tc support for CBS offload in traffic control setup
Posted by Justin Lai 8 months, 4 weeks ago
> 
> > On Fri, Mar 14, 2025 at 05:40:21PM +0800, Justin Lai wrote:
> > > Add support for ndo_setup_tc to enable CBS offload functionality as
> > > part of traffic control configuration for network devices.
> > >
> > > Signed-off-by: Justin Lai <justinlai0215@realtek.com>
> >
> > ...
> >
> > > diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > > b/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > > index 2aacc1996796..2a61cd192026 100644
> > > --- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > > +++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > > @@ -1661,6 +1661,54 @@ static void rtase_get_stats64(struct
> > > net_device
> > *dev,
> > >       stats->rx_length_errors = tp->stats.rx_length_errors;  }
> > >
> > > +static void rtase_set_hw_cbs(const struct rtase_private *tp, u32
> > > +queue) {
> > > +     u32 idle = tp->tx_qos[queue].idleslope * RTASE_1T_CLOCK;
> > > +     u32 val, i;
> > > +
> > > +     val = u32_encode_bits(idle / RTASE_1T_POWER,
> > RTASE_IDLESLOPE_INT_MASK);
> > > +     idle %= RTASE_1T_POWER;
> > > +
> > > +     for (i = 1; i <= RTASE_IDLESLOPE_INT_SHIFT; i++) {
> > > +             idle *= 2;
> > > +             if ((idle / RTASE_1T_POWER) == 1)
> > > +                     val |= BIT(RTASE_IDLESLOPE_INT_SHIFT - i);
> > > +
> > > +             idle %= RTASE_1T_POWER;
> > > +     }
> > > +
> > > +     rtase_w32(tp, RTASE_TXQCRDT_0 + queue * 4, val); }
> > > +
> > > +static void rtase_setup_tc_cbs(struct rtase_private *tp,
> > > +                            const struct tc_cbs_qopt_offload *qopt)
> {
> > > +     u32 queue = qopt->queue;
> >
> > Hi Justin,
> >
> > Does queue need to be checked somewhere to make sure it is in range?
> 
> Hi Simon,
> 
> Thank you for your response. I will add a check to ensure that the queue is
> within the specified range.

Hi Simon,

Given that our hardware supports CBS offload on each queue, could it
be possible that checking the range of qopt->queue might not be
necessary?

> >
> > > +
> > > +     tp->tx_qos[queue].hicredit = qopt->hicredit;
> > > +     tp->tx_qos[queue].locredit = qopt->locredit;
> > > +     tp->tx_qos[queue].idleslope = qopt->idleslope;
> > > +     tp->tx_qos[queue].sendslope = qopt->sendslope;
> >
> > Does qopt->enable need to be honoured in order to allow the offload to
> > be both enabled and disabled?
> >
> Thank you for your suggestion. I will add a check for qopt->enable and handle
> it appropriately.
> 
> > > +
> > > +     rtase_set_hw_cbs(tp, queue);
> > > +}
> > > +
> > > +static int rtase_setup_tc(struct net_device *dev, enum tc_setup_type
> type,
> > > +                       void *type_data) {
> > > +     struct rtase_private *tp = netdev_priv(dev);
> > > +
> > > +     switch (type) {
> > > +     case TC_SETUP_QDISC_CBS:
> > > +             rtase_setup_tc_cbs(tp, type_data);
> > > +             break;
> > > +     default:
> > > +             return -EOPNOTSUPP;
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > >  static netdev_features_t rtase_fix_features(struct net_device *dev,
> > >                                           netdev_features_t
> > features)
> > > {
> >
> > ...
Re: [PATCH net-next] rtase: Add ndo_setup_tc support for CBS offload in traffic control setup
Posted by Simon Horman 8 months, 3 weeks ago
On Mon, Mar 24, 2025 at 12:06:09PM +0000, Justin Lai wrote:
> > 
> > > On Fri, Mar 14, 2025 at 05:40:21PM +0800, Justin Lai wrote:
> > > > Add support for ndo_setup_tc to enable CBS offload functionality as
> > > > part of traffic control configuration for network devices.
> > > >
> > > > Signed-off-by: Justin Lai <justinlai0215@realtek.com>
> > >
> > > ...
> > >
> > > > diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > > > b/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > > > index 2aacc1996796..2a61cd192026 100644
> > > > --- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > > > +++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > > > @@ -1661,6 +1661,54 @@ static void rtase_get_stats64(struct
> > > > net_device
> > > *dev,
> > > >       stats->rx_length_errors = tp->stats.rx_length_errors;  }
> > > >
> > > > +static void rtase_set_hw_cbs(const struct rtase_private *tp, u32
> > > > +queue) {
> > > > +     u32 idle = tp->tx_qos[queue].idleslope * RTASE_1T_CLOCK;
> > > > +     u32 val, i;
> > > > +
> > > > +     val = u32_encode_bits(idle / RTASE_1T_POWER,
> > > RTASE_IDLESLOPE_INT_MASK);
> > > > +     idle %= RTASE_1T_POWER;
> > > > +
> > > > +     for (i = 1; i <= RTASE_IDLESLOPE_INT_SHIFT; i++) {
> > > > +             idle *= 2;
> > > > +             if ((idle / RTASE_1T_POWER) == 1)
> > > > +                     val |= BIT(RTASE_IDLESLOPE_INT_SHIFT - i);
> > > > +
> > > > +             idle %= RTASE_1T_POWER;
> > > > +     }
> > > > +
> > > > +     rtase_w32(tp, RTASE_TXQCRDT_0 + queue * 4, val); }
> > > > +
> > > > +static void rtase_setup_tc_cbs(struct rtase_private *tp,
> > > > +                            const struct tc_cbs_qopt_offload *qopt)
> > {
> > > > +     u32 queue = qopt->queue;
> > >
> > > Hi Justin,
> > >
> > > Does queue need to be checked somewhere to make sure it is in range?
> > 
> > Hi Simon,
> > 
> > Thank you for your response. I will add a check to ensure that the queue is
> > within the specified range.
> 
> Hi Simon,
> 
> Given that our hardware supports CBS offload on each queue, could it
> be possible that checking the range of qopt->queue might not be
> necessary?

Hi Justin,

If qopt->queue can only be a valid queue, and all queues support
CBS, then I guess it would not be necessary.