[PATCH net-next 0/3] net: ethernet: am65-cpsw: Add ethtool standard MAC stats
STALE1048d
13 messages,
4 authors,
2023-11-14 · open the first message on its own page
Hi,
Gets 'ethtool -S eth0 --groups eth-mac' command to work.
Also set default TX channels to maximum available.
cheers,
-roger
Roger Quadros (3):
net: ethernet: am65-cpsw: Add standard Ethernet MAC stats to ethtool
net: ethernet: am65-cpsw: Set default TX channels to maximum
net: ethernet: am65-cpsw: Error out if Enable TX/RX channel fails
drivers/net/ethernet/ti/am65-cpsw-ethtool.c | 26 +++++++++++++++
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 37 ++++++++++++++++-----
2 files changed, 55 insertions(+), 8 deletions(-)
base-commit: 89cdf9d556016a54ff6ddd62324aa5ec790c05cc
--
2.34.1
Gets 'ethtool -S eth0 --groups eth-mac' command to work.
Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
drivers/net/ethernet/ti/am65-cpsw-ethtool.c | 26 +++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c
index c51e2af91f69..ac7276f0f77a 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c @@ -662,6 +662,31 @@ static void am65_cpsw_get_ethtool_stats(struct net_device *ndev,
hw_stats [ i ]. offset );
}
+ static void am65_cpsw_get_eth_mac_stats ( struct net_device * ndev ,
+ struct ethtool_eth_mac_stats * s )
+ {
+ struct am65_cpsw_port * port = am65_ndev_to_port ( ndev );
+ struct am65_cpsw_stats_regs * stats ;
+
+ stats = port -> stat_base ;
+
+ s -> FramesTransmittedOK = readl_relaxed ( & stats -> tx_good_frames );
+ s -> SingleCollisionFrames = readl_relaxed ( & stats -> tx_single_coll_frames );
+ s -> MultipleCollisionFrames = readl_relaxed ( & stats -> tx_mult_coll_frames );
+ s -> FramesReceivedOK = readl_relaxed ( & stats -> rx_good_frames );
+ s -> FrameCheckSequenceErrors = readl_relaxed ( & stats -> rx_crc_errors );
+ s -> AlignmentErrors = readl_relaxed ( & stats -> rx_align_code_errors );
+ s -> OctetsTransmittedOK = readl_relaxed ( & stats -> tx_octets );
+ s -> FramesWithDeferredXmissions = readl_relaxed ( & stats -> tx_deferred_frames );
+ s -> LateCollisions = readl_relaxed ( & stats -> tx_late_collisions );
+ s -> CarrierSenseErrors = readl_relaxed ( & stats -> tx_carrier_sense_errors );
+ s -> OctetsReceivedOK = readl_relaxed ( & stats -> rx_octets );
+ s -> MulticastFramesXmittedOK = readl_relaxed ( & stats -> tx_multicast_frames );
+ s -> BroadcastFramesXmittedOK = readl_relaxed ( & stats -> tx_broadcast_frames );
+ s -> MulticastFramesReceivedOK = readl_relaxed ( & stats -> rx_multicast_frames );
+ s -> BroadcastFramesReceivedOK = readl_relaxed ( & stats -> rx_broadcast_frames );
+ };
+
static int am65_cpsw_get_ethtool_ts_info ( struct net_device * ndev ,
struct ethtool_ts_info * info )
{ @@ -729,6 +754,7 @@ const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
. get_sset_count = am65_cpsw_get_sset_count ,
. get_strings = am65_cpsw_get_strings ,
. get_ethtool_stats = am65_cpsw_get_ethtool_stats ,
+ . get_eth_mac_stats = am65_cpsw_get_eth_mac_stats ,
. get_ts_info = am65_cpsw_get_ethtool_ts_info ,
. get_priv_flags = am65_cpsw_get_ethtool_priv_flags ,
. set_priv_flags = am65_cpsw_set_ethtool_priv_flags , --
2.34.1
am65-cpsw supports 8 TX hardware queues. Set this as default.
Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index ece9f8df98ae..7c440899c93c 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -136,6 +136,8 @@
NETIF_MSG_IFUP | NETIF_MSG_PROBE | NETIF_MSG_IFDOWN | \
NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR )
+ #define AM65_CPSW_DEFAULT_TX_CHNS 8
+
static void am65_cpsw_port_set_sl_mac ( struct am65_cpsw_port * slave ,
const u8 * dev_addr )
{ @@ -2897,7 +2899,7 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
common -> rx_flow_id_base = -1 ;
init_completion ( & common -> tdown_complete );
- common -> tx_ch_num = 1 ;
+ common -> tx_ch_num = AM65_CPSW_DEFAULT_TX_CHNS ;
common -> pf_p0_rx_ptype_rrobin = false ;
common -> default_vlan = 1 ;
--
2.34.1
k3_udma_glue_enable_rx/tx_chn returns error code on failure.
Bail out on error while enabling TX/RX channel.
Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 33 +++++++++++++++++++-----
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 7c440899c93c..340f25bf33b1 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -372,7 +372,7 @@ static void am65_cpsw_init_port_emac_ale(struct am65_cpsw_port *port);
static int am65_cpsw_nuss_common_open ( struct am65_cpsw_common * common )
{
struct am65_cpsw_host * host_p = am65_common_get_host ( common );
- int port_idx , i , ret ;
+ int port_idx , i , ret , tx ;
struct sk_buff * skb ;
u32 val , port_mask ;
@@ -453,13 +453,22 @@ static int am65_cpsw_nuss_common_open(struct am65_cpsw_common *common)
}
kmemleak_not_leak ( skb );
}
- k3_udma_glue_enable_rx_chn ( common -> rx_chns . rx_chn );
- for ( i = 0 ; i < common -> tx_ch_num ; i ++ ) {
- ret = k3_udma_glue_enable_tx_chn ( common -> tx_chns [ i ]. tx_chn );
- if ( ret )
- return ret ;
- napi_enable ( & common -> tx_chns [ i ]. napi_tx );
+ ret = k3_udma_glue_enable_rx_chn ( common -> rx_chns . rx_chn );
+ if ( ret ) {
+ dev_err ( common -> dev , "couldn't enable rx chn: %d \n " , ret );
+ return ret ;
+ }
+
+ for ( tx = 0 ; tx < common -> tx_ch_num ; tx ++ ) {
+ ret = k3_udma_glue_enable_tx_chn ( common -> tx_chns [ tx ]. tx_chn );
+ if ( ret ) {
+ dev_err ( common -> dev , "couldn't enable tx chn %d: %d \n " ,
+ tx , ret );
+ tx -- ;
+ goto fail_tx ;
+ }
+ napi_enable ( & common -> tx_chns [ tx ]. napi_tx );
}
napi_enable ( & common -> napi_rx ); @@ -470,6 +479,16 @@ static int am65_cpsw_nuss_common_open(struct am65_cpsw_common *common)
dev_dbg ( common -> dev , "cpsw_nuss started \n " );
return 0 ;
+
+ fail_tx :
+ while ( tx >= 0 ) {
+ napi_disable ( & common -> tx_chns [ tx ]. napi_tx );
+ k3_udma_glue_disable_tx_chn ( common -> tx_chns [ tx ]. tx_chn );
+ tx -- ;
+ }
+
+ k3_udma_glue_disable_rx_chn ( common -> rx_chns . rx_chn );
+ return ret ;
}
static void am65_cpsw_nuss_tx_cleanup ( void * data , dma_addr_t desc_dma ); --
2.34.1
On Mon, Nov 13, 2023 at 01:07:06PM +0200, Roger Quadros wrote: Gets 'ethtool -S eth0 --groups eth-mac' command to work.
Signed-off-by: Roger Quadros <rogerq@kernel.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
On Mon, Nov 13, 2023 at 01:07:07PM +0200, Roger Quadros wrote: am65-cpsw supports 8 TX hardware queues. Set this as default.
Signed-off-by: Roger Quadros <rogerq@kernel.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
On Mon, Nov 13, 2023 at 01:07:08PM +0200, Roger Quadros wrote: k3_udma_glue_enable_rx/tx_chn returns error code on failure.
Bail out on error while enabling TX/RX channel.
Signed-off-by: Roger Quadros <rogerq@kernel.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
On Mon, Nov 13, 2023 at 01:07:06PM +0200, Roger Quadros wrote: quoted hunk Gets 'ethtool -S eth0 --groups eth-mac' command to work.
Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
drivers/net/ethernet/ti/am65-cpsw-ethtool.c | 26 +++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c
index c51e2af91f69..ac7276f0f77a 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c @@ -662,6 +662,31 @@ static void am65_cpsw_get_ethtool_stats(struct net_device *ndev,
hw_stats [ i ]. offset );
}
+ static void am65_cpsw_get_eth_mac_stats ( struct net_device * ndev ,
+ struct ethtool_eth_mac_stats * s )
+ {
+ struct am65_cpsw_port * port = am65_ndev_to_port ( ndev );
+ struct am65_cpsw_stats_regs * stats ;
Hi Roger,
I think that stats needs an __iomem annotation
to address the issues flagged by Sparse.
drivers/net/ethernet/ti/am65-cpsw-ethtool.c:671:15: warning: incorrect type in assignment (different address spaces)
drivers/net/ethernet/ti/am65-cpsw-ethtool.c:671:15: expected struct am65_cpsw_stats_regs *stats
drivers/net/ethernet/ti/am65-cpsw-ethtool.c:671:15: got void [noderef] __iomem *stat_base
drivers/net/ethernet/ti/am65-cpsw-ethtool.c:673:34: warning: incorrect type in argument 1 (different address spaces)
drivers/net/ethernet/ti/am65-cpsw-ethtool.c:673:34: expected void const volatile [noderef] __iomem *addr
drivers/net/ethernet/ti/am65-cpsw-ethtool.c:673:34: got unsigned int *
...
+
+ stats = port->stat_base;
+
+ s->FramesTransmittedOK = readl_relaxed(&stats->tx_good_frames);
+ s->SingleCollisionFrames = readl_relaxed(&stats->tx_single_coll_frames);
+ s->MultipleCollisionFrames = readl_relaxed(&stats->tx_mult_coll_frames);
+ s->FramesReceivedOK = readl_relaxed(&stats->rx_good_frames);
+ s->FrameCheckSequenceErrors = readl_relaxed(&stats->rx_crc_errors);
+ s->AlignmentErrors = readl_relaxed(&stats->rx_align_code_errors);
+ s->OctetsTransmittedOK = readl_relaxed(&stats->tx_octets);
+ s->FramesWithDeferredXmissions = readl_relaxed(&stats->tx_deferred_frames);
+ s->LateCollisions = readl_relaxed(&stats->tx_late_collisions);
+ s->CarrierSenseErrors = readl_relaxed(&stats->tx_carrier_sense_errors);
+ s->OctetsReceivedOK = readl_relaxed(&stats->rx_octets);
+ s->MulticastFramesXmittedOK = readl_relaxed(&stats->tx_multicast_frames);
+ s->BroadcastFramesXmittedOK = readl_relaxed(&stats->tx_broadcast_frames);
+ s->MulticastFramesReceivedOK = readl_relaxed(&stats->rx_multicast_frames);
+ s->BroadcastFramesReceivedOK = readl_relaxed(&stats->rx_broadcast_frames);
+};
+
static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev,
struct ethtool_ts_info *info)
{
...
On 13/11/2023 18:42, Simon Horman wrote: On Mon, Nov 13, 2023 at 01:07:06PM +0200, Roger Quadros wrote: quoted Gets 'ethtool -S eth0 --groups eth-mac' command to work.
Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
drivers/net/ethernet/ti/am65-cpsw-ethtool.c | 26 +++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c
index c51e2af91f69..ac7276f0f77a 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c @@ -662,6 +662,31 @@ static void am65_cpsw_get_ethtool_stats(struct net_device *ndev,
hw_stats [ i ]. offset );
}
+ static void am65_cpsw_get_eth_mac_stats ( struct net_device * ndev ,
+ struct ethtool_eth_mac_stats * s )
+ {
+ struct am65_cpsw_port * port = am65_ndev_to_port ( ndev );
+ struct am65_cpsw_stats_regs * stats ;
Hi Roger,
I think that stats needs an __iomem annotation
to address the issues flagged by Sparse.
drivers/net/ethernet/ti/am65-cpsw-ethtool.c:671:15: warning: incorrect type in assignment (different address spaces)
drivers/net/ethernet/ti/am65-cpsw-ethtool.c:671:15: expected struct am65_cpsw_stats_regs *stats
drivers/net/ethernet/ti/am65-cpsw-ethtool.c:671:15: got void [noderef] __iomem *stat_base
drivers/net/ethernet/ti/am65-cpsw-ethtool.c:673:34: warning: incorrect type in argument 1 (different address spaces)
drivers/net/ethernet/ti/am65-cpsw-ethtool.c:673:34: expected void const volatile [noderef] __iomem *addr
drivers/net/ethernet/ti/am65-cpsw-ethtool.c:673:34: got unsigned int *
...
Thanks for the catch Simon.
I'll fix it up.
quoted +
+ stats = port->stat_base;
+
+ s->FramesTransmittedOK = readl_relaxed(&stats->tx_good_frames);
+ s->SingleCollisionFrames = readl_relaxed(&stats->tx_single_coll_frames);
+ s->MultipleCollisionFrames = readl_relaxed(&stats->tx_mult_coll_frames);
+ s->FramesReceivedOK = readl_relaxed(&stats->rx_good_frames);
+ s->FrameCheckSequenceErrors = readl_relaxed(&stats->rx_crc_errors);
+ s->AlignmentErrors = readl_relaxed(&stats->rx_align_code_errors);
+ s->OctetsTransmittedOK = readl_relaxed(&stats->tx_octets);
+ s->FramesWithDeferredXmissions = readl_relaxed(&stats->tx_deferred_frames);
+ s->LateCollisions = readl_relaxed(&stats->tx_late_collisions);
+ s->CarrierSenseErrors = readl_relaxed(&stats->tx_carrier_sense_errors);
+ s->OctetsReceivedOK = readl_relaxed(&stats->rx_octets);
+ s->MulticastFramesXmittedOK = readl_relaxed(&stats->tx_multicast_frames);
+ s->BroadcastFramesXmittedOK = readl_relaxed(&stats->tx_broadcast_frames);
+ s->MulticastFramesReceivedOK = readl_relaxed(&stats->rx_multicast_frames);
+ s->BroadcastFramesReceivedOK = readl_relaxed(&stats->rx_broadcast_frames);
+};
+
static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev,
struct ethtool_ts_info *info)
{
...
--
cheers,
-roger
On Mon, Nov 13, 2023 at 01:07:08PM +0200, Roger Quadros wrote: quoted hunk k3_udma_glue_enable_rx/tx_chn returns error code on failure.
Bail out on error while enabling TX/RX channel.
Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 33 +++++++++++++++++++-----
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 7c440899c93c..340f25bf33b1 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -372,7 +372,7 @@ static void am65_cpsw_init_port_emac_ale(struct am65_cpsw_port *port);
static int am65_cpsw_nuss_common_open ( struct am65_cpsw_common * common )
{
struct am65_cpsw_host * host_p = am65_common_get_host ( common );
- int port_idx , i , ret ;
+ int port_idx , i , ret , tx ;
struct sk_buff * skb ;
u32 val , port_mask ;
@@ -453,13 +453,22 @@ static int am65_cpsw_nuss_common_open(struct am65_cpsw_common *common)
}
kmemleak_not_leak ( skb );
}
- k3_udma_glue_enable_rx_chn ( common -> rx_chns . rx_chn );
- for ( i = 0 ; i < common -> tx_ch_num ; i ++ ) {
- ret = k3_udma_glue_enable_tx_chn ( common -> tx_chns [ i ]. tx_chn );
- if ( ret )
- return ret ;
Can you comment on the kmemleak_not_leak(skb) call above, and its
relationship to the pre-existing error handling path in am65_cpsw_nuss_common_open()?
I see that the dev_kfree_skb_any() call is being made from am65_cpsw_nuss_rx_cleanup(),
which is only called from am65_cpsw_nuss_common_stop().
So if there are errors during am65_cpsw_nuss_common_open() and
descriptors have already been added to the RX DMA channel, they will not
be removed either from hardware or from software. How does that work?
On Mon, Nov 13, 2023 at 01:07:07PM +0200, Roger Quadros wrote: am65-cpsw supports 8 TX hardware queues. Set this as default.
Motivation? Drawbacks / reasons why this was not done from the beginning?
On 14/11/2023 14:07, Vladimir Oltean wrote: On Mon, Nov 13, 2023 at 01:07:08PM +0200, Roger Quadros wrote: quoted k3_udma_glue_enable_rx/tx_chn returns error code on failure.
Bail out on error while enabling TX/RX channel.
Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 33 +++++++++++++++++++-----
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 7c440899c93c..340f25bf33b1 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -372,7 +372,7 @@ static void am65_cpsw_init_port_emac_ale(struct am65_cpsw_port *port);
static int am65_cpsw_nuss_common_open ( struct am65_cpsw_common * common )
{
struct am65_cpsw_host * host_p = am65_common_get_host ( common );
- int port_idx , i , ret ;
+ int port_idx , i , ret , tx ;
struct sk_buff * skb ;
u32 val , port_mask ;
@@ -453,13 +453,22 @@ static int am65_cpsw_nuss_common_open(struct am65_cpsw_common *common)
}
kmemleak_not_leak ( skb );
}
- k3_udma_glue_enable_rx_chn ( common -> rx_chns . rx_chn );
- for ( i = 0 ; i < common -> tx_ch_num ; i ++ ) {
- ret = k3_udma_glue_enable_tx_chn ( common -> tx_chns [ i ]. tx_chn );
- if ( ret )
- return ret ;
Can you comment on the kmemleak_not_leak(skb) call above, and its
relationship to the pre-existing error handling path in am65_cpsw_nuss_common_open()?
I am not aware why it was added. It sure looks odd and I'll get rid of it
and add the necessary error handling.
I see that the dev_kfree_skb_any() call is being made from am65_cpsw_nuss_rx_cleanup(),
which is only called from am65_cpsw_nuss_common_stop().
So if there are errors during am65_cpsw_nuss_common_open() and
descriptors have already been added to the RX DMA channel, they will not
be removed either from hardware or from software. How does that work?
I believe this is a gap and I will address it in the next revision. Thanks!
--
cheers,
-roger
On 14/11/2023 14:13, Vladimir Oltean wrote: On Mon, Nov 13, 2023 at 01:07:07PM +0200, Roger Quadros wrote: quoted am65-cpsw supports 8 TX hardware queues. Set this as default.
Motivation? Drawbacks / reasons why this was not done from the beginning?
Motivation was to get the "kselftest -t net/forwarding:ethtool_mm.sh" test to work
without requiring additional manual step of increasing the TX channels.
Another issue is that all network interfaces (can be up to 4 on some devices) have to be
brought down if TX channel count needs to change.
I am not aware why this was not done from the beginning.
--
cheers,
-roger