netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [net-next] enetc: add support Credit Based Shaper(CBS) for hardware offload
@ 2019-11-22  7:17 Po Liu
  2019-11-24  3:02 ` Jakub Kicinski
  2019-11-25  5:56 ` [v2,net-next] " Po Liu
  0 siblings, 2 replies; 6+ messages in thread
From: Po Liu @ 2019-11-22  7:17 UTC (permalink / raw)
  To: davem, linux-kernel, netdev
  Cc: vinicius.gomes, Po Liu, Claudiu Manoil, Vladimir Oltean,
	Alexandru Marginean, Xiaoliang Yang, Roy Zang, Mingkai Hu,
	Jerry Huang, Leo Li, Po Liu

The ENETC hardware support the Credit Based Shaper(CBS) which part
of the IEEE-802.1Qav. The CBS driver was loaded by the sch_cbs
interface when set in the QOS in the kernel.

Here is an example command to set 20Mbits bandwidth in 1Gbits port
for taffic class 7:

tc qdisc add dev eth0 root handle 1: mqprio \
	   num_tc 8 map 0 1 2 3 4 5 6 7 hw 1

tc qdisc replace dev eth0 parent 1:8 cbs \
	   locredit -1470 hicredit 30 \
	   sendslope -980000 idleslope 20000 offload 1

Signed-off-by: Po Liu <Po.Liu@nxp.com>
Reviewed-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/Kconfig  |   4 +-
 drivers/net/ethernet/freescale/enetc/enetc.c  |   2 +
 drivers/net/ethernet/freescale/enetc/enetc.h  |   2 +
 .../net/ethernet/freescale/enetc/enetc_hw.h   |   4 +
 .../net/ethernet/freescale/enetc/enetc_qos.c  | 126 ++++++++++++++++++
 5 files changed, 136 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig
index 491659fe3e35..edad4ca46327 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -53,10 +53,10 @@ config FSL_ENETC_HW_TIMESTAMPING
 
 config FSL_ENETC_QOS
 	bool "ENETC hardware Time-sensitive Network support"
-	depends on (FSL_ENETC || FSL_ENETC_VF) && NET_SCH_TAPRIO
+	depends on (FSL_ENETC || FSL_ENETC_VF) && (NET_SCH_TAPRIO || NET_SCH_CBS)
 	help
 	  There are Time-Sensitive Network(TSN) capabilities(802.1Qbv/802.1Qci
 	  /802.1Qbu etc.) supported by ENETC. These TSN capabilities can be set
 	  enable/disable from user space via Qos commands(tc). In the kernel
 	  side, it can be loaded by Qos driver. Currently, it is only support
-	  taprio(802.1Qbv).
+	  taprio(802.1Qbv) and Credit Based Shaper(802.1Qbu).
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 27f6fd1708f0..9db1b96ed9b9 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1496,6 +1496,8 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
 		return enetc_setup_tc_mqprio(ndev, type_data);
 	case TC_SETUP_QDISC_TAPRIO:
 		return enetc_setup_tc_taprio(ndev, type_data);
+	case TC_SETUP_QDISC_CBS:
+		return enetc_setup_tc_cbs(ndev, type_data);
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 89f23156f330..7ee0da6d0015 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -255,7 +255,9 @@ int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
 #ifdef CONFIG_FSL_ENETC_QOS
 int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data);
 void enetc_sched_speed_set(struct net_device *ndev);
+int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data);
 #else
 #define enetc_setup_tc_taprio(ndev, type_data) -EOPNOTSUPP
 #define enetc_sched_speed_set(ndev) (void)0
+#define enetc_setup_tc_cbs(ndev, type_data) -EOPNOTSUPP
 #endif
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
index 924ddb6d358a..51f543ef37a8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
@@ -185,6 +185,8 @@ enum enetc_bdr_type {TX, RX};
 #define ENETC_PSICFGR0_SIVC(bmp)	(((bmp) & 0xff) << 24) /* VLAN_TYPE */
 
 #define ENETC_PTCCBSR0(n)	(0x1110 + (n) * 8) /* n = 0 to 7*/
