From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f46.google.com (mail-pj1-f46.google.com [209.85.216.46]) (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 9A48E47CC9B for ; Wed, 10 Jun 2026 20:26:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.46 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781123185; cv=none; b=s0+yGLxmeXNcBj74fvzg/gK0vweJQhG/soSo0gRnL2Pnm7JgNym2w9qbYDLeX1A6UyqwCaaA7yBBHoN5gLY/fyRF8xyBZ01UT4rHdC7Dje3a8M07Lgaog5UD1sZvUWlZQTG3mhrgIIxdxfRQGMr1P5XmEwidxKU9CUaLbsJ6hIs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781123185; c=relaxed/simple; bh=QmD01g2zflQj5xOEhdldYgX49cHQ+Jueyl2jKhidRV4=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=B2ZfHqIMbzH0uPLpIngAE5TolkGNpD1SlKYHcZUljrGkEH91PO1M3sdKsQGrtCuSCAYzSfm8OrbClWP+viiDwDe2TfW2AlTgGU1hR8iETNqX3gTchlsNzQ9AdNLnaE40LUdHv85bCTtfuvhzmKxXVu/aqF6HEAZ40cXbIi2af1M= 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=ef3TgI3I; arc=none smtp.client-ip=209.85.216.46 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="ef3TgI3I" Received: by mail-pj1-f46.google.com with SMTP id 98e67ed59e1d1-36d98c9b596so4584864a91.3 for ; Wed, 10 Jun 2026 13:26:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781123183; x=1781727983; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=wLJkMnHOGm8b5wMRcq5jC/SYuU+KHKbJfoRRO9fW7T8=; b=ef3TgI3IfbkOLRWKM9Bmj5eKy/yflicNsYEzmhZ+o65IVQrrK6P+kGT0Iu/B3ry8xo SF8fIJqMYTlvmDld8zQS7qskBGoXth9hGVbxPOoeLjWGoSk9atuy2wUtIT1rZ6SngMCf PaqbKY3QQ8rdNkI8nwmww8yhOENmyjv/kjno7sqN89efuaYp6AuSX+DJpjX6hYGc17Xu VkQz2iFR3Rl8jmFjragrU6IHOkne4ySc7fUMqFV4EqaNJbqnPOs+W/96w4FcieBo1LJ0 qYZJcoHr0dgF1zHJyKb5rOlyzR5Db5V5tsl/4RP7xYv9YSp0uHTq2a1BB38Gdzv9mEds eWLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781123183; x=1781727983; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=wLJkMnHOGm8b5wMRcq5jC/SYuU+KHKbJfoRRO9fW7T8=; b=STlsPh8Q0D2Cbc63i0BL8nGEiisEZOEetaFwppUE4orT/Pvr6u2FNvAKI+MTiqtTpx BRUIu5S/XRtFDOdZs8DdRs7zYRz8lyQsmvPOowp4F1YyqOaiK+AVw/1uKAS+KlrQAoGi YnpAlA1Wux/mVFq3GZ6DejkTH6WLqeXdFzsvtK/+hh33FzmxO7VFMgkka27CnD/Nhwa1 ULMOCGUC1REHIeEkBXCG5T/EmqxFfLW4aK+sFPrliPfKSG4WqtUvtTiBF8WripUTuBY+ +EN0chOK6I7d8IbCOFApV+WTeN4KqU4cvXLJIsJxTUjoB0ZeKDYCSon9FNATzW9zkLNP SLKA== X-Forwarded-Encrypted: i=1; AFNElJ98fYm8ztya35eO0dNOu9k/UBiGeVQMAV+kiGjApnqxrz849QDOg2qX0/9dcv6VHmHkk03oscbcMDluRJQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwyEvLg/bvjsaJyCeC0IFtS+h9Lg0eGu423ZWZu8jAEyHbvdTND RK3y4cpwo2o1K/LJcd5Xjdljzk5UzJpfOxnGWKK3t8JaVhbpMJOTif0k X-Gm-Gg: Acq92OGmmqr4nGlWpL4lafCnaW/eIXuT53hqN8eRHKJe2obGbLu50IRQ7FN6I4vCrwg xWBqr2zypa+HHxlnJdDHShPk2qeviTZni0Dnt17q+1Zgcn1KhZmP614mnK7zaUW6Dr66ijFLdv8 Gq94wouDirXjg52fB4hkkPv5MPjLLvFfRJ2Q7HmkQvWIFLd2amfuQlhjLm8/90YzgR7zmfmJ7Dk Ev36XzHgD96+OPZUYTTD4nm9LmEch8ZMoDE1sv0s1ZDNcZLD13P/vbNlN489ntnaWKloqUjiuCK OsUjYXNuGNs/cTYgvRpdjz+B1AaUUaVmOwedx7IRnKuHP6Np5bvMZrOlEllX3XW4QeE8LR7Gysi eN1XWs3vrVQ/Zq7AfbkvmpfNhbtvTIfCzpJ+/QnIFlODZ9MAEtNluZL28ggCyCUlBfmKcfCG5wq 7K2Q2GO0NOgt69/Ze5kWNDaoJ3ksItKcRIry8eYWhyRUs3r8jSPhW5N/CIsAGX X-Received: by 2002:a17:902:c942:b0:2b0:608d:d8a8 with SMTP id d9443c01a7336-2c1e79e2aa7mr311088325ad.1.1781123182787; Wed, 10 Jun 2026 13:26:22 -0700 (PDT) Received: from d.home.yangfl.dn42 ([2a09:bac5:661a:3046::4cf:38]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2c164f84335sm254754925ad.19.2026.06.10.13.26.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Jun 2026 13:26: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] net: dsa: yt921x: Add limited ACL flow statistics support Date: Thu, 11 Jun 2026 04:25:05 +0800 Message-ID: <20260610202508.845328-1-mmyangfl@gmail.com> X-Mailer: git-send-email 2.53.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit The yt921x supports flow statistics, which might be used to implement .cls_flower_stats(). However, the number of flow counter are limited, and you must choose between byte mode or packet mode. As there is no interface for statistics preference for now, we pick one on our own initiative. Signed-off-by: David Yang --- drivers/net/dsa/yt921x.c | 87 ++++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/yt921x.h | 13 ++++++ 2 files changed, 100 insertions(+) diff --git a/drivers/net/dsa/yt921x.c b/drivers/net/dsa/yt921x.c index 9929676a15e1..a553c966916a 100644 --- a/drivers/net/dsa/yt921x.c +++ b/drivers/net/dsa/yt921x.c @@ -373,6 +373,11 @@ yt921x_regs_clear_bits(struct yt921x_priv *priv, u32 reg, const u32 *masks, return yt921x_regs_write(priv, reg, vs, num_regs); } +static int yt921x_reg64_read(struct yt921x_priv *priv, u32 reg, u32 *vals) +{ + return yt921x_regs_read(priv, reg, vals, 2); +} + static int yt921x_reg64_write(struct yt921x_priv *priv, u32 reg, const u32 *vals) { @@ -2224,6 +2229,40 @@ yt921x_acl_reserve(struct yt921x_priv *priv, unsigned int entscnt, return UINT_MAX; } +static int +yt921x_acl_stat(struct yt921x_priv *priv, enum tc_setup_type type, + unsigned long tag, u64 *statp) +{ + const struct yt921x_acl_rule *aclrule; + const struct yt921x_acl_blk *aclblk; + unsigned int statid; + unsigned int binid; + unsigned int blkid; + unsigned int entid; + u32 vals[2]; + int res; + + entid = yt921x_acl_find(priv, type, tag); + if (entid == UINT_MAX) + return -ENOENT; + + blkid = entid / YT921X_ACL_ENT_PER_BLK; + binid = entid % YT921X_ACL_ENT_PER_BLK; + aclblk = priv->acl_blks[blkid]; + aclrule = aclblk->rules[binid]; + + if (!(aclrule->action[0] & YT921X_ACL_ACTa_FLOWSTAT_EN)) + return -EOPNOTSUPP; + + statid = FIELD_GET(YT921X_ACL_ACTa_FLOWSTAT_ID_M, aclrule->action[0]); + res = yt921x_reg64_read(priv, YT921X_FLOWSTATn_STAT(statid), vals); + if (res) + return res; + + *statp = ((u64)vals[1] << 32) | vals[0]; + return 0; +} + static int yt921x_acl_commit(struct yt921x_priv *priv, unsigned int entid, u8 entsmask) { @@ -2336,6 +2375,10 @@ yt921x_acl_del(struct yt921x_priv *priv, enum tc_setup_type type, clear_bit(FIELD_GET(YT921X_ACL_ACTa_METER_ID_M, aclrule->action[0]), priv->meters_map); + if (aclrule->action[0] & YT921X_ACL_ACTa_FLOWSTAT_EN) + clear_bit(FIELD_GET(YT921X_ACL_ACTa_FLOWSTAT_ID_M, + aclrule->action[0]), + priv->flowstats_map); priv->acl_masks[blkid] &= ~aclrule->mask; kvfree(aclrule); if (!priv->acl_masks[blkid]) { @@ -2355,11 +2398,13 @@ yt921x_acl_add(struct yt921x_priv *priv, struct yt921x_acl_blk *aclblk; bool use_trap = false; unsigned int meterid; + unsigned int statid; unsigned long mask; unsigned int binid; unsigned int blkid; unsigned int entid; unsigned int o; + u32 ctrl; int res; /* Allocate resources */ @@ -2386,6 +2431,22 @@ yt921x_acl_add(struct yt921x_priv *priv, } } + statid = find_first_zero_bit(priv->flowstats_map, YT921X_FLOWSTAT_NUM); + if (statid < YT921X_FLOWSTAT_NUM) { + u32 zeros[2] = {}; + + ctrl = YT921X_FLOWSTAT_CTRL_EN | YT921X_FLOWSTAT_CTRL_TYPE_FLOW; + res = yt921x_reg_write(priv, YT921X_FLOWSTATn_CTRL(statid), + ctrl); + if (res) + return res; + + res = yt921x_reg64_write(priv, YT921X_FLOWSTATn_STAT(statid), + zeros); + if (res) + return res; + } + /* Prepare acl block ctrlblk */ blkid = entid / YT921X_ACL_ENT_PER_BLK; binid = entid % YT921X_ACL_ENT_PER_BLK; @@ -2426,6 +2487,9 @@ yt921x_acl_add(struct yt921x_priv *priv, aclrule->action[0] |= YT921X_ACL_ACTa_METER_ID(meterid); else aclrule->action[0] &= ~YT921X_ACL_ACTa_METER_EN; + if (statid < YT921X_FLOWSTAT_NUM) + aclrule->action[0] |= YT921X_ACL_ACTa_FLOWSTAT_EN | + YT921X_ACL_ACTa_FLOWSTAT_ID(statid); /* Write rules */ aclblk->rules[binid] = aclrule; @@ -2438,6 +2502,8 @@ yt921x_acl_add(struct yt921x_priv *priv, if (meterid < YT921X_METER_NUM) set_bit(meterid, priv->meters_map); + if (statid < YT921X_FLOWSTAT_NUM) + set_bit(statid, priv->flowstats_map); priv->acl_masks[blkid] |= aclrule->mask; return 0; @@ -2449,6 +2515,26 @@ yt921x_acl_add(struct yt921x_priv *priv, return res; } +static int +yt921x_dsa_cls_flower_stats(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress) +{ + struct yt921x_priv *priv = to_yt921x_priv(ds); + int res; + + mutex_lock(&priv->reg_lock); + res = yt921x_acl_stat(priv, TC_SETUP_CLSFLOWER, cls->cookie, + &cls->stats.bytes); + mutex_unlock(&priv->reg_lock); + + if (res) + return res; + + cls->stats.used_hw_stats = FLOW_ACTION_HW_STATS_IMMEDIATE; + cls->stats.used_hw_stats_valid = true; + return 0; +} + static int yt921x_dsa_cls_flower_del(struct dsa_switch *ds, int port, struct flow_cls_offload *cls, bool ingress) @@ -4817,6 +4903,7 @@ static const struct dsa_switch_ops yt921x_dsa_switch_ops = { .port_policer_add = yt921x_dsa_port_policer_add, .port_setup_tc = yt921x_dsa_port_setup_tc, /* acl */ + .cls_flower_stats = yt921x_dsa_cls_flower_stats, .cls_flower_del = yt921x_dsa_cls_flower_del, .cls_flower_add = yt921x_dsa_cls_flower_add, /* hsr */ diff --git a/drivers/net/dsa/yt921x.h b/drivers/net/dsa/yt921x.h index 555046526669..5952900f1794 100644 --- a/drivers/net/dsa/yt921x.h +++ b/drivers/net/dsa/yt921x.h @@ -759,6 +759,16 @@ enum yt921x_l4_type { #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(x) (0x221000 + 8 * (x)) +#define YT921X_FLOWSTATn_STAT(x) (0x221400 + 8 * (x)) +#define YT921X_FLOWSTATn_CTRL(x) (0x221c00 + 4 * (x)) +#define YT921X_FLOWSTAT_CTRL_EN BIT(3) +#define YT921X_FLOWSTAT_CTRL_PKT_MODE BIT(2) /* 0: byte mode */ +#define YT921X_FLOWSTAT_CTRL_TYPE_M GENMASK(1, 0) +#define YT921X_FLOWSTAT_CTRL_TYPE(x) FIELD_PREP(YT921X_FLOWSTAT_CTRL_TYPE_M, (x)) +#define YT921X_FLOWSTAT_CTRL_TYPE_FLOW YT921X_FLOWSTAT_CTRL_TYPE(0) +#define YT921X_FLOWSTAT_CTRL_TYPE_CPU_CODE YT921X_FLOWSTAT_CTRL_TYPE(1) +#define YT921X_FLOWSTAT_CTRL_TYPE_DROP_CODE YT921X_FLOWSTAT_CTRL_TYPE(2) +#define YT921X_FLOWSTAT_CTRL_TYPE_PORT YT921X_FLOWSTAT_CTRL_TYPE(3) #define YT921X_PORTn_VLAN_CTRL(port) (0x230010 + 4 * (port)) #define YT921X_PORT_VLAN_CTRL_SVLAN_PRIO_EN BIT(31) @@ -830,6 +840,8 @@ enum yt921x_fdb_entry_status { #define YT921X_SHAPE_CIR_MAX ((1 << 18) - 1) #define YT921X_SHAPE_CBS_MAX ((1 << 14) - 1) +#define YT921X_FLOWSTAT_NUM 64 + #define YT921X_LAG_NUM 2 #define YT921X_LAG_PORT_NUM 4 @@ -969,6 +981,7 @@ struct yt921x_priv { u16 eee_ports_mask; DECLARE_BITMAP(meters_map, YT921X_METER_NUM); + DECLARE_BITMAP(flowstats_map, YT921X_FLOWSTAT_NUM); u8 acl_masks[YT921X_ACL_BLK_NUM]; struct yt921x_acl_blk *acl_blks[YT921X_ACL_BLK_NUM]; -- 2.53.0