From: David Yang <mmyangfl@gmail.com>
To: netdev@vger.kernel.org
Cc: David Yang <mmyangfl@gmail.com>, Andrew Lunn <andrew@lunn.ch>,
Vladimir Oltean <olteanv@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH net-next v3 3/4] net: dsa: motorcomm: Enable ACL on demand
Date: Sat, 10 Oct 2026 00:58:21 +0800 [thread overview]
Message-ID: <20261009165825.359259-4-mmyangfl@gmail.com> (raw)
In-Reply-To: <20261009165825.359259-1-mmyangfl@gmail.com>
Track the usage of ACL rules and enable it per port only when it is
actually used. This is aligned with ODM recommendations and helps reduce
latency.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
drivers/net/dsa/motorcomm/chip.h | 2 +
drivers/net/dsa/motorcomm/tc.c | 70 ++++++++++++++++++++++++++++----
2 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/drivers/net/dsa/motorcomm/chip.h b/drivers/net/dsa/motorcomm/chip.h
index 012de4f444f5..7047ad98f431 100644
--- a/drivers/net/dsa/motorcomm/chip.h
+++ b/drivers/net/dsa/motorcomm/chip.h
@@ -462,6 +462,8 @@ struct yt921x_port {
/* BR_ISOLATED */
bool isolated:1;
+ unsigned short acl_cnt;
+
#if IS_ENABLED(CONFIG_NET_DSA_YT921X_LEDS)
unsigned char led_duty;
unsigned short led_cycle;
diff --git a/drivers/net/dsa/motorcomm/tc.c b/drivers/net/dsa/motorcomm/tc.c
index be3321df8868..a302016912b5 100644
--- a/drivers/net/dsa/motorcomm/tc.c
+++ b/drivers/net/dsa/motorcomm/tc.c
@@ -1055,6 +1055,19 @@ yt921x_acl_rule_ext_parse_flow(struct yt921x_acl_rule_ext *ruleext, int port,
return 0;
}
+/* Ports that _should_ have ACL activated on. ACL_PORT \succeq activated_ports()
+ */
+static u16 yt921x_acl_activated_ports(const struct yt921x_priv *priv)
+{
+ u16 mask = 0;
+
+ for (int port = 0; port < YT921X_PORT_NUM; port++)
+ if (priv->ports[port].acl_cnt)
+ mask |= BIT(port);
+
+ return mask;
+}
+
static unsigned int
yt921x_acl_find(const struct yt921x_priv *priv, enum tc_setup_type type,
unsigned long tag)
@@ -1199,10 +1212,15 @@ yt921x_acl_del(struct yt921x_priv *priv, enum tc_setup_type type,
{
struct yt921x_acl_rule *aclrule;
struct yt921x_acl_blk *aclblk;
+ bool refresh_en = false;
unsigned int binid;
unsigned int blkid;
unsigned int entid;
+ unsigned long m;
+ unsigned int o;
+ u32 ctrl;
int res;
+ int ret;
entid = yt921x_acl_find(priv, type, tag);
if (entid == UINT_MAX)
@@ -1214,9 +1232,27 @@ yt921x_acl_del(struct yt921x_priv *priv, enum tc_setup_type type,
aclrule = aclblk->rules[binid];
aclblk->rules[binid] = NULL;
- res = yt921x_acl_commit(priv, entid, aclrule->mask);
+ ret = yt921x_acl_commit(priv, entid, aclrule->mask);
/* the kernel never rolls back on failure */
+ m = FIELD_GET(YT921X_ACL_KEYb_SPORTS_M, aclrule->entries[0].key[1]);
+ for_each_set_bit(o, &m, YT921X_PORT_NUM) {
+ struct yt921x_port *pp = &priv->ports[o];
+
+ if (!WARN_ON(!pp->acl_cnt)) {
+ pp->acl_cnt--;
+ if (pp->acl_cnt)
+ continue;
+ }
+ refresh_en = true;
+ }
+ if (refresh_en) {
+ ctrl = yt921x_acl_activated_ports(priv);
+ res = yt921x_reg_write(priv, YT921X_ACL_PORT, ctrl);
+ if (res)
+ ret = res;
+ }
+
if (aclrule->action[0] & YT921X_ACL_ACTa_METER_EN)
clear_bit(FIELD_GET(YT921X_ACL_ACTa_METER_ID_M,
aclrule->action[0]),
@@ -1227,7 +1263,7 @@ yt921x_acl_del(struct yt921x_priv *priv, enum tc_setup_type type,
kvfree(aclblk);
priv->acl_blks[blkid] = NULL;
}
- return res;
+ return ret;
}
static int
@@ -1240,11 +1276,12 @@ yt921x_acl_add(struct yt921x_priv *priv,
struct yt921x_acl_blk *aclblk;
bool use_trap = false;
unsigned int meterid;
- unsigned long mask;
unsigned int binid;
unsigned int blkid;
unsigned int entid;
+ unsigned long m;
unsigned int o;
+ u32 ctrl;
int res;
/* Allocate resources */
@@ -1293,8 +1330,8 @@ yt921x_acl_add(struct yt921x_priv *priv,
/* Replace the placeholder resource IDs */
aclrule->mask = 0;
- mask = priv->acl_masks[blkid];
- for_each_clear_bit(o, &mask, YT921X_ACL_ENT_PER_BLK) {
+ m = priv->acl_masks[blkid];
+ for_each_clear_bit(o, &m, YT921X_ACL_ENT_PER_BLK) {
aclrule->mask |= BIT(o);
entscnt--;
if (!entscnt)
@@ -1312,21 +1349,39 @@ yt921x_acl_add(struct yt921x_priv *priv,
else
aclrule->action[0] &= ~YT921X_ACL_ACTa_METER_EN;
+ /* Activate ACL if needed */
+ ctrl = 0;
+ m = FIELD_GET(YT921X_ACL_KEYb_SPORTS_M, ruleext->r.entries[0].key[1]);
+ for_each_set_bit(o, &m, YT921X_PORT_NUM)
+ if (!priv->ports[o].acl_cnt)
+ ctrl |= YT921X_ACL_PORT_PORTn(o);
+ if (ctrl) {
+ ctrl |= yt921x_acl_activated_ports(priv);
+ res = yt921x_reg_write(priv, YT921X_ACL_PORT, ctrl);
+ if (res)
+ goto err;
+ }
+
/* Write rules */
aclblk->rules[binid] = aclrule;
res = yt921x_acl_commit(priv, entid, aclrule->mask);
if (res) {
aclblk->rules[binid] = NULL;
- kvfree(aclrule);
goto err;
}
+ /* Bookkeeping */
+ m = FIELD_GET(YT921X_ACL_KEYb_SPORTS_M, ruleext->r.entries[0].key[1]);
+ for_each_set_bit(o, &m, YT921X_PORT_NUM)
+ priv->ports[o].acl_cnt++;
+
if (meterid < YT921X_METER_NUM)
set_bit(meterid, priv->meters_map);
priv->acl_masks[blkid] |= aclrule->mask;
return 0;
err:
+ kvfree(aclrule);
if (!priv->acl_masks[blkid]) {
kvfree(aclblk);
priv->acl_blks[blkid] = NULL;
@@ -1487,8 +1542,7 @@ int yt921x_chip_setup_acl(struct yt921x_priv *priv)
if (res)
return res;
- ctrl = YT921X_ACL_PORT_PORTS_M;
- res = yt921x_reg_write(priv, YT921X_ACL_PORT, ctrl);
+ res = yt921x_reg_write(priv, YT921X_ACL_PORT, 0);
if (res)
return res;
--
2.53.0
next prev parent reply other threads:[~2026-10-09 16:58 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 16:58 [PATCH net-next v3 0/4] net: dsa: motorcomm: TC offload follow-ups David Yang
2026-10-09 16:58 ` [PATCH net-next v3 1/4] net: dsa: motorcomm: Split TC module David Yang
2026-10-09 16:58 ` [PATCH net-next v3 2/4] net: dsa: motorcomm: Use NSEC_PER_SEC David Yang
2026-10-09 16:58 ` David Yang [this message]
2026-10-09 16:58 ` [PATCH net-next v3 4/4] net: dsa: motorcomm: Add TC prio support David Yang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261009165825.359259-4-mmyangfl@gmail.com \
--to=mmyangfl@gmail.com \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®