From nobody Sat Feb 7 17:04:30 2026 Received: from mail-pl1-f194.google.com (mail-pl1-f194.google.com [209.85.214.194]) (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 DCA0937B3F6 for ; Thu, 29 Jan 2026 08:53:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.194 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769676805; cv=none; b=e12RyOf3yyhFBwJ6XjhS3+XMqVv5abe3kwIkbm3I6pLSnfcpFUYlkc4N4Qum0pfAsZYLZNDz9xBoBTSWPvqRRp6eo/tYhp7othIFUHNkiAM7oS9ri9FIHJiSF5v0Fibi4F+BiyOMMT4KkvV+YqdXTjUwyfB17vYznxtZ0Ix7fjA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769676805; c=relaxed/simple; bh=9cHg4yudx0KYot1AXmxgLTYZE6CP3WU8JWGdgL+x0d8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SPZFL7BuNvHuaiMzD5UvuQ5gSpAhZQuH48ouDPyr9BN/OJJN8Uc5beA1dm0mSAma99+/d/mcYVfyCMDHYM2T3Op5yWMsHKAAo2l2eRjO74c+voRBnKflIRpvw79+xdL9S0QfUCsZlboMisZKU6uXKXsftphJkQRrjtilGQeU4r4= 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=BUGOxAHo; arc=none smtp.client-ip=209.85.214.194 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="BUGOxAHo" Received: by mail-pl1-f194.google.com with SMTP id d9443c01a7336-2a7a94c6d4fso3560215ad.0 for ; Thu, 29 Jan 2026 00:53:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769676801; x=1770281601; 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=2XpMMUS1e/vYJVAQpO8ah+VrCXSORaptOSTTscCu+vs=; b=BUGOxAHohipQgMilGogatL46TtzHHjTj/p0uyXylRdsUN0ybP9m12vC9hp4UVPb8md Ezxjj/viH4Oq6R+Jw6ClxCHJvy7SZmGNjSNsfBwjB+HzV5JxKEzGjbafbQjNAsts7hu9 dxMd7WcMMdjRex4lstMA4RYFCKOGZySu5BI9XERjkgIUDU9bXyuGELLQUyncmg4X1AKI LSX0SnxOyf9hcs+TPOtKY1aEfyL3bUMb9tWrtq/V629eFYoygu1QiJm5sCwgfkKW0ui1 VihMncM0/W1EatZ7jyYMC87p3GIiVD/12TBW/76hVeq46Pr7eF9WsHumy3Ygo7LVTOou BlgQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769676801; x=1770281601; 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=2XpMMUS1e/vYJVAQpO8ah+VrCXSORaptOSTTscCu+vs=; b=EQ4soWMoMjbrdVrUdEU178bfzfCQMAj5zSc+/8o+51FwAzWt5NoFOVKMVOeC58bVEE oyJArvv04ERLtTv+TjAzLhWz1tY2ghH3vP5EZ/LDO6TRvAG6pEdC97HxgfzD9VpG1br3 35pVGUMaM8kq4Iuudr+4y3rqP8mXI3Zjg6oLmS73mbQziTXztC1jfLim8T+b77R6fR5R OSdzLKH8Aw+OwPzfmVUGJJL9GnV9KEUoRuss6hy3OTrXKQUrI1VgSu6VODFPIY0cTWNd w1P+E7MtMYvtQ+LW9vyk7VH729AWyxXiYnQXDVCAWfRVqcUrzhnMv3OE0dVa4Jyhc8iM uY9A== X-Forwarded-Encrypted: i=1; AJvYcCXSUJdz15K9OmNguKQMC828udK7SgK+N7+Yxk44UaULlTYYgbEWnM57FgXacm0T6pU4jrPDKZvP+tCKUBQ=@vger.kernel.org X-Gm-Message-State: AOJu0Yy7bAJKxVzOAt6l8gRaphvzxh/y1fgbirL5O2337EMJ2pBkyLiZ F+BHTQXV1dSvEE02GHahlYvlaIaEK4LF/8A+TFZ4znFqzvr1+eiEgMZPND6BVIwPGjg= X-Gm-Gg: AZuq6aIFAdG8PI5x6HYUTldd0PlK84T3m9xT4NU6TM6BmvfQ+DHf9DePGhwZx7N5pwn enVmR1qmjJ0FMNh0Y12N6kuGYZ2Iu+0U8AgciY4YkSrRR9G4qcVGf1eyR0JIRt5h5aM5dLOh4T1 fEnywrrTkYZSJ8oTkM3rTIgHwrwkQulgqJYwiSDqofH/E6WIij9GxaKTJQz0LccOEflGKRK6rAx Ph5lXi6UIJyiArYPYG4F9KwsXQumYdhfGQNIgVtKxpI6Jd41uVKFmNrSCzJCsruqwtdpEP96WG7 cw5iPkVKKMnY4KYW0OxOSUVXi8Dabs3CxyztgrOLPuWVnnI9TDdH0Qm4V22KeqP9+jVSO1Jgv/r llotUB76GOmNDgcNw060zDpEOoAn+H26xaBxfze56N9RNPRtvAYB59bIUhz1cHvsGvSynycGbXr JexJQFD5F87ryHUd5hL1Is0sTgYPijTGC16vg= X-Received: by 2002:a17:902:cf0d:b0:2a7:919c:34c6 with SMTP id d9443c01a7336-2a870ddea27mr77364185ad.38.1769676801431; Thu, 29 Jan 2026 00:53:21 -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.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Jan 2026 00:53:21 -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 1/4] net: dsa: yt921x: Refactor port error message Date: Thu, 29 Jan 2026 16:51:33 +0800 Message-ID: <20260129085139.2767649-2-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" Sometimes we might get error codes from the underlying bus but the return type of the method is void, so an error message is desired. There're many instances of the same pattern, refactor it. Signed-off-by: David Yang --- drivers/net/dsa/yt921x.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c index 112c2a237d9c..1b66b07f45b2 100644 --- a/drivers/net/dsa/yt921x.c +++ b/drivers/net/dsa/yt921x.c @@ -185,6 +185,9 @@ struct yt921x_reg_mdio { #define to_yt921x_priv(_ds) container_of_const(_ds, struct yt921x_priv, ds) #define to_device(priv) ((priv)->ds.dev) =20 +#define print_port_err(dev, port, res, action) dev_err( \ + (dev), "Failed to %s port %d: %i\n", (action), (port), (res)) + static int yt921x_reg_read(struct yt921x_priv *priv, u32 reg, u32 *valp) { WARN_ON(!mutex_is_locked(&priv->reg_lock)); @@ -720,8 +723,7 @@ static int yt921x_read_mib(struct yt921x_priv *priv, in= t port) mib->tx_jumbo; =20 if (res) - dev_err(dev, "Failed to %s port %d: %i\n", "read stats for", - port, res); + print_port_err(dev, port, res, "read stats for"); return res; } =20 @@ -1101,8 +1103,7 @@ yt921x_dsa_port_mirror_del(struct dsa_switch *ds, int= port, mutex_unlock(&priv->reg_lock); =20 if (res) - dev_err(dev, "Failed to %s port %d: %i\n", "unmirror", - port, res); + print_port_err(dev, port, res, "unmirror"); } =20 static int @@ -1689,8 +1690,7 @@ static void yt921x_dsa_port_fast_age(struct dsa_switc= h *ds, int port) mutex_unlock(&priv->reg_lock); =20 if (res) - dev_err(dev, "Failed to %s port %d: %i\n", "clear FDB for", - port, res); + print_port_err(dev, port, res, "clear FDB for"); } =20 static int @@ -2265,8 +2265,7 @@ yt921x_dsa_port_bridge_leave(struct dsa_switch *ds, i= nt port, mutex_unlock(&priv->reg_lock); =20 if (res) - dev_err(dev, "Failed to %s port %d: %i\n", "unbridge", - port, res); + print_port_err(dev, port, res, "unbridge"); } =20 static int @@ -2398,8 +2397,7 @@ yt921x_dsa_port_stp_state_set(struct dsa_switch *ds, = int port, u8 state) mutex_unlock(&priv->reg_lock); =20 if (res) - dev_err(dev, "Failed to %s port %d: %i\n", "set STP state for", - port, res); + print_port_err(dev, port, res, "set STP state for"); } =20 static int __maybe_unused @@ -2737,8 +2735,7 @@ yt921x_phylink_mac_link_down(struct phylink_config *c= onfig, unsigned int mode, mutex_unlock(&priv->reg_lock); =20 if (res) - dev_err(dp->ds->dev, "Failed to %s port %d: %i\n", "bring down", - port, res); + print_port_err(dp->ds->dev, port, res, "bring down"); } =20 static void @@ -2758,8 +2755,7 @@ yt921x_phylink_mac_link_up(struct phylink_config *con= fig, mutex_unlock(&priv->reg_lock); =20 if (res) - dev_err(dp->ds->dev, "Failed to %s port %d: %i\n", "bring up", - port, res); + print_port_err(dp->ds->dev, port, res, "bring up"); =20 schedule_delayed_work(&priv->ports[port].mib_read, 0); } @@ -2778,8 +2774,7 @@ yt921x_phylink_mac_config(struct phylink_config *conf= ig, unsigned int mode, mutex_unlock(&priv->reg_lock); =20 if (res) - dev_err(dp->ds->dev, "Failed to %s port %d: %i\n", "config", - port, res); + print_port_err(dp->ds->dev, port, res, "config"); } =20 static void --=20 2.51.0 From nobody Sat Feb 7 17:04:30 2026 Received: from mail-pl1-f178.google.com (mail-pl1-f178.google.com [209.85.214.178]) (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 B4C8E37E2F5 for ; Thu, 29 Jan 2026 08:53:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769676809; cv=none; b=ILBaOj3amU/BNKYxU+4M0ecfdWppBrNzocJXgdblD/4UoTmcHBuRZNZzwqXhOZF3ZtLoHO1hH2sn4mQgekQQXBBlyUNHXreiyUep+jqIVU2wWRiULR9Oxd0UkNxODRpaZCkprNntFbUsJybWTowA/+m0wEPcJWZIIoaA9ZyPKu4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769676809; c=relaxed/simple; bh=mHqbGJIkqoBZSnW2vPkOyMPzqzf9tX/A5IvVfY7jnfY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=olhPhDQPSEbf7YeWzt/G1KrpkqSVJeUgNM6G4R6G9XRX/ctI3AFmiJFIk2tUkLDVUtSOoJwbWflC09HvCrREma1dyOPyKDhwQfLFFaqLOEUSeBakzVQJg124xAgFYDJl2AABbPHttaeGsrvZo7zOeutBwIChbPS2/t7DI+h+/Zo= 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=QAcVmVRE; arc=none smtp.client-ip=209.85.214.178 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="QAcVmVRE" Received: by mail-pl1-f178.google.com with SMTP id d9443c01a7336-2a7b47a5460so8337345ad.1 for ; Thu, 29 Jan 2026 00:53:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769676805; x=1770281605; 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=sORuOYB8nAnpTBlWyOyBnkB80Z24IiAB6EFkDsgeBkc=; b=QAcVmVRE+azYycK0e/cEQ2bQHEyG/8ax9QpuW09uC0DH6QPDQ4kDa54FdTsmkGPHFM SdF/SkksRpIKFklZQsEObNkyqywb54+gX/N/BK/HvMmjEm4FssDTo0CGsEWiCfLH/L8h IZ8SgDngK0qeuzqpIy/nU9ErmDdZNnsxEgH3r9FiHKRDzAf+ovTkfi32+0rip/dGrUvL caCojXFALA0O+X/38Bt1Zxt0dIYQ9uAmFmSQhMYh+XRZdNJrg4O7NsFPJ4fIQ2LJzDK1 vQGUO4Xy81r3foQLOnHTH/hQCa6gZfbdtM0KmC0cT6Iym+x7KhX+yL0zJGJLhkLVVdAy CW7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769676805; x=1770281605; 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=sORuOYB8nAnpTBlWyOyBnkB80Z24IiAB6EFkDsgeBkc=; b=dbIRJ/JaAvffC7SWnlLMYHX85UEFVUO4f0Ph3jHepoJCF4/9N6+lPlTe+sBwg2TjNU SKUncyRY6kJC1JsHN3gLQ8SzWP0VdcAFbLc6oicYAN3lKn0jAY6bgQgjVD883nPDkfMc 82DHKhZaE0Dx2YfTuLAvf5hEKtbJ5++N1Kts/pmWdpXTL81AcI20GMcmZ5haBAmrujdo GkvQpA/9fz5ZbID8lWPJk60oiAFChccY0Xw9cyBYlv3umUmVZMLoEPePawCrR5mP2h/l TxB4GdyIZpHiSDFU71oziLdnbakFwpdN7x3i0fVQ/urQgpUUcclqtG5oCJPShcPhPEKk CK6A== X-Forwarded-Encrypted: i=1; AJvYcCVhAkPe1/WKcq//pQTDTceXgcY74s0kkuQOHQHlGPk0t0VDVikNXuyyiOuVK8gnQqzS++MjgxQiGgUwFQY=@vger.kernel.org X-Gm-Message-State: AOJu0Yzfs/HZwN3XW8Dr+k8QGqeIe5tmjD345xe8gcqPLxIdiS+31Orh 3BT4UmNrvm7R9xfk/R95ciZyIx5xB0PXy3KbCS0jUAhCjG+OEHTqBKRF X-Gm-Gg: AZuq6aLQCK0d0gnhodAthKpPTSiYi0WGAifXCo0d4qz41ZJlDMhzXLhRTr5cwAwyviZ 478DijH1rkxzqXrCKtWZ9b9ZiTcsNb5VlFCRV0o7D+E2aEaWgHrf/2R9w+3jSzDsP/AU2BkPf7g dOdlAozTP9XhiPUS0a03mZmdQzPIg0b5bNdlYgz1Sg92/RBPleHwhTCAb4fzzJJMQ1F4XUHje/Z gCuShY+WeB1b91SsKTtlXPc5Md1W4e/VZikFd5Z1zDccoP3MM6+/BsKqmzQCV9eOd7EAjy03OAW 5Ij2oCBL7oGWKth51TpyyYJzU1ibV+BrYokUUNQgssqMUDfVAi5leoIPcjZYwcTPxLOC5CKvVWa BD2+S9Aku2YtIO4m7J8gQOxs72yYptnTLbtfCRMBgof+NwmtxgkPilHpGpiyBux+1Yj3ApYTxuO 2ac9+J4pi9CTNWVEelctpGFb3RazPcEBcnKgA= X-Received: by 2002:a17:903:1aa6:b0:2a0:acb8:9e80 with SMTP id d9443c01a7336-2a8bd53eab0mr24562525ad.29.1769676804834; Thu, 29 Jan 2026 00:53:24 -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.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Jan 2026 00:53:24 -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 2/4] net: dsa: yt921x: Refactor long register helpers Date: Thu, 29 Jan 2026 16:51:34 +0800 Message-ID: <20260129085139.2767649-3-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" Dealing long registers with u64 is good, until you realize there are longer registers that are 96 bits. Use u32 arrays instead. Signed-off-by: David Yang --- drivers/net/dsa/yt921x.c | 152 +++++++++++++++++++++++++-------------- drivers/net/dsa/yt921x.h | 37 +++++----- 2 files changed, 116 insertions(+), 73 deletions(-) diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c index 1b66b07f45b2..6d03888b6743 100644 --- a/drivers/net/dsa/yt921x.c +++ b/drivers/net/dsa/yt921x.c @@ -258,63 +258,102 @@ yt921x_reg_toggle_bits(struct yt921x_priv *priv, u32= reg, u32 mask, bool set) return yt921x_reg_update_bits(priv, reg, mask, !set ? 0 : mask); } =20 -/* Some registers, like VLANn_CTRL, should always be written in 64-bit, ev= en if - * you are to write only the lower / upper 32 bits. +/* Some registers, like VLANn_CTRL, should always be written in chunks, ev= en if + * you only want to write parts of 32 bits. * - * There is no such restriction for reading, but we still provide 64-bit r= ead - * wrappers so that we always handle u64 values. + * There is no such restriction for reading, but we still provide multi-ch= unk + * read wrappers so that we can handle them consistently. */ =20 -static int yt921x_reg64_read(struct yt921x_priv *priv, u32 reg, u64 *valp) +static int +yt921x_longreg_read(struct yt921x_priv *priv, u32 reg, u32 *vals, + unsigned int span) { - u32 lo; - u32 hi; int res; =20 - res =3D yt921x_reg_read(priv, reg, &lo); - if (res) - return res; - res =3D yt921x_reg_read(priv, reg + 4, &hi); - if (res) - return res; + for (unsigned int i =3D 0; i < span; i++) { + res =3D yt921x_reg_read(priv, reg + 4 * i, &vals[i]); + if (res) + return res; + } =20 - *valp =3D ((u64)hi << 32) | lo; return 0; } =20 -static int yt921x_reg64_write(struct yt921x_priv *priv, u32 reg, u64 val) +static int +yt921x_longreg_write(struct yt921x_priv *priv, u32 reg, const u32 *vals, + unsigned int span) { int res; =20 - res =3D yt921x_reg_write(priv, reg, (u32)val); - if (res) - return res; - return yt921x_reg_write(priv, reg + 4, (u32)(val >> 32)); + for (unsigned int i =3D 0; i < span; i++) { + res =3D yt921x_reg_write(priv, reg + 4 * i, vals[i]); + if (res) + return res; + } + + return 0; } =20 static int -yt921x_reg64_update_bits(struct yt921x_priv *priv, u32 reg, u64 mask, u64 = val) +yt921x_longreg_update_bits(struct yt921x_priv *priv, u32 reg, const u32 *m= asks, + const u32 *vals, unsigned int span) { + bool changed =3D false; + u32 vs[4]; int res; - u64 v; - u64 u; =20 - res =3D yt921x_reg64_read(priv, reg, &v); + BUILD_BUG_ON(span > ARRAY_SIZE(vs)); + + res =3D yt921x_longreg_read(priv, reg, vs, span); if (res) return res; =20 - u =3D v; - u &=3D ~mask; - u |=3D val; - if (u =3D=3D v) + for (unsigned int i =3D 0; i < span; i++) { + u32 u =3D vs[i]; + + u &=3D ~masks[i]; + u |=3D vals[i]; + if (u !=3D vs[i]) + changed =3D true; + + vs[i] =3D u; + } + + if (!changed) return 0; =20 - return yt921x_reg64_write(priv, reg, u); + return yt921x_longreg_write(priv, reg, vs, span); } =20 -static int yt921x_reg64_clear_bits(struct yt921x_priv *priv, u32 reg, u64 = mask) +static int +yt921x_longreg_clear_bits(struct yt921x_priv *priv, u32 reg, const u32 *ma= sks, + unsigned int span) { - return yt921x_reg64_update_bits(priv, reg, mask, 0); + bool changed =3D false; + u32 vs[4]; + int res; + + BUILD_BUG_ON(span > ARRAY_SIZE(vs)); + + res =3D yt921x_longreg_read(priv, reg, vs, span); + if (res) + return res; + + for (unsigned int i =3D 0; i < span; i++) { + u32 u =3D vs[i]; + + u &=3D ~masks[i]; + if (u !=3D vs[i]) + changed =3D true; + + vs[i] =3D u; + } + + if (!changed) + return 0; + + return yt921x_longreg_write(priv, reg, vs, span); } =20 static int yt921x_reg_mdio_read(void *context, u32 reg, u32 *valp) @@ -1843,33 +1882,32 @@ yt921x_vlan_filtering(struct yt921x_priv *priv, int= port, bool vlan_filtering) return 0; } =20 -static int -yt921x_vlan_del(struct yt921x_priv *priv, int port, u16 vid) +static int yt921x_vlan_del(struct yt921x_priv *priv, int port, u16 vid) { - u64 mask64; + u32 masks[YT921X_VLAN_CTRL_S]; =20 - mask64 =3D YT921X_VLAN_CTRL_PORTS(port) | - YT921X_VLAN_CTRL_UNTAG_PORTn(port); + masks[0] =3D YT921X_VLAN_CTRLa_PORTn(port); + masks[1] =3D YT921X_VLAN_CTRLb_UNTAG_PORTn(port); =20 - return yt921x_reg64_clear_bits(priv, YT921X_VLANn_CTRL(vid), mask64); + return yt921x_longreg_clear_bits(priv, YT921X_VLANn_CTRL(vid), masks, + YT921X_VLAN_CTRL_S); } =20 static int yt921x_vlan_add(struct yt921x_priv *priv, int port, u16 vid, bool untagged) { - u64 mask64; - u64 ctrl64; + u32 masks[YT921X_VLAN_CTRL_S]; + u32 ctrls[YT921X_VLAN_CTRL_S]; =20 - mask64 =3D YT921X_VLAN_CTRL_PORTn(port) | - YT921X_VLAN_CTRL_PORTS(priv->cpu_ports_mask); - ctrl64 =3D mask64; + masks[0] =3D YT921X_VLAN_CTRLa_PORTn(port) | + YT921X_VLAN_CTRLa_PORTS(priv->cpu_ports_mask); + ctrls[0] =3D masks[0]; =20 - mask64 |=3D YT921X_VLAN_CTRL_UNTAG_PORTn(port); - if (untagged) - ctrl64 |=3D YT921X_VLAN_CTRL_UNTAG_PORTn(port); + masks[1] =3D YT921X_VLAN_CTRLb_UNTAG_PORTn(port); + ctrls[1] =3D untagged ? masks[1] : 0; =20 - return yt921x_reg64_update_bits(priv, YT921X_VLANn_CTRL(vid), - mask64, ctrl64); + return yt921x_longreg_update_bits(priv, YT921X_VLANn_CTRL(vid), + masks, ctrls, YT921X_VLAN_CTRL_S); } =20 static int @@ -2329,8 +2367,8 @@ yt921x_dsa_vlan_msti_set(struct dsa_switch *ds, struc= t dsa_bridge bridge, const struct switchdev_vlan_msti *msti) { struct yt921x_priv *priv =3D to_yt921x_priv(ds); - u64 mask64; - u64 ctrl64; + u32 masks[YT921X_VLAN_CTRL_S]; + u32 ctrls[YT921X_VLAN_CTRL_S]; int res; =20 if (!msti->vid) @@ -2338,12 +2376,14 @@ yt921x_dsa_vlan_msti_set(struct dsa_switch *ds, str= uct dsa_bridge bridge, if (!msti->msti || msti->msti >=3D YT921X_MSTI_NUM) return -EINVAL; =20 - mask64 =3D YT921X_VLAN_CTRL_STP_ID_M; - ctrl64 =3D YT921X_VLAN_CTRL_STP_ID(msti->msti); + masks[0] =3D 0; + ctrls[0] =3D 0; + masks[1] =3D YT921X_VLAN_CTRLb_STP_ID_M; + ctrls[1] =3D YT921X_VLAN_CTRLb_STP_ID(msti->msti); =20 mutex_lock(&priv->reg_lock); - res =3D yt921x_reg64_update_bits(priv, YT921X_VLANn_CTRL(msti->vid), - mask64, ctrl64); + res =3D yt921x_longreg_update_bits(priv, YT921X_VLANn_CTRL(msti->vid), + masks, ctrls, YT921X_VLAN_CTRL_S); mutex_unlock(&priv->reg_lock); =20 return res; @@ -3090,8 +3130,8 @@ static int yt921x_chip_reset(struct yt921x_priv *priv) static int yt921x_chip_setup_dsa(struct yt921x_priv *priv) { struct dsa_switch *ds =3D &priv->ds; + u32 ctrls[YT921X_VLAN_CTRL_S]; unsigned long cpu_ports_mask; - u64 ctrl64; u32 ctrl; int port; int res; @@ -3152,8 +3192,10 @@ static int yt921x_chip_setup_dsa(struct yt921x_priv = *priv) /* Tagged VID 0 should be treated as untagged, which confuses the * hardware a lot */ - ctrl64 =3D YT921X_VLAN_CTRL_LEARN_DIS | YT921X_VLAN_CTRL_PORTS_M; - res =3D yt921x_reg64_write(priv, YT921X_VLANn_CTRL(0), ctrl64); + ctrls[0] =3D YT921X_VLAN_CTRLa_LEARN_DIS | YT921X_VLAN_CTRLa_PORTS_M; + ctrls[1] =3D 0; + res =3D yt921x_longreg_write(priv, YT921X_VLANn_CTRL(0), ctrls, + YT921X_VLAN_CTRL_S); if (res) return res; =20 diff --git a/drivers/net/dsa/yt921x.h b/drivers/net/dsa/yt921x.h index 3f129b8d403f..361470582687 100644 --- a/drivers/net/dsa/yt921x.h +++ b/drivers/net/dsa/yt921x.h @@ -429,24 +429,25 @@ enum yt921x_app_selector { #define YT921X_FDB_HW_FLUSH_ON_LINKDOWN BIT(0) =20 #define YT921X_VLANn_CTRL(vlan) (0x188000 + 8 * (vlan)) -#define YT921X_VLAN_CTRL_UNTAG_PORTS_M GENMASK_ULL(50, 40) -#define YT921X_VLAN_CTRL_UNTAG_PORTS(x) FIELD_PREP(YT921X_VLAN_CTRL_UNT= AG_PORTS_M, (x)) -#define YT921X_VLAN_CTRL_UNTAG_PORTn(port) BIT_ULL((port) + 40) -#define YT921X_VLAN_CTRL_STP_ID_M GENMASK_ULL(39, 36) -#define YT921X_VLAN_CTRL_STP_ID(x) FIELD_PREP(YT921X_VLAN_CTRL_STP_ID_= M, (x)) -#define YT921X_VLAN_CTRL_SVLAN_EN BIT_ULL(35) -#define YT921X_VLAN_CTRL_FID_M GENMASK_ULL(34, 23) -#define YT921X_VLAN_CTRL_FID(x) FIELD_PREP(YT921X_VLAN_CTRL_FID_M, (x)) -#define YT921X_VLAN_CTRL_LEARN_DIS BIT_ULL(22) -#define YT921X_VLAN_CTRL_PRIO_EN BIT_ULL(21) -#define YT921X_VLAN_CTRL_PRIO_M GENMASK_ULL(20, 18) -#define YT921X_VLAN_CTRL_PRIO(x) FIELD_PREP(YT921X_VLAN_CTRL_PRIO_M, (= x)) -#define YT921X_VLAN_CTRL_PORTS_M GENMASK_ULL(17, 7) -#define YT921X_VLAN_CTRL_PORTS(x) FIELD_PREP(YT921X_VLAN_CTRL_PORTS_M,= (x)) -#define YT921X_VLAN_CTRL_PORTn(port) BIT_ULL((port) + 7) -#define YT921X_VLAN_CTRL_BYPASS_1X_AC BIT_ULL(6) -#define YT921X_VLAN_CTRL_METER_EN BIT_ULL(5) -#define YT921X_VLAN_CTRL_METER_ID_M GENMASK_ULL(4, 0) +#define YT921X_VLAN_CTRL_S 2 +#define YT921X_VLAN_CTRLb_UNTAG_PORTS_M GENMASK(18, 8) +#define YT921X_VLAN_CTRLb_UNTAG_PORTS(x) FIELD_PREP(YT921X_VLAN_CTRLb_U= NTAG_PORTS_M, (x)) +#define YT921X_VLAN_CTRLb_UNTAG_PORTn(port) BIT((port) + 8) +#define YT921X_VLAN_CTRLb_STP_ID_M GENMASK(7, 4) +#define YT921X_VLAN_CTRLb_STP_ID(x) FIELD_PREP(YT921X_VLAN_CTRLb_STP_I= D_M, (x)) +#define YT921X_VLAN_CTRLb_SVLAN_EN BIT(3) +#define YT921X_VLAN_CTRLab_FID_M GENMASK_ULL(34, 23) +#define YT921X_VLAN_CTRLab_FID(x) FIELD_PREP(YT921X_VLAN_CTRLab_FID_M,= (x)) +#define YT921X_VLAN_CTRLa_LEARN_DIS BIT(22) +#define YT921X_VLAN_CTRLa_PRIO_EN BIT(21) +#define YT921X_VLAN_CTRLa_PRIO_M GENMASK(20, 18) +#define YT921X_VLAN_CTRLa_PRIO(x) FIELD_PREP(YT921X_VLAN_CTRLa_PRIO_M,= (x)) +#define YT921X_VLAN_CTRLa_PORTS_M GENMASK(17, 7) +#define YT921X_VLAN_CTRLa_PORTS(x) FIELD_PREP(YT921X_VLAN_CTRLa_PORTS_= M, (x)) +#define YT921X_VLAN_CTRLa_PORTn(port) BIT((port) + 7) +#define YT921X_VLAN_CTRLa_BYPASS_1X_AC BIT(6) +#define YT921X_VLAN_CTRLa_METER_EN BIT(5) +#define YT921X_VLAN_CTRLa_METER_ID_M GENMASK(4, 0) =20 #define YT921X_TPID_IGRn(x) (0x210000 + 4 * (x)) /* [0, 3] */ #define YT921X_TPID_IGR_TPID_M GENMASK(15, 0) --=20 2.51.0 From nobody Sat Feb 7 17:04:30 2026 Received: from mail-pl1-f196.google.com (mail-pl1-f196.google.com [209.85.214.196]) (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 27BA937E309 for ; Thu, 29 Jan 2026 08:53:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769676814; cv=none; b=QpMuPQCuPQl9oYi1tYmhE3In38r7i4eoaG6jVpFzGwzVjHz3LnGC4vG1igvoGL/hE4q3xKd9qHxCB0lu+dphBKW5mHizQIPDkxihdTOayHgGeeS4UuA5Y63+J24cfg0LOb37v1IFqddJm7vDQabuzqyPIRAPT+KGmxh/b/oMFsM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769676814; c=relaxed/simple; bh=XMvN8ZTq7GHPxlr3sFkJ1y/cVq+Y062nCOx1lnUG18k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=V7tUNFS9KRplTkU8mucbuVgImyQt/ortt8266PrAn4FTc06UWzRUHG7ZjgxxqdyD1fUaFexGq+OIdjKz3mYnI1x9vnyZ3fXkrQ5qwVBh4RBpTbXiSeP9fRjnPSvi5NEc92roFZo5fpgssDqmp7NOv/IeeiOzUmYjLduZi3ayqWg= 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=PPVJWnEl; arc=none smtp.client-ip=209.85.214.196 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="PPVJWnEl" Received: by mail-pl1-f196.google.com with SMTP id d9443c01a7336-2a1022dda33so4102395ad.2 for ; Thu, 29 Jan 2026 00:53:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769676809; x=1770281609; 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=poMxq/4p/orTNgWmytXg7LTqAfSrNEbsQxhTV3fiZ6Q=; b=PPVJWnElqAC0Mp7CEaBvbrSR13wCKgoHpgyBZ1ea/gmOxn15cR9hXhEgSxxqOKsfj2 dM7Hp2IBVNdUkTgB9FYrowFTYJrU8CiV0GIANSbZLdEHPW0bU22uFEXlsq39NMp27aVn rm5wSCS2VzHAvn6/hnFqOKHVs94lhwmOqzz9HztOoYxmserbqa6lsLg0Mgkube/CobUN 51M45+0lQ9J3Dq39WI0k8Yi/UsM8jjgaT87OCm5OfOpZ6jFY0XYKUazvhEysiV/hlQQM T1NhWlBlxHgWXrEKVuZsLGheM3/u1FlF/n/2pL3DVGoBa3jB++RAOofyF0h7A2pbnw+A W5aQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769676809; x=1770281609; 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=poMxq/4p/orTNgWmytXg7LTqAfSrNEbsQxhTV3fiZ6Q=; b=XYmmSyjRILfSqSNJY78BLzuArSH3HmKXPKFmD7J9Z+FCzi+QaOs/GWXyO4g9R8PzCS Kb6JyNs0+ovPogpubkq47IOQfdCsZGnad+Su4ctklkXIzlA+wnLgU60dns22BYmViH/U zGLLLRHxqsR897sK4VyUq0l2oRB5SVh2pDJWpcmklDh2opnS06v4bqaFMF9S4LZ6W4sN FNnjEO0v6HHuph6O0/lG/niB1Y8Z2yGdIRk3K36I5cmU8tkRUXe6EdpMukLs4H21HqCq sI4y2+/KY2sQjLlD002FiyzHqK5dbwhT0LZc/85CHnlDEOh2VdK7ZRWWOkjFl8Kyc6kW UrFg== X-Forwarded-Encrypted: i=1; AJvYcCUh0dvdzE5de/v+5SQ2FQ277QXYd0EyP/Fz/4XKQuNg9UNO4AkyWyOlQaNtmQ7fsMbjC59DJafjPin54dM=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/vC+G8jVnzmPqHAKmvOFcphQZmjg05a4MC3KekQsxpqeu30FS uiEKthx2LJOOXQIXYJGW8+26NigqQiUeKXWOfozxQ21btaxHcpn5CCH9u60YDjRQ1HE= X-Gm-Gg: AZuq6aIC5DRYVX864x4ZqWlOg2wcXxK0nESWTbtvDIhUxBw6u1Gr7mvpAr1zX7/NQXc 4vdwLN9Xv7NAD03cOJYpS5O7KTqptyyqwNUYrZhB5OsV1IOezkcAnPfpUr0JG8Itf/3C9olTEbc ftFKu6BXJfkoGjIlpOUS+zlg7H0qWEBSTNPMKdv0aB/2gKog/qEdRkWd19VQDBHvnvbNUau9KZS ysJgYwG0s7uphDqgN/xKFl8jWIjH3Qs0x3qhEYJOHt6xiJzGKbMbqM4Hc+zv5Y6oNFqipwHH/C4 xyUyIRhcnoVrktOG+7gERsXioeJNtu4Xcw08Xakgz3Zg13QP7ncy0+cCxwEC8VVevAfx50JgILL xWUEZavloH36GBRjQX9u6U9sBLSh8pSZaskHqWSbKibnuvbqseJ3HVXcjiJSNzoUSuFToZPENW0 cnyZWBx/Bf5/oTTMRlp9Y8ndGSFsPeQ4xvkCM= X-Received: by 2002:a17:903:4b08:b0:2a7:6114:4865 with SMTP id d9443c01a7336-2a870dfbf3emr76893405ad.61.1769676808616; Thu, 29 Jan 2026 00:53:28 -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.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Jan 2026 00:53:28 -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 3/4] net: dsa: yt921x: Add port police support Date: Thu, 29 Jan 2026 16:51:35 +0800 Message-ID: <20260129085139.2767649-4-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 rate meter ability and support limiting the rate of incoming traffic. Signed-off-by: David Yang --- drivers/net/dsa/yt921x.c | 255 ++++++++++++++++++++++++++++++++++++++- drivers/net/dsa/yt921x.h | 56 +++++++++ 2 files changed, 310 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c index 6d03888b6743..f1465c4d9b1b 100644 --- a/drivers/net/dsa/yt921x.c +++ b/drivers/net/dsa/yt921x.c @@ -356,6 +356,14 @@ yt921x_longreg_clear_bits(struct yt921x_priv *priv, u3= 2 reg, const u32 *masks, return yt921x_longreg_write(priv, reg, vs, span); } =20 +static void u32a_update_u64(u32 *arr, u64 mask, u64 val) +{ + arr[0] &=3D ~((u32)mask); + arr[1] &=3D ~((u32)(mask >> 32)); + arr[0] |=3D (u32)val; + arr[1] |=3D (u32)(val >> 32); +} + static int yt921x_reg_mdio_read(void *context, u32 reg, u32 *valp) { struct yt921x_reg_mdio *mdio =3D context; @@ -1047,6 +1055,13 @@ yt921x_dsa_set_mac_eee(struct dsa_switch *ds, int po= rt, struct ethtool_keee *e) return res; } =20 +static int yt921x_mtu_fetch(struct yt921x_priv *priv, int port) +{ + struct dsa_port *dp =3D dsa_to_port(&priv->ds, port); + + return dp->user ? READ_ONCE(dp->user->mtu) : ETH_DATA_LEN; +} + static int yt921x_dsa_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) { @@ -1078,6 +1093,204 @@ static int yt921x_dsa_port_max_mtu(struct dsa_switc= h *ds, int port) return YT921X_FRAME_SIZE_MAX - ETH_HLEN - ETH_FCS_LEN - YT921X_TAG_LEN; } =20 +/* v * 2^e */ +#define ldexpi(v, e) ({ \ + __auto_type _v =3D (v); \ + __auto_type _e =3D (e); \ + _e >=3D 0 ? _v << _e : _v >> -_e; \ +}) + +/* slot (ns) * rate (/s) / 10^9 (ns/s) =3D 2^C * token * 4^unit */ +#define rate2token(rate, unit, slot_ns, C) \ + ((u32)(ldexpi((slot_ns) * (rate), \ + -(2 * (unit) + (C) + YT921X_TOKEN_RATE_C)) / 1000000000)) +#define token2rate(token, unit, slot_ns, C) \ + (ldexpi(1000000000 * (u64)(token), \ + 2 * (unit) + (C) + YT921X_TOKEN_RATE_C) / (slot_ns)) + +/* burst =3D 2^C * token * 4^unit */ +#define burst2token(burst, unit, C) ((u32)ldexpi((burst), -(2 * (unit) + (= C)))) +#define token2burst(token, unit, C) ldexpi((u64)(token), 2 * (unit) + (C)) + +struct yt921x_meter { + u32 cir; + u32 cbs; + u32 ebs; + int unit; +}; + +#define YT921X_METER_PKT_MODE BIT(0) +#define YT921X_METER_SINGLE_BUCKET BIT(1) + +static struct yt921x_meter +yt921x_meter_tfm(struct yt921x_priv *priv, int port, unsigned int slot_ns, + u64 rate, u64 burst, unsigned int flags, + u32 cir_max, u32 cbs_max, int unit_max) +{ + const int C =3D flags & YT921X_METER_PKT_MODE ? YT921X_TOKEN_PKT_C : + YT921X_TOKEN_BYTE_C; + struct device *dev =3D to_device(priv); + struct yt921x_meter meter; + bool distorted; + u64 burst_est; + u64 burst_max; + u64 rate_max; + + meter.unit =3D unit_max; + rate_max =3D token2rate(cir_max, meter.unit, slot_ns, C); + burst_max =3D token2burst(cbs_max, meter.unit, C); + + /* clamp rate and burst */ + if (rate > rate_max || burst > burst_max) { + dev_warn(dev, + "rate %llu, burst %llu too high, max is %llu, %llu, clamping...\n", + rate, burst, rate_max, burst_max); + + if (rate > rate_max) + rate =3D rate_max; + if (burst > burst_max) + burst =3D burst_max; + + burst_est =3D slot_ns * rate / 1000000000; + } else { + u64 burst_sug; + + burst_est =3D slot_ns * rate / 1000000000; + burst_sug =3D burst_est; + if (flags & YT921X_METER_PKT_MODE) + burst_sug++; + else + burst_sug +=3D ETH_HLEN + yt921x_mtu_fetch(priv, port) + + ETH_FCS_LEN; + if (burst_sug > burst) + dev_warn(dev, + "Consider using burst at least %llu to match rate %llu\n", + burst_sug, rate); + + /* select unit */ + for (; meter.unit > 0; meter.unit--) { + if (rate > (rate_max >> 2) || burst > (burst_max >> 2)) + break; + rate_max >>=3D 2; + burst_max >>=3D 2; + } + } + + /* calculate information rate and bucket size */ + distorted =3D false; + meter.cir =3D rate2token(rate, meter.unit, slot_ns, C); + if (!meter.cir) { + distorted =3D true; + meter.cir =3D 1; + } else if (meter.cir > cir_max) { + WARN_ON(1); + meter.cir =3D cir_max; + } + meter.cbs =3D burst2token(burst, meter.unit, C); + if (!meter.cbs) { + distorted =3D true; + meter.cbs =3D 1; + } else if (meter.cbs > cbs_max) { + WARN_ON(1); + meter.cbs =3D cbs_max; + } + if (distorted) + dev_warn(dev, + "Have to increase rate %llu, burst %llu to %llu, %llu\n", + rate, burst, + token2rate(meter.cir, meter.unit, slot_ns, C), + token2burst(meter.cbs, meter.unit, C)); + + /* cut ebs */ + meter.ebs =3D 0; + if (!(flags & YT921X_METER_SINGLE_BUCKET)) { + /* we don't have a chance to adjust rate when MTU is changed */ + if (flags & YT921X_METER_PKT_MODE) + burst_est++; + else + burst_est +=3D YT921X_FRAME_SIZE_MAX; + + if (burst_est < burst) { + u32 pbs =3D meter.cbs; + + meter.cbs =3D burst2token(burst_est, meter.unit, C); + if (!meter.cbs) { + meter.cbs =3D 1; + } else if (meter.cbs > cbs_max) { + WARN_ON(1); + meter.cbs =3D cbs_max; + } + + if (pbs > meter.cbs) + meter.ebs =3D pbs - meter.cbs; + } + } + + dev_dbg(dev, + "slot %u ns, rate %llu, burst %llu -> unit %d, cir %u, cbs %u, ebs %u\n", + slot_ns, rate, burst, + meter.unit, meter.cir, meter.cbs, meter.ebs); + + return meter; +} + +static void yt921x_dsa_port_policer_del(struct dsa_switch *ds, int port) +{ + struct yt921x_priv *priv =3D to_yt921x_priv(ds); + struct device *dev =3D to_device(priv); + int res; + + mutex_lock(&priv->reg_lock); + res =3D yt921x_reg_write(priv, YT921X_PORTn_METER(port), 0); + mutex_unlock(&priv->reg_lock); + + if (res) + print_port_err(dev, port, res, "delete policer on"); +} + +static int +yt921x_dsa_port_policer_add(struct dsa_switch *ds, int port, + struct dsa_mall_policer_tc_entry *policer) +{ + struct yt921x_priv *priv =3D to_yt921x_priv(ds); + u32 ctrls[YT921X_METER_CTRL_S]; + struct yt921x_meter meter; + u64 burst; + u64 rate; + u32 ctrl; + int res; + + rate =3D policer->rate_bytes_per_sec; + burst =3D policer->burst; + meter =3D yt921x_meter_tfm(priv, port, priv->meter_slot_ns, rate, burst, + 0, YT921X_METER_RATE_MAX, + YT921X_METER_BURST_MAX, YT921X_METER_UNIT_MAX); + + mutex_lock(&priv->reg_lock); + ctrl =3D YT921X_PORT_METER_ID(port) | YT921X_PORT_METER_EN; + res =3D yt921x_reg_write(priv, YT921X_PORTn_METER(port), ctrl); + if (res) + goto end; + + ctrls[0] =3D 0; + ctrls[1] =3D YT921X_METER_CTRLb_CIR(meter.cir); + ctrls[2] =3D YT921X_METER_CTRLc_UNIT(meter.unit) | + YT921X_METER_CTRLc_DROP_R | + YT921X_METER_CTRLc_TOKEN_OVERFLOW_EN | + YT921X_METER_CTRLc_METER_EN; + u32a_update_u64(&ctrls[0], YT921X_METER_CTRLab_EBS_M, + YT921X_METER_CTRLab_EBS(meter.ebs)); + u32a_update_u64(&ctrls[1], YT921X_METER_CTRLbc_CBS_M, + YT921X_METER_CTRLbc_CBS(meter.cbs)); + res =3D yt921x_longreg_write(priv, + YT921X_METERn_CTRL(port + YT921X_METER_NUM), + ctrls, YT921X_METER_CTRL_S); +end: + mutex_unlock(&priv->reg_lock); + + return res; +} + static int yt921x_mirror_del(struct yt921x_priv *priv, int port, bool ingress) { @@ -3040,6 +3253,7 @@ static int yt921x_chip_detect(struct yt921x_priv *pri= v) u32 chipid; u32 major; u32 mode; + u32 val; int res; =20 res =3D yt921x_reg_read(priv, YT921X_CHIP_ID, &chipid); @@ -3074,12 +3288,27 @@ static int yt921x_chip_detect(struct yt921x_priv *p= riv) return -ENODEV; } =20 + res =3D yt921x_reg_read(priv, YT921X_SYS_CLK, &val); + if (res) + return res; + switch (FIELD_GET(YT921X_SYS_CLK_SEL_M, val)) { + case 0: + priv->cycle_ns =3D info->major =3D=3D YT9215_MAJOR ? 8 : 6; + break; + case YT921X_SYS_CLK_143M: + priv->cycle_ns =3D 7; + break; + default: + priv->cycle_ns =3D 8; + } + /* Print chipid here since we are interested in lower 16 bits */ dev_info(dev, "Motorcomm %s ethernet switch, chipid: 0x%x, chipmode: 0x%x 0x%x\n", info->name, chipid, mode, extmode); =20 priv->info =3D info; + return 0; } =20 @@ -3202,6 +3431,23 @@ static int yt921x_chip_setup_dsa(struct yt921x_priv = *priv) return 0; } =20 +static int yt921x_chip_setup_tc(struct yt921x_priv *priv) +{ + unsigned int op_ns; + u32 ctrl; + int res; + + op_ns =3D 8 * priv->cycle_ns; + + ctrl =3D max(priv->meter_slot_ns / op_ns, YT921X_METER_SLOT_MIN); + res =3D yt921x_reg_write(priv, YT921X_METER_SLOT, ctrl); + if (res) + return res; + priv->meter_slot_ns =3D ctrl * op_ns; + + return 0; +} + static int __maybe_unused yt921x_chip_setup_qos(struct yt921x_priv *priv) { u32 ctrl; @@ -3248,7 +3494,7 @@ static int yt921x_chip_setup(struct yt921x_priv *priv) u32 ctrl; int res; =20 - ctrl =3D YT921X_FUNC_MIB; + ctrl =3D YT921X_FUNC_MIB | YT921X_FUNC_METER; res =3D yt921x_reg_set_bits(priv, YT921X_FUNC, ctrl); if (res) return res; @@ -3257,6 +3503,10 @@ static int yt921x_chip_setup(struct yt921x_priv *pri= v) if (res) return res; =20 + res =3D yt921x_chip_setup_tc(priv); + if (res) + return res; + #if IS_ENABLED(CONFIG_DCB) res =3D yt921x_chip_setup_qos(priv); if (res) @@ -3348,6 +3598,9 @@ static const struct dsa_switch_ops yt921x_dsa_switch_= ops =3D { /* mtu */ .port_change_mtu =3D yt921x_dsa_port_change_mtu, .port_max_mtu =3D yt921x_dsa_port_max_mtu, + /* rate */ + .port_policer_del =3D yt921x_dsa_port_policer_del, + .port_policer_add =3D yt921x_dsa_port_policer_add, /* 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 361470582687..129073ed3a4b 100644 --- a/drivers/net/dsa/yt921x.h +++ b/drivers/net/dsa/yt921x.h @@ -23,6 +23,7 @@ #define YT921X_RST_HW BIT(31) #define YT921X_RST_SW BIT(1) #define YT921X_FUNC 0x80004 +#define YT921X_FUNC_METER BIT(4) #define YT921X_FUNC_MIB BIT(1) #define YT921X_CHIP_ID 0x80008 #define YT921X_CHIP_ID_MAJOR GENMASK(31, 16) @@ -239,6 +240,11 @@ #define YT921X_EDATA_DATA_STATUS_M GENMASK(3, 0) #define YT921X_EDATA_DATA_STATUS(x) FIELD_PREP(YT921X_EDATA_DATA_STATU= S_M, (x)) #define YT921X_EDATA_DATA_IDLE YT921X_EDATA_DATA_STATUS(3) +#define YT921X_SYS_CLK 0xe0040 +#define YT921X_SYS_CLK_SEL_M GENMASK(1, 0) /* unknown: 167M */ +#define YT9215_SYS_CLK_125M 0 +#define YT9218_SYS_CLK_167M 0 +#define YT921X_SYS_CLK_143M 1 =20 #define YT921X_EXT_MBUS_OP 0x6a000 #define YT921X_INT_MBUS_OP 0xf0000 @@ -466,6 +472,44 @@ enum yt921x_app_selector { #define YT921X_LAG_HASH_MAC_DA BIT(1) #define YT921X_LAG_HASH_SRC_PORT BIT(0) =20 +#define YT921X_PORTn_RATE(port) (0x220000 + 4 * (port)) +#define YT921X_PORT_RATE_GAP_VALUE GENMASK(4, 0) /* default 20 */ +#define YT921X_METER_SLOT 0x220104 +#define YT921X_METER_SLOT_SLOT_M GENMASK(11, 0) +#define YT921X_PORTn_METER(port) (0x220108 + 4 * (port)) +#define YT921X_PORT_METER_EN BIT(4) +#define YT921X_PORT_METER_ID_M GENMASK(3, 0) +#define YT921X_PORT_METER_ID(x) FIELD_PREP(YT921X_PORT_METER_ID_M, (x)) +#define YT921X_METERn_CTRL(x) (0x220800 + 0x10 * (x)) +#define YT921X_METER_CTRL_S 3 +#define YT921X_METER_CTRLc_METER_EN BIT(14) +#define YT921X_METER_CTRLc_TOKEN_OVERFLOW_EN BIT(13) /* RFC4115: yellow u= se unused green bw */ +#define YT921X_METER_CTRLc_DROP_M GENMASK(12, 11) +#define YT921X_METER_CTRLc_DROP(x) FIELD_PREP(YT921X_METER_CTRLc_DROP_= M, (x)) +#define YT921X_METER_CTRLc_DROP_GYR YT921X_METER_CTRLc_DROP(0) +#define YT921X_METER_CTRLc_DROP_YR YT921X_METER_CTRLc_DROP(1) +#define YT921X_METER_CTRLc_DROP_R YT921X_METER_CTRLc_DROP(2) +#define YT921X_METER_CTRLc_DROP_NONE YT921X_METER_CTRLc_DROP(3) +#define YT921X_METER_CTRLc_COLOR_BLIND BIT(10) +#define YT921X_METER_CTRLc_UNIT_M GENMASK(9, 7) +#define YT921X_METER_CTRLc_UNIT(x) FIELD_PREP(YT921X_METER_CTRLc_UNIT_= M, (x)) +#define YT921X_METER_CTRLc_BYTE_MODE_INCLUDE_GAP BIT(6) /* +GAP_VALUE byt= es each packet */ +#define YT921X_METER_CTRLc_PKT_MODE BIT(5) /* 0: byte rate mode */ +#define YT921X_METER_CTRLc_RFC2698 BIT(4) /* 0: RFC4115 */ +#define YT921X_METER_CTRLbc_CBS_M GENMASK_ULL(35, 20) +#define YT921X_METER_CTRLbc_CBS(x) FIELD_PREP(YT921X_METER_CTRLbc_CBS_= M, (x)) +#define YT921X_METER_CTRLb_CIR_M GENMASK(19, 2) +#define YT921X_METER_CTRLb_CIR(x) FIELD_PREP(YT921X_METER_CTRLb_CIR_M,= (x)) +#define YT921X_METER_CTRLab_EBS_M GENMASK_ULL(33, 18) +#define YT921X_METER_CTRLab_EBS(x) FIELD_PREP(YT921X_METER_CTRLab_EBS_= M, (x)) +#define YT921X_METER_CTRLa_EIR_M GENMASK(17, 0) +#define YT921X_METER_CTRLa_EIR(x) FIELD_PREP(YT921X_METER_CTRLa_EIR_M,= (x)) + +#define YT921X_METERn_STAT_EXCESS(x) (0x221000 + 8 * (x)) +#define YT921X_METERn_STAT_COMMITTED(x) (0x221004 + 8 * (x)) +#define YT921X_METER_STAT_TOKEN_M GENMASK(30, 15) +#define YT921X_METER_STAT_QUEUE_M GENMASK(14, 0) + #define YT921X_PORTn_VLAN_CTRL(port) (0x230010 + 4 * (port)) #define YT921X_PORT_VLAN_CTRL_SVLAN_PRIO_EN BIT(31) #define YT921X_PORT_VLAN_CTRL_CVLAN_PRIO_EN BIT(30) @@ -509,6 +553,16 @@ enum yt921x_fdb_entry_status { =20 #define YT921X_MSTI_NUM 16 =20 +#define YT921X_TOKEN_BYTE_C 1 /* 1 token =3D 2^1 byte */ +#define YT921X_TOKEN_PKT_C -6 /* 1 token =3D 2^-6 packets */ +#define YT921X_TOKEN_RATE_C -15 +/* for VLAN only, not including port meters */ +#define YT921X_METER_NUM 64 +#define YT921X_METER_SLOT_MIN 80 +#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_LAG_NUM 2 #define YT921X_LAG_PORT_NUM 4 =20 @@ -603,8 +657,10 @@ struct yt921x_priv { struct dsa_switch ds; =20 const struct yt921x_info *info; + unsigned int meter_slot_ns; /* cache of dsa_cpu_ports(ds) */ u16 cpu_ports_mask; + u8 cycle_ns; =20 /* protect the access to the switch registers */ struct mutex reg_lock; --=20 2.51.0 From nobody Sat Feb 7 17:04:30 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