From nobody Mon Feb 9 06:25:23 2026 Received: from mail-pf1-f175.google.com (mail-pf1-f175.google.com [209.85.210.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8FB1B37E2E6 for ; Thu, 29 Jan 2026 08:53:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769676818; cv=none; b=Trc0B6Yd3z8N4C/g9g1MqJOHA4aDDCBtVgXS6WL4h5ZUm7vXXV9bRZewn1PSLsPbNOOjiRPg+8Z1PNrwjcV82Hb0WOz7PoxxXYStKceBFzwYLthyIjdUzvn7yZwrfIlHFRFSBSBA0MeXpioUf89vB1gQhf9R/k+DWomAqKSD7lI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769676818; c=relaxed/simple; bh=J8x+gpWIU4xPWLJUL20SP6uxFJQBFf53d6giQxdUFVo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IALALF0FYbKngoGmWWlwxPJ3QLfcOvgqp4x4pW8l1snInAyDf1p57lwRxAm2VyzAwcyeCxgH/JpkU4oKjmbqVuqPtquQaCCEaCastI3sievRXcNS0vVcfVXjsq7Bs82rtDSZ3O8PShSIOjpBVun1WGfurrzJsUsMkJvr72FtODg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Icpxbqc2; arc=none smtp.client-ip=209.85.210.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Icpxbqc2" Received: by mail-pf1-f175.google.com with SMTP id d2e1a72fcca58-81dbc0a99d2so360038b3a.1 for ; Thu, 29 Jan 2026 00:53:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769676813; x=1770281613; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=l+eQCaJasdwise2KMZcUhrqlyiXBHdQjhfaNW7h8jho=; b=Icpxbqc2Q8ePEr0/fj6DVbuXllHl7XEJRXgsLopjLKvIwaRRC+qXQRPaoW195Oi/ax JJ3hXT+QrAr69ET3L3umGFnHodaEr+DNbTnPmBMNNBeV8Jlb86wHmx/t27Ey79mpVuRx yfzvMYM0Rw8CiwcJWUXXWGA3rW9nVx5sR4yoj9w/QEzyf532Kn5Xgk7D6/dNKGqYHoxZ tTJlEdIUHFjGjfuUVMAqSqVhfMpsL0IYs2wevC3hFIOyxqf2qw+ADhJUVFbgFDdspVkk GH6nykv1tXKu+j03EMpaxQyDoIBcUcwuHZtNQPx8IM/k6Baf8FYMaeMGQPP7ZdLahvWV WPyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769676813; x=1770281613; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=l+eQCaJasdwise2KMZcUhrqlyiXBHdQjhfaNW7h8jho=; b=Y/wKdRm3z1VMOEHNZ1Zj/q/7LQ/wHpcig0yRWOH+Z77KKJ6WXLXe9HD04zmE+OSw81 +5NkwhHAXn5UwbSBp0+NUsK9NEcyCAQwLBabw/cT0Qnq2AIFbPE6wfB9eDPBGvDu3sjZ qsuNvvtZfAavsioUltokh031DtgxPsPLjBeFeI/2WJDs/7cBuLYqdIBcAPLNW+XL4cHM pJOiCgvNMyWVNkGfKolcNTDG9orFs8glaVes2TwbFENxxxJXfKfK/oG1cMulR0G0EYwe L77vEmHFTMI3nqyX1VXESFjH8xenbrbImCV0GC3Yx8eK3Itio3aXhwmobdSYTjj2KKw1 KhCQ== X-Forwarded-Encrypted: i=1; AJvYcCUW/peDsiR6YJSHuS2hPxU/w/vzgrXno30p2mlheX2BfJOgRbSNju9uWH0WOP3ue/RvdYJR5NKymEWQo+Q=@vger.kernel.org X-Gm-Message-State: AOJu0Yzav8uOLaRddcfJLJpTt4Emf9iIqCIgoXQarCAIEUyR4WF5tgpO BE8Zg+uHOT6I8gkfWajt9NUP6xw5RFcbhXck2197L7WSMyUgjzxVXMpzq/W2RTT6 X-Gm-Gg: AZuq6aIOi9GCbhDCZFI8xMfc+aEdy2d4ncYf+idHUg8kH8CPbtbnksrWATcfVD6ipI4 +VkceqZkQ/AJZiOiyPymQnM6M3tI3t0xaGPoEzmwqzlrmsjY7Kws4ui04daaHo5AJAq7839d+59 9u0o/fsYGZmfCzFDN5IiDaNoM+8JkBfu92pip3B3IWx/ch2cUHk/jnLoSMI0phdtUIQSx83cEPs r8svOjj65Sq9ZVGsTFLPZ2c7I2t4WsSsyglfAxYG0oYPugGG/s2qS4gjwewJ77fHM1Y7J3Z1KYE wTMoN4ysfF8IzbAy9kXKMAoXMSz8H2+mHVj7CsvI1K41dhB8nr5kczoUxEvDDoE1NFnx/33DHCD anQLdqVcI+o1NDk8cxoZZAde9pDrBfcJ/iWW++hLVzU1Qllm1tUhYyQ68rLe3zd7M45GzGMFx+N b7lrwxvEi1KyA8Qu8uWIUzuSXAbhTXZuCLTKpRU7vZUbSgEA== X-Received: by 2002:a05:6a21:62c1:b0:387:5ded:994a with SMTP id adf61e73a8af0-38ec657e4d6mr6127625637.60.1769676813248; Thu, 29 Jan 2026 00:53:33 -0800 (PST) Received: from d.home.mmyangfl.tk ([2a09:bac1:7680:d30::4:384]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2a88b3eef50sm44651165ad.12.2026.01.29.00.53.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Jan 2026 00:53:33 -0800 (PST) From: David Yang To: netdev@vger.kernel.org Cc: David Yang , Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , linux-kernel@vger.kernel.org Subject: [RFC net-next 4/4] net: dsa: yt921x: Add port qdisc tbf support Date: Thu, 29 Jan 2026 16:51:36 +0800 Message-ID: <20260129085139.2767649-5-mmyangfl@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260129085139.2767649-1-mmyangfl@gmail.com> References: <20260129085139.2767649-1-mmyangfl@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Enable port shaping and support limiting the rate of outgoing traffic. Signed-off-by: David Yang --- drivers/net/dsa/yt921x.c | 113 +++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/yt921x.h | 18 +++++++ 2 files changed, 131 insertions(+) diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c index f1465c4d9b1b..dd279f1db837 100644 --- a/drivers/net/dsa/yt921x.c +++ b/drivers/net/dsa/yt921x.c @@ -24,6 +24,7 @@ #include #include #include +#include =20 #include "yt921x.h" =20 @@ -1291,6 +1292,110 @@ yt921x_dsa_port_policer_add(struct dsa_switch *ds, = int port, return res; } =20 +static int +yt921x_tbf_validate(struct yt921x_priv *priv, + const struct tc_tbf_qopt_offload *qopt, int *queuep) +{ + struct device *dev =3D to_device(priv); + int queue =3D -1; + + if (qopt->parent !=3D TC_H_ROOT) { + dev_err(dev, "Parent should be \"root\"\n"); + return -EOPNOTSUPP; + } + + switch (qopt->command) { + case TC_TBF_REPLACE: { + const struct tc_tbf_qopt_offload_replace_params *p; + + p =3D &qopt->replace_params; + + if (!p->rate.mpu) { + dev_info(dev, "Assuming you want mpu =3D 64\n"); + } else if (p->rate.mpu !=3D 64) { + dev_err(dev, "mpu other than 64 not supported\n"); + return -EINVAL; + } + } + default: + break; + } + + *queuep =3D queue; + return 0; +} + +static int +yt921x_dsa_port_setup_tc_tbf_port(struct dsa_switch *ds, int port, + const struct tc_tbf_qopt_offload *qopt) +{ + struct yt921x_priv *priv =3D to_yt921x_priv(ds); + u32 ctrls[YT921X_PORT_SHAPE_CTRL_S]; + int res; + + switch (qopt->command) { + case TC_TBF_DESTROY: + ctrls[0] =3D 0; + ctrls[1] =3D 0; + break; + case TC_TBF_REPLACE: { + const struct tc_tbf_qopt_offload_replace_params *p; + struct yt921x_meter meter; + u64 burst; + + p =3D &qopt->replace_params; + + /* where is burst??? */ + burst =3D priv->port_shape_slot_ns * p->rate.rate_bytes_ps / + 1000000000 + 10000; + meter =3D yt921x_meter_tfm(priv, port, priv->port_shape_slot_ns, + p->rate.rate_bytes_ps, burst, + YT921X_METER_SINGLE_BUCKET, + YT921X_SHAPE_RATE_MAX, + YT921X_SHAPE_BURST_MAX, + YT921X_SHAPE_UNIT_MAX); + + ctrls[0] =3D YT921X_PORT_SHAPE_CTRLa_CIR(meter.cir) | + YT921X_PORT_SHAPE_CTRLa_CBS(meter.cbs); + ctrls[1] =3D YT921X_PORT_SHAPE_CTRLb_UNIT(meter.unit) | + YT921X_PORT_SHAPE_CTRLb_EN; + break; + } + default: + return -EOPNOTSUPP; + } + + mutex_lock(&priv->reg_lock); + res =3D yt921x_longreg_write(priv, YT921X_PORTn_SHAPE_CTRL(port), + ctrls, YT921X_PORT_SHAPE_CTRL_S); + mutex_unlock(&priv->reg_lock); + + return res; +} + +static int +yt921x_dsa_port_setup_tc(struct dsa_switch *ds, int port, + enum tc_setup_type type, void *type_data) +{ + struct yt921x_priv *priv =3D to_yt921x_priv(ds); + int res; + + switch (type) { + case TC_SETUP_QDISC_TBF: { + const struct tc_tbf_qopt_offload *qopt =3D type_data; + int queue; + + res =3D yt921x_tbf_validate(priv, qopt, &queue); + if (res) + return res; + + return yt921x_dsa_port_setup_tc_tbf_port(ds, port, qopt); + } + default: + return -EOPNOTSUPP; + } +} + static int yt921x_mirror_del(struct yt921x_priv *priv, int port, bool ingress) { @@ -3445,6 +3550,13 @@ static int yt921x_chip_setup_tc(struct yt921x_priv *= priv) return res; priv->meter_slot_ns =3D ctrl * op_ns; =20 + ctrl =3D max(priv->port_shape_slot_ns / op_ns, + YT921X_PORT_SHAPE_SLOT_MIN); + res =3D yt921x_reg_write(priv, YT921X_PORT_SHAPE_SLOT, ctrl); + if (res) + return res; + priv->port_shape_slot_ns =3D ctrl * op_ns; + return 0; } =20 @@ -3601,6 +3713,7 @@ static const struct dsa_switch_ops yt921x_dsa_switch_= ops =3D { /* rate */ .port_policer_del =3D yt921x_dsa_port_policer_del, .port_policer_add =3D yt921x_dsa_port_policer_add, + .port_setup_tc =3D yt921x_dsa_port_setup_tc, /* hsr */ .port_hsr_leave =3D dsa_port_simple_hsr_leave, .port_hsr_join =3D dsa_port_simple_hsr_join, diff --git a/drivers/net/dsa/yt921x.h b/drivers/net/dsa/yt921x.h index 129073ed3a4b..dbcd89c7bd6c 100644 --- a/drivers/net/dsa/yt921x.h +++ b/drivers/net/dsa/yt921x.h @@ -537,6 +537,19 @@ enum yt921x_app_selector { #define YT921X_MIRROR_PORT_M GENMASK(3, 0) #define YT921X_MIRROR_PORT(x) FIELD_PREP(YT921X_MIRROR_PORT_M, (x)) =20 +#define YT921X_PORT_SHAPE_SLOT 0x34000c +#define YT921X_PORT_SHAPE_SLOT_SLOT_M GENMASK(11, 0) +#define YT921X_PORTn_SHAPE_CTRL(port) (0x354000 + 8 * (port)) +#define YT921X_PORT_SHAPE_CTRL_S 2 +#define YT921X_PORT_SHAPE_CTRLb_EN BIT(4) +#define YT921X_PORT_SHAPE_CTRLb_PKT_MODE BIT(3) /* 0: byte rate mode */ +#define YT921X_PORT_SHAPE_CTRLb_UNIT_M GENMASK(2, 0) +#define YT921X_PORT_SHAPE_CTRLb_UNIT(x) FIELD_PREP(YT921X_PORT_SHAPE_CT= RLb_UNIT_M, (x)) +#define YT921X_PORT_SHAPE_CTRLa_CBS_M GENMASK(31, 18) +#define YT921X_PORT_SHAPE_CTRLa_CBS(x) FIELD_PREP(YT921X_PORT_SHAPE_CTR= La_CBS_M, (x)) +#define YT921X_PORT_SHAPE_CTRLa_CIR_M GENMASK(17, 0) +#define YT921X_PORT_SHAPE_CTRLa_CIR(x) FIELD_PREP(YT921X_PORT_SHAPE_CTR= La_CIR_M, (x)) + #define YT921X_EDATA_EXTMODE 0xfb #define YT921X_EDATA_LEN 0x100 =20 @@ -562,6 +575,10 @@ enum yt921x_fdb_entry_status { #define YT921X_METER_UNIT_MAX ((1 << 3) - 1) #define YT921X_METER_BURST_MAX ((1 << 16) - 1) #define YT921X_METER_RATE_MAX ((1 << 18) - 1) +#define YT921X_PORT_SHAPE_SLOT_MIN 80 +#define YT921X_SHAPE_UNIT_MAX ((1 << 3) - 1) +#define YT921X_SHAPE_BURST_MAX ((1 << 14) - 1) +#define YT921X_SHAPE_RATE_MAX ((1 << 18) - 1) =20 #define YT921X_LAG_NUM 2 #define YT921X_LAG_PORT_NUM 4 @@ -658,6 +675,7 @@ struct yt921x_priv { =20 const struct yt921x_info *info; unsigned int meter_slot_ns; + unsigned int port_shape_slot_ns; /* cache of dsa_cpu_ports(ds) */ u16 cpu_ports_mask; u8 cycle_ns; --=20 2.51.0