+#define ENETC_CBSE		BIT(31)
+#define ENETC_CBS_BW_MASK	GENMASK(6, 0)
 #define ENETC_PTCCBSR1(n)	(0x1114 + (n) * 8) /* n = 0 to 7*/
 #define ENETC_RSSHASH_KEY_SIZE	40
 #define ENETC_PRSSK(n)		(0x1410 + (n) * 4) /* n = [0..9] */
@@ -603,6 +605,8 @@ struct enetc_cbd {
 	u8 status_flags;
 };
 
+#define ENETC_CLK  400000000ULL
+
 /* port time gating control register */
 #define ENETC_QBV_PTGCR_OFFSET		0x11a00
 #define ENETC_QBV_TGE			BIT(31)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
index 66a3da61ca16..98c3d062459a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
@@ -170,3 +170,129 @@ int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data)
 
 	return err;
 }
+
+static u32 enetc_get_cbs_enable(struct enetc_hw *hw, u8 tc)
+{
+	return enetc_port_rd(hw, ENETC_PTCCBSR0(tc)) & ENETC_CBSE;
+}
+
+static u8 enetc_get_cbs_bw(struct enetc_hw *hw, u8 tc)
+{
+	return enetc_port_rd(hw, ENETC_PTCCBSR0(tc)) & ENETC_CBS_BW_MASK;
+}
+
+int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct tc_cbs_qopt_offload *cbs = type_data;
+	u32 port_transmit_rate = priv->speed;
+	u8 tc_nums = netdev_get_num_tc(ndev);
+	struct enetc_si *si = priv->si;
+	u32 hi_credit_bit, hi_credit_reg;
+	u32 max_interference_size;
+	u32 port_frame_max_size;
+	u32 tc_max_sized_frame;
+	u8 tc = cbs->queue;
+	u8 prio_top, prio_next;
+	int bw_sum = 0;
+	u8 bw;
+
+	prio_top = netdev_get_prio_tc_map(ndev, tc_nums - 1);
+	prio_next = netdev_get_prio_tc_map(ndev, tc_nums - 2);
+
+	/* Support highest prio and second prio tc in cbs mode */
+	if (tc != prio_top && tc != prio_next)
+		return -EOPNOTSUPP;
+
+	if (!cbs->enable) {
+		/* Make sure the other TC that are numerically
+		 * lower than this TC have been disabled.
+		 */
+		if (tc == prio_top &&
+		    enetc_get_cbs_enable(&si->hw, prio_next)) {
+			dev_err(&ndev->dev,
+				"Disable TC%d before disable TC%d\n",
+				prio_next, tc);
+			return -EINVAL;
+		}
+
+		enetc_port_wr(&si->hw, ENETC_PTCCBSR1(tc), 0);
+		enetc_port_wr(&si->hw, ENETC_PTCCBSR0(tc), 0);
+
+		return 0;
+	}
+
+	if (cbs->idleslope - cbs->sendslope != port_transmit_rate * 1000L ||
+	    cbs->idleslope < 0 || cbs->sendslope > 0)
+		return -EOPNOTSUPP;
+
+	port_frame_max_size = ndev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
+
+	bw = cbs->idleslope / (port_transmit_rate * 10UL);
+
+	/* Make sure the other TC that are numerically
+	 * higher than this TC have been enabled.
+	 */
+	if (tc == prio_next) {
+		if (!enetc_get_cbs_enable(&si->hw, prio_top)) {
+			dev_err(&ndev->dev,
+				"Enable TC%d first before enable TC%d\n",
+				prio_top, prio_next);
+			return -EINVAL;
+		}
+		bw_sum += enetc_get_cbs_bw(&si->hw, prio_top);
+	}
+
+	if (bw_sum + bw >= 100) {
+		dev_err(&ndev->dev,
+			"The sum of all CBS Bandwidth can't exceed 100\n");
+		return -EINVAL;
+	}
+
+	tc_max_sized_frame = enetc_port_rd(&si->hw, ENETC_PTCMSDUR(tc));
+
+	/* For top prio TC, the max_interfrence_size is maxSizedFrame.
+	 *
+	 * For next prio TC, the max_interfrence_size is calculated as below:
+	 *
+	 *      max_interference_size = M0 + Ma + Ra * M0 / (R0 - Ra)
+	 *
+	 *	- RA: idleSlope for AVB Class A
+	 *	- R0: port transmit rate
+	 *	- M0: maximum sized frame for the port
+	 *	- MA: maximum sized frame for AVB Class A
+	 */
+
+	if (tc == prio_top) {
+		max_interference_size = port_frame_max_size * 8;
+	} else {
+		u32 m0, ma, r0, ra;
+
+		m0 = port_frame_max_size * 8;
+		ma = enetc_port_rd(&si->hw, ENETC_PTCMSDUR(prio_top)) * 8;
+		ra = enetc_get_cbs_bw(&si->hw, prio_top) *
+			port_transmit_rate * 10000ULL;
+		r0 = port_transmit_rate * 1000000ULL;
+		max_interference_size = m0 + ma + (u64)ra * m0 / (r0 - ra);
+	}
+
+	/* hiCredit bits calculate by:
+	 *
+	 * maxSizedFrame * (idleSlope/portTxRate)
+	 */
+	hi_credit_bit = max_interference_size * bw / 100;
+
+	/* hiCredit bits to hiCredit register need to calculated as:
+	 *
+	 * (enetClockFrequency / portTransmitRate) * 100
+	 */
+	hi_credit_reg = (ENETC_CLK * 100ULL) * hi_credit_bit
+			/ (port_transmit_rate * 1000000ULL);
+
+	enetc_port_wr(&si->hw, ENETC_PTCCBSR1(tc), hi_credit_reg);
+
+	/* Set bw register and enable this traffic class */
+	enetc_port_wr(&si->hw, ENETC_PTCCBSR0(tc), bw | ENETC_CBSE);
+
+	return 0;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [net-next] enetc: add support Credit Based Shaper(CBS) for hardware offload
  2019-11-22  7:17 [net-next] enetc: add support Credit Based Shaper(CBS) for hardware offload Po Liu
