i40e: free skb after clearing lock in ptp_stop
Subsystems (2)
PATCH 1/9 i40e: free skb after clearing lock in ptp_stop
From: Jacob Keller <[email protected]>
Use the same logic to free the skb after clearing the Tx timestamp bit lock in i40e_ptp_stop as we use in the other locations. It is not as important here since we are not racing against a future Tx timestamp request (as we are disabling PTP at this point). However it is good to be consistent in how we approach the bit lock so that future callers don't copy the old anti-pattern.
--- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/i40e/i40e_ptp.c +3 -1
@@ -799,9 +799,11 @@ void i40e_ptp_stop(struct i40e_pf *pf) pf->ptp_rx = false;if (pf->ptp_tx_skb) { -dev_kfree_skb_any (pf->ptp_tx_skb); +struct sk_buff *skb = pf->ptp_tx_skb; + pf->ptp_tx_skb =NULL ;clear_bit_unlock (__I40E_PTP_TX_IN_PROGRESS, pf->state); +dev_kfree_skb_any (skb); }if (pf->ptp_clock) {
Signature · 1 line
2.9.5
PATCH 2/9 i40e: always return VEB stat strings
From: Jacob Keller <[email protected]>
The ethtool API for obtaining device statistics is not intended to allow runtime changes in the number of statistics reported. It may *appear* this way, as there is an ability to request the number of stats using ethtool_get_set_count(). However, it is expected that this must always return the same value for invocations of the same device.
If we don't satisfy this contract, and allow the number of stats to change during run time, we could cause invalid memory accesses or report the stat strings incorrectly. This is because the API for obtaining stats is to (1) get the size, (2) get the strings and finally (3) get the stats. Since these are each separate ethtool op commands, it is not possible to maintain consistency by holding the RTNL lock over the whole operation. This results in the potential for a race condition to occur where the size changed between any of the 3 calls.
Avoid this issue by requiring that we always return the same value for a given device. We can check any values which remain constant for the life of the device, but must not report different sizes depending on runtime attributes.
This patch specifically fixes the VEB statistics strings to always be reported. Other issues will be fixed in future patches.
--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 52 ++++++++++++-------------- 1 file changed, 23 insertions(+), 29 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_ethtool.c +23 -29
@@ -1541,15 +1541,10 @@ static int i40e_get_stats_count(struct net_device *netdev)struct i40e_vsi *vsi = np->vsi;struct i40e_pf *pf = vsi->back; -if (vsi == pf->vsi[pf->lan_vsi] && pf->hw.partition_id ==1 ) { -if (pf->lan_veb !=I40E_NO_VEB && - pf->flags &I40E_FLAG_VEB_STATS_ENABLED ) -return I40E_PF_STATS_LEN (netdev) +I40E_VEB_STATS_TOTAL ; -else -return I40E_PF_STATS_LEN (netdev); - }else { +if (vsi == pf->vsi[pf->lan_vsi] && pf->hw.partition_id ==1 ) +return I40E_PF_STATS_LEN (netdev) +I40E_VEB_STATS_TOTAL ; +else return I40E_VSI_STATS_LEN (netdev); - } }static int i40e_get_sset_count (struct net_device *netdev,int sset)
@@ -1640,6 +1635,8 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, data[i++] = veb->tc_stats.tc_rx_packets[j]; data[i++] = veb->tc_stats.tc_rx_bytes[j]; } + }else { + i +=I40E_VEB_STATS_TOTAL ; }for (j =0 ; j <I40E_GLOBAL_STATS_LEN ; j++) { p = (char *)pf + i40e_gstrings_stats[j].stat_offset;
@@ -1696,27 +1693,24 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id !=1 )return ; -if ((pf->lan_veb !=I40E_NO_VEB ) && - (pf->flags &I40E_FLAG_VEB_STATS_ENABLED )) { -for (i =0 ; i <I40E_VEB_STATS_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"veb.%s" , - i40e_gstrings_veb_stats[i].stat_string); - p +=ETH_GSTRING_LEN ; - } -for (i =0 ; i <I40E_MAX_TRAFFIC_CLASS ; i++) { -snprintf (p,ETH_GSTRING_LEN , -"veb.tc_%d_tx_packets" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , -"veb.tc_%d_tx_bytes" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , -"veb.tc_%d_rx_packets" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , -"veb.tc_%d_rx_bytes" , i); - p +=ETH_GSTRING_LEN ; - } +for (i =0 ; i <I40E_VEB_STATS_LEN ; i++) { +snprintf (p,ETH_GSTRING_LEN ,"veb.%s" , + i40e_gstrings_veb_stats[i].stat_string); + p +=ETH_GSTRING_LEN ; + } +for (i =0 ; i <I40E_MAX_TRAFFIC_CLASS ; i++) { +snprintf (p,ETH_GSTRING_LEN , +"veb.tc_%u_tx_packets" , i); + p +=ETH_GSTRING_LEN ; +snprintf (p,ETH_GSTRING_LEN , +"veb.tc_%u_tx_bytes" , i); + p +=ETH_GSTRING_LEN ; +snprintf (p,ETH_GSTRING_LEN , +"veb.tc_%u_rx_packets" , i); + p +=ETH_GSTRING_LEN ; +snprintf (p,ETH_GSTRING_LEN , +"veb.tc_%u_rx_bytes" , i); + p +=ETH_GSTRING_LEN ; }for (i =0 ; i <I40E_GLOBAL_STATS_LEN ; i++) { snprintf(p, ETH_GSTRING_LEN, "port.%s",
Signature · 1 line
2.9.5
Bowers
PATCH 2/9 i40e: always return VEB stat strings
Quoted 30 lines
-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at osuosl.org] On Behalf Of Alice Michael
Sent: Thursday, May 17, 2018 1:09 AM
To: Michael, Alice <[email protected]>; intel-wired-
lan at lists.osuosl.org
Subject: [Intel-wired-lan] [next PATCH S92 2/9] i40e: always return VEB stat stringsFrom: Jacob Keller <[email protected]>
The ethtool API for obtaining device statistics is not intended to allow runtime changes in the number of statistics reported. It may *appear* this way, as there is an ability to request the number of stats using
ethtool_get_set_count(). However, it is expected that this must always return the same value for invocations of the same device.If we don't satisfy this contract, and allow the number of stats to change during run time, we could cause invalid memory accesses or report the stat strings incorrectly. This is because the API for obtaining stats is to (1) get the size, (2) get the strings and finally (3) get the stats. Since these are each separate ethtool op commands, it is not possible to maintain consistency by holding the RTNL lock over the whole operation. This results in the potential for a race condition to occur where the size changed between any of the 3 calls.
Avoid this issue by requiring that we always return the same value for a given device. We can check any values which remain constant for the life of the device, but must not report different sizes depending on runtime attributes.
Quoted 8 lines
This patch specifically fixes the VEB statistics strings to always be reported. Other issues will be fixed in future patches.
Signed-off-by Jacob Keller <[email protected]>--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 52 ++++++++++++---------- ---- 1 file changed, 23 insertions(+), 29 deletions(-)
PATCH 3/9 i40e: always return all queue stat strings
In reply to Alice MichaelFrom: Jacob Keller <[email protected]>
The ethtool API for obtaining device statistics is not intended to allow runtime changes in the number of statistics reported. It may *appear* this way, as there is an ability to request the number of stats using ethtool_get_set_count(). However, it is expected that this must always return the same value for invocations of the same device.
If we don't satisfy this contract, and allow the number of stats to change during run time, we could cause invalid memory accesses or report the stat strings incorrectly. This is because the API for obtaining stats is to (1) get the size, (2) get the strings and finally (3) get the stats. Since these are each separate ethtool op commands, it is not possible to maintain consistency by holding the RTNL lock over the whole operation. This results in the potential for a race condition to occur where the size changed between any of the 3 calls.
Avoid this issue by requiring that we always return the same value for a given device. We can check any values which remain constant for the life of the device, but must not report different sizes depending on runtime attributes.
This patch specifically fixes the queue statistics to always return every queue even if it's not currently in use.
--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_ethtool.c +17 -5
@@ -140,8 +140,12 @@ static const struct i40e_stats i40e_gstrings_stats[] = { I40E_PF_STAT("rx_lpi_count", stats.rx_lpi_count), }; -#define I40E_QUEUE_STATS_LEN (n) \ - (((struct i40e_netdev_priv *)netdev_priv((n)))->vsi->num_queue_pairs \ +/* We use num_tx_queues here as a proxy for the maximum number of queues +* available because we always allocate queues symmetrically. +*/ +#define I40E_MAX_NUM_QUEUES (n) ((n)->num_tx_queues) +#define I40E_QUEUE_STATS_LEN (n) \ + (I40E_MAX_NUM_QUEUES(n) \ * 2/* Tx and Rx together */ \ * (sizeof(struct i40e_queue_stats) / sizeof(u64)))#define I40E_GLOBAL_STATS_LEN ARRAY_SIZE(i40e_gstrings_stats)
@@ -1592,11 +1596,19 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, sizeof(u64)) ? *(u64 *)p : *(u32 *)p; }rcu_read_lock (); -for (j =0 ; j < vsi->num_queue_pairs; j++) { +for (j =0 ; j <I40E_MAX_NUM_QUEUES (netdev) ; j++) { tx_ring =READ_ONCE (vsi->tx_rings[j]); -if (!tx_ring) +if (!tx_ring) { +/* Bump the stat counter to skip these stats, and make +* sure the memory is zero'd +*/ + data[i++] =0 ; + data[i++] =0 ; + data[i++] =0 ; + data[i++] =0 ;continue ; + }/* process Tx ring statistics */ do {
@@ -1680,7 +1692,7 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset, i40e_gstrings_misc_stats[i].stat_string); p +=ETH_GSTRING_LEN ; } -for (i =0 ; i < vsi->num_queue_pairs; i++) { +for (i =0 ; i <I40E_MAX_NUM_QUEUES (netdev); i++) {snprintf (p,ETH_GSTRING_LEN ,"tx-%d.tx_packets" , i); p +=ETH_GSTRING_LEN ;snprintf (p,ETH_GSTRING_LEN ,"tx-%d.tx_bytes" , i);
Signature · 1 line
2.9.5
Bowers
PATCH 3/9 i40e: always return all queue stat strings
Quoted 30 lines
-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at osuosl.org] On Behalf Of Alice Michael
Sent: Thursday, May 17, 2018 1:09 AM
To: Michael, Alice <[email protected]>; intel-wired-
lan at lists.osuosl.org
Subject: [Intel-wired-lan] [next PATCH S92 3/9] i40e: always return all queue stat stringsFrom: Jacob Keller <[email protected]>
The ethtool API for obtaining device statistics is not intended to allow runtime changes in the number of statistics reported. It may *appear* this way, as there is an ability to request the number of stats using
ethtool_get_set_count(). However, it is expected that this must always return the same value for invocations of the same device.If we don't satisfy this contract, and allow the number of stats to change during run time, we could cause invalid memory accesses or report the stat strings incorrectly. This is because the API for obtaining stats is to (1) get the size, (2) get the strings and finally (3) get the stats. Since these are each separate ethtool op commands, it is not possible to maintain consistency by holding the RTNL lock over the whole operation. This results in the potential for a race condition to occur where the size changed between any of the 3 calls.
Avoid this issue by requiring that we always return the same value for a given device. We can check any values which remain constant for the life of the device, but must not report different sizes depending on runtime attributes.
Quoted 8 lines
This patch specifically fixes the queue statistics to always return every queue even if it's not currently in use.
Signed-off-by Jacob Keller <[email protected]>--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 22 +++++++++++++++++-- --- 1 file changed, 17 insertions(+), 5 deletions(-)
PATCH 4/9 i40e: split i40e_get_strings() into smaller functions
In reply to Alice MichaelFrom: Jacob Keller <[email protected]>
Split the statistic strings and private flags strings into their own separate functions to aid code readability.
--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 183 ++++++++++++++----------- 1 file changed, 100 insertions(+), 83 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_ethtool.c +100 -83
@@ -1667,8 +1667,7 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, data[i++] = pf->stats.priority_xon_2_xoff[j]; } -static void i40e_get_strings (struct net_device *netdev,u32 stringset, -u8 *data) +static void i40e_get_stat_strings (struct net_device *netdev,u8 *data) {struct i40e_netdev_priv *np =netdev_priv (netdev);struct i40e_vsi *vsi = np->vsi;
@@ -1676,95 +1675,113 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,char *p = (char *)data;unsigned int i; +for (i =0 ; i <I40E_NETDEV_STATS_LEN ; i++) { +snprintf (p,ETH_GSTRING_LEN ,"%s" , + i40e_gstrings_net_stats[i].stat_string); + p +=ETH_GSTRING_LEN ; + } +for (i =0 ; i <I40E_MISC_STATS_LEN ; i++) { +snprintf (p,ETH_GSTRING_LEN ,"%s" , + i40e_gstrings_misc_stats[i].stat_string); + p +=ETH_GSTRING_LEN ; + } +for (i =0 ; i <I40E_MAX_NUM_QUEUES (netdev); i++) { +snprintf (p,ETH_GSTRING_LEN ,"tx-%u.tx_packets" , i); + p +=ETH_GSTRING_LEN ; +snprintf (p,ETH_GSTRING_LEN ,"tx-%u.tx_bytes" , i); + p +=ETH_GSTRING_LEN ; +snprintf (p,ETH_GSTRING_LEN ,"rx-%u.rx_packets" , i); + p +=ETH_GSTRING_LEN ; +snprintf (p,ETH_GSTRING_LEN ,"rx-%u.rx_bytes" , i); + p +=ETH_GSTRING_LEN ; + } +if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id !=1 ) +return ; + +for (i =0 ; i <I40E_VEB_STATS_LEN ; i++) { +snprintf (p,ETH_GSTRING_LEN ,"veb.%s" , + i40e_gstrings_veb_stats[i].stat_string); + p +=ETH_GSTRING_LEN ; + } +for (i =0 ; i <I40E_MAX_TRAFFIC_CLASS ; i++) { +snprintf (p,ETH_GSTRING_LEN , +"veb.tc_%u_tx_packets" , i); + p +=ETH_GSTRING_LEN ; +snprintf (p,ETH_GSTRING_LEN , +"veb.tc_%u_tx_bytes" , i); + p +=ETH_GSTRING_LEN ; +snprintf (p,ETH_GSTRING_LEN , +"veb.tc_%u_rx_packets" , i); + p +=ETH_GSTRING_LEN ; +snprintf (p,ETH_GSTRING_LEN , +"veb.tc_%u_rx_bytes" , i); + p +=ETH_GSTRING_LEN ; + } + +for (i =0 ; i <I40E_GLOBAL_STATS_LEN ; i++) { +snprintf (p,ETH_GSTRING_LEN ,"port.%s" , + i40e_gstrings_stats[i].stat_string); + p +=ETH_GSTRING_LEN ; + } +for (i =0 ; i <I40E_MAX_USER_PRIORITY ; i++) { +snprintf (p,ETH_GSTRING_LEN , +"port.tx_priority_%u_xon" , i); + p +=ETH_GSTRING_LEN ; +snprintf (p,ETH_GSTRING_LEN , +"port.tx_priority_%u_xoff" , i); + p +=ETH_GSTRING_LEN ; + } +for (i =0 ; i <I40E_MAX_USER_PRIORITY ; i++) { +snprintf (p,ETH_GSTRING_LEN , +"port.rx_priority_%u_xon" , i); + p +=ETH_GSTRING_LEN ; +snprintf (p,ETH_GSTRING_LEN , +"port.rx_priority_%u_xoff" , i); + p +=ETH_GSTRING_LEN ; + } +for (i =0 ; i <I40E_MAX_USER_PRIORITY ; i++) { +snprintf (p,ETH_GSTRING_LEN , +"port.rx_priority_%u_xon_2_xoff" , i); + p +=ETH_GSTRING_LEN ; + } +/* BUG_ON(p - data != I40E_STATS_LEN * ETH_GSTRING_LEN); */ +} + +static void i40e_get_priv_flag_strings (struct net_device *netdev,u8 *data) +{ +struct i40e_netdev_priv *np =netdev_priv (netdev); +struct i40e_vsi *vsi = np->vsi; +struct i40e_pf *pf = vsi->back; +char *p = (char *)data; +unsigned int i; + +for (i =0 ; i <I40E_PRIV_FLAGS_STR_LEN ; i++) { +snprintf (p,ETH_GSTRING_LEN ,"%s" , + i40e_gstrings_priv_flags[i].flag_string); + p +=ETH_GSTRING_LEN ; + } +if (pf->hw.pf_id !=0 ) +return ; +for (i =0 ; i <I40E_GL_PRIV_FLAGS_STR_LEN ; i++) { +snprintf (p,ETH_GSTRING_LEN ,"%s" , + i40e_gl_gstrings_priv_flags[i].flag_string); + p +=ETH_GSTRING_LEN ; + } +} + +static void i40e_get_strings (struct net_device *netdev,u32 stringset, +u8 *data) +{switch (stringset) {case ETH_SS_TEST :memcpy (data, i40e_gstrings_test,I40E_TEST_LEN *ETH_GSTRING_LEN );break ;case ETH_SS_STATS : -for (i =0 ; i <I40E_NETDEV_STATS_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"%s" , - i40e_gstrings_net_stats[i].stat_string); - p +=ETH_GSTRING_LEN ; - } -for (i =0 ; i <I40E_MISC_STATS_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"%s" , - i40e_gstrings_misc_stats[i].stat_string); - p +=ETH_GSTRING_LEN ; - } -for (i =0 ; i <I40E_MAX_NUM_QUEUES (netdev); i++) { -snprintf (p,ETH_GSTRING_LEN ,"tx-%d.tx_packets" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN ,"tx-%d.tx_bytes" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN ,"rx-%d.rx_packets" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN ,"rx-%d.rx_bytes" , i); - p +=ETH_GSTRING_LEN ; - } -if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id !=1 ) -return ; - -for (i =0 ; i <I40E_VEB_STATS_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"veb.%s" , - i40e_gstrings_veb_stats[i].stat_string); - p +=ETH_GSTRING_LEN ; - } -for (i =0 ; i <I40E_MAX_TRAFFIC_CLASS ; i++) { -snprintf (p,ETH_GSTRING_LEN , -"veb.tc_%u_tx_packets" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , -"veb.tc_%u_tx_bytes" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , -"veb.tc_%u_rx_packets" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , -"veb.tc_%u_rx_bytes" , i); - p +=ETH_GSTRING_LEN ; - } -for (i =0 ; i <I40E_GLOBAL_STATS_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"port.%s" , - i40e_gstrings_stats[i].stat_string); - p +=ETH_GSTRING_LEN ; - } -for (i =0 ; i <I40E_MAX_USER_PRIORITY ; i++) { -snprintf (p,ETH_GSTRING_LEN , -"port.tx_priority_%d_xon" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , -"port.tx_priority_%d_xoff" , i); - p +=ETH_GSTRING_LEN ; - } -for (i =0 ; i <I40E_MAX_USER_PRIORITY ; i++) { -snprintf (p,ETH_GSTRING_LEN , -"port.rx_priority_%d_xon" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , -"port.rx_priority_%d_xoff" , i); - p +=ETH_GSTRING_LEN ; - } -for (i =0 ; i <I40E_MAX_USER_PRIORITY ; i++) { -snprintf (p,ETH_GSTRING_LEN , -"port.rx_priority_%d_xon_2_xoff" , i); - p +=ETH_GSTRING_LEN ; - } -/* BUG_ON(p - data != I40E_STATS_LEN * ETH_GSTRING_LEN); */ +i40e_get_stat_strings (netdev, data);break ;case ETH_SS_PRIV_FLAGS : -for (i =0 ; i <I40E_PRIV_FLAGS_STR_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"%s" , - i40e_gstrings_priv_flags[i].flag_string); - p +=ETH_GSTRING_LEN ; - } -if (pf->hw.pf_id !=0 ) -break ; -for (i =0 ; i <I40E_GL_PRIV_FLAGS_STR_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"%s" , - i40e_gl_gstrings_priv_flags[i].flag_string); - p +=ETH_GSTRING_LEN ; - } +i40e_get_priv_flag_strings (netdev, data);break ;default :break ;
Signature · 1 line
2.9.5
Bowers
PATCH 4/9 i40e: split i40e_get_strings() into smaller functions
Quoted 11 lines
-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at osuosl.org] On Behalf Of Alice Michael
Sent: Thursday, May 17, 2018 1:09 AM
To: Michael, Alice <[email protected]>; intel-wired-
lan at lists.osuosl.org
Subject: [Intel-wired-lan] [next PATCH S92 4/9] i40e: spliti40e_get_strings()into smaller functionsFrom: Jacob Keller <[email protected]>
Quoted 8 lines
Split the statistic strings and private flags strings into their own separate functions to aid code readability.
Signed-off-by Jacob Keller <[email protected]>--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 183 ++++++++++++++------ ----- 1 file changed, 100 insertions(+), 83 deletions(-)
PATCH 5/9 i40e: use WARN_ONCE to replace the commented BUG_ON size check
In reply to Alice MichaelFrom: Jacob Keller <[email protected]>
We don't really want to use BUG_ON here since that would completely crash the kernel, thus the reason we commented it out. We *can't* use BUILD_BUG_ON because at least now (a) the sizes aren't constant (we are fixing this) and (b) not all compilers are smart enough to understand that "p - data" is a constant.
Instead, just use a WARN_ONCE so that the first time we end up with an incorrect size we will dump a stack trace and a message, hopefully highlighting the issues early in testing.
--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_ethtool.c +4 -2
@@ -1672,8 +1672,8 @@ static void i40e_get_stat_strings(struct net_device *netdev, u8 *data)struct i40e_netdev_priv *np =netdev_priv (netdev);struct i40e_vsi *vsi = np->vsi;struct i40e_pf *pf = vsi->back; -char *p = (char *)data;unsigned int i; +u8 *p = data;for (i =0 ; i <I40E_NETDEV_STATS_LEN ; i++) { snprintf(p, ETH_GSTRING_LEN, "%s",
@@ -1744,7 +1744,9 @@ static void i40e_get_stat_strings(struct net_device *netdev, u8 *data) "port.rx_priority_%u_xon_2_xoff", i); p +=ETH_GSTRING_LEN ; } -/* BUG_ON(p - data != I40E_STATS_LEN * ETH_GSTRING_LEN); */ + +WARN_ONCE (p - data !=i40e_get_stats_count (netdev) *ETH_GSTRING_LEN , +"stat strings count mismatch!" ); }static void i40e_get_priv_flag_strings (struct net_device *netdev,u8 *data)
Signature · 1 line
2.9.5
Bowers
PATCH 5/9 i40e: use WARN_ONCE to replace the commented BUG_ON size check
Quoted 17 lines
-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at osuosl.org] On Behalf Of Alice Michael
Sent: Thursday, May 17, 2018 1:09 AM
To: Michael, Alice <[email protected]>; intel-wired- lan at lists.osuosl.org
Subject: [Intel-wired-lan] [next PATCH S92 5/9] i40e: useWARN_ONCEto replace the commentedBUG_ONsize checkFrom: Jacob Keller <[email protected]>
We don't really want to use
BUG_ONhere since that would completely crash the kernel, thus the reason we commented it out. We *can't* useBUILD_BUG_ONbecause at least now (a) the sizes aren't constant (we are fixing this) and (b) not all compilers are smart enough to understand that "p - data" is a constant.
Quoted 8 lines
Instead, just use a
WARN_ONCEso that the first time we end up with an incorrect size we will dump a stack trace and a message, hopefully highlighting the issues early in testing.Signed-off-by Jacob Keller <[email protected]>--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
PATCH 6/9 i40e: fold prefix strings directly into stat names
In reply to Alice MichaelFrom: Jacob Keller <[email protected]>
We always prefix these stats with a fixed string, so just fold this prefix into the stat string definition. This preparatory work will make it easier to implement a helper function to copy stats and strings into the supplied buffers in a future patch.
--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 137 +++++++++++++------------ 1 file changed, 69 insertions(+), 68 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_ethtool.c +69 -68
@@ -42,18 +42,18 @@ static const struct i40e_stats i40e_gstrings_net_stats[] = { };static const struct i40e_stats i40e_gstrings_veb_stats[] = { -I40E_VEB_STAT ("rx_bytes" , stats.rx_bytes), -I40E_VEB_STAT ("tx_bytes" , stats.tx_bytes), -I40E_VEB_STAT ("rx_unicast" , stats.rx_unicast), -I40E_VEB_STAT ("tx_unicast" , stats.tx_unicast), -I40E_VEB_STAT ("rx_multicast" , stats.rx_multicast), -I40E_VEB_STAT ("tx_multicast" , stats.tx_multicast), -I40E_VEB_STAT ("rx_broadcast" , stats.rx_broadcast), -I40E_VEB_STAT ("tx_broadcast" , stats.tx_broadcast), -I40E_VEB_STAT ("rx_discards" , stats.rx_discards), -I40E_VEB_STAT ("tx_discards" , stats.tx_discards), -I40E_VEB_STAT ("tx_errors" , stats.tx_errors), -I40E_VEB_STAT ("rx_unknown_protocol" , stats.rx_unknown_protocol), +I40E_VEB_STAT ("veb.rx_bytes" , stats.rx_bytes), +I40E_VEB_STAT ("veb.tx_bytes" , stats.tx_bytes), +I40E_VEB_STAT ("veb.rx_unicast" , stats.rx_unicast), +I40E_VEB_STAT ("veb.tx_unicast" , stats.tx_unicast), +I40E_VEB_STAT ("veb.rx_multicast" , stats.rx_multicast), +I40E_VEB_STAT ("veb.tx_multicast" , stats.tx_multicast), +I40E_VEB_STAT ("veb.rx_broadcast" , stats.rx_broadcast), +I40E_VEB_STAT ("veb.tx_broadcast" , stats.tx_broadcast), +I40E_VEB_STAT ("veb.rx_discards" , stats.rx_discards), +I40E_VEB_STAT ("veb.tx_discards" , stats.tx_discards), +I40E_VEB_STAT ("veb.tx_errors" , stats.tx_errors), +I40E_VEB_STAT ("veb.rx_unknown_protocol" , stats.rx_unknown_protocol), };static const struct i40e_stats i40e_gstrings_misc_stats[] = {
@@ -82,62 +82,63 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = {* is queried on the base PF netdev, not on the VMDq or FCoE netdev. */ static const struct i40e_stats i40e_gstrings_stats[] = { -I40E_PF_STAT ("rx_bytes" , stats.eth.rx_bytes), -I40E_PF_STAT ("tx_bytes" , stats.eth.tx_bytes), -I40E_PF_STAT ("rx_unicast" , stats.eth.rx_unicast), -I40E_PF_STAT ("tx_unicast" , stats.eth.tx_unicast), -I40E_PF_STAT ("rx_multicast" , stats.eth.rx_multicast), -I40E_PF_STAT ("tx_multicast" , stats.eth.tx_multicast), -I40E_PF_STAT ("rx_broadcast" , stats.eth.rx_broadcast), -I40E_PF_STAT ("tx_broadcast" , stats.eth.tx_broadcast), -I40E_PF_STAT ("tx_errors" , stats.eth.tx_errors), -I40E_PF_STAT ("rx_dropped" , stats.eth.rx_discards), -I40E_PF_STAT ("tx_dropped_link_down" , stats.tx_dropped_link_down), -I40E_PF_STAT ("rx_crc_errors" , stats.crc_errors), -I40E_PF_STAT ("illegal_bytes" , stats.illegal_bytes), -I40E_PF_STAT ("mac_local_faults" , stats.mac_local_faults), -I40E_PF_STAT ("mac_remote_faults" , stats.mac_remote_faults), -I40E_PF_STAT ("tx_timeout" , tx_timeout_count), -I40E_PF_STAT ("rx_csum_bad" , hw_csum_rx_error), -I40E_PF_STAT ("rx_length_errors" , stats.rx_length_errors), -I40E_PF_STAT ("link_xon_rx" , stats.link_xon_rx), -I40E_PF_STAT ("link_xoff_rx" , stats.link_xoff_rx), -I40E_PF_STAT ("link_xon_tx" , stats.link_xon_tx), -I40E_PF_STAT ("link_xoff_tx" , stats.link_xoff_tx), -I40E_PF_STAT ("rx_size_64" , stats.rx_size_64), -I40E_PF_STAT ("rx_size_127" , stats.rx_size_127), -I40E_PF_STAT ("rx_size_255" , stats.rx_size_255), -I40E_PF_STAT ("rx_size_511" , stats.rx_size_511), -I40E_PF_STAT ("rx_size_1023" , stats.rx_size_1023), -I40E_PF_STAT ("rx_size_1522" , stats.rx_size_1522), -I40E_PF_STAT ("rx_size_big" , stats.rx_size_big), -I40E_PF_STAT ("tx_size_64" , stats.tx_size_64), -I40E_PF_STAT ("tx_size_127" , stats.tx_size_127), -I40E_PF_STAT ("tx_size_255" , stats.tx_size_255), -I40E_PF_STAT ("tx_size_511" , stats.tx_size_511), -I40E_PF_STAT ("tx_size_1023" , stats.tx_size_1023), -I40E_PF_STAT ("tx_size_1522" , stats.tx_size_1522), -I40E_PF_STAT ("tx_size_big" , stats.tx_size_big), -I40E_PF_STAT ("rx_undersize" , stats.rx_undersize), -I40E_PF_STAT ("rx_fragments" , stats.rx_fragments), -I40E_PF_STAT ("rx_oversize" , stats.rx_oversize), -I40E_PF_STAT ("rx_jabber" , stats.rx_jabber), -I40E_PF_STAT ("VF_admin_queue_requests" , vf_aq_requests), -I40E_PF_STAT ("arq_overflows" , arq_overflows), -I40E_PF_STAT ("rx_hwtstamp_cleared" , rx_hwtstamp_cleared), -I40E_PF_STAT ("tx_hwtstamp_skipped" , tx_hwtstamp_skipped), -I40E_PF_STAT ("fdir_flush_cnt" , fd_flush_cnt), -I40E_PF_STAT ("fdir_atr_match" , stats.fd_atr_match), -I40E_PF_STAT ("fdir_atr_tunnel_match" , stats.fd_atr_tunnel_match), -I40E_PF_STAT ("fdir_atr_status" , stats.fd_atr_status), -I40E_PF_STAT ("fdir_sb_match" , stats.fd_sb_match), -I40E_PF_STAT ("fdir_sb_status" , stats.fd_sb_status), +I40E_PF_STAT ("port.rx_bytes" , stats.eth.rx_bytes), +I40E_PF_STAT ("port.tx_bytes" , stats.eth.tx_bytes), +I40E_PF_STAT ("port.rx_unicast" , stats.eth.rx_unicast), +I40E_PF_STAT ("port.tx_unicast" , stats.eth.tx_unicast), +I40E_PF_STAT ("port.rx_multicast" , stats.eth.rx_multicast), +I40E_PF_STAT ("port.tx_multicast" , stats.eth.tx_multicast), +I40E_PF_STAT ("port.rx_broadcast" , stats.eth.rx_broadcast), +I40E_PF_STAT ("port.tx_broadcast" , stats.eth.tx_broadcast), +I40E_PF_STAT ("port.tx_errors" , stats.eth.tx_errors), +I40E_PF_STAT ("port.rx_dropped" , stats.eth.rx_discards), +I40E_PF_STAT ("port.tx_dropped_link_down" , stats.tx_dropped_link_down), +I40E_PF_STAT ("port.rx_crc_errors" , stats.crc_errors), +I40E_PF_STAT ("port.illegal_bytes" , stats.illegal_bytes), +I40E_PF_STAT ("port.mac_local_faults" , stats.mac_local_faults), +I40E_PF_STAT ("port.mac_remote_faults" , stats.mac_remote_faults), +I40E_PF_STAT ("port.tx_timeout" , tx_timeout_count), +I40E_PF_STAT ("port.rx_csum_bad" , hw_csum_rx_error), +I40E_PF_STAT ("port.rx_length_errors" , stats.rx_length_errors), +I40E_PF_STAT ("port.link_xon_rx" , stats.link_xon_rx), +I40E_PF_STAT ("port.link_xoff_rx" , stats.link_xoff_rx), +I40E_PF_STAT ("port.link_xon_tx" , stats.link_xon_tx), +I40E_PF_STAT ("port.link_xoff_tx" , stats.link_xoff_tx), +I40E_PF_STAT ("port.rx_size_64" , stats.rx_size_64), +I40E_PF_STAT ("port.rx_size_127" , stats.rx_size_127), +I40E_PF_STAT ("port.rx_size_255" , stats.rx_size_255), +I40E_PF_STAT ("port.rx_size_511" , stats.rx_size_511), +I40E_PF_STAT ("port.rx_size_1023" , stats.rx_size_1023), +I40E_PF_STAT ("port.rx_size_1522" , stats.rx_size_1522), +I40E_PF_STAT ("port.rx_size_big" , stats.rx_size_big), +I40E_PF_STAT ("port.tx_size_64" , stats.tx_size_64), +I40E_PF_STAT ("port.tx_size_127" , stats.tx_size_127), +I40E_PF_STAT ("port.tx_size_255" , stats.tx_size_255), +I40E_PF_STAT ("port.tx_size_511" , stats.tx_size_511), +I40E_PF_STAT ("port.tx_size_1023" , stats.tx_size_1023), +I40E_PF_STAT ("port.tx_size_1522" , stats.tx_size_1522), +I40E_PF_STAT ("port.tx_size_big" , stats.tx_size_big), +I40E_PF_STAT ("port.rx_undersize" , stats.rx_undersize), +I40E_PF_STAT ("port.rx_fragments" , stats.rx_fragments), +I40E_PF_STAT ("port.rx_oversize" , stats.rx_oversize), +I40E_PF_STAT ("port.rx_jabber" , stats.rx_jabber), +I40E_PF_STAT ("port.VF_admin_queue_requests" , vf_aq_requests), +I40E_PF_STAT ("port.arq_overflows" , arq_overflows), +I40E_PF_STAT ("port.tx_hwtstamp_timeouts" , tx_hwtstamp_timeouts), +I40E_PF_STAT ("port.rx_hwtstamp_cleared" , rx_hwtstamp_cleared), +I40E_PF_STAT ("port.tx_hwtstamp_skipped" , tx_hwtstamp_skipped), +I40E_PF_STAT ("port.fdir_flush_cnt" , fd_flush_cnt), +I40E_PF_STAT ("port.fdir_atr_match" , stats.fd_atr_match), +I40E_PF_STAT ("port.fdir_atr_tunnel_match" , stats.fd_atr_tunnel_match), +I40E_PF_STAT ("port.fdir_atr_status" , stats.fd_atr_status), +I40E_PF_STAT ("port.fdir_sb_match" , stats.fd_sb_match), +I40E_PF_STAT ("port.fdir_sb_status" , stats.fd_sb_status),/* LPI stats */ -I40E_PF_STAT ("tx_lpi_status" , stats.tx_lpi_status), -I40E_PF_STAT ("rx_lpi_status" , stats.rx_lpi_status), -I40E_PF_STAT ("tx_lpi_count" , stats.tx_lpi_count), -I40E_PF_STAT ("rx_lpi_count" , stats.rx_lpi_count), +I40E_PF_STAT ("port.tx_lpi_status" , stats.tx_lpi_status), +I40E_PF_STAT ("port.rx_lpi_status" , stats.rx_lpi_status), +I40E_PF_STAT ("port.tx_lpi_count" , stats.tx_lpi_count), +I40E_PF_STAT ("port.rx_lpi_count" , stats.rx_lpi_count), };/* We use num_tx_queues here as a proxy for the maximum number of queues
@@ -1699,7 +1700,7 @@ static void i40e_get_stat_strings(struct net_device *netdev, u8 *data)return ;for (i =0 ; i <I40E_VEB_STATS_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"veb.%s" , +snprintf (p,ETH_GSTRING_LEN ,"%s" , i40e_gstrings_veb_stats[i].stat_string); p +=ETH_GSTRING_LEN ; }
@@ -1719,7 +1720,7 @@ static void i40e_get_stat_strings(struct net_device *netdev, u8 *data) }for (i =0 ; i <I40E_GLOBAL_STATS_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"port.%s" , +snprintf (p,ETH_GSTRING_LEN ,"%s" , i40e_gstrings_stats[i].stat_string); p +=ETH_GSTRING_LEN ; }
Signature · 1 line
2.9.5
Bowers
PATCH 6/9 i40e: fold prefix strings directly into stat names
Quoted 16 lines
-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at osuosl.org] On Behalf Of Alice Michael
Sent: Thursday, May 17, 2018 1:09 AM
To: Michael, Alice <[email protected]>; intel-wired- lan at lists.osuosl.org
Subject: [Intel-wired-lan] [next PATCH S92 6/9] i40e: fold prefix strings directly into stat namesFrom: Jacob Keller <[email protected]>
We always prefix these stats with a fixed string, so just fold this prefix into the stat string definition. This preparatory work will make it easier to implement a helper function to copy stats and strings into the supplied buffers in a future patch.
Quoted 5 lines
Signed-off-by Jacob Keller <[email protected]>--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 137 +++++++++++++------- ----- 1 file changed, 69 insertions(+), 68 deletions(-)
PATCH 7/9 i40e: update data pointer directly when copying to the buffer
In reply to Alice MichaelFrom: Jacob Keller <[email protected]>
A future patch is going to add a helper function i40e_add_ethtool_stats that will help lower the amount of boiler plate code in the i40e_get_ethtool_stats function.
This conversion will take place over many patches, and the helper function will work by directly updating a reference to the data pointer.
Since this would not work combined with the current method of accessing data like an array, update all the code that copies stats into the data buffer to use direct updates to the pointer instead of array accesses.
This will prevent incorrect stat updates for patches in between the conversion.
Similarly, when copying strings, we used a separate char *p pointer. Instead, use the data pointer directly as it's already a (u8 *) type which is the same size.
--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 117 ++++++++++++------------- 1 file changed, 58 insertions(+), 59 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_ethtool.c +58 -59
@@ -1579,7 +1579,6 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,struct i40e_vsi *vsi = np->vsi;struct i40e_pf *pf = vsi->back;unsigned int j; -int i =0 ;char *p;struct rtnl_link_stats64 *net_stats =i40e_get_vsi_stats_struct (vsi);unsigned int start;
@@ -1588,12 +1587,12 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,for (j =0 ; j <I40E_NETDEV_STATS_LEN ; j++) { p = (char *)net_stats + i40e_gstrings_net_stats[j].stat_offset; - data[i++] = (i40e_gstrings_net_stats[j].sizeof_stat == + *(data++) = (i40e_gstrings_net_stats[j].sizeof_stat ==sizeof (u64)) ? *(u64 *)p : *(u32 *)p; }for (j =0 ; j <I40E_MISC_STATS_LEN ; j++) { p = (char *)vsi + i40e_gstrings_misc_stats[j].stat_offset; - data[i++] = (i40e_gstrings_misc_stats[j].sizeof_stat == + *(data++) = (i40e_gstrings_misc_stats[j].sizeof_stat ==sizeof (u64)) ? *(u64 *)p : *(u32 *)p; }rcu_read_lock ();
@@ -1604,29 +1603,29 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,/* Bump the stat counter to skip these stats, and make * sure the memory is zero'd */ - data[i++] =0 ; - data[i++] =0 ; - data[i++] =0 ; - data[i++] =0 ; + *(data++) =0 ; + *(data++) =0 ; + *(data++) =0 ; + *(data++) =0 ;continue ; }/* process Tx ring statistics */ do { start =u64_stats_fetch_begin_irq (&tx_ring->syncp); - data[i] = tx_ring->stats.packets; - data[i +1 ] = tx_ring->stats.bytes; + data[0 ] = tx_ring->stats.packets; + data[1 ] = tx_ring->stats.bytes; }while (u64_stats_fetch_retry_irq (&tx_ring->syncp, start)); - i +=2 ; + data +=2 ;/* Rx ring is the 2nd half of the queue pair */ rx_ring = &tx_ring[1 ];do { start =u64_stats_fetch_begin_irq (&rx_ring->syncp); - data[i] = rx_ring->stats.packets; - data[i +1 ] = rx_ring->stats.bytes; + data[0 ] = rx_ring->stats.packets; + data[1 ] = rx_ring->stats.bytes; }while (u64_stats_fetch_retry_irq (&rx_ring->syncp, start)); - i +=2 ; + data +=2 ; }rcu_read_unlock ();if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id !=1 )
@@ -1639,33 +1638,33 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,for (j =0 ; j <I40E_VEB_STATS_LEN ; j++) { p = (char *)veb; p += i40e_gstrings_veb_stats[j].stat_offset; - data[i++] = (i40e_gstrings_veb_stats[j].sizeof_stat == + *(data++) = (i40e_gstrings_veb_stats[j].sizeof_stat ==sizeof (u64)) ? *(u64 *)p : *(u32 *)p; }for (j =0 ; j <I40E_MAX_TRAFFIC_CLASS ; j++) { - data[i++] = veb->tc_stats.tc_tx_packets[j]; - data[i++] = veb->tc_stats.tc_tx_bytes[j]; - data[i++] = veb->tc_stats.tc_rx_packets[j]; - data[i++] = veb->tc_stats.tc_rx_bytes[j]; + *(data++) = veb->tc_stats.tc_tx_packets[j]; + *(data++) = veb->tc_stats.tc_tx_bytes[j]; + *(data++) = veb->tc_stats.tc_rx_packets[j]; + *(data++) = veb->tc_stats.tc_rx_bytes[j]; } }else { - i +=I40E_VEB_STATS_TOTAL ; + data +=I40E_VEB_STATS_TOTAL ; }for (j =0 ; j <I40E_GLOBAL_STATS_LEN ; j++) { p = (char *)pf + i40e_gstrings_stats[j].stat_offset; - data[i++] = (i40e_gstrings_stats[j].sizeof_stat == + *(data++) = (i40e_gstrings_stats[j].sizeof_stat ==sizeof (u64)) ? *(u64 *)p : *(u32 *)p; }for (j =0 ; j <I40E_MAX_USER_PRIORITY ; j++) { - data[i++] = pf->stats.priority_xon_tx[j]; - data[i++] = pf->stats.priority_xoff_tx[j]; + *(data++) = pf->stats.priority_xon_tx[j]; + *(data++) = pf->stats.priority_xoff_tx[j]; }for (j =0 ; j <I40E_MAX_USER_PRIORITY ; j++) { - data[i++] = pf->stats.priority_xon_rx[j]; - data[i++] = pf->stats.priority_xoff_rx[j]; + *(data++) = pf->stats.priority_xon_rx[j]; + *(data++) = pf->stats.priority_xoff_rx[j]; }for (j =0 ; j <I40E_MAX_USER_PRIORITY ; j++) - data[i++] = pf->stats.priority_xon_2_xoff[j]; + *(data++) = pf->stats.priority_xon_2_xoff[j]; }static void i40e_get_stat_strings (struct net_device *netdev,u8 *data)
@@ -1677,73 +1676,73 @@ static void i40e_get_stat_strings(struct net_device *netdev, u8 *data)u8 *p = data;for (i =0 ; i <I40E_NETDEV_STATS_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"%s" , +snprintf (data,ETH_GSTRING_LEN ,"%s" , i40e_gstrings_net_stats[i].stat_string); - p +=ETH_GSTRING_LEN ; + data +=ETH_GSTRING_LEN ; }for (i =0 ; i <I40E_MISC_STATS_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"%s" , +snprintf (data,ETH_GSTRING_LEN ,"%s" , i40e_gstrings_misc_stats[i].stat_string); - p +=ETH_GSTRING_LEN ; + data +=ETH_GSTRING_LEN ; }for (i =0 ; i <I40E_MAX_NUM_QUEUES (netdev); i++) { -snprintf (p,ETH_GSTRING_LEN ,"tx-%u.tx_packets" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN ,"tx-%u.tx_bytes" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN ,"rx-%u.rx_packets" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN ,"rx-%u.rx_bytes" , i); - p +=ETH_GSTRING_LEN ; +snprintf (data,ETH_GSTRING_LEN ,"tx-%u.tx_packets" , i); + data +=ETH_GSTRING_LEN ; +snprintf (data,ETH_GSTRING_LEN ,"tx-%u.tx_bytes" , i); + data +=ETH_GSTRING_LEN ; +snprintf (data,ETH_GSTRING_LEN ,"rx-%u.rx_packets" , i); + data +=ETH_GSTRING_LEN ; +snprintf (data,ETH_GSTRING_LEN ,"rx-%u.rx_bytes" , i); + data +=ETH_GSTRING_LEN ; }if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id !=1 )return ;for (i =0 ; i <I40E_VEB_STATS_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"%s" , +snprintf (data,ETH_GSTRING_LEN ,"%s" , i40e_gstrings_veb_stats[i].stat_string); - p +=ETH_GSTRING_LEN ; + data +=ETH_GSTRING_LEN ; }for (i =0 ; i <I40E_MAX_TRAFFIC_CLASS ; i++) { -snprintf (p,ETH_GSTRING_LEN , +snprintf (data,ETH_GSTRING_LEN ,"veb.tc_%u_tx_packets" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , + data +=ETH_GSTRING_LEN ; +snprintf (data,ETH_GSTRING_LEN ,"veb.tc_%u_tx_bytes" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , + data +=ETH_GSTRING_LEN ; +snprintf (data,ETH_GSTRING_LEN ,"veb.tc_%u_rx_packets" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , + data +=ETH_GSTRING_LEN ; +snprintf (data,ETH_GSTRING_LEN ,"veb.tc_%u_rx_bytes" , i); - p +=ETH_GSTRING_LEN ; + data +=ETH_GSTRING_LEN ; }for (i =0 ; i <I40E_GLOBAL_STATS_LEN ; i++) { -snprintf (p,ETH_GSTRING_LEN ,"%s" , +snprintf (data,ETH_GSTRING_LEN ,"%s" , i40e_gstrings_stats[i].stat_string); - p +=ETH_GSTRING_LEN ; + data +=ETH_GSTRING_LEN ; }for (i =0 ; i <I40E_MAX_USER_PRIORITY ; i++) { -snprintf (p,ETH_GSTRING_LEN , +snprintf (data,ETH_GSTRING_LEN ,"port.tx_priority_%u_xon" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , + data +=ETH_GSTRING_LEN ; +snprintf (data,ETH_GSTRING_LEN ,"port.tx_priority_%u_xoff" , i); - p +=ETH_GSTRING_LEN ; + data +=ETH_GSTRING_LEN ; }for (i =0 ; i <I40E_MAX_USER_PRIORITY ; i++) { -snprintf (p,ETH_GSTRING_LEN , +snprintf (data,ETH_GSTRING_LEN ,"port.rx_priority_%u_xon" , i); - p +=ETH_GSTRING_LEN ; -snprintf (p,ETH_GSTRING_LEN , + data +=ETH_GSTRING_LEN ; +snprintf (data,ETH_GSTRING_LEN ,"port.rx_priority_%u_xoff" , i); - p +=ETH_GSTRING_LEN ; + data +=ETH_GSTRING_LEN ; }for (i =0 ; i <I40E_MAX_USER_PRIORITY ; i++) { -snprintf (p,ETH_GSTRING_LEN , +snprintf (data,ETH_GSTRING_LEN ,"port.rx_priority_%u_xon_2_xoff" , i); - p +=ETH_GSTRING_LEN ; + data +=ETH_GSTRING_LEN ; } WARN_ONCE(p - data != i40e_get_stats_count(netdev) * ETH_GSTRING_LEN,
Signature · 1 line
2.9.5
PATCH 7/9 i40e: update data pointer directly when copying to the buffer
Quoted 20 lines · Alice Michael
From: Jacob Keller <[email protected]>
A future patch is going to add a helper function
i40e_add_ethtool_statsthat will help lower the amount of boiler plate code in thei40e_get_ethtool_statsfunction.This conversion will take place over many patches, and the helper function will work by directly updating a reference to the data pointer.
Since this would not work combined with the current method of accessing data like an array, update all the code that copies stats into the data buffer to use direct updates to the pointer instead of array accesses.
This will prevent incorrect stat updates for patches in between the conversion.
Similarly, when copying strings, we used a separate char *p pointer. Instead, use the data pointer directly as it's already a (u8 *) type which is the same size.
[...]
Quoted 13 lines
/* process Tx ring statistics */ do { start = u64_stats_fetch_begin_irq(&tx_ring->syncp);drivers/net/ethernet/intel/i40e/i40e_ethtool.c +3
-3- data[i] = tx_ring->stats.packets; - data[i +1 ] = tx_ring->stats.bytes; + data[0 ] = tx_ring->stats.packets; + data[1 ] = tx_ring->stats.bytes; }while (u64_stats_fetch_retry_irq (&tx_ring->syncp, start)); - i +=2 ; + data +=2 ;/* Rx ring is the 2nd half of the queue pair */ rx_ring = &tx_ring[1 ];
drivers/net/ethernet/intel/i40e/i40e_ethtool.c static void i40e_get_ethtool_stats(struct net_device *netdev, · line 1629
Quoted 10 lines
drivers/net/ethernet/intel/i40e/i40e_ethtool.c +3
-3do { start =u64_stats_fetch_begin_irq (&rx_ring->syncp); - data[i] = rx_ring->stats.packets; - data[i +1 ] = rx_ring->stats.bytes; + data[0 ] = rx_ring->stats.packets; + data[1 ] = rx_ring->stats.bytes; }while (u64_stats_fetch_retry_irq (&rx_ring->syncp, start)); - i +=2 ; + data +=2 ; }
These two chunks still using an array reference seem out of place with the rest of this patch using pointer references.
sln
Bowers
PATCH 7/9 i40e: update data pointer directly when copying to the buffer
In reply to Alice MichaelQuoted 29 lines
-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at osuosl.org] On Behalf Of Alice Michael
Sent: Thursday, May 17, 2018 1:09 AM
To: Michael, Alice <[email protected]>; intel-wired- lan at lists.osuosl.org
Subject: [Intel-wired-lan] [next PATCH S92 7/9] i40e: update data pointer directly when copying to the bufferFrom: Jacob Keller <[email protected]>
A future patch is going to add a helper function
i40e_add_ethtool_statsthat will help lower the amount of boiler plate code in thei40e_get_ethtool_statsfunction.This conversion will take place over many patches, and the helper function will work by directly updating a reference to the data pointer.
Since this would not work combined with the current method of accessing data like an array, update all the code that copies stats into the data buffer to use direct updates to the pointer instead of array accesses.
This will prevent incorrect stat updates for patches in between the conversion.
Similarly, when copying strings, we used a separate char *p pointer. Instead, use the data pointer directly as it's already a (u8 *) type which is the same size.
Quoted 5 lines
Signed-off-by Jacob Keller <[email protected]>--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 117 ++++++++++++--------- ---- 1 file changed, 58 insertions(+), 59 deletions(-)
PATCH 8/9 i40e: add function doc headers for ethtool stats functions
In reply to Alice MichaelFrom: Jacob Keller <[email protected]>
Add documentation for the i40e_get_stats_count, i40e_get_stat_strings and i40e_get_ethtool_stats explaining that the number and ordering of statistics must remain constant for a given netdevice.
--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
drivers/net/ethernet/intel/i40e/i40e_ethtool.c +38 -0
@@ -1540,6 +1540,20 @@ static int i40e_set_ringparam(struct net_device *netdev,return err; } +/** +* i40e_get_stats_count - return the stats count for a device +* @netdev: the netdev to return the count for +* +* Returns the total number of statistics for this netdev. Note that even +* though this is a function, it is required that the count for a specific +* netdev must never change. Basing the count on static values such as the +* maximum number of queues or the device type is ok. However, the API for +* obtaining stats is *not* safe against changes based on non-static +* values such as the *current* number of queues, or runtime flags. +* +* If a statistic is not always enabled, return it as part of the count +* anyways, always return its string, and report its value as zero. +**/ static int i40e_get_stats_count (struct net_device *netdev) {struct i40e_netdev_priv *np =netdev_priv (netdev);
@@ -1571,6 +1585,20 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset) } } +/** +* i40e_get_ethtool_stats - copy stat values into supplied buffer +* @netdev: the netdev to collect stats for +* @stats: ethtool stats command structure +* @data: ethtool supplied buffer +* +* Copy the stats values for this netdev into the buffer. Expects data to be +* pre-allocated to the size returned by i40e_get_stats_count.. Note that all +* statistics must be copied in a static order, and the count must not change +* for a given netdev. See i40e_get_stats_count for more details. +* +* If a statistic is not currently valid (such as a disabled queue), this +* function reports its value as zero. +**/ static void i40e_get_ethtool_stats (struct net_device *netdev,struct ethtool_stats *stats,u64 *data) {
@@ -1667,6 +1695,16 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, *(data++) = pf->stats.priority_xon_2_xoff[j]; } +/** +* i40e_get_stat_strings - copy stat strings into supplied buffer +* @netdev: the netdev to collect strings for +* @data: supplied buffer to copy strings into +* +* Copy the strings related to stats for this netdev. Expects data to be +* pre-allocated with the size reported by i40e_get_stats_count. Note that the +* strings must be copied in a static order and the total count must not +* change for a given netdev. See i40e_get_stats_count for more details. +**/ static void i40e_get_stat_strings (struct net_device *netdev,u8 *data) {struct i40e_netdev_priv *np =netdev_priv (netdev);
Signature · 1 line
2.9.5
Bowers
PATCH 8/9 i40e: add function doc headers for ethtool stats functions
Quoted 15 lines
-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at osuosl.org] On Behalf Of Alice Michael
Sent: Thursday, May 17, 2018 1:09 AM
To: Michael, Alice <[email protected]>; intel-wired- lan at lists.osuosl.org
Subject: [Intel-wired-lan] [next PATCH S92 8/9] i40e: add function doc headers for ethtool stats functionsFrom: Jacob Keller <[email protected]>
Add documentation for the
i40e_get_stats_count,i40e_get_stat_stringsandi40e_get_ethtool_statsexplaining that the number and ordering of statistics must remain constant for a given netdevice.
Quoted 5 lines
Signed-off-by Jacob Keller <[email protected]>--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
PATCH 9/9 i40e: use the more traditional 'i' loop variable
In reply to Alice MichaelFrom: Jacob Keller <[email protected]>
Since we no longer use i as an array index for the data variable, replace the use of 'j' with 'i' so that we match the general loop variable name.
--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 56 +++++++++++++------------- 1 file changed, 28 insertions(+), 28 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_ethtool.c +28 -28
@@ -1606,26 +1606,26 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,struct i40e_ring *tx_ring, *rx_ring;struct i40e_vsi *vsi = np->vsi;struct i40e_pf *pf = vsi->back; -unsigned int j; +unsigned int i;char *p;struct rtnl_link_stats64 *net_stats =i40e_get_vsi_stats_struct (vsi);unsigned int start;i40e_update_stats (vsi); -for (j =0 ; j <I40E_NETDEV_STATS_LEN ; j++) { - p = (char *)net_stats + i40e_gstrings_net_stats[j].stat_offset; - *(data++) = (i40e_gstrings_net_stats[j].sizeof_stat == +for (i =0 ; i <I40E_NETDEV_STATS_LEN ; i++) { + p = (char *)net_stats + i40e_gstrings_net_stats[i].stat_offset; + *(data++) = (i40e_gstrings_net_stats[i].sizeof_stat ==sizeof (u64)) ? *(u64 *)p : *(u32 *)p; } -for (j =0 ; j <I40E_MISC_STATS_LEN ; j++) { - p = (char *)vsi + i40e_gstrings_misc_stats[j].stat_offset; - *(data++) = (i40e_gstrings_misc_stats[j].sizeof_stat == +for (i =0 ; i <I40E_MISC_STATS_LEN ; i++) { + p = (char *)vsi + i40e_gstrings_misc_stats[i].stat_offset; + *(data++) = (i40e_gstrings_misc_stats[i].sizeof_stat ==sizeof (u64)) ? *(u64 *)p : *(u32 *)p; }rcu_read_lock (); -for (j =0 ; j <I40E_MAX_NUM_QUEUES (netdev) ; j++) { - tx_ring =READ_ONCE (vsi->tx_rings[j]); +for (i =0 ; i <I40E_MAX_NUM_QUEUES (netdev) ; i++) { + tx_ring =READ_ONCE (vsi->tx_rings[i]);if (!tx_ring) {/* Bump the stat counter to skip these stats, and make
@@ -1663,36 +1663,36 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)) {struct i40e_veb *veb = pf->veb[pf->lan_veb]; -for (j =0 ; j <I40E_VEB_STATS_LEN ; j++) { +for (i =0 ; i <I40E_VEB_STATS_LEN ; i++) { p = (char *)veb; - p += i40e_gstrings_veb_stats[j].stat_offset; - *(data++) = (i40e_gstrings_veb_stats[j].sizeof_stat == + p += i40e_gstrings_veb_stats[i].stat_offset; + *(data++) = (i40e_gstrings_veb_stats[i].sizeof_stat ==sizeof (u64)) ? *(u64 *)p : *(u32 *)p; } -for (j =0 ; j <I40E_MAX_TRAFFIC_CLASS ; j++) { - *(data++) = veb->tc_stats.tc_tx_packets[j]; - *(data++) = veb->tc_stats.tc_tx_bytes[j]; - *(data++) = veb->tc_stats.tc_rx_packets[j]; - *(data++) = veb->tc_stats.tc_rx_bytes[j]; +for (i =0 ; i <I40E_MAX_TRAFFIC_CLASS ; i++) { + *(data++) = veb->tc_stats.tc_tx_packets[i]; + *(data++) = veb->tc_stats.tc_tx_bytes[i]; + *(data++) = veb->tc_stats.tc_rx_packets[i]; + *(data++) = veb->tc_stats.tc_rx_bytes[i]; } } else { data +=I40E_VEB_STATS_TOTAL ; } -for (j =0 ; j <I40E_GLOBAL_STATS_LEN ; j++) { - p = (char *)pf + i40e_gstrings_stats[j].stat_offset; - *(data++) = (i40e_gstrings_stats[j].sizeof_stat == +for (i =0 ; i <I40E_GLOBAL_STATS_LEN ; i++) { + p = (char *)pf + i40e_gstrings_stats[i].stat_offset; + *(data++) = (i40e_gstrings_stats[i].sizeof_stat ==sizeof (u64)) ? *(u64 *)p : *(u32 *)p; } -for (j =0 ; j <I40E_MAX_USER_PRIORITY ; j++) { - *(data++) = pf->stats.priority_xon_tx[j]; - *(data++) = pf->stats.priority_xoff_tx[j]; +for (i =0 ; i <I40E_MAX_USER_PRIORITY ; i++) { + *(data++) = pf->stats.priority_xon_tx[i]; + *(data++) = pf->stats.priority_xoff_tx[i]; } -for (j =0 ; j <I40E_MAX_USER_PRIORITY ; j++) { - *(data++) = pf->stats.priority_xon_rx[j]; - *(data++) = pf->stats.priority_xoff_rx[j]; +for (i =0 ; i <I40E_MAX_USER_PRIORITY ; i++) { + *(data++) = pf->stats.priority_xon_rx[i]; + *(data++) = pf->stats.priority_xoff_rx[i]; } -for (j =0 ; j <I40E_MAX_USER_PRIORITY ; j++) - *(data++) = pf->stats.priority_xon_2_xoff[j]; +for (i =0 ; i <I40E_MAX_USER_PRIORITY ; i++) + *(data++) = pf->stats.priority_xon_2_xoff[i]; }/**
Signature · 1 line
2.9.5
Bowers
PATCH 9/9 i40e: use the more traditional 'i' loop variable
Quoted 11 lines
-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at osuosl.org] On Behalf Of Alice Michael
Sent: Thursday, May 17, 2018 1:09 AM
To: Michael, Alice <[email protected]>; intel-wired-
lan at lists.osuosl.org
Subject: [Intel-wired-lan] [next PATCH S92 9/9] i40e: use the more traditional 'i' loop variableFrom: Jacob Keller <[email protected]>
Quoted 8 lines
Since we no longer use i as an array index for the data variable, replace the use of 'j' with 'i' so that we match the general loop variable name.
Signed-off-by Jacob Keller <[email protected]>--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 56 +++++++++++++--------- ---- 1 file changed, 28 insertions(+), 28 deletions(-)
Bowers
PATCH 1/9 i40e: free skb after clearing lock in ptp_stop
In reply to Alice MichaelQuoted 17 lines
-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at osuosl.org] On Behalf Of Alice Michael
Sent: Thursday, May 17, 2018 1:09 AM
To: Michael, Alice <[email protected]>; intel-wired-
lan at lists.osuosl.org
Subject: [Intel-wired-lan] [next PATCH S92 1/9] i40e: free skb after clearing lock inptp_stopFrom: Jacob Keller <[email protected]>
Use the same logic to free the skb after clearing the Tx timestamp bit lock in
i40e_ptp_stopas we use in the other locations. It is not as important here since we are not racing against a future Tx timestamp request (as we are disabling PTP at this point). However it is good to be consistent in how we approach the bit lock so that future callers don't copy the old anti-pattern.
Quoted 4 lines
Signed-off-by Jacob Keller <[email protected]>--- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)