From: MD Danish Anwar 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 Signed-off-by: Meghana Malladi --- v3-v2: - Fixed build warning raised by kernel test bot v2-v1: - Following changes have been done as suggested by Vladimir Oltean * Add sanity check to ensure valid min_frag_size is requested by the user. * Add comments wherever applicable w.r.t min_frag_size. * Make it uniform to return all valures from the driver for .get_mm() * Use ETHTOOL_MM_MAX_VERIFY_TIME_MS macro for 128 * Use NL_SET_ERR_MSG_MOD() wherever applicable * Re-schedule the iet work thread whenever there .set_mm() get called based on fpe_enabled flag. drivers/net/ethernet/ti/icssg/icssg_ethtool.c | 86 ++++++++++++++++++- 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, 118 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..3c4ff154f6d1 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,88 @@ 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; + + 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 (!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); + + 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 +398,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 7a586038adf8..5271a013df64 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 8aa79b68ad54..b18a93f9181a 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_qos.h +++ b/drivers/net/ethernet/ti/icssg/icssg_qos.h @@ -55,4 +55,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 #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