@ 2019-11-24  3:02 ` Jakub Kicinski
  2019-11-24 23:34   ` Jakub Kicinski
  2019-11-25  5:56 ` [v2,net-next] " Po Liu
  1 sibling, 1 reply; 6+ messages in thread
From: Jakub Kicinski @ 2019-11-24  3:02 UTC (permalink / raw)
  To: Po Liu
  Cc: davem, linux-kernel, netdev, vinicius.gomes, Claudiu Manoil,
	Vladimir Oltean, Alexandru Marginean, Xiaoliang Yang, Roy Zang,
	Mingkai Hu, Jerry Huang, Leo Li

On Fri, 22 Nov 2019 07:17:18 +0000, Po Liu wrote:
> +	if (tc == prio_top) {
> +		max_interference_size = port_frame_max_size * 8;
> +	} else {
> +		u32 m0, ma, r0, ra;
> +
> +		m0 = port_frame_max_size * 8;
> +		ma = enetc_port_rd(&si->hw, ENETC_PTCMSDUR(prio_top)) * 8;
> +		ra = enetc_get_cbs_bw(&si->hw, prio_top) *
> +			port_transmit_rate * 10000ULL;
> +		r0 = port_transmit_rate * 1000000ULL;
> +		max_interference_size = m0 + ma + (u64)ra * m0 / (r0 - ra);
> +	}
> +
> +	/* hiCredit bits calculate by:
> +	 *
> +	 * maxSizedFrame * (idleSlope/portTxRate)
> +	 */
> +	hi_credit_bit = max_interference_size * bw / 100;
> +
> +	/* hiCredit bits to hiCredit register need to calculated as:
> +	 *
> +	 * (enetClockFrequency / portTransmitRate) * 100
> +	 */
> +	hi_credit_reg = (ENETC_CLK * 100ULL) * hi_credit_bit
> +			/ (port_transmit_rate * 1000000ULL);

Hi! The patch looks good to me, but I'm concerned about those 64bit
divisions here. Don't these need to be div_u64() & co.? Otherwise
we may see one of the:

ERROR: "__udivdi3" [drivers/net/ethernet/freescale/enetc/fsl-enetc.ko] undefined!

messages from the build bot..

I could be wrong, I haven't actually tested..

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [net-next] enetc: add support Credit Based Shaper(CBS) for hardware offload
  2019-11-24  3:02 ` Jakub Kicinski
