66#include "i40e.h"
77#include "i40e_diag.h"
88
9- struct i40e_stats {
10- /* The stat_string is expected to be a format string formatted using
11- * vsnprintf by i40e_add_stat_strings. Every member of a stats array
12- * should use the same format specifiers as they will be formatted
13- * using the same variadic arguments.
14- */
15- char stat_string [ETH_GSTRING_LEN ];
16- int sizeof_stat ;
17- int stat_offset ;
18- };
9+ #include "i40e_ethtool_stats.h"
1910
20- #define I40E_STAT (_type , _name , _stat ) { \
21- .stat_string = _name, \
22- .sizeof_stat = FIELD_SIZEOF(_type, _stat), \
23- .stat_offset = offsetof(_type, _stat) \
24- }
25-
26- #define I40E_NETDEV_STAT (_net_stat ) \
27- I40E_STAT(struct rtnl_link_stats64, #_net_stat, _net_stat)
2811#define I40E_PF_STAT (_name , _stat ) \
2912 I40E_STAT(struct i40e_pf, _name, _stat)
3013#define I40E_VSI_STAT (_name , _stat ) \
@@ -33,6 +16,8 @@ struct i40e_stats {
3316 I40E_STAT(struct i40e_veb, _name, _stat)
3417#define I40E_PFC_STAT (_name , _stat ) \
3518 I40E_STAT(struct i40e_pfc_stats, _name, _stat)
19+ #define I40E_QUEUE_STAT (_name , _stat ) \
20+ I40E_STAT(struct i40e_ring, _name, _stat)
3621
3722static const struct i40e_stats i40e_gstrings_net_stats [] = {
3823 I40E_NETDEV_STAT (rx_packets ),
@@ -171,20 +156,11 @@ static const struct i40e_stats i40e_gstrings_pfc_stats[] = {
171156 I40E_PFC_STAT ("port.rx_priority_%u_xon_2_xoff" , priority_xon_2_xoff ),
172157};
173158
174- /* We use num_tx_queues here as a proxy for the maximum number of queues
175- * available because we always allocate queues symmetrically.
176- */
177- #define I40E_MAX_NUM_QUEUES (n ) ((n)->num_tx_queues)
178- #define I40E_QUEUE_STATS_LEN (n ) \
179- (I40E_MAX_NUM_QUEUES(n) \
180- * 2 /* Tx and Rx together */ \
181- * (sizeof (struct i40e_queue_stats ) / sizeof (u64 )))
182- #define I40E_GLOBAL_STATS_LEN ARRAY_SIZE(i40e_gstrings_stats)
183159#define I40E_NETDEV_STATS_LEN ARRAY_SIZE(i40e_gstrings_net_stats)
160+
184161#define I40E_MISC_STATS_LEN ARRAY_SIZE(i40e_gstrings_misc_stats)
185- #define I40E_VSI_STATS_LEN (n ) (I40E_NETDEV_STATS_LEN + \
186- I40E_MISC_STATS_LEN + \
187- I40E_QUEUE_STATS_LEN((n)))
162+
163+ #define I40E_VSI_STATS_LEN (I40E_NETDEV_STATS_LEN + I40E_MISC_STATS_LEN)
188164
189165#define I40E_PFC_STATS_LEN (ARRAY_SIZE(i40e_gstrings_pfc_stats) * \
190166 I40E_MAX_USER_PRIORITY)
@@ -193,10 +169,15 @@ static const struct i40e_stats i40e_gstrings_pfc_stats[] = {
193169 (ARRAY_SIZE(i40e_gstrings_veb_tc_stats) * \
194170 I40E_MAX_TRAFFIC_CLASS))
195171
196- #define I40E_PF_STATS_LEN (n ) (I40E_GLOBAL_STATS_LEN + \
172+ #define I40E_GLOBAL_STATS_LEN ARRAY_SIZE(i40e_gstrings_stats)
173+
174+ #define I40E_PF_STATS_LEN (I40E_GLOBAL_STATS_LEN + \
197175 I40E_PFC_STATS_LEN + \
198176 I40E_VEB_STATS_LEN + \
199- I40E_VSI_STATS_LEN((n)))
177+ I40E_VSI_STATS_LEN)
178+
179+ /* Length of stats for a single queue */
180+ #define I40E_QUEUE_STATS_LEN ARRAY_SIZE(i40e_gstrings_queue_stats)
200181
201182enum i40e_ethtool_test_id {
202183 I40E_ETH_TEST_REG = 0 ,
@@ -1701,11 +1682,30 @@ static int i40e_get_stats_count(struct net_device *netdev)
17011682 struct i40e_netdev_priv * np = netdev_priv (netdev );
17021683 struct i40e_vsi * vsi = np -> vsi ;
17031684 struct i40e_pf * pf = vsi -> back ;
1685+ int stats_len ;
17041686
17051687 if (vsi == pf -> vsi [pf -> lan_vsi ] && pf -> hw .partition_id == 1 )
1706- return I40E_PF_STATS_LEN ( netdev ) ;
1688+ stats_len = I40E_PF_STATS_LEN ;
17071689 else
1708- return I40E_VSI_STATS_LEN (netdev );
1690+ stats_len = I40E_VSI_STATS_LEN ;
1691+
1692+ /* The number of stats reported for a given net_device must remain
1693+ * constant throughout the life of that device.
1694+ *
1695+ * This is because the API for obtaining the size, strings, and stats
1696+ * is spread out over three separate ethtool ioctls. There is no safe
1697+ * way to lock the number of stats across these calls, so we must
1698+ * assume that they will never change.
1699+ *
1700+ * Due to this, we report the maximum number of queues, even if not
1701+ * every queue is currently configured. Since we always allocate
1702+ * queues in pairs, we'll just use netdev->num_tx_queues * 2. This
1703+ * works because the num_tx_queues is set at device creation and never
1704+ * changes.
1705+ */
1706+ stats_len += I40E_QUEUE_STATS_LEN * 2 * netdev -> num_tx_queues ;
1707+
1708+ return stats_len ;
17091709}
17101710
17111711static int i40e_get_sset_count (struct net_device * netdev , int sset )
@@ -1727,89 +1727,6 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset)
17271727 }
17281728}
17291729
1730- /**
1731- * i40e_add_one_ethtool_stat - copy the stat into the supplied buffer
1732- * @data: location to store the stat value
1733- * @pointer: basis for where to copy from
1734- * @stat: the stat definition
1735- *
1736- * Copies the stat data defined by the pointer and stat structure pair into
1737- * the memory supplied as data. Used to implement i40e_add_ethtool_stats.
1738- * If the pointer is null, data will be zero'd.
1739- */
1740- static inline void
1741- i40e_add_one_ethtool_stat (u64 * data , void * pointer ,
1742- const struct i40e_stats * stat )
1743- {
1744- char * p ;
1745-
1746- if (!pointer ) {
1747- /* ensure that the ethtool data buffer is zero'd for any stats
1748- * which don't have a valid pointer.
1749- */
1750- * data = 0 ;
1751- return ;
1752- }
1753-
1754- p = (char * )pointer + stat -> stat_offset ;
1755- switch (stat -> sizeof_stat ) {
1756- case sizeof (u64 ):
1757- * data = * ((u64 * )p );
1758- break ;
1759- case sizeof (u32 ):
1760- * data = * ((u32 * )p );
1761- break ;
1762- case sizeof (u16 ):
1763- * data = * ((u16 * )p );
1764- break ;
1765- case sizeof (u8 ):
1766- * data = * ((u8 * )p );
1767- break ;
1768- default :
1769- WARN_ONCE (1 , "unexpected stat size for %s" ,
1770- stat -> stat_string );
1771- * data = 0 ;
1772- }
1773- }
1774-
1775- /**
1776- * __i40e_add_ethtool_stats - copy stats into the ethtool supplied buffer
1777- * @data: ethtool stats buffer
1778- * @pointer: location to copy stats from
1779- * @stats: array of stats to copy
1780- * @size: the size of the stats definition
1781- *
1782- * Copy the stats defined by the stats array using the pointer as a base into
1783- * the data buffer supplied by ethtool. Updates the data pointer to point to
1784- * the next empty location for successive calls to __i40e_add_ethtool_stats.
1785- * If pointer is null, set the data values to zero and update the pointer to
1786- * skip these stats.
1787- **/
1788- static inline void
1789- __i40e_add_ethtool_stats (u64 * * data , void * pointer ,
1790- const struct i40e_stats stats [],
1791- const unsigned int size )
1792- {
1793- unsigned int i ;
1794-
1795- for (i = 0 ; i < size ; i ++ )
1796- i40e_add_one_ethtool_stat ((* data )++ , pointer , & stats [i ]);
1797- }
1798-
1799- /**
1800- * i40e_add_ethtool_stats - copy stats into ethtool supplied buffer
1801- * @data: ethtool stats buffer
1802- * @pointer: location where stats are stored
1803- * @stats: static const array of stat definitions
1804- *
1805- * Macro to ease the use of __i40e_add_ethtool_stats by taking a static
1806- * constant stats array and passing the ARRAY_SIZE(). This avoids typos by
1807- * ensuring that we pass the size associated with the given stats array.
1808- * Assumes that stats is an array.
1809- **/
1810- #define i40e_add_ethtool_stats (data , pointer , stats ) \
1811- __i40e_add_ethtool_stats(data, pointer, stats, ARRAY_SIZE(stats))
1812-
18131730/**
18141731 * i40e_get_pfc_stats - copy HW PFC statistics to formatted structure
18151732 * @pf: the PF device structure
@@ -1853,12 +1770,10 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,
18531770 struct ethtool_stats * stats , u64 * data )
18541771{
18551772 struct i40e_netdev_priv * np = netdev_priv (netdev );
1856- struct i40e_ring * tx_ring , * rx_ring ;
18571773 struct i40e_vsi * vsi = np -> vsi ;
18581774 struct i40e_pf * pf = vsi -> back ;
18591775 struct i40e_veb * veb = pf -> veb [pf -> lan_veb ];
18601776 unsigned int i ;
1861- unsigned int start ;
18621777 bool veb_stats ;
18631778 u64 * p = data ;
18641779
@@ -1870,38 +1785,12 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,
18701785 i40e_add_ethtool_stats (& data , vsi , i40e_gstrings_misc_stats );
18711786
18721787 rcu_read_lock ();
1873- for (i = 0 ; i < I40E_MAX_NUM_QUEUES (netdev ) ; i ++ ) {
1874- tx_ring = READ_ONCE (vsi -> tx_rings [i ]);
1875-
1876- if (!tx_ring ) {
1877- /* Bump the stat counter to skip these stats, and make
1878- * sure the memory is zero'd
1879- */
1880- * (data ++ ) = 0 ;
1881- * (data ++ ) = 0 ;
1882- * (data ++ ) = 0 ;
1883- * (data ++ ) = 0 ;
1884- continue ;
1885- }
1886-
1887- /* process Tx ring statistics */
1888- do {
1889- start = u64_stats_fetch_begin_irq (& tx_ring -> syncp );
1890- data [0 ] = tx_ring -> stats .packets ;
1891- data [1 ] = tx_ring -> stats .bytes ;
1892- } while (u64_stats_fetch_retry_irq (& tx_ring -> syncp , start ));
1893- data += 2 ;
1894-
1895- /* Rx ring is the 2nd half of the queue pair */
1896- rx_ring = & tx_ring [1 ];
1897- do {
1898- start = u64_stats_fetch_begin_irq (& rx_ring -> syncp );
1899- data [0 ] = rx_ring -> stats .packets ;
1900- data [1 ] = rx_ring -> stats .bytes ;
1901- } while (u64_stats_fetch_retry_irq (& rx_ring -> syncp , start ));
1902- data += 2 ;
1788+ for (i = 0 ; i < netdev -> num_tx_queues ; i ++ ) {
1789+ i40e_add_queue_stats (& data , READ_ONCE (vsi -> tx_rings [i ]));
1790+ i40e_add_queue_stats (& data , READ_ONCE (vsi -> rx_rings [i ]));
19031791 }
19041792 rcu_read_unlock ();
1793+
19051794 if (vsi != pf -> vsi [pf -> lan_vsi ] || pf -> hw .partition_id != 1 )
19061795 goto check_data_pointer ;
19071796
@@ -1932,42 +1821,6 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,
19321821 "ethtool stats count mismatch!" );
19331822}
19341823
1935- /**
1936- * __i40e_add_stat_strings - copy stat strings into ethtool buffer
1937- * @p: ethtool supplied buffer
1938- * @stats: stat definitions array
1939- * @size: size of the stats array
1940- *
1941- * Format and copy the strings described by stats into the buffer pointed at
1942- * by p.
1943- **/
1944- static void __i40e_add_stat_strings (u8 * * p , const struct i40e_stats stats [],
1945- const unsigned int size , ...)
1946- {
1947- unsigned int i ;
1948-
1949- for (i = 0 ; i < size ; i ++ ) {
1950- va_list args ;
1951-
1952- va_start (args , size );
1953- vsnprintf (* p , ETH_GSTRING_LEN , stats [i ].stat_string , args );
1954- * p += ETH_GSTRING_LEN ;
1955- va_end (args );
1956- }
1957- }
1958-
1959- /**
1960- * 40e_add_stat_strings - copy stat strings into ethtool buffer
1961- * @p: ethtool supplied buffer
1962- * @stats: stat definitions array
1963- *
1964- * Format and copy the strings described by the const static stats value into
1965- * the buffer pointed at by p. Assumes that stats can have ARRAY_SIZE called
1966- * for it.
1967- **/
1968- #define i40e_add_stat_strings (p , stats , ...) \
1969- __i40e_add_stat_strings(p, stats, ARRAY_SIZE(stats), ## __VA_ARGS__)
1970-
19711824/**
19721825 * i40e_get_stat_strings - copy stat strings into supplied buffer
19731826 * @netdev: the netdev to collect strings for
@@ -1990,16 +1843,13 @@ static void i40e_get_stat_strings(struct net_device *netdev, u8 *data)
19901843
19911844 i40e_add_stat_strings (& data , i40e_gstrings_misc_stats );
19921845
1993- for (i = 0 ; i < I40E_MAX_NUM_QUEUES (netdev ); i ++ ) {
1994- snprintf (data , ETH_GSTRING_LEN , "tx-%u.tx_packets" , i );
1995- data += ETH_GSTRING_LEN ;
1996- snprintf (data , ETH_GSTRING_LEN , "tx-%u.tx_bytes" , i );
1997- data += ETH_GSTRING_LEN ;
1998- snprintf (data , ETH_GSTRING_LEN , "rx-%u.rx_packets" , i );
1999- data += ETH_GSTRING_LEN ;
2000- snprintf (data , ETH_GSTRING_LEN , "rx-%u.rx_bytes" , i );
2001- data += ETH_GSTRING_LEN ;
1846+ for (i = 0 ; i < netdev -> num_tx_queues ; i ++ ) {
1847+ i40e_add_stat_strings (& data , i40e_gstrings_queue_stats ,
1848+ "tx" , i );
1849+ i40e_add_stat_strings (& data , i40e_gstrings_queue_stats ,
1850+ "rx" , i );
20021851 }
1852+
20031853 if (vsi != pf -> vsi [pf -> lan_vsi ] || pf -> hw .partition_id != 1 )
20041854 return ;
20051855
0 commit comments