From: Meghana Malladi <m-malladi@ti.com>
To: <haokexin@gmail.com>, <vadim.fedorenko@linux.dev>,
<jacob.e.keller@intel.com>, <m-malladi@ti.com>,
<horms@kernel.org>, <basharath@couthit.com>,
<parvathi@couthit.com>, <afd@ti.com>, <vladimir.oltean@nxp.com>,
<rogerq@kernel.org>, <danishanwar@ti.com>, <pabeni@redhat.com>,
<kuba@kernel.org>, <edumazet@google.com>, <davem@davemloft.net>,
<andrew+netdev@lunn.ch>
Cc: <linux-arm-kernel@lists.infradead.org>, <netdev@vger.kernel.org>,
<linux-kernel@vger.kernel.org>, <srk@ti.com>,
Vignesh Raghavendra <vigneshr@ti.com>
Subject: [PATCH net-next v4 2/2] net: ti: icssg-prueth: Add ethtool ops for Frame Preemption MAC Merge
Date: Tue, 24 Feb 2026 18:18:03 +0530 [thread overview]
Message-ID: <20260224124803.3634808-3-m-malladi@ti.com> (raw)
In-Reply-To: <20260224124803.3634808-1-m-malladi@ti.com>
From: MD Danish Anwar <danishanwar@ti.com>
Add driver support for viewing / changing the MAC Merge sublayer
parameters and dump the Mac Merge stats via ethtool ops: .set_mm(),
.get_mm() and .get_mm_stats().
The minimum size of non-final mPacket fragments supported by the firmware
without leading errors is 64 Bytes (in octets). Add a check to ensure
user passed tx_min_frag_size argument via ethtool, honors this .
Add pa stats registers to check statistics for preemption, which can be
dumped using ethtool ops.
Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
Signed-off-by: Meghana Malladi <m-malladi@ti.com>
---
v4-v3:
- Added pa-stats availability check inside emac_get_mm_stats() as flagged
by AI-generated review.
- Return -EOPNOTSUPP for SR1 devices inside ethtool_*_mm() functions
drivers/net/ethernet/ti/icssg/icssg_ethtool.c | 98 ++++++++++++++++++-
drivers/net/ethernet/ti/icssg/icssg_prueth.h | 5 +-
drivers/net/ethernet/ti/icssg/icssg_qos.h | 20 ++++
drivers/net/ethernet/ti/icssg/icssg_stats.c | 1 -
drivers/net/ethernet/ti/icssg/icssg_stats.h | 5 +
.../net/ethernet/ti/icssg/icssg_switch_map.h | 5 +
6 files changed, 130 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
index b715af21d23a..2176536a0989 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
@@ -6,7 +6,6 @@
*/
#include "icssg_prueth.h"
-#include "icssg_stats.h"
static void emac_get_drvinfo(struct net_device *ndev,
struct ethtool_drvinfo *info)
@@ -294,6 +293,100 @@ static int emac_set_per_queue_coalesce(struct net_device *ndev, u32 queue,
return 0;
}
+static int emac_get_mm(struct net_device *ndev, struct ethtool_mm_state *state)
+{
+ struct prueth_emac *emac = netdev_priv(ndev);
+ struct prueth_qos_iet *iet = &emac->qos.iet;
+
+ if (emac->is_sr1)
+ return -EOPNOTSUPP;
+
+ state->tx_enabled = iet->fpe_enabled;
+ state->pmac_enabled = true;
+ state->tx_min_frag_size = iet->tx_min_frag_size;
+ /* 64Bytes is the minimum fragment size supported
+ * by the firmware. <64B leads to min frame errors
+ */
+ state->rx_min_frag_size = 64;
+ state->tx_active = iet->fpe_active;
+ state->verify_enabled = iet->mac_verify_configure;
+ state->verify_time = iet->verify_time_ms;
+
+ switch (iet->verify_status) {
+ case ICSSG_IETFPE_STATE_DISABLED:
+ state->verify_status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
+ break;
+ case ICSSG_IETFPE_STATE_SUCCEEDED:
+ state->verify_status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
+ break;
+ case ICSSG_IETFPE_STATE_FAILED:
+ state->verify_status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
+ break;
+ default:
+ state->verify_status = ETHTOOL_MM_VERIFY_STATUS_UNKNOWN;
+ break;
+ }
+
+ /* 802.3-2018 clause 30.14.1.6, says that the aMACMergeVerifyTime
+ * variable has a range between 1 and 128 ms inclusive. Limit to that.
+ */
+ state->max_verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS;
+
+ return 0;
+}
+
+static int emac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
+ struct netlink_ext_ack *extack)
+{
+ struct prueth_emac *emac = netdev_priv(ndev);
+ struct prueth_qos_iet *iet = &emac->qos.iet;
+ int err;
+
+ if (emac->is_sr1)
+ return -EOPNOTSUPP;
+
+ if (!cfg->pmac_enabled)
+ NL_SET_ERR_MSG_MOD(extack, "preemptible MAC is always enabled");
+
+ err = icssg_qos_frag_size_min_to_add(cfg->tx_min_frag_size, extack);
+ if (err)
+ return err;
+
+ iet->verify_time_ms = cfg->verify_time;
+ iet->tx_min_frag_size = cfg->tx_min_frag_size;
+
+ iet->fpe_enabled = cfg->tx_enabled;
+ iet->mac_verify_configure = cfg->verify_enabled;
+
+ /* Re-trigger the state machine to incorporate the updated configuration */
+ if (iet->fpe_enabled)
+ atomic_set(&iet->enable_fpe_config, 1);
+ else
+ atomic_set(&iet->enable_fpe_config, 0);
+
+ schedule_work(&iet->fpe_config_task);
+
+ return 0;
+}
+
+static void emac_get_mm_stats(struct net_device *ndev,
+ struct ethtool_mm_stats *s)
+{
+ struct prueth_emac *emac = netdev_priv(ndev);
+
+ if (emac->is_sr1)
+ return;
+
+ if (!emac->prueth->pa_stats)
+ return;
+
+ s->MACMergeFrameAssOkCount = emac_get_stat_by_name(emac, "FW_PREEMPT_ASSEMBLY_OK");
+ s->MACMergeFrameAssErrorCount = emac_get_stat_by_name(emac, "FW_PREEMPT_ASSEMBLY_ERR");
+ s->MACMergeFragCountRx = emac_get_stat_by_name(emac, "FW_PREEMPT_FRAG_CNT_RX");
+ s->MACMergeFragCountTx = emac_get_stat_by_name(emac, "FW_PREEMPT_FRAG_CNT_TX");
+ s->MACMergeFrameSmdErrorCount = emac_get_stat_by_name(emac, "FW_PREEMPT_BAD_FRAG");
+}
+
const struct ethtool_ops icssg_ethtool_ops = {
.get_drvinfo = emac_get_drvinfo,
.get_msglevel = emac_get_msglevel,
@@ -317,5 +410,8 @@ const struct ethtool_ops icssg_ethtool_ops = {
.set_eee = emac_set_eee,
.nway_reset = emac_nway_reset,
.get_rmon_stats = emac_get_rmon_stats,
+ .get_mm = emac_get_mm,
+ .set_mm = emac_set_mm,
+ .get_mm_stats = emac_get_mm_stats,
};
EXPORT_SYMBOL_GPL(icssg_ethtool_ops);
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
index 37de534e4d43..d9f95d6edc8d 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
@@ -45,6 +45,7 @@
#include "icss_iep.h"
#include "icssg_switch_map.h"
#include "icssg_qos.h"
+#include "icssg_stats.h"
#define PRUETH_MAX_MTU (2000 - ETH_HLEN - ETH_FCS_LEN)
#define PRUETH_MIN_PKT_SIZE (VLAN_ETH_ZLEN)
@@ -58,8 +59,8 @@
#define ICSSG_MAX_RFLOWS 8 /* per slice */
-#define ICSSG_NUM_PA_STATS 32
-#define ICSSG_NUM_MIIG_STATS 60
+#define ICSSG_NUM_PA_STATS ARRAY_SIZE(icssg_all_pa_stats)
+#define ICSSG_NUM_MIIG_STATS ARRAY_SIZE(icssg_all_miig_stats)
/* Number of ICSSG related stats */
#define ICSSG_NUM_STATS (ICSSG_NUM_MIIG_STATS + ICSSG_NUM_PA_STATS)
#define ICSSG_NUM_STANDARD_STATS 31
diff --git a/drivers/net/ethernet/ti/icssg/icssg_qos.h b/drivers/net/ethernet/ti/icssg/icssg_qos.h
index 653dbb57791d..bf84cc1b8282 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_qos.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_qos.h
@@ -57,4 +57,24 @@ void icssg_qos_link_up(struct net_device *ndev);
void icssg_qos_link_down(struct net_device *ndev);
int icssg_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type,
void *type_data);
+static inline int icssg_qos_frag_size_min_to_add(u32 min_frag_size,
+ struct netlink_ext_ack *extack)
+{
+ /* The minimum size of the non-final mPacket supported
+ * by the firmware is 64B and multiples of 64B.
+ */
+ if (min_frag_size < 64) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "tx_min_frag_size must be at least 64 bytes");
+ return -EINVAL;
+ }
+
+ if (min_frag_size % (ETH_ZLEN + ETH_FCS_LEN)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "tx_min_frag_size must be a multiple of 64 bytes");
+ return -EINVAL;
+ }
+
+ return 0;
+}
#endif /* __NET_TI_ICSSG_QOS_H */
diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.c b/drivers/net/ethernet/ti/icssg/icssg_stats.c
index 7159baa0155c..d27e1c48976f 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_stats.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_stats.c
@@ -6,7 +6,6 @@
*/
#include "icssg_prueth.h"
-#include "icssg_stats.h"
#include <linux/regmap.h>
#define ICSSG_TX_PACKET_OFFSET 0xA0
diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.h b/drivers/net/ethernet/ti/icssg/icssg_stats.h
index 5ec0b38e0c67..f35ae1b4f846 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_stats.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_stats.h
@@ -189,6 +189,11 @@ static const struct icssg_pa_stats icssg_all_pa_stats[] = {
ICSSG_PA_STATS(FW_INF_DROP_PRIOTAGGED),
ICSSG_PA_STATS(FW_INF_DROP_NOTAG),
ICSSG_PA_STATS(FW_INF_DROP_NOTMEMBER),
+ ICSSG_PA_STATS(FW_PREEMPT_BAD_FRAG),
+ ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_ERR),
+ ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_TX),
+ ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_OK),
+ ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_RX),
ICSSG_PA_STATS(FW_RX_EOF_SHORT_FRMERR),
ICSSG_PA_STATS(FW_RX_B0_DROP_EARLY_EOF),
ICSSG_PA_STATS(FW_TX_JUMBO_FRM_CUTOFF),
diff --git a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
index 7e053b8af3ec..855fd4ed0b3f 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
@@ -256,6 +256,11 @@
#define FW_INF_DROP_PRIOTAGGED 0x0148
#define FW_INF_DROP_NOTAG 0x0150
#define FW_INF_DROP_NOTMEMBER 0x0158
+#define FW_PREEMPT_BAD_FRAG 0x0160
+#define FW_PREEMPT_ASSEMBLY_ERR 0x0168
+#define FW_PREEMPT_FRAG_CNT_TX 0x0170
+#define FW_PREEMPT_ASSEMBLY_OK 0x0178
+#define FW_PREEMPT_FRAG_CNT_RX 0x0180
#define FW_RX_EOF_SHORT_FRMERR 0x0188
#define FW_RX_B0_DROP_EARLY_EOF 0x0190
#define FW_TX_JUMBO_FRM_CUTOFF 0x0198
--
2.43.0
next prev parent reply other threads:[~2026-02-24 12:48 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-24 12:48 [PATCH net-next v4 0/2] Add Frame Preemption MAC Merge support for ICSSG Meghana Malladi
2026-02-24 12:48 ` [PATCH net-next v4 1/2] net: ti: icssg-prueth: Add Frame Preemption MAC Merge support Meghana Malladi
2026-02-26 16:19 ` Vladimir Oltean
2026-02-24 12:48 ` Meghana Malladi [this message]
2026-02-26 18:08 ` [PATCH net-next v4 2/2] net: ti: icssg-prueth: Add ethtool ops for Frame Preemption MAC Merge Vladimir Oltean
2026-03-01 15:10 ` [net-next,v4,2/2] " Simon Horman
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=20260224124803.3634808-3-m-malladi@ti.com \
--to=m-malladi@ti.com \
--cc=afd@ti.com \
--cc=andrew+netdev@lunn.ch \
--cc=basharath@couthit.com \
--cc=danishanwar@ti.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=haokexin@gmail.com \
--cc=horms@kernel.org \
--cc=jacob.e.keller@intel.com \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=parvathi@couthit.com \
--cc=rogerq@kernel.org \
--cc=srk@ti.com \
--cc=vadim.fedorenko@linux.dev \
--cc=vigneshr@ti.com \
--cc=vladimir.oltean@nxp.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