@ 2019-11-24 23:34   ` Jakub Kicinski
  2019-11-25  3:03     ` [EXT] " Po Liu
  0 siblings, 1 reply; 6+ messages in thread
From: Jakub Kicinski @ 2019-11-24 23:34 UTC (permalink / raw)
  To: Po Liu
  Cc: davem, linux-kernel, netdev, vinicius.gomes, Claudiu Manoil,
	Vladimir Oltean, Alexandru Marginean, Xiaoliang Yang, Roy Zang,
	Mingkai Hu, Jerry Huang, Leo Li

On Sat, 23 Nov 2019 19:02:09 -0800, Jakub Kicinski wrote:
> On Fri, 22 Nov 2019 07:17:18 +0000, Po Liu wrote:
> > +	if (tc == prio_top) {
> > +		max_interference_size = port_frame_max_size * 8;
> > +	} else {
> > +		u32 m0, ma, r0, ra;
> > +
> > +		m0 = port_frame_max_size * 8;
> > +		ma = enetc_port_rd(&si->hw, ENETC_PTCMSDUR(prio_top)) * 8;
> > +		ra = enetc_get_cbs_bw(&si->hw, prio_top) *
> > +			port_transmit_rate * 10000ULL;
> > +		r0 = port_transmit_rate * 1000000ULL;
> > +		max_interference_size = m0 + ma + (u64)ra * m0 / (r0 - ra);
> > +	}
> > +
> > +	/* hiCredit bits calculate by:
> > +	 *
> > +	 * maxSizedFrame * (idleSlope/portTxRate)
> > +	 */
> > +	hi_credit_bit = max_interference_size * bw / 100;
> > +
> > +	/* hiCredit bits to hiCredit register need to calculated as:
> > +	 *
> > +	 * (enetClockFrequency / portTransmitRate) * 100
> > +	 */
> > +	hi_credit_reg = (ENETC_CLK * 100ULL) * hi_credit_bit
> > +			/ (port_transmit_rate * 1000000ULL);  
> 
> Hi! The patch looks good to me, but I'm concerned about those 64bit
> divisions here. Don't these need to be div_u64() & co.? Otherwise
> we may see one of the:
> 
> ERROR: "__udivdi3" [drivers/net/ethernet/freescale/enetc/fsl-enetc.ko] undefined!
> 
> messages from the build bot..
> 
> I could be wrong, I haven't actually tested..

Yup:

drivers/net/ethernet/freescale/enetc/enetc_qos.o: In function `enetc_setup_tc_cbs':
enetc_qos.c:(.text+0x5b4): undefined reference to `__udivdi3'
enetc_qos.c:(.text+0x608): undefined reference to `__udivdi3'
/home/jkicinski/devel/linux/Makefile:1077: recipe for target 'vmlinux' failed
make[1]: *** [vmlinux] Error 1
make[1]: Leaving directory '/home/jkicinski/devel/linux/build_tmp2'
Makefile:179: recipe for target 'sub-make' failed
make: *** [sub-make] Error 2

Please fix and repost.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: [EXT] Re: [net-next] enetc: add support Credit Based Shaper(CBS) for hardware offload
  2019-11-24 23:34   ` Jakub Kicinski
