From patchwork Fri Nov 26 11:20:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 12640405 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60337C433FE for ; Fri, 26 Nov 2021 11:23:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346423AbhKZL0R (ORCPT ); Fri, 26 Nov 2021 06:26:17 -0500 Received: from relay11.mail.gandi.net ([217.70.178.231]:57147 "EHLO relay11.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239120AbhKZLYQ (ORCPT ); Fri, 26 Nov 2021 06:24:16 -0500 Received: (Authenticated sender: maxime.chevallier@bootlin.com) by relay11.mail.gandi.net (Postfix) with ESMTPSA id D3A5810000D; Fri, 26 Nov 2021 11:21:01 +0000 (UTC) From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, gregory.clement@bootlin.com, Andrew Lunn , =?utf-8?q?Pali_R?= =?utf-8?q?oh=C3=A1r?= , Jakub Kicinski Subject: [PATCH net-next v2 1/4] net: mvneta: Use struct tc_mqprio_qopt_offload for MQPrio configuration Date: Fri, 26 Nov 2021 12:20:53 +0100 Message-Id: <20211126112056.849123-2-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20211126112056.849123-1-maxime.chevallier@bootlin.com> References: <20211126112056.849123-1-maxime.chevallier@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org The struct tc_mqprio_qopt_offload is a container for struct tc_mqprio_qopt, that allows passing extra parameters, such as traffic shaping. This commit converts the current mqprio code to that new struct. Signed-off-by: Maxime Chevallier --- V2 : No changes drivers/net/ethernet/marvell/mvneta.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 80e4b500695e..46b7604805f7 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -38,6 +38,7 @@ #include #include #include +#include #include /* Registers */ @@ -4908,14 +4909,14 @@ static void mvneta_setup_rx_prio_map(struct mvneta_port *pp) } static int mvneta_setup_mqprio(struct net_device *dev, - struct tc_mqprio_qopt *qopt) + struct tc_mqprio_qopt_offload *mqprio) { struct mvneta_port *pp = netdev_priv(dev); u8 num_tc; int i; - qopt->hw = TC_MQPRIO_HW_OFFLOAD_TCS; - num_tc = qopt->num_tc; + mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS; + num_tc = mqprio->qopt.num_tc; if (num_tc > rxq_number) return -EINVAL; @@ -4926,13 +4927,15 @@ static int mvneta_setup_mqprio(struct net_device *dev, return 0; } - memcpy(pp->prio_tc_map, qopt->prio_tc_map, sizeof(pp->prio_tc_map)); + memcpy(pp->prio_tc_map, mqprio->qopt.prio_tc_map, + sizeof(pp->prio_tc_map)); mvneta_setup_rx_prio_map(pp); - netdev_set_num_tc(dev, qopt->num_tc); - for (i = 0; i < qopt->num_tc; i++) - netdev_set_tc_queue(dev, i, qopt->count[i], qopt->offset[i]); + netdev_set_num_tc(dev, mqprio->qopt.num_tc); + for (i = 0; i < mqprio->qopt.num_tc; i++) + netdev_set_tc_queue(dev, i, mqprio->qopt.count[i], + mqprio->qopt.offset[i]); return 0; } From patchwork Fri Nov 26 11:20:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 12640409 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2E73C4332F for ; Fri, 26 Nov 2021 11:23:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347081AbhKZL0U (ORCPT ); Fri, 26 Nov 2021 06:26:20 -0500 Received: from relay11.mail.gandi.net ([217.70.178.231]:48135 "EHLO relay11.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239194AbhKZLYR (ORCPT ); Fri, 26 Nov 2021 06:24:17 -0500 Received: (Authenticated sender: maxime.chevallier@bootlin.com) by relay11.mail.gandi.net (Postfix) with ESMTPSA id E1CD6100013; Fri, 26 Nov 2021 11:21:02 +0000 (UTC) From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, gregory.clement@bootlin.com, Andrew Lunn , =?utf-8?q?Pali_R?= =?utf-8?q?oh=C3=A1r?= , Jakub Kicinski Subject: [PATCH net-next v2 2/4] net: mvneta: Don't force-set the offloading flag Date: Fri, 26 Nov 2021 12:20:54 +0100 Message-Id: <20211126112056.849123-3-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20211126112056.849123-1-maxime.chevallier@bootlin.com> References: <20211126112056.849123-1-maxime.chevallier@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org The qopt->hw flag is set by the TC code according to the offloading mode asked by user. Don't force-set it in the driver, but instead read it to make sure we do what's asked. Signed-off-by: Maxime Chevallier --- V2 : No changes drivers/net/ethernet/marvell/mvneta.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 46b7604805f7..d3ce87e69d2a 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -4915,7 +4915,9 @@ static int mvneta_setup_mqprio(struct net_device *dev, u8 num_tc; int i; - mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS; + if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) + return 0; + num_tc = mqprio->qopt.num_tc; if (num_tc > rxq_number) From patchwork Fri Nov 26 11:20:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 12640407 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7D04FC433F5 for ; Fri, 26 Nov 2021 11:23:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346725AbhKZL0T (ORCPT ); Fri, 26 Nov 2021 06:26:19 -0500 Received: from relay11.mail.gandi.net ([217.70.178.231]:60257 "EHLO relay11.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239198AbhKZLYT (ORCPT ); Fri, 26 Nov 2021 06:24:19 -0500 Received: (Authenticated sender: maxime.chevallier@bootlin.com) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 70D83100005; Fri, 26 Nov 2021 11:21:04 +0000 (UTC) From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, gregory.clement@bootlin.com, Andrew Lunn , =?utf-8?q?Pali_R?= =?utf-8?q?oh=C3=A1r?= , Jakub Kicinski Subject: [PATCH net-next v2 3/4] net: mvneta: Allow having more than one queue per TC Date: Fri, 26 Nov 2021 12:20:55 +0100 Message-Id: <20211126112056.849123-4-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20211126112056.849123-1-maxime.chevallier@bootlin.com> References: <20211126112056.849123-1-maxime.chevallier@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org The current mqprio implementation assumed that we are only using one queue per TC. Use the offset and count parameters to allow using multiple queues per TC. In that case, the controller will use a standard round-robin algorithm to pick queues assigned to the same TC, with the same priority. This only applies to VLAN priorities in ingress traffic, each TC corresponding to a vlan priority. Signed-off-by: Maxime Chevallier --- V2 : No changes drivers/net/ethernet/marvell/mvneta.c | 35 +++++++++++++++------------ 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index d3ce87e69d2a..aba452e8abfe 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -493,7 +493,6 @@ struct mvneta_port { u8 mcast_count[256]; u16 tx_ring_size; u16 rx_ring_size; - u8 prio_tc_map[8]; phy_interface_t phy_interface; struct device_node *dn; @@ -4897,13 +4896,12 @@ static void mvneta_clear_rx_prio_map(struct mvneta_port *pp) mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, 0); } -static void mvneta_setup_rx_prio_map(struct mvneta_port *pp) +static void mvneta_map_vlan_prio_to_rxq(struct mvneta_port *pp, u8 pri, u8 rxq) { - u32 val = 0; - int i; + u32 val = mvreg_read(pp, MVNETA_VLAN_PRIO_TO_RXQ); - for (i = 0; i < rxq_number; i++) - val |= MVNETA_VLAN_PRIO_RXQ_MAP(i, pp->prio_tc_map[i]); + val &= ~MVNETA_VLAN_PRIO_RXQ_MAP(pri, 0x7); + val |= MVNETA_VLAN_PRIO_RXQ_MAP(pri, rxq); mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, val); } @@ -4912,8 +4910,8 @@ static int mvneta_setup_mqprio(struct net_device *dev, struct tc_mqprio_qopt_offload *mqprio) { struct mvneta_port *pp = netdev_priv(dev); + int rxq, tc; u8 num_tc; - int i; if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) return 0; @@ -4923,21 +4921,28 @@ static int mvneta_setup_mqprio(struct net_device *dev, if (num_tc > rxq_number) return -EINVAL; + mvneta_clear_rx_prio_map(pp); + if (!num_tc) { - mvneta_clear_rx_prio_map(pp); netdev_reset_tc(dev); return 0; } - memcpy(pp->prio_tc_map, mqprio->qopt.prio_tc_map, - sizeof(pp->prio_tc_map)); + netdev_set_num_tc(dev, mqprio->qopt.num_tc); + + for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { + netdev_set_tc_queue(dev, tc, mqprio->qopt.count[tc], + mqprio->qopt.offset[tc]); - mvneta_setup_rx_prio_map(pp); + for (rxq = mqprio->qopt.offset[tc]; + rxq < mqprio->qopt.count[tc] + mqprio->qopt.offset[tc]; + rxq++) { + if (rxq >= rxq_number) + return -EINVAL; - netdev_set_num_tc(dev, mqprio->qopt.num_tc); - for (i = 0; i < mqprio->qopt.num_tc; i++) - netdev_set_tc_queue(dev, i, mqprio->qopt.count[i], - mqprio->qopt.offset[i]); + mvneta_map_vlan_prio_to_rxq(pp, tc, rxq); + } + } return 0; } From patchwork Fri Nov 26 11:20:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Chevallier X-Patchwork-Id: 12640411 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54A0EC433F5 for ; Fri, 26 Nov 2021 11:23:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347495AbhKZL0X (ORCPT ); Fri, 26 Nov 2021 06:26:23 -0500 Received: from relay11.mail.gandi.net ([217.70.178.231]:52681 "EHLO relay11.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239294AbhKZLYU (ORCPT ); Fri, 26 Nov 2021 06:24:20 -0500 Received: (Authenticated sender: maxime.chevallier@bootlin.com) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 7D602100017; Fri, 26 Nov 2021 11:21:05 +0000 (UTC) From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, gregory.clement@bootlin.com, Andrew Lunn , =?utf-8?q?Pali_R?= =?utf-8?q?oh=C3=A1r?= , Jakub Kicinski Subject: [PATCH net-next v2 4/4] net: mvneta: Add TC traffic shaping offload Date: Fri, 26 Nov 2021 12:20:56 +0100 Message-Id: <20211126112056.849123-5-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20211126112056.849123-1-maxime.chevallier@bootlin.com> References: <20211126112056.849123-1-maxime.chevallier@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org The mvneta controller is able to do some tocken-bucket per-queue traffic shaping. This commit adds support for setting these using the TC mqprio interface. The token-bucket parameters are customisable, but the current implementation configures them to have a 10kbps resolution for the rate limitation, since it allows to cover the whole range of max_rate values from 10kbps to 5Gbps with 10kbps increments. Signed-off-by: Maxime Chevallier --- V2 : Use div_u64_rem for u64 division, as suggested by Jakub. It also allowed to simplify the code a little bit. drivers/net/ethernet/marvell/mvneta.c | 120 +++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index aba452e8abfe..2368ae3f0e10 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -248,12 +248,39 @@ #define MVNETA_TXQ_SENT_DESC_MASK 0x3fff0000 #define MVNETA_PORT_TX_RESET 0x3cf0 #define MVNETA_PORT_TX_DMA_RESET BIT(0) +#define MVNETA_TXQ_CMD1_REG 0x3e00 +#define MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 BIT(3) +#define MVNETA_TXQ_CMD1_BW_LIM_EN BIT(0) +#define MVNETA_REFILL_NUM_CLK_REG 0x3e08 +#define MVNETA_REFILL_MAX_NUM_CLK 0x0000ffff #define MVNETA_TX_MTU 0x3e0c #define MVNETA_TX_TOKEN_SIZE 0x3e14 #define MVNETA_TX_TOKEN_SIZE_MAX 0xffffffff +#define MVNETA_TXQ_BUCKET_REFILL_REG(q) (0x3e20 + ((q) << 2)) +#define MVNETA_TXQ_BUCKET_REFILL_PERIOD_MASK 0x3ff00000 +#define MVNETA_TXQ_BUCKET_REFILL_PERIOD_SHIFT 20 +#define MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX 0x0007ffff #define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2)) #define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff +/* The values of the bucket refill base period and refill period are taken from + * the reference manual, and adds up to a base resolution of 10Kbps. This allows + * to cover all rate-limit values from 10Kbps up to 5Gbps + */ + +/* Base period for the rate limit algorithm */ +#define MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS 100 + +/* Number of Base Period to wait between each bucket refill */ +#define MVNETA_TXQ_BUCKET_REFILL_PERIOD 1000 + +/* The base resolution for rate limiting, in bps. Any max_rate value should be + * a multiple of that value. + */ +#define MVNETA_TXQ_RATE_LIMIT_RESOLUTION (NSEC_PER_SEC / \ + (MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS * \ + MVNETA_TXQ_BUCKET_REFILL_PERIOD)) + #define MVNETA_LPI_CTRL_0 0x2cc0 #define MVNETA_LPI_CTRL_1 0x2cc4 #define MVNETA_LPI_REQUEST_ENABLE BIT(0) @@ -4906,11 +4933,74 @@ static void mvneta_map_vlan_prio_to_rxq(struct mvneta_port *pp, u8 pri, u8 rxq) mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, val); } +static int mvneta_enable_per_queue_rate_limit(struct mvneta_port *pp) +{ + unsigned long core_clk_rate; + u32 refill_cycles; + u32 val; + + core_clk_rate = clk_get_rate(pp->clk); + if (!core_clk_rate) + return -EINVAL; + + refill_cycles = MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS / + (NSEC_PER_SEC / core_clk_rate); + + if (refill_cycles > MVNETA_REFILL_MAX_NUM_CLK) + return -EINVAL; + + /* Enable bw limit algorithm version 3 */ + val = mvreg_read(pp, MVNETA_TXQ_CMD1_REG); + val &= ~(MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 | MVNETA_TXQ_CMD1_BW_LIM_EN); + mvreg_write(pp, MVNETA_TXQ_CMD1_REG, val); + + /* Set the base refill rate */ + mvreg_write(pp, MVNETA_REFILL_NUM_CLK_REG, refill_cycles); + + return 0; +} + +static void mvneta_disable_per_queue_rate_limit(struct mvneta_port *pp) +{ + u32 val = mvreg_read(pp, MVNETA_TXQ_CMD1_REG); + + val |= (MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 | MVNETA_TXQ_CMD1_BW_LIM_EN); + mvreg_write(pp, MVNETA_TXQ_CMD1_REG, val); +} + +static int mvneta_setup_queue_rates(struct mvneta_port *pp, int queue, + u64 min_rate, u64 max_rate) +{ + u32 refill_val, rem; + u32 val = 0; + + /* Convert to from Bps to bps */ + max_rate *= 8; + + if (min_rate) + return -EINVAL; + + refill_val = div_u64_rem(max_rate, MVNETA_TXQ_RATE_LIMIT_RESOLUTION, + &rem); + + if (rem || !refill_val || + refill_val > MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX) + return -EINVAL; + + val = refill_val; + val |= (MVNETA_TXQ_BUCKET_REFILL_PERIOD << + MVNETA_TXQ_BUCKET_REFILL_PERIOD_SHIFT); + + mvreg_write(pp, MVNETA_TXQ_BUCKET_REFILL_REG(queue), val); + + return 0; +} + static int mvneta_setup_mqprio(struct net_device *dev, struct tc_mqprio_qopt_offload *mqprio) { struct mvneta_port *pp = netdev_priv(dev); - int rxq, tc; + int rxq, txq, tc, ret; u8 num_tc; if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) @@ -4924,6 +5014,7 @@ static int mvneta_setup_mqprio(struct net_device *dev, mvneta_clear_rx_prio_map(pp); if (!num_tc) { + mvneta_disable_per_queue_rate_limit(pp); netdev_reset_tc(dev); return 0; } @@ -4944,6 +5035,33 @@ static int mvneta_setup_mqprio(struct net_device *dev, } } + if (mqprio->shaper != TC_MQPRIO_SHAPER_BW_RATE) { + mvneta_disable_per_queue_rate_limit(pp); + return 0; + } + + if (mqprio->qopt.num_tc > txq_number) + return -EINVAL; + + ret = mvneta_enable_per_queue_rate_limit(pp); + if (ret) + return ret; + + for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { + for (txq = mqprio->qopt.offset[tc]; + txq < mqprio->qopt.count[tc] + mqprio->qopt.offset[tc]; + txq++) { + if (txq >= txq_number) + return -EINVAL; + + ret = mvneta_setup_queue_rates(pp, txq, + mqprio->min_rate[tc], + mqprio->max_rate[tc]); + if (ret) + return ret; + } + } + return 0; }