From nobody Mon Jun 15 02:46:43 2026 Received: from mail-pg1-f181.google.com (mail-pg1-f181.google.com [209.85.215.181]) (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 CD2C73CF05F for ; Tue, 7 Apr 2026 16:10:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775578226; cv=none; b=cVwu8u4CVskT4UkInJYg9hSZNIXtDEl40kqojHJfgpGqHzNCu+a0GajJcBUSLU36iQpjPucQnoi3w1Qbkr4KlrZaRA3NFYL5GYamNkQ0y/PncZc+P/DEPhAlhWZyudF3+MyM8Id92F+bCZZMisAcCxav0VKkU1JflWKAwEsTXv8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775578226; c=relaxed/simple; bh=v+E1MO93EOHLyDkpX6IzNEHlsvKdg/1FgUS+hyR8of4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BXkpJXYEEf4i1JzT5NFBAUdF47lJD94ocK4sVXpxIKSzfFsk3f2AF/SKzHreWm/MvwIGCLfgjgQb+69vw0DMhcznTNMTHzO6kL2iBypfDpbXRwZXljh00PGw3wvRA6iqDd6INv1zfKCLRsvMR7JWyJqxmqQkE/mTJNdzhRFgilo= 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=UZTpZcQ9; arc=none smtp.client-ip=209.85.215.181 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="UZTpZcQ9" Received: by mail-pg1-f181.google.com with SMTP id 41be03b00d2f7-c76af79f029so2125383a12.3 for ; Tue, 07 Apr 2026 09:10:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775578218; x=1776183018; 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=Vm1sew/8xxotCRJE85MOTIviBnsMsznbuVyL8JjP6fo=; b=UZTpZcQ9wc+CFaMHYsyXcRlKDJGjvKxd8bgMasKI5YLKYOcKNAO8IteifxlJe46ts3 +r7Gx++jVgej0cVmzgG1VYJuDgWrnrJKQ+y6Fk/WlENZcOS1V3304R5KxIFaSEefPjwx 7o+lbazpNg3uAIzNl6jevvJANnYQYLW+OJkzYQs/gxzZfOj4EaTHZvU3f1E42Ze2gT+m A/VsR4lMKggEKSqXxI2dRK3EYmqToEHdSJZFy7FZERt4qUtf9OmqGami8ldYbR5efyiJ x74jXyZfqAy+F7x8+GByib0ktyM+nZxy/ZxlrWj60iQDnUoZZ3gIVs49wyIfwHcJZ9Kz r38Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775578218; x=1776183018; 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=Vm1sew/8xxotCRJE85MOTIviBnsMsznbuVyL8JjP6fo=; b=NbHC0+J9hZ1ZvdJObk8vGwHoeoUXR06AD713bANpV1yGa8WbizOEAhwjIn60B3SobE w2kyDWkBNZIlEp6kivfb/HNNHUFf7dxyk7dAZXQjFRSWjoYvN2RZzM+zW3bqBgb5o6Zx OcAwQ4/n7/KZpMtqYyHn7/jAg1zLZNW3FVHcWCgxUMrokHvdYA/5W7ItlLZUPNiUwlu7 41QUXjzoYh9SBa5NdBTr4jnn/PykSWhuyoXwpsMr0QI89qh7ypYy1zKhRfu84MioV5pq +hTLh+rW0snwGnXd7QETJmTw3P+7I2fmB1i5YicEaLBdHbEFb1AOrdap1jRcEv+6+LGR zcBA== X-Forwarded-Encrypted: i=1; AJvYcCWAYo8Q0IsfJANy3pwaDFlLlTABS9bkTZbP27Om2wTlwGru9gsaIkQv2NUCsbEqwo47N+2t9SNGgLeXZzw=@vger.kernel.org X-Gm-Message-State: AOJu0Yw34vX3okN5U3fF85xPTlSlixkn/sMcUsyG/8UeZu4RB1wXck3u iAz4TIQaLStyKqB6XoCRKJLybAQ2Lx3c9VCg7smU5+P/BuGVboSxCxqN X-Gm-Gg: AeBDies+6ag4wpBtPc2bJ51rBc2iYRN33CbIqxiHE8hRlYAIx9mkGtAfbkK/WtgnLuI lQBwr21dHmKCOkYOwgxvwc4Kbug9e/pBrEb1q7N4rn+11MBiU1QSDJCozZu3bR1/bljrj7nP0yE ZVC9UCR//cA1owIcYUTXnvEx9OqzCNp9Ubkb11MWUqgWfYa00/izWKTZDmfmAOly78rkRghIRpW ysRMjAd67JK0Uf7cQn74fksqxlVCs0/l0R7k/IyhtbE/JJ94z21PWnpbLG/YhebkHsGjUJ1aYXI Skh6CL6JCb3AKn4EtE/ejq3S9P1WtWjfmu7SHMwqvQnV/s/FRWfpRRTqM5yTf6Y0sPZa+t6IPwv DJz8nIFvSR34VzT9YbUJWmcuwlEvj5OXsX5uKNpsWxzk0Tj62eE/StEW68BVgvIogiv9n5uSGJC UROEpyz3BGgVoeXHqaQztFCa016vJNHnaCiOGqGJbEvV6qieWT X-Received: by 2002:a05:6a20:a11a:b0:398:9301:b9ae with SMTP id adf61e73a8af0-39f2f11b8a1mr18437529637.52.1775578218119; Tue, 07 Apr 2026 09:10:18 -0700 (PDT) Received: from d.home.yangfl.dn42 ([2a09:bac1:7680:d30::4cf:90]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c76c6372078sm15650238a12.0.2026.04.07.09.10.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Apr 2026 09:10:17 -0700 (PDT) From: David Yang To: netdev@vger.kernel.org Cc: David Yang , Andrew Lunn , Vladimir Oltean , UNGLinuxDriver@microchip.com, "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , linux-kernel@vger.kernel.org Subject: [PATCH net-next v3 1/4] net: dsa: pass extack to user tc policers Date: Wed, 8 Apr 2026 00:05:53 +0800 Message-ID: <20260407160559.1747616-2-mmyangfl@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260407160559.1747616-1-mmyangfl@gmail.com> References: <20260407160559.1747616-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" Users may use extack for a friendly error message instead of dumping everything into dmesg. Make the according transformations to the two users (sja1105 and felix). Signed-off-by: David Yang Reviewed-by: Andrew Lunn --- drivers/net/dsa/ocelot/felix.c | 3 ++- drivers/net/dsa/sja1105/sja1105_main.c | 3 ++- include/net/dsa.h | 3 ++- net/dsa/user.c | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 84cf8e7fb17a..4272ea6e9ca8 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -2001,7 +2001,8 @@ static int felix_cls_flower_stats(struct dsa_switch *= ds, int port, } =20 static int felix_port_policer_add(struct dsa_switch *ds, int port, - const struct flow_action_police *policer) + const struct flow_action_police *policer, + struct netlink_ext_ack *extack) { struct ocelot *ocelot =3D ds->priv; struct ocelot_policer pol =3D { diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja11= 05/sja1105_main.c index c72c2bfdcffb..dbfa45064747 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -2847,7 +2847,8 @@ static void sja1105_mirror_del(struct dsa_switch *ds,= int port, } =20 static int sja1105_port_policer_add(struct dsa_switch *ds, int port, - const struct flow_action_police *policer) + const struct flow_action_police *policer, + struct netlink_ext_ack *extack) { struct sja1105_l2_policing_entry *policing; struct sja1105_private *priv =3D ds->priv; diff --git a/include/net/dsa.h b/include/net/dsa.h index 8b6d34e8a6f0..4cc67469cf2e 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -1122,7 +1122,8 @@ struct dsa_switch_ops { void (*port_mirror_del)(struct dsa_switch *ds, int port, struct dsa_mall_mirror_tc_entry *mirror); int (*port_policer_add)(struct dsa_switch *ds, int port, - const struct flow_action_police *policer); + const struct flow_action_police *policer, + struct netlink_ext_ack *extack); void (*port_policer_del)(struct dsa_switch *ds, int port); int (*port_setup_tc)(struct dsa_switch *ds, int port, enum tc_setup_type type, void *type_data); diff --git a/net/dsa/user.c b/net/dsa/user.c index c4bd6fe90b45..8704c1a3a5b7 100644 --- a/net/dsa/user.c +++ b/net/dsa/user.c @@ -1499,7 +1499,7 @@ dsa_user_add_cls_matchall_police(struct net_device *d= ev, policer =3D &mall_tc_entry->policer; *policer =3D act->police; =20 - err =3D ds->ops->port_policer_add(ds, dp->index, policer); + err =3D ds->ops->port_policer_add(ds, dp->index, policer, extack); if (err) { kfree(mall_tc_entry); return err; --=20 2.53.0 From nobody Mon Jun 15 02:46:43 2026 Received: from mail-pg1-f181.google.com (mail-pg1-f181.google.com [209.85.215.181]) (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 DD4E4386541 for ; Tue, 7 Apr 2026 16:10:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775578230; cv=none; b=nj9lBCkASBJiMB89tMx5O9dRYjBNeNJhD2ODh3IjPITKHHspfcaXPgeI5rSGIy5IQkm2ZgQr2E18CDOihT4t9SfTJW2O3JoQuYglHTtIN4/BaeFqPI8dq9AwUZP4b0WWr8woyHxwluBhotkpsIyW+z3U9wWGc96QveUfmPPbtd4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775578230; c=relaxed/simple; bh=00JYzBQ/fGB6OBkHYf37XI57wrah6rPGE2MFkhMCV6o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eMSRRbvGy+mfTzqBB49HovEzxnEnEtFKN2ac80LZ5J0EtKI8unJ1B7FpEXmB4Jy+cZWPrj/4y2zqsbrEgWx5VS2WBN2DU/vk7MI9xlzjNlc6p7UzwaQsOpWYDtyXr7Fq8tpiTcwIMVAnFu3nZvDVU6PUvVJUIF7t/WWEhNzF52Y= 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=UWMpYr33; arc=none smtp.client-ip=209.85.215.181 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="UWMpYr33" Received: by mail-pg1-f181.google.com with SMTP id 41be03b00d2f7-c76b87931b8so3616195a12.2 for ; Tue, 07 Apr 2026 09:10:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775578223; x=1776183023; 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=osFjjLnInsmXNvjP78Zxgysf1bF9rd2bISOLOklUimE=; b=UWMpYr33km5xfoc2r6Ng+oinqqFMKeGpi6GX/sCkN07ARxUsF6DzlZosNKvcSrChRq NLfOhpCJGS1Pj77cyCMWeXCXARYTMBMn1RixTh8jJc3slzq5wBkPuBWrPsRalMg/XzqU cVTsU47P5PABgaeNlqpvNkiiJyQ1MwHlx51BNphjoJOdIzE1h/4tFRltOvgOLsahnLIG U+1+mMYqMA6rkX8Z7EmCTafaVdxh6LBTypITcGyCb9BAVij0tPEh5sodgBK+a1+bSHR0 uSQNeZR0+PrfSGFr0Xa0zyKIC7f/fvkGUua1Dpe2yxnnxrj+AsvE1l5sIyjA3UEUZ91L UueQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775578223; x=1776183023; 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=osFjjLnInsmXNvjP78Zxgysf1bF9rd2bISOLOklUimE=; b=SUZ36vhDCSjbJra4ykVNQRJBlYH7S/ev6rtv0qDXwJrcKExUGPFL138O2EctBluV20 Z57LRpKSx9Jj7HHodt26BnvofFJKyP65MxK8sNz3/cz4Je+BMJqhREWPrAUgE6CleZM5 3RxVJ8lmNsJWdGaAuPM46I2mZ4fZGRYkH165CIwkdJRz1dLPU8a6bKLpp01n9CdBr1vE 2oe5oQBZ9+KcZoRlOL/6z3SqmpOVCMKJP2d16/wIdql416APO6A4oRh8oT7jBN/J1RUG qdxx55QrSdJpevjZ8q/QgiVVgdnwSziDsMhtEE/nZTtboXO5Z+9ExGyJiLxtOowYR9Iz NuLw== X-Forwarded-Encrypted: i=1; AJvYcCXwwCHS5fXZf8/1BPP69Ed7e/5S3mMXqVa3XnQpa2/lRfzJrvln8ZBvERgJeR0Z9CnhUQ0Z7FLXJTn3s08=@vger.kernel.org X-Gm-Message-State: AOJu0YwP9ePfs6Wi5l5dleywDN5s3Qv5/UyT3KrGqOOnZvr2XqZbC3jY B9QCeh9q0jOiqYVnYNKKK8E89x8gEGdG3TvQtnGGCJ9v6EKkBqKzOKSa X-Gm-Gg: AeBDietW9EyY5jguiWSk0FVrfMtW8+nqJWYXC6GQ3iK0OnZtvLCuHQgfoUfBLYBpeAK LV1rLvihcrt6ky8CG7sgdFh1lPJO6ZBv/XefNtC5QW+Ow2S7OjbNAgy6rcaeS7CnaKn9YLF9usb Sl7tbmb3I0kbGqCL783YTXsr2UMNjWLw/ODdrO0R+UqL0XKT/+Pt1mzNooqWXizwjqcjcL1dV43 DBLp2Rnx8A0/kfYu9CH73sTMk1uY+Hlo/DXxbz8LCWBWoBfgOIMXBSUB2nNM9hXm5ANIkPKcsEE b4/P2JLQRryOkp72KLabKW+HFwa4qwzTwWfC5DoHkDIW6SRnOJc8d+0OJwFoXx8c+s8M3wGx0+9 IG0QmQPY24SuYv6IHratxZ8ssTpGvrx9aDhTpETspzPgIcgkS6qk62wFPu5ekOqM1k2/9sz0e9+ 9i/tOvqjOuWPspm8XPo2BdENTWKMZi1WxvLa6QP9GwsXaUhdDo X-Received: by 2002:a05:6a20:7354:b0:39b:e321:784f with SMTP id adf61e73a8af0-39f2f05041dmr18842777637.40.1775578222608; Tue, 07 Apr 2026 09:10:22 -0700 (PDT) Received: from d.home.yangfl.dn42 ([2a09:bac1:7680:d30::4cf:90]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c76c6372078sm15650238a12.0.2026.04.07.09.10.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Apr 2026 09:10:22 -0700 (PDT) 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: [PATCH net-next v3 2/4] net: dsa: yt921x: Refactor long register helpers Date: Wed, 8 Apr 2026 00:05:54 +0800 Message-ID: <20260407160559.1747616-3-mmyangfl@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260407160559.1747616-1-mmyangfl@gmail.com> References: <20260407160559.1747616-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 96-bit registers. Refactor reg64 helpers with u32 arrays, so they are aligned with further reg96 helpers. We do not keep the u64 implement to avoid duplicated wrappers, although it looks better when we deal with reg64 *only*. Helpers for reg96 should be added when they are actually used to avoid function unused warnings. Signed-off-by: David Yang --- drivers/net/dsa/yt921x.c | 161 ++++++++++++++++++++++++++------------- drivers/net/dsa/yt921x.h | 36 ++++----- 2 files changed, 128 insertions(+), 69 deletions(-) diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c index 87139448bec3..de6aa5835616 100644 --- a/drivers/net/dsa/yt921x.c +++ b/drivers/net/dsa/yt921x.c @@ -255,63 +255,121 @@ 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 whole, even i= f 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 the read + * wrapper so that we can handle them consistently. */ =20 -static int yt921x_reg64_read(struct yt921x_priv *priv, u32 reg, u64 *valp) +static int +yt921x_regs_read(struct yt921x_priv *priv, u32 reg, u32 *vals, + unsigned int num_regs) { - 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 < num_regs; i++) { + res =3D yt921x_reg_read(priv, reg + 4 * i, &vals[i]); + if (res) + return res; + } + + return 0; +} + +static int +yt921x_regs_write(struct yt921x_priv *priv, u32 reg, const u32 *vals, + unsigned int num_regs) +{ + int res; + + for (unsigned int i =3D 0; i < num_regs; i++) { + res =3D yt921x_reg_write(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_regs_update_bits(struct yt921x_priv *priv, u32 reg, const u32 *mask= s, + const u32 *vals, unsigned int num_regs) { + bool changed =3D false; + u32 vs[4]; int res; =20 - res =3D yt921x_reg_write(priv, reg, (u32)val); + BUILD_BUG_ON(num_regs > ARRAY_SIZE(vs)); + + res =3D yt921x_regs_read(priv, reg, vs, num_regs); if (res) return res; - return yt921x_reg_write(priv, reg + 4, (u32)(val >> 32)); + + for (unsigned int i =3D 0; i < num_regs; 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; + + return yt921x_regs_write(priv, reg, vs, num_regs); } =20 static int -yt921x_reg64_update_bits(struct yt921x_priv *priv, u32 reg, u64 mask, u64 = val) +yt921x_regs_clear_bits(struct yt921x_priv *priv, u32 reg, const u32 *masks, + unsigned int num_regs) { + 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(num_regs > ARRAY_SIZE(vs)); + + res =3D yt921x_regs_read(priv, reg, vs, num_regs); 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 < num_regs; 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; =20 - return yt921x_reg64_write(priv, reg, u); + return yt921x_regs_write(priv, reg, vs, num_regs); +} + +static int +yt921x_reg64_write(struct yt921x_priv *priv, u32 reg, const u32 *vals) +{ + return yt921x_regs_write(priv, reg, vals, 2); } =20 -static int yt921x_reg64_clear_bits(struct yt921x_priv *priv, u32 reg, u64 = mask) +static int +yt921x_reg64_update_bits(struct yt921x_priv *priv, u32 reg, const u32 *mas= ks, + const u32 *vals) { - return yt921x_reg64_update_bits(priv, reg, mask, 0); + return yt921x_regs_update_bits(priv, reg, masks, vals, 2); +} + +static int +yt921x_reg64_clear_bits(struct yt921x_priv *priv, u32 reg, const u32 *mask= s) +{ + return yt921x_regs_clear_bits(priv, reg, masks, 2); } =20 static int yt921x_reg_mdio_read(void *context, u32 reg, u32 *valp) @@ -1844,33 +1902,31 @@ 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[2]; =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_reg64_clear_bits(priv, YT921X_VLANn_CTRL(vid), masks); } =20 static int yt921x_vlan_add(struct yt921x_priv *priv, int port, u16 vid, bool untagged) { - u64 mask64; - u64 ctrl64; + u32 masks[2]; + u32 ctrls[2]; =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); + masks, ctrls); } =20 static int @@ -2318,8 +2374,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[2]; + u32 ctrls[2]; int res; =20 if (!msti->vid) @@ -2327,12 +2383,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); + masks, ctrls); mutex_unlock(&priv->reg_lock); =20 return res; @@ -3084,7 +3142,7 @@ static int yt921x_chip_setup_dsa(struct yt921x_priv *= priv) { struct dsa_switch *ds =3D &priv->ds; unsigned long cpu_ports_mask; - u64 ctrl64; + u32 ctrls[2]; u32 ctrl; int port; int res; @@ -3145,8 +3203,9 @@ 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_reg64_write(priv, YT921X_VLANn_CTRL(0), ctrls); if (res) return res; =20 diff --git a/drivers/net/dsa/yt921x.h b/drivers/net/dsa/yt921x.h index 3f129b8d403f..4989d87c2492 100644 --- a/drivers/net/dsa/yt921x.h +++ b/drivers/net/dsa/yt921x.h @@ -429,24 +429,24 @@ 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_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.53.0 From nobody Mon Jun 15 02:46:43 2026 Received: from mail-pg1-f171.google.com (mail-pg1-f171.google.com [209.85.215.171]) (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 228BD3CE492 for ; Tue, 7 Apr 2026 16:10:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775578234; cv=none; b=NlP2RRnDszgDjlX7Q8CzLAExVVGXR7gRF99MDSlQBIx1HC3hlfKtm1UuD2l8jQOaytnZHsoOPyXPFAEryojRSy5hXZSU2/4MM/Oab+NmBk89TKdXCDSmRlJIKpGxQI+vJ7VdDB2dONCVklC8/jQReyBSxJ+qCDsBTBTRbwIPpU8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775578234; c=relaxed/simple; bh=g2mfLVmLwZ+cJYfQtFfWR/Yr96oiHaXcdKw8NGPLMbE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OnhKHwxsuLhDrb3CwBa2RkXesepI9CTq1DcIAeQbcoHTzgmDd+J6MYrWgHS/d2vScNfBpmMsnDBzlGdwQr6K6NTlc9Pr9xctTnTLgWZt8dY8zfrzf4DvDxWfdVpZ769yFJe2gkZk+NJPktxUZ9dQNqU4Db0SNYM378b4LOCBYB8= 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=Xfmu6t4p; arc=none smtp.client-ip=209.85.215.171 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="Xfmu6t4p" Received: by mail-pg1-f171.google.com with SMTP id 41be03b00d2f7-c736261ee8dso1734846a12.1 for ; Tue, 07 Apr 2026 09:10:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775578226; x=1776183026; 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=sYakr9JQEjE2FqaXKjcdVODvFiPPk2RzFGSKQlkcOZ4=; b=Xfmu6t4pjnmuNmDK4oweKsvDCRXDo2DpW26vFs6MDhiT2bkR7A8Gs7PDrDQmTaqfAc ZZzgByGld0rRlYVB39spjHAVk3RkRvUC8Pfwien11yobD6zb5gGUFQ97mE0iGyIzQaG5 TpVbwObj0QoKwWwctvOogShh0tz6sOeKxabQ+y6PJfWmNCHR1EfpHfZIVzLqPsgzJOuA J0xsiVz1hCOQwCQjW0TBtdnsoPq++HcLWyZMHukoTcSMnyyLV4F3VpOXTZZT6+sK0Dx3 WkFEAxGAkEzsaTfzSKfgJQW17SqOdd7wwtyAVh9zKTRBZqjfU6WZL2vQnB8zuAvAEo09 eTxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775578226; x=1776183026; 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=sYakr9JQEjE2FqaXKjcdVODvFiPPk2RzFGSKQlkcOZ4=; b=F5us9z3G1BN3FxkOg+afm04sY47686H9QphsDBHL+4LsfwDuD9/aNEHuOnNwBx1TqK 3Zn5+2NDEjOG0WljUUTFVrGhz4JbmvRH4YI3c2gK/4S6EPdKpqgmtuCjNmog0aXLGYIL Cvj9OEW1E3ltlqsm9CIGyeBvfeVhIHt7Mic2WyL70G2SJe+/isyF/P0y1UoY/k20mpwp 5JNpTjaezRX+o57UzLjOzuyrGcdOP8PEeEdFn/qB0NXPsv40vcNUbp54PVCrNgzbFeDI bpwZuTA/rbh2boEdtN78XjLZ0bMTnZ9idtwl5iZCJaKCXux/tGmFHoG+Z3EOGp6VxzCD //uQ== X-Forwarded-Encrypted: i=1; AJvYcCXnW2rsKJGZvEdBrVuPAkLoKr0k0dfpz/uqb+ykKADNPdzmC9jhmfyAValz9Ad2cdDwEFAr7AxTNFTbCVc=@vger.kernel.org X-Gm-Message-State: AOJu0Yy5fBArzreKHhIjNUuY2IBn+/MwKAAxLPDbzyxFH+N3VHNoKkFk bAFYff7qVHNx+iOarkGhA55CNUitFUrTGX3NYYs1RMDbgvnvK32agdqz X-Gm-Gg: AeBDievuec04NMziIHq6McKn6R05sdJNTwyNBUTMwSGHSB4LSF1CQpO1irJIq0112x/ 1Qjr1gkB4GFxnZam7kefYR1YscocpQChvf2HAXOqdeCoB4CzRTdh6MXE45OYHObBE7MRRByX6hX iOxnGbWchJOc/xZKqp3S/6auiiKoxESUyaf20eNIGfiwdtcQUYJpDPsJmRZ4oPnm9eQTri130dL hc6WwmNSCeHtD5SYvbpglAduwM8DeCcHfPHq1L+iln0AX86kHmisFxHuHnim7SMRZhmXVVNuQbE 89FED8BICZadRJNj9ROenVRV6NApnpaWxwLsnpY7d47Qh0uRyIEyfhXi+GLLxvCkvEzAGm4GKGG 7e3evmEOD674su0+oAxlGMSq5vbKdEL4jlkCVxpHtlfV2uHCicZYJMvNm56hoKUiUROfOE9M7yX BgNemyxlrypgUXVnTKtGQC1mtylzwuFWwXRNPWIeTfMgIJMswc X-Received: by 2002:a05:6a20:430b:b0:39b:e789:7d10 with SMTP id adf61e73a8af0-39f2f20dfc7mr18092550637.57.1775578225497; Tue, 07 Apr 2026 09:10:25 -0700 (PDT) Received: from d.home.yangfl.dn42 ([2a09:bac1:7680:d30::4cf:90]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c76c6372078sm15650238a12.0.2026.04.07.09.10.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Apr 2026 09:10:25 -0700 (PDT) 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: [PATCH net-next v3 3/4] net: dsa: yt921x: Add port police support Date: Wed, 8 Apr 2026 00:05:55 +0800 Message-ID: <20260407160559.1747616-4-mmyangfl@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260407160559.1747616-1-mmyangfl@gmail.com> References: <20260407160559.1747616-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 | 276 ++++++++++++++++++++++++++++++++++++++- drivers/net/dsa/yt921x.h | 54 ++++++++ 2 files changed, 329 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c index de6aa5835616..e77bd4a34e10 100644 --- a/drivers/net/dsa/yt921x.c +++ b/drivers/net/dsa/yt921x.c @@ -262,6 +262,14 @@ yt921x_reg_toggle_bits(struct yt921x_priv *priv, u32 r= eg, u32 mask, bool set) * wrapper so that we can handle them consistently. */ =20 +static void update_ctrls_unaligned(u32 *lo, u32 *hi, u64 mask, u64 val) +{ + *lo &=3D ~lower_32_bits(mask); + *hi &=3D ~upper_32_bits(mask); + *lo |=3D lower_32_bits(val); + *hi |=3D upper_32_bits(val); +} + static int yt921x_regs_read(struct yt921x_priv *priv, u32 reg, u32 *vals, unsigned int num_regs) @@ -372,6 +380,12 @@ yt921x_reg64_clear_bits(struct yt921x_priv *priv, u32 = reg, const u32 *masks) return yt921x_regs_clear_bits(priv, reg, masks, 2); } =20 +static int +yt921x_reg96_write(struct yt921x_priv *priv, u32 reg, const u32 *vals) +{ + return yt921x_regs_write(priv, reg, vals, 3); +} + static int yt921x_reg_mdio_read(void *context, u32 reg, u32 *valp) { struct yt921x_reg_mdio *mdio =3D context; @@ -1065,6 +1079,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) { @@ -1096,6 +1117,219 @@ 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 */ +static u64 ldexpu64(u64 v, int e) +{ + return e >=3D 0 ? v << e : v >> -e; +} + +/* slot (ns) * rate (/s) / 10^9 (ns/s) =3D 2^C * token * 4^unit */ +static u32 rate2token(u64 rate, unsigned int slot_ns, int unit, int C) +{ + int e =3D 2 * unit + C + YT921X_TOKEN_RATE_C; + + return div_u64(ldexpu64(slot_ns * rate, -e), 1000000000); +} + +static u64 token2rate(u32 token, unsigned int slot_ns, int unit, int C) +{ + int e =3D 2 * unit + C + YT921X_TOKEN_RATE_C; + + return div_u64(ldexpu64(mul_u32_u32(1000000000, token), e), slot_ns); +} + +/* burst =3D 2^C * token * 4^unit */ +static u32 burst2token(u64 burst, int unit, int C) +{ + return ldexpu64(burst, -(2 * unit + C)); +} + +static u64 token2burst(u32 token, int unit, int C) +{ + return ldexpu64(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 int +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, + struct yt921x_meter *meterp) +{ + 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; + u64 burst_est; + u64 burst_sug; + u64 burst_max; + u64 rate_max; + + meter.unit =3D unit_max; + rate_max =3D token2rate(cir_max, slot_ns, meter.unit, C); + burst_max =3D token2burst(cbs_max, meter.unit, C); + + /* Check for unusual values */ + if (rate > rate_max || burst > burst_max) + return -ERANGE; + + /* Check for matching burst */ + burst_est =3D div_u64(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 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 */ + meter.cir =3D rate2token(rate, slot_ns, meter.unit, C); + if (!meter.cir) + meter.cir =3D 1; + else if (WARN_ON(meter.cir > cir_max)) + meter.cir =3D cir_max; + meter.cbs =3D burst2token(burst, meter.unit, C); + if (!meter.cbs) + meter.cbs =3D 1; + else if (WARN_ON(meter.cbs > cbs_max)) + meter.cbs =3D cbs_max; + + /* 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); + + *meterp =3D meter; + return 0; +} + +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) + dev_err(dev, "Failed to %s port %d: %i\n", "delete policer on", + port, res); +} + +static int +yt921x_dsa_port_policer_add(struct dsa_switch *ds, int port, + const struct flow_action_police *policer, + struct netlink_ext_ack *extack) +{ + struct yt921x_priv *priv =3D to_yt921x_priv(ds); + struct yt921x_meter meter; + bool pkt_mode; + u32 ctrls[3]; + u64 burst; + u64 rate; + u32 ctrl; + int res; + + /* mtu defaults to unlimited but we got 2040 here, don't know why */ + if (policer->peakrate_bytes_ps || policer->avrate || policer->overhead) { + NL_SET_ERR_MSG_MOD(extack, + "peakrate / avrate / overhead not supported"); + return -EOPNOTSUPP; + } + if (policer->exceed.act_id !=3D FLOW_ACTION_DROP || + policer->notexceed.act_id !=3D FLOW_ACTION_ACCEPT) { + NL_SET_ERR_MSG_MOD(extack, + "conform-exceed other than drop-ok not supported"); + return -EOPNOTSUPP; + } + + pkt_mode =3D !!policer->rate_pkt_ps; + rate =3D pkt_mode ? policer->rate_pkt_ps : policer->rate_bytes_ps; + burst =3D pkt_mode ? policer->burst_pkt : policer->burst; + res =3D yt921x_meter_tfm(priv, port, priv->meter_slot_ns, rate, burst, + pkt_mode ? YT921X_METER_PKT_MODE : 0, + YT921X_METER_CIR_MAX, YT921X_METER_CBS_MAX, + YT921X_METER_UNIT_MAX, &meter); + if (res) { + NL_SET_ERR_MSG_MOD(extack, "Unexpected tremendous rate"); + return res; + } + + 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; + update_ctrls_unaligned(&ctrls[0], &ctrls[1], + YT921X_METER_CTRLab_EBS_M, + YT921X_METER_CTRLab_EBS(meter.ebs)); + update_ctrls_unaligned(&ctrls[1], &ctrls[2], + YT921X_METER_CTRLbc_CBS_M, + YT921X_METER_CTRLbc_CBS(meter.cbs)); + res =3D yt921x_reg96_write(priv, + YT921X_METERn_CTRL(port + YT921X_METER_NUM), + ctrls); +end: + mutex_unlock(&priv->reg_lock); + + return res; +} + static int yt921x_mirror_del(struct yt921x_priv *priv, int port, bool ingress) { @@ -3051,6 +3285,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); @@ -3085,12 +3320,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 @@ -3212,6 +3462,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; @@ -3258,7 +3525,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; @@ -3267,6 +3534,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) @@ -3358,6 +3629,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 4989d87c2492..a640672d1f1e 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 @@ -465,6 +471,42 @@ 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_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) @@ -508,6 +550,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_CIR_MAX ((1 << 18) - 1) +#define YT921X_METER_CBS_MAX ((1 << 16) - 1) + #define YT921X_LAG_NUM 2 #define YT921X_LAG_PORT_NUM 4 =20 @@ -602,8 +654,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.53.0 From nobody Mon Jun 15 02:46:43 2026 Received: from mail-pj1-f50.google.com (mail-pj1-f50.google.com [209.85.216.50]) (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 4B20936D9F9 for ; Tue, 7 Apr 2026 16:10:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775578237; cv=none; b=iLgmUSBW2J5f/zckTjrLhsp/bYqzQtDjFtwnoByotlXJcJkl+XylhaP9BFIDWQWzbFgzsIGlqtPB3ZocvYlTyMuEwBa81LP2+6GyU3b0vLzzHMDu0MuEd4JomZwXD5BTHBgzU4X/UEH06ixViOedANl58JSLFnmy+OkNQp8gWcg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775578237; c=relaxed/simple; bh=hF82NWQJBc2WFU61B+UG2P726TqXY6jc7G43zMgos4o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HQitfFwf+ucMd5VRlcaVgAjiAe411nlS3mW1Jslg9SB4ReOw3Y5cl33rzUbfJEsm13a7cSAopZTtR+q2VI5nwq5cJWCNpNYGJ43MDM1Uq37ymtk3HFDO7mBzy+BjE+rNzyGkth0C7kbVjjzGdETW1nW8Rz6hEZ0Ajx7W5b9ky30= 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=MSaP78Sj; arc=none smtp.client-ip=209.85.216.50 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="MSaP78Sj" Received: by mail-pj1-f50.google.com with SMTP id 98e67ed59e1d1-354a18c48b5so4550857a91.1 for ; Tue, 07 Apr 2026 09:10:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775578229; x=1776183029; 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=JRUvXpceETuGX3yJUhh4jXH+4ZRB9zEdwf1xaftsJqs=; b=MSaP78Sj7FRxGMaHonQUKdZwa8HfXm1zCuP7QRYUcYQRxsJX94jaLMGDuORHxVoGYv 8X4KHzGjri1f4NFvnYXJOZmiy6oqT793fVFAHd8kcAsU7sI9qVGVTGL+Ccoh4N4hCAqS H2vx/CAxWdOVkXkGzi+6ZTkRWIzbief5Fc9QObBwgFOvBAb9zRzuP9vn2DzEabyPlgIo qYdINbwhWvHj+FZgyCos8JDYsVWhAs3UlzsOtgy/ove6v4QGMxKoX46M9UsBuW84ldEy 7efw2xXtAXIXqNRt4tlzGek7CkiOgyOR6HvBjkpJFu2H9WC87cO6qIbMV9BDirx/ak2F kwpQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775578229; x=1776183029; 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=JRUvXpceETuGX3yJUhh4jXH+4ZRB9zEdwf1xaftsJqs=; b=gJj8in2pBHkTogXXw6sOJF32/8CLlmVvoBI5/Kv3yHGuMYLlcvclhcp9TsJH91/Kv0 0bX90iivPLpVf4VUUPb1qYKns0K+2D0oMsDZzsbtEITbsZV2ZCBo2s+KrdOchhARjBwh JBDmh31QEFfOsp9iSzbNmuObWIY0x/WeitI8BNLbD5/Jj9t+Db2fl1sFgQyp2ZdDKV0/ pofMcMz6TaiKrwAMDiuFQxIbtp9pXcqBXRshONyix7yu/+U7+kAGTP4SvyhvqCTHCtZJ hSDgAncbGnUjs2Eg6DH8bohvdybUrynNNmcNeFzlUY80v+2e9tB7cwp7IV9RZBKNDCpG +lWg== X-Forwarded-Encrypted: i=1; AJvYcCVbg7X+Q5/MbmwcV2fy+/a/VNNn+3PGHjK8Z5gSBxxs8k0Behiwm4nloyvE8UCOJ6pF/b8NoGTuhuJaaW0=@vger.kernel.org X-Gm-Message-State: AOJu0YzRl1BXf3/lc3NfN97dWc0SkZC5nkVWnvVzIVWA3pHXGKhkLUPg AQ6vXFP/wA1oYTDOEEo3HpR3JS6PZ1puVdKf0AxW35UDgN7FxDmr/C3P X-Gm-Gg: AeBDieshbJd84G6zeYo8dnjOwJzjsUOP5MnzI2ciCqsLW8IYJjF4z78XXbUiUMsl4Oo pnVULd47fzSpTw8V9hsWQL+92VmNHTYZHDywDl0G8E1UyUhgALJRd8usPbBi0FtRxG42WZFiyVg 2rzYePbntAmJOfcVtYR5YHPfjBy+d9RZW7edfT6UY598rmgcm0AQ1NtfMFCcJGjmcnlDzgQ13sA xud0UA5/EhI6IiopzHF0y8D/O4qKlxRKERQnC3WG69SHFQWPCzwr+f4BYYoF7W2VSPAgcCtEPmR CLlFA079iEigSihqzI7uy6xZmzRxCaAxht/1VPiTYAdKiItz6acYLH7SZ1f3fuCKFGEmvv485A4 Qi5IGoeqIuvDobokdiCiQze+zVa9/x75qOYC6qyqFRxTMJvzEx0aIEgVHkQOKMaVWpmXoVm0Crg W4gIu83i/AhNLHR6rAtPRn5ow1Bq7fUZLCkh1hn4Pmb0EKF448 X-Received: by 2002:a05:6a21:a105:b0:39c:a791:6ab1 with SMTP id adf61e73a8af0-39f2f050544mr15128274637.31.1775578228850; Tue, 07 Apr 2026 09:10:28 -0700 (PDT) Received: from d.home.yangfl.dn42 ([2a09:bac1:7680:d30::4cf:90]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c76c6372078sm15650238a12.0.2026.04.07.09.10.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Apr 2026 09:10:28 -0700 (PDT) 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: [PATCH net-next v3 4/4] net: dsa: yt921x: Add port qdisc tbf support Date: Wed, 8 Apr 2026 00:05:56 +0800 Message-ID: <20260407160559.1747616-5-mmyangfl@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260407160559.1747616-1-mmyangfl@gmail.com> References: <20260407160559.1747616-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 | 123 +++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/yt921x.h | 65 ++++++++++++++++++++- 2 files changed, 187 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c index e77bd4a34e10..0c87a0e02148 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 @@ -1330,6 +1331,113 @@ 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; + + /* TODO: queue support */ + 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; + } + break; + } + 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[2]; + 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 div_u64(priv->port_shape_slot_ns * p->rate.rate_bytes_ps, + 1000000000) + 10000; + res =3D yt921x_meter_tfm(priv, port, priv->port_shape_slot_ns, + p->rate.rate_bytes_ps, burst, + YT921X_METER_SINGLE_BUCKET, + YT921X_SHAPE_CIR_MAX, + YT921X_SHAPE_CBS_MAX, + YT921X_SHAPE_UNIT_MAX, &meter); + if (res) + return res; + + 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_reg64_write(priv, YT921X_PORTn_SHAPE_CTRL(port), ctrls); + 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) { @@ -3476,6 +3584,20 @@ 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; + + ctrl =3D max(priv->queue_shape_slot_ns / op_ns, + YT921X_QUEUE_SHAPE_SLOT_MIN); + res =3D yt921x_reg_write(priv, YT921X_QUEUE_SHAPE_SLOT, ctrl); + if (res) + return res; + priv->queue_shape_slot_ns =3D ctrl * op_ns; + return 0; } =20 @@ -3632,6 +3754,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 a640672d1f1e..991989a31727 100644 --- a/drivers/net/dsa/yt921x.h +++ b/drivers/net/dsa/yt921x.h @@ -524,6 +524,12 @@ enum yt921x_app_selector { #define YT921X_PORT_VLAN_CTRL1_CVLAN_DROP_TAGGED BIT(1) #define YT921X_PORT_VLAN_CTRL1_CVLAN_DROP_UNTAGGED BIT(0) =20 +#define YT921X_PORTn_PRIO_UCAST_QUEUE(port) (0x300200 + 4 * (port)) +#define YT921X_PORT_PRIOm_UCAST_QUEUE_M(m) (7 << (3 * (m))) +#define YT921X_PORT_PRIOm_UCAST_QUEUE(m, x) ((x) << (3 * (m))) +#define YT921X_PORTn_PRIO_MCAST_QUEUE(port) (0x300280 + 4 * (port)) +#define YT921X_PORT_PRIOm_MCAST_QUEUE_M(m) (3 << (2 * (m))) +#define YT921X_PORT_PRIOm_MCAST_QUEUE(m, x) ((x) << (2 * (m))) #define YT921X_MIRROR 0x300300 #define YT921X_MIRROR_IGR_PORTS_M GENMASK(26, 16) #define YT921X_MIRROR_IGR_PORTS(x) FIELD_PREP(YT921X_MIRROR_IGR_PORTS_= M, (x)) @@ -534,6 +540,47 @@ 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_QUEUE_SHAPE_SLOT 0x340008 +#define YT921X_QUEUE_SHAPE_SLOT_SLOT_M GENMASK(11, 0) +#define YT921X_PORT_SHAPE_SLOT 0x34000c +#define YT921X_PORT_SHAPE_SLOT_SLOT_M GENMASK(11, 0) +#define YT921X_QUEUEn_SCH(x) (0x341000 + 4 * (x)) +#define YT921X_QUEUE_SCH_E_DWRR_M GENMASK(27, 18) +#define YT921X_QUEUE_SCH_E_DWRR(x) FIELD_PREP(YT921X_QUEUE_SCH_E_DWRR_= M, (x)) +#define YT921X_QUEUE_SCH_C_DWRR_M GENMASK(17, 8) +#define YT921X_QUEUE_SCH_C_DWRR(x) FIELD_PREP(YT921X_QUEUE_SCH_C_DWRR_= M, (x)) +#define YT921X_QUEUE_SCH_E_PRIO_M GENMASK(7, 4) +#define YT921X_QUEUE_SCH_E_PRIO(x) FIELD_PREP(YT921X_QUEUE_SCH_E_PRIO_= M, (x)) +#define YT921X_QUEUE_SCH_C_PRIO_M GENMASK(3, 0) +#define YT921X_QUEUE_SCH_C_PRIO(x) FIELD_PREP(YT921X_QUEUE_SCH_C_PRIO_= M, (x)) +#define YT921X_C_DWRRn(x) (0x342000 + 4 * (x)) +#define YT921X_E_DWRRn(x) (0x343000 + 4 * (x)) +#define YT921X_DWRR_PKT_MODE BIT(0) /* 0: byte rate mode */ +#define YT921X_QUEUEn_SHAPE_CTRL(x) (0x34c000 + 0x10 * (x)) +#define YT921X_QUEUE_SHAPE_CTRLc_TOKEN_OVERFLOW_EN BIT(6) +#define YT921X_QUEUE_SHAPE_CTRLc_E_EN BIT(5) +#define YT921X_QUEUE_SHAPE_CTRLc_C_EN BIT(4) +#define YT921X_QUEUE_SHAPE_CTRLc_PKT_MODE BIT(3) /* 0: byte rate mode */ +#define YT921X_QUEUE_SHAPE_CTRLc_UNIT_M GENMASK(2, 0) +#define YT921X_QUEUE_SHAPE_CTRLc_UNIT(x) FIELD_PREP(YT921X_QUEUE_SHAPE_= CTRLc_UNIT_M, (x)) +#define YT921X_QUEUE_SHAPE_CTRLb_EBS_M GENMASK(31, 18) +#define YT921X_QUEUE_SHAPE_CTRLb_EBS(x) FIELD_PREP(YT921X_QUEUE_SHAPE_C= TRLb_EBS_M, (x)) +#define YT921X_QUEUE_SHAPE_CTRLb_EIR_M GENMASK(17, 0) +#define YT921X_QUEUE_SHAPE_CTRLb_EIR(x) FIELD_PREP(YT921X_QUEUE_SHAPE_C= TRLb_EIR_M, (x)) +#define YT921X_QUEUE_SHAPE_CTRLa_CBS_M GENMASK(31, 18) +#define YT921X_QUEUE_SHAPE_CTRLa_CBS(x) FIELD_PREP(YT921X_QUEUE_SHAPE_C= TRLa_CBS_M, (x)) +#define YT921X_QUEUE_SHAPE_CTRLa_CIR_M GENMASK(17, 0) +#define YT921X_QUEUE_SHAPE_CTRLa_CIR(x) FIELD_PREP(YT921X_QUEUE_SHAPE_C= TRLa_CIR_M, (x)) +#define YT921X_PORTn_SHAPE_CTRL(port) (0x354000 + 8 * (port)) +#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 @@ -559,6 +606,11 @@ enum yt921x_fdb_entry_status { #define YT921X_METER_UNIT_MAX ((1 << 3) - 1) #define YT921X_METER_CIR_MAX ((1 << 18) - 1) #define YT921X_METER_CBS_MAX ((1 << 16) - 1) +#define YT921X_PORT_SHAPE_SLOT_MIN 80 +#define YT921X_QUEUE_SHAPE_SLOT_MIN 132 +#define YT921X_SHAPE_UNIT_MAX ((1 << 3) - 1) +#define YT921X_SHAPE_CIR_MAX ((1 << 18) - 1) +#define YT921X_SHAPE_CBS_MAX ((1 << 14) - 1) =20 #define YT921X_LAG_NUM 2 #define YT921X_LAG_PORT_NUM 4 @@ -576,7 +628,16 @@ enum yt921x_fdb_entry_status { #define YT921X_TAG_LEN 8 =20 /* 8 internal + 2 external + 1 mcu */ -#define YT921X_PORT_NUM 11 +#define YT921X_PORT_NUM 11 +#define YT921X_UCAST_QUEUE_NUM 8 +#define YT921X_MCAST_QUEUE_NUM 4 +#define YT921X_PORT_QUEUE_NUM \ + (YT921X_UCAST_QUEUE_NUM + YT921X_MCAST_QUEUE_NUM) +#define YT921X_UCAST_QUEUE_ID(port, queue) \ + (YT921X_UCAST_QUEUE_NUM * (port) + (queue)) +#define YT921X_MCAST_QUEUE_ID(port, queue) \ + (YT921X_UCAST_QUEUE_NUM * YT921X_PORT_NUM + \ + YT921X_MCAST_QUEUE_NUM * (port) + (queue)) =20 #define yt921x_port_is_internal(port) ((port) < 8) #define yt921x_port_is_external(port) (8 <=3D (port) && (port) < 9) @@ -655,6 +716,8 @@ struct yt921x_priv { =20 const struct yt921x_info *info; unsigned int meter_slot_ns; + unsigned int port_shape_slot_ns; + unsigned int queue_shape_slot_ns; /* cache of dsa_cpu_ports(ds) */ u16 cpu_ports_mask; u8 cycle_ns; --=20 2.53.0