@ 2019-11-25  3:03     ` Po Liu
  0 siblings, 0 replies; 6+ messages in thread
From: Po Liu @ 2019-11-25  3:03 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: davem, linux-kernel, netdev, vinicius.gomes, Claudiu Manoil,
	Vladimir Oltean, Alexandru Marginean, Xiaoliang Yang, Roy Zang,
	Mingkai Hu, Jerry Huang, Leo Li

Hi Jakub,

Thanks!


Br,
Po Liu

> -----Original Message-----
> From: Jakub Kicinski <jakub.kicinski@netronome.com>
> Sent: 2019年11月25日 7:35
> To: Po Liu <po.liu@nxp.com>
> Cc: davem@davemloft.net; linux-kernel@vger.kernel.org;
> netdev@vger.kernel.org; vinicius.gomes@intel.com; Claudiu Manoil
> <claudiu.manoil@nxp.com>; Vladimir Oltean <vladimir.oltean@nxp.com>;
> Alexandru Marginean <alexandru.marginean@nxp.com>; Xiaoliang Yang
> <xiaoliang.yang_1@nxp.com>; Roy Zang <roy.zang@nxp.com>; Mingkai Hu
> <mingkai.hu@nxp.com>; Jerry Huang <jerry.huang@nxp.com>; Leo Li
> <leoyang.li@nxp.com>
> Subject: [EXT] Re: [net-next] enetc: add support Credit Based Shaper(CBS) for
> hardware offload
> 
> Caution: EXT Email
> 
> On Sat, 23 Nov 2019 19:02:09 -0800, Jakub Kicinski wrote:
> > On Fri, 22 Nov 2019 07:17:18 +0000, Po Liu wrote:
> > > +   if (tc == prio_top) {
> > > +           max_interference_size = port_frame_max_size * 8;
> > > +   } else {
> > > +           u32 m0, ma, r0, ra;
> > > +
> > > +           m0 = port_frame_max_size * 8;
> > > +           ma = enetc_port_rd(&si->hw, ENETC_PTCMSDUR(prio_top)) * 8;
> > > +           ra = enetc_get_cbs_bw(&si->hw, prio_top) *
> > > +                   port_transmit_rate * 10000ULL;
> > > +           r0 = port_transmit_rate * 1000000ULL;
> > > +           max_interference_size = m0 + ma + (u64)ra * m0 / (r0 - ra);
> > > +   }
> > > +
> > > +   /* hiCredit bits calculate by:
> > > +    *
> > > +    * maxSizedFrame * (idleSlope/portTxRate)
> > > +    */
> > > +   hi_credit_bit = max_interference_size * bw / 100;
> > > +
> > > +   /* hiCredit bits to hiCredit register need to calculated as:
> > > +    *
> > > +    * (enetClockFrequency / portTransmitRate) * 100
> > > +    */
> > > +   hi_credit_reg = (ENETC_CLK * 100ULL) * hi_credit_bit
> > > +                   / (port_transmit_rate * 1000000ULL);
> >
> > Hi! The patch looks good to me, but I'm concerned about those 64bit
> > divisions here. Don't these need to be div_u64() & co.? Otherwise we
> > may see one of the:
> >
> > ERROR: "__udivdi3" [drivers/net/ethernet/freescale/enetc/fsl-enetc.ko]
> undefined!
> >
> > messages from the build bot..
> >
> > I could be wrong, I haven't actually tested..
> 
> Yup:
> 
> drivers/net/ethernet/freescale/enetc/enetc_qos.o: In function
> `enetc_setup_tc_cbs':
> enetc_qos.c:(.text+0x5b4): undefined reference to `__udivdi3'
> enetc_qos.c:(.text+0x608): undefined reference to `__udivdi3'
> /home/jkicinski/devel/linux/Makefile:1077: recipe for target 'vmlinux' failed
> make[1]: *** [vmlinux] Error 1
> make[1]: Leaving directory '/home/jkicinski/devel/linux/build_tmp2'
> Makefile:179: recipe for target 'sub-make' failed
> make: *** [sub-make] Error 2
> 
> Please fix and repost.

