BPF List
 help / color / mirror / Atom feed
From: Jakub Kicinski <kuba@kernel.org>
To: Ratheesh Kannoth <rkannoth@marvell.com>
Cc: <bpf@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<netdev@vger.kernel.org>, <andrew+netdev@lunn.ch>,
	<ast@kernel.org>, <daniel@iogearbox.net>, <davem@davemloft.net>,
	<edumazet@kernel.org>, <hawk@kernel.org>,
	<john.fastabend@gmail.com>, <pabeni@redhat.com>,
	<sdf@fomichev.me>, <sgoutham@marvell.com>,
	Simon Horman <horms@kernel.org>
Subject: Re: [PATCH v21 net-next 2/2] octeontx2: add mqprio bandwidth offload for NIX TX schedulers
Date: Fri, 13 Nov 2026 18:42:02 -0800	[thread overview]
Message-ID: <20261113184202.678ed2f7@kernel.org> (raw)
In-Reply-To: <20261109033154.2161803-3-rkannoth@marvell.com>

On Mon, 9 Nov 2026 09:01:53 +0530 Ratheesh Kannoth wrote:
> Add TC_SETUP_QDISC_MQPRIO offload with TC_MQPRIO_SHAPER_BW_RATE on PF and
> VF netdevs. Program per-queue MDQ CIR/PIR via the NIX TX scheduler mailbox;
> when active, allocate one SMQ per non-QoS queue under TL4[0].
> 
> The TX scheduler cannot be reprogrammed live, so add/replace/delete and
> failed setup bounce the netdev through ndo_stop()/ndo_open(). Cache rates
> in software and restore them from otx2_mqprio_up() on open, failing closed
> on error.
> 
> Stage tc replace in mq_offload_snap snapshots committed on TC_ROOT_GRAFT or
> replaced-qdisc teardown.
> 
> Require a running interface with CIR+PIR support. Reject offload with PFC,
> XDP, HTB, SDP representors, per-TC rates on multi-queue classes, and
> ethtool channel changes while active.
> 
> Reviewed-by: Simon Horman <horms@kernel.org>
> Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
> ---
>  .../marvell/octeontx2/nic/otx2_common.c       | 143 ++-
>  .../marvell/octeontx2/nic/otx2_common.h       |  34 +
>  .../marvell/octeontx2/nic/otx2_dcbnl.c        |   6 +
>  .../marvell/octeontx2/nic/otx2_ethtool.c      |   8 +
>  .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  34 +-
>  .../ethernet/marvell/octeontx2/nic/otx2_tc.c  | 936 ++++++++++++++++++
>  .../ethernet/marvell/octeontx2/nic/otx2_vf.c  |  28 +-
>  .../net/ethernet/marvell/octeontx2/nic/qos.c  |  11 +
>  8 files changed, 1179 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
> index f4047b0d5d96..b4a738cf9a8b 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
> @@ -615,6 +615,139 @@ void otx2_get_mac_from_af(struct net_device *netdev)
>  }
>  EXPORT_SYMBOL(otx2_get_mac_from_af);
>  
> +static int
> +otx2_nix_tmq_reg_write(struct otx2_nic *pfvf, int cnt,
> +		       u64 reg_addr[MAX_REGS_PER_MBOX_MSG],
> +		       u64 reg_val[MAX_REGS_PER_MBOX_MSG])
> +{
> +	struct mbox *mbox = &pfvf->mbox;
> +	struct nix_txschq_config *req;
> +	int i, err;
> +
> +	mutex_lock(&mbox->lock);
> +	req = otx2_mbox_alloc_msg_nix_txschq_cfg(mbox);
> +	if (!req) {
> +		mutex_unlock(&mbox->lock);
> +		return -ENOMEM;
> +	}
> +
> +	req->lvl = NIX_TXSCH_LVL_MDQ;
> +	req->num_regs = cnt;
> +
> +	for (i = 0; i < cnt; i++) {
> +		req->reg[i] = reg_addr[i];
> +		req->regval[i] = reg_val[i];
> +	}
> +
> +	err = otx2_sync_mbox_msg(mbox);
> +	mutex_unlock(&mbox->lock);
> +
> +	return err;
> +}
> +
> +int otx2_nix_tm_clear_queue_shaper(struct otx2_nic *pfvf)
> +{
> +	u64 reg_addr[MAX_REGS_PER_MBOX_MSG];
> +	u64 reg_val[MAX_REGS_PER_MBOX_MSG];
> +	int err, smq, i, cnt = 0;
> +
> +	for (i = 0; i < pfvf->hw.txschq_cnt[NIX_TXSCH_LVL_SMQ]; i++) {
> +		smq = pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][i];
> +
> +		reg_addr[cnt] = NIX_AF_MDQX_PIR(smq);
> +		reg_val[cnt] = 0;
> +		cnt++;
> +
> +		reg_addr[cnt] = NIX_AF_MDQX_CIR(smq);
> +		reg_val[cnt] = 0;
> +		cnt++;
> +
> +		if (cnt < MAX_REGS_PER_MBOX_MSG - 1)
> +			continue;
> +
> +		err = otx2_nix_tmq_reg_write(pfvf, cnt,
> +					     reg_addr, reg_val);
> +		if (err)
> +			goto fail;
> +		cnt = 0;
> +	}
> +
> +	if (cnt) {
> +		err = otx2_nix_tmq_reg_write(pfvf, cnt,
> +					     reg_addr, reg_val);
> +		if (err)
> +			goto fail;
> +	}
> +
> +	return 0;
> +fail:
> +	return err;