Will update to div_u64().

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [v2,net-next] enetc: add support Credit Based Shaper(CBS) for hardware offload
  2019-11-22  7:17 [net-next] enetc: add support Credit Based Shaper(CBS) for hardware offload Po Liu
  2019-11-24  3:02 ` Jakub Kicinski
@ 2019-11-25  5:56 ` Po Liu
  2019-11-25 18:53   ` David Miller
  1 sibling, 1 reply; 6+ messages in thread
From: Po Liu @ 2019-11-25  5:56 UTC (permalink / raw)
  To: davem, linux-kernel, netdev
  Cc: vinicius.gomes, Po Liu, Claudiu Manoil, Vladimir Oltean,
	Alexandru Marginean, Xiaoliang Yang, Roy Zang, Mingkai Hu,
	Jerry Huang, Leo Li, Po Liu

The ENETC hardware support the Credit Based Shaper(CBS) which part
of the IEEE-802.1Qav. The CBS driver was loaded by the sch_cbs
interface when set in the QOS in the kernel.

Here is an example command to set 20Mbits bandwidth in 1Gbits port
for taffic class 7:

tc qdisc add dev eth0 root handle 1: mqprio \
	   num_tc 8 map 0 1 2 3 4 5 6 7 hw 1

tc qdisc replace dev eth0 parent 1:8 cbs \
	   locredit -1470 hicredit 30 \
	   sendslope -980000 idleslope 20000 offload 1

Signed-off-by: Po Liu <Po.Liu@nxp.com>
Reviewed-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
changes:
v2:
- replace with div_u64() for division suggested by Jakub Kicinski.

 drivers/net/ethernet/freescale/enetc/Kconfig  |   4 +-
 drivers/net/ethernet/freescale/enetc/enetc.c  |   2 +
 drivers/net/ethernet/freescale/enetc/enetc.h  |   2 +
 .../net/ethernet/freescale/enetc/enetc_hw.h   |   4 +
 .../net/ethernet/freescale/enetc/enetc_qos.c  | 128 ++++++++++++++++++
 5 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig
index 491659fe3e35..edad4ca46327 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -53,10 +53,10 @@ config FSL_ENETC_HW_TIMESTAMPING
 
 config FSL_ENETC_QOS
 	bool "ENETC hardware Time-sensitive Network support"
-	depends on (FSL_ENETC || FSL_ENETC_VF) && NET_SCH_TAPRIO
+	depends on (FSL_ENETC || FSL_ENETC_VF) && (NET_SCH_TAPRIO || NET_SCH_CBS)
 	help
 	  There are Time-Sensitive Network(TSN) capabilities(802.1Qbv/802.1Qci
 	  /802.1Qbu etc.) supported by ENETC. These TSN capabilities can be set
 	  enable/disable from user space via Qos commands(tc). In the kernel
 	  side, it can be loaded by Qos driver. Currently, it is only support
-	  taprio(802.1Qbv).
+	  taprio(802.1Qbv) and Credit Based Shaper(802.1Qbu).
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 27f6fd1708f0..9db1b96ed9b9 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1496,6 +1496,8 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
 		return enetc_setup_tc_mqprio(ndev, type_data);
 	case TC_SETUP_QDISC_TAPRIO:
 		return enetc_setup_tc_taprio(ndev, type_data);
+	case TC_SETUP_QDISC_CBS:
+		return enetc_setup_tc_cbs(ndev, type_data);
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 89f23156f330..7ee0da6d0015 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -255,7 +255,9 @@ int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
 #ifdef CONFIG_FSL_ENETC_QOS
 int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data);
 void enetc_sched_speed_set(struct net_device *ndev);
+int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data);
 #else
 #define enetc_setup_tc_taprio(ndev, type_data) -EOPNOTSUPP
 #define enetc_sched_speed_set(ndev) (void)0
+#define enetc_setup_tc_cbs(ndev, type_data) -EOPNOTSUPP
 #endif
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
index 924ddb6d358a..51f543ef37a8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
@@ -185,6 +185,8 @@ enum enetc_bdr_type {TX, RX};
 #define ENETC_PSICFGR0_SIVC(bmp)	(((bmp) & 0xff) << 24) /* VLAN_TYPE */
 
 #define ENETC_PTCCBSR0(n)	(0x1110 + (n) * 8) /* n = 0 to 7*/
+#define ENETC_CBSE		BIT(31)
+#define ENETC_CBS_BW_MASK	GENMASK(6, 0)
 #define ENETC_PTCCBSR1(n)	(0x1114 + (n) * 8) /* n = 0 to 7*/
 #define ENETC_RSSHASH_KEY_SIZE	40
 #define ENETC_PRSSK(n)		(0x1410 + (n) * 4) /* n = [0..9] */
@@ -603,6 +605,8 @@ struct enetc_cbd {
 	u8 status_flags;
 };
 
+#define ENETC_CLK  400000000ULL
+
 /* port time gating control register */
 #define ENETC_QBV_PTGCR_OFFSET		0x11a00
 #define ENETC_QBV_TGE			BIT(31)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
index 66a3da61ca16..2e99438cb1bf 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
@@ -4,6 +4,7 @@
 #include "enetc.h"
 
 #include <net/pkt_sched.h>
+#include <linux/math64.h>
 
 static u16 enetc_get_max_gcl_len(struct enetc_hw *hw)
 {
@@ -170,3 +171,130 @@ int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data)
 
 	return err;
 }
+
+static u32 enetc_get_cbs_enable(struct enetc_hw *hw, u8 tc)
+{
+	return enetc_port_rd(hw, ENETC_PTCCBSR0(tc)) & ENETC_CBSE;
+}
+
+static u8 enetc_get_cbs_bw(struct enetc_hw *hw, u8 tc)
+{
+	return enetc_port_rd(hw, ENETC_PTCCBSR0(tc)) & ENETC_CBS_BW_MASK;
+}
+
+int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct tc_cbs_qopt_offload *cbs = type_data;
+	u32 port_transmit_rate = priv->speed;
+	u8 tc_nums = netdev_get_num_tc(ndev);
+	struct enetc_si *si = priv->si;
+	u32 hi_credit_bit, hi_credit_reg;
+	u32 max_interference_size;
+	u32 port_frame_max_size;
+	u32 tc_max_sized_frame;
+	u8 tc = cbs->queue;
+	u8 prio_top, prio_next;
+	int bw_sum = 0;
+	u8 bw;
+
+	prio_top = netdev_get_prio_tc_map(ndev, tc_nums - 1);
+	prio_next = netdev_get_prio_tc_map(ndev, tc_nums - 2);
+
+	/* Support highest prio and second prio tc in cbs mode */
+	if (tc != prio_top && tc != prio_next)
+		return -EOPNOTSUPP;
+
+	if (!cbs->enable) {
+		/* Make sure the other TC that are numerically
+		 * lower than this TC have been disabled.
+		 */
+		if (tc == prio_top &&
+		    enetc_get_cbs_enable(&si->hw, prio_next)) {
+			dev_err(&ndev->dev,
+				"Disable TC%d before disable TC%d\n",
+				prio_next, tc);
+			return -EINVAL;
+		}
+
+		enetc_port_wr(&si->hw, ENETC_PTCCBSR1(tc), 0);
+		enetc_port_wr(&si->hw, ENETC_PTCCBSR0(tc), 0);
+
+		return 0;
+	}
+
+	if (cbs->idleslope - cbs->sendslope != port_transmit_rate * 1000L ||
+	    cbs->idleslope < 0 || cbs->sendslope > 0)
+		return -EOPNOTSUPP;
+
+	port_frame_max_size = ndev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
+
+	bw = cbs->idleslope / (port_transmit_rate * 10UL);
+
+	/* Make sure the other TC that are numerically
+	 * higher than this TC have been enabled.
+	 */
+	if (tc == prio_next) {
+		if (!enetc_get_cbs_enable(&si->hw, prio_top)) {
+			dev_err(&ndev->dev,
+				"Enable TC%d first before enable TC%d\n",
+				prio_top, prio_next);
+			return -EINVAL;
+		}
+		bw_sum += enetc_get_cbs_bw(&si->hw, prio_top);
+	}
+
+	if (bw_sum + bw >= 100) {
+		dev_err(&ndev->dev,
+			"The sum of all CBS Bandwidth can't exceed 100\n");
+		return -EINVAL;
+	}
+
+	tc_max_sized_frame = enetc_port_rd(&si->hw, ENETC_PTCMSDUR(tc));
+
+	/* For top prio TC, the max_interfrence_size is maxSizedFrame.
+	 *
+	 * For next prio TC, the max_interfrence_size is calculated as below:
+	 *
+	 *      max_interference_size = M0 + Ma + Ra * M0 / (R0 - Ra)
+	 *
+	 *	- RA: idleSlope for AVB Class A
+	 *	- R0: port transmit rate
+	 *	- M0: maximum sized frame for the port
+	 *	- MA: maximum sized frame for AVB Class A
+	 */
+
+	if (tc == prio_top) {
+		max_interference_size = port_frame_max_size * 8;
+	} else {
+		u32 m0, ma, r0, ra;
+
+		m0 = port_frame_max_size * 8;
+		ma = enetc_port_rd(&si->hw, ENETC_PTCMSDUR(prio_top)) * 8;
+		ra = enetc_get_cbs_bw(&si->hw, prio_top) *
+			port_transmit_rate * 10000ULL;
+		r0 = port_transmit_rate * 1000000ULL;
+		max_interference_size = m0 + ma +
+			(u32)div_u64((u64)ra * m0, r0 - ra);
+	}
+
+	/* hiCredit bits calculate by:
+	 *
+	 * maxSizedFrame * (idleSlope/portTxRate)
+	 */
+	hi_credit_bit = max_interference_size * bw / 100;
+
+	/* hiCredit bits to hiCredit register need to calculated as:
+	 *
+	 * (enetClockFrequency / portTransmitRate) * 100
+	 */
+	hi_credit_reg = (u32)div_u64((ENETC_CLK * 100ULL) * hi_credit_bit,
+				     port_transmit_rate * 1000000ULL);
+
+	enetc_port_wr(&si->hw, ENETC_PTCCBSR1(tc), hi_credit_reg);
+
+	/* Set bw register and enable this traffic class */
+	enetc_port_wr(&si->hw, ENETC_PTCCBSR0(tc), bw | ENETC_CBSE);
+
+	return 0;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [v2,net-next] enetc: add support Credit Based Shaper(CBS) for hardware offload
  2019-11-25  5:56 ` [v2,net-next] " Po Liu
@ 2019-11-25 18:53   ` David Miller
  0 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2019-11-25 18:53 UTC (permalink / raw)
  To: po.liu
  Cc: linux-kernel, netdev, vinicius.gomes, claudiu.manoil,
	vladimir.oltean, alexandru.marginean, xiaoliang.yang_1, roy.zang,
	mingkai.hu, jerry.huang, leoyang.li

From: Po Liu <po.liu@nxp.com>
Date: Mon, 25 Nov 2019 05:56:56 +0000

> The ENETC hardware support the Credit Based Shaper(CBS) which part
> of the IEEE-802.1Qav. The CBS driver was loaded by the sch_cbs
> interface when set in the QOS in the kernel.
> 
> Here is an example command to set 20Mbits bandwidth in 1Gbits port
> for taffic class 7:
> 
> tc qdisc add dev eth0 root handle 1: mqprio \
> 	   num_tc 8 map 0 1 2 3 4 5 6 7 hw 1
> 
> tc qdisc replace dev eth0 parent 1:8 cbs \
> 	   locredit -1470 hicredit 30 \
> 	   sendslope -980000 idleslope 20000 offload 1
> 
> Signed-off-by: Po Liu <Po.Liu@nxp.com>
> Reviewed-by: Claudiu Manoil <claudiu.manoil@nxp.com>
> Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>

Applied, thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-11-25 18:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-22  7:17 [net-next] enetc: add support Credit Based Shaper(CBS) for hardware offload Po Liu
2019-11-24  3:02 ` Jakub Kicinski
2019-11-24 23:34   ` Jakub Kicinski
2019-11-25  3:03     ` [EXT] " Po Liu
2019-11-25  5:56 ` [v2,net-next] " Po Liu
2019-11-25 18:53   ` David Miller

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).