just return err; why the label ?


> +struct mq_offload_snap {
> +	u64 min_rate[TC_QOPT_MAX_QUEUE];
> +	u64 max_rate[TC_QOPT_MAX_QUEUE];
> +	u32 flags;
> +	__u8 num_tc;
> +	__u16 count[TC_QOPT_MAX_QUEUE];
> +	__u16 offset[TC_QOPT_MAX_QUEUE];
> +	__u8 prio_tc_map[TC_QOPT_BITMASK + 1];

Why is this using __u types?

> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
> index 4fe473d9ea0d..5428b3d1b332 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
> @@ -287,6 +287,14 @@ static int otx2_set_channels(struct net_device *dev,
>  		return -EINVAL;
>  	}
>  
> +	if (pfvf->mqprio.rate_limit &&
> +	    (channel->tx_count != pfvf->hw.tx_queues ||
> +	     channel->rx_count != pfvf->hw.rx_queues)) {
> +		netdev_info(dev,
> +			    "Not permitted to change channel count while MQ prio is active\n");

Why? This seems quite limiting.
User has to remove the root qdisc to change the queue count?

> +		return -EINVAL;
> +	}
> +
>  	if (if_up)
>  		dev->netdev_ops->ndo_stop(dev);

> +	if (prog && pf->mqprio.rate_limit) {
> +		netdev_err(dev,
> +			   "XDP: cannot attach while mqprio bandwidth offload is active\n");

Again - why?

> +		return -EOPNOTSUPP;
> +	}
> +
>  	if (prog && dev->mtu > MAX_XDP_MTU) {
>  		netdev_warn(dev, "Jumbo frames not yet supported with XDP\n");
>  		return -EOPNOTSUPP;

> +static void otx2_mqprio_free_cache(struct otx2_nic *pfvf)
> +{
> +	devm_kfree(pfvf->dev, pfvf->mqprio.min_rate);
> +	devm_kfree(pfvf->dev, pfvf->mqprio.max_rate);

devm_kfree() is a red flag, either this is something tied to the
lifetime of the driver, or you need to clean this up. Saying that
something "doesn't leak because it was devm_kmalloc()ed" is invalid.
Drivers don't get re-probed in real life, memory parked in devm_ is 
as bad as leaked.

> +static int otx2_mqprio_restart_netdev(struct net_device *netdev, bool rate_limit)
> +{
> +	struct otx2_nic *pfvf = netdev_priv(netdev);
> +	const struct net_device_ops *ops = netdev->netdev_ops;
> +	bool running = netif_running(netdev);
> +	int err;
> +
> +	/* TODO: Explore live TX scheduler reprogramming to avoid a full
> +	 * ndo_stop()/ndo_open() bounce on every mqprio change.
> +	 */
> +	netdev_dbg(netdev,
> +		   "mqprio: restarting interface to reprogram TX scheduler\n");
> +
> +	if (running) {
> +		clear_bit(__LINK_STATE_START, &netdev->state);

Messing with internal netdev state like this from the driver is
obviously unacceptable.

> +		smp_mb__after_atomic(); /* Commit netif_running(). */
> +	}

> +	/* TODO: per-TC TL4 shapers or equal per-queue MDQ split for multi-queue TC rates. */
> +	netdev_err(netdev,
> +		   "mqprio: %s rate for tc %d not supported with %u queues\n",
> +		   name, tc, qcount);
> +	NL_SET_ERR_MSG_FMT_MOD(extack,
> +			       "mqprio: tc %d rate needs 1 queue (has %u)",
> +			       tc, qcount);

Doubling out output to extack and dmesg is not okay, user space should
look at the extack. And a decade after it was added it mostly does.

You are at v21 this is nowhere near the acceptable quality. You should
probably give up.

      parent reply	other threads:[~2026-11-14  2:42 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09  3:31 [PATCH v21 net-next 0/2] octeontx2: mqprio bandwidth offload for NIX TX schedulers Ratheesh Kannoth
2026-11-09  3:31 ` [PATCH v21 net-next 1/2] octeontx2: use atomic bitops for PF/VF and rep flags Ratheesh Kannoth
2026-11-10  3:33   ` sashiko-bot
2026-11-11 21:32   ` netdev-bot+sashiko
2026-11-12  1:56     ` Ratheesh Kannoth
2026-11-09  3:31 ` [PATCH v21 net-next 2/2] octeontx2: add mqprio bandwidth offload for NIX TX schedulers Ratheesh Kannoth
2026-11-10  3:33   ` sashiko-bot
2026-11-11 21:32   ` netdev-bot+sashiko
2026-11-12  1:55     ` Ratheesh Kannoth
2026-11-14  2:42   ` Jakub Kicinski [this message]

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=20261113184202.678ed2f7@kernel.org \
    --to=kuba@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=edumazet@kernel.org \
    --cc=hawk@kernel.org \
    --cc=horms@kernel.org \
    --cc=john.fastabend@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=rkannoth@marvell.com \
    --cc=sdf@fomichev.me \
    --cc=sgoutham@marvell.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