e1000e: convert to stats64
Based on the patch provided by Flavio Leitner <fleitner@redhat.com> Provides accurate stats at the time user reads them. v2: fixed whitespace/merging issues (by Jeff Kirsher) v3: fixed namespacing issues (by Bruce Allan) CC: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com> Signed-off-by: Flavio Leitner <fleitner@redhat.com>
This commit is contained in:
		
							parent
							
								
									bb134d2298
								
							
						
					
					
						commit
						67fd4fcb78
					
				| @ -364,6 +364,7 @@ struct e1000_adapter { | |||||||
| 	/* structs defined in e1000_hw.h */ | 	/* structs defined in e1000_hw.h */ | ||||||
| 	struct e1000_hw hw; | 	struct e1000_hw hw; | ||||||
| 
 | 
 | ||||||
|  | 	spinlock_t stats64_lock; | ||||||
| 	struct e1000_hw_stats stats; | 	struct e1000_hw_stats stats; | ||||||
| 	struct e1000_phy_info phy_info; | 	struct e1000_phy_info phy_info; | ||||||
| 	struct e1000_phy_stats phy_stats; | 	struct e1000_phy_stats phy_stats; | ||||||
| @ -494,7 +495,9 @@ extern int e1000e_setup_rx_resources(struct e1000_adapter *adapter); | |||||||
| extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter); | extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter); | ||||||
| extern void e1000e_free_rx_resources(struct e1000_adapter *adapter); | extern void e1000e_free_rx_resources(struct e1000_adapter *adapter); | ||||||
| extern void e1000e_free_tx_resources(struct e1000_adapter *adapter); | extern void e1000e_free_tx_resources(struct e1000_adapter *adapter); | ||||||
| extern void e1000e_update_stats(struct e1000_adapter *adapter); | extern struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, | ||||||
|  |                                                     struct rtnl_link_stats64 | ||||||
|  |                                                     *stats); | ||||||
| extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); | extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); | ||||||
| extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); | extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); | ||||||
| extern void e1000e_get_hw_control(struct e1000_adapter *adapter); | extern void e1000e_get_hw_control(struct e1000_adapter *adapter); | ||||||
|  | |||||||
| @ -46,15 +46,15 @@ struct e1000_stats { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define E1000_STAT(str, m) { \ | #define E1000_STAT(str, m) { \ | ||||||
| 			.stat_string = str, \ | 		.stat_string = str, \ | ||||||
| 			.type = E1000_STATS, \ | 		.type = E1000_STATS, \ | ||||||
| 			.sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \ | 		.sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \ | ||||||
| 			.stat_offset = offsetof(struct e1000_adapter, m) } | 		.stat_offset = offsetof(struct e1000_adapter, m) } | ||||||
| #define E1000_NETDEV_STAT(str, m) { \ | #define E1000_NETDEV_STAT(str, m) { \ | ||||||
| 			.stat_string = str, \ | 		.stat_string = str, \ | ||||||
| 			.type = NETDEV_STATS, \ | 		.type = NETDEV_STATS, \ | ||||||
| 			.sizeof_stat = sizeof(((struct net_device *)0)->m), \ | 		.sizeof_stat = sizeof(((struct rtnl_link_stats64 *)0)->m), \ | ||||||
| 			.stat_offset = offsetof(struct net_device, m) } | 		.stat_offset = offsetof(struct rtnl_link_stats64, m) } | ||||||
| 
 | 
 | ||||||
| static const struct e1000_stats e1000_gstrings_stats[] = { | static const struct e1000_stats e1000_gstrings_stats[] = { | ||||||
| 	E1000_STAT("rx_packets", stats.gprc), | 	E1000_STAT("rx_packets", stats.gprc), | ||||||
| @ -65,21 +65,21 @@ static const struct e1000_stats e1000_gstrings_stats[] = { | |||||||
| 	E1000_STAT("tx_broadcast", stats.bptc), | 	E1000_STAT("tx_broadcast", stats.bptc), | ||||||
| 	E1000_STAT("rx_multicast", stats.mprc), | 	E1000_STAT("rx_multicast", stats.mprc), | ||||||
| 	E1000_STAT("tx_multicast", stats.mptc), | 	E1000_STAT("tx_multicast", stats.mptc), | ||||||
| 	E1000_NETDEV_STAT("rx_errors", stats.rx_errors), | 	E1000_NETDEV_STAT("rx_errors", rx_errors), | ||||||
| 	E1000_NETDEV_STAT("tx_errors", stats.tx_errors), | 	E1000_NETDEV_STAT("tx_errors", tx_errors), | ||||||
| 	E1000_NETDEV_STAT("tx_dropped", stats.tx_dropped), | 	E1000_NETDEV_STAT("tx_dropped", tx_dropped), | ||||||
| 	E1000_STAT("multicast", stats.mprc), | 	E1000_STAT("multicast", stats.mprc), | ||||||
| 	E1000_STAT("collisions", stats.colc), | 	E1000_STAT("collisions", stats.colc), | ||||||
| 	E1000_NETDEV_STAT("rx_length_errors", stats.rx_length_errors), | 	E1000_NETDEV_STAT("rx_length_errors", rx_length_errors), | ||||||
| 	E1000_NETDEV_STAT("rx_over_errors", stats.rx_over_errors), | 	E1000_NETDEV_STAT("rx_over_errors", rx_over_errors), | ||||||
| 	E1000_STAT("rx_crc_errors", stats.crcerrs), | 	E1000_STAT("rx_crc_errors", stats.crcerrs), | ||||||
| 	E1000_NETDEV_STAT("rx_frame_errors", stats.rx_frame_errors), | 	E1000_NETDEV_STAT("rx_frame_errors", rx_frame_errors), | ||||||
| 	E1000_STAT("rx_no_buffer_count", stats.rnbc), | 	E1000_STAT("rx_no_buffer_count", stats.rnbc), | ||||||
| 	E1000_STAT("rx_missed_errors", stats.mpc), | 	E1000_STAT("rx_missed_errors", stats.mpc), | ||||||
| 	E1000_STAT("tx_aborted_errors", stats.ecol), | 	E1000_STAT("tx_aborted_errors", stats.ecol), | ||||||
| 	E1000_STAT("tx_carrier_errors", stats.tncrs), | 	E1000_STAT("tx_carrier_errors", stats.tncrs), | ||||||
| 	E1000_NETDEV_STAT("tx_fifo_errors", stats.tx_fifo_errors), | 	E1000_NETDEV_STAT("tx_fifo_errors", tx_fifo_errors), | ||||||
| 	E1000_NETDEV_STAT("tx_heartbeat_errors", stats.tx_heartbeat_errors), | 	E1000_NETDEV_STAT("tx_heartbeat_errors", tx_heartbeat_errors), | ||||||
| 	E1000_STAT("tx_window_errors", stats.latecol), | 	E1000_STAT("tx_window_errors", stats.latecol), | ||||||
| 	E1000_STAT("tx_abort_late_coll", stats.latecol), | 	E1000_STAT("tx_abort_late_coll", stats.latecol), | ||||||
| 	E1000_STAT("tx_deferred_ok", stats.dc), | 	E1000_STAT("tx_deferred_ok", stats.dc), | ||||||
| @ -1982,14 +1982,15 @@ static void e1000_get_ethtool_stats(struct net_device *netdev, | |||||||
| 				    u64 *data) | 				    u64 *data) | ||||||
| { | { | ||||||
| 	struct e1000_adapter *adapter = netdev_priv(netdev); | 	struct e1000_adapter *adapter = netdev_priv(netdev); | ||||||
|  | 	struct rtnl_link_stats64 net_stats; | ||||||
| 	int i; | 	int i; | ||||||
| 	char *p = NULL; | 	char *p = NULL; | ||||||
| 
 | 
 | ||||||
| 	e1000e_update_stats(adapter); | 	e1000e_get_stats64(netdev, &net_stats); | ||||||
| 	for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { | 	for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { | ||||||
| 		switch (e1000_gstrings_stats[i].type) { | 		switch (e1000_gstrings_stats[i].type) { | ||||||
| 		case NETDEV_STATS: | 		case NETDEV_STATS: | ||||||
| 			p = (char *) netdev + | 			p = (char *) &net_stats + | ||||||
| 					e1000_gstrings_stats[i].stat_offset; | 					e1000_gstrings_stats[i].stat_offset; | ||||||
| 			break; | 			break; | ||||||
| 		case E1000_STATS: | 		case E1000_STATS: | ||||||
|  | |||||||
| @ -900,8 +900,6 @@ next_desc: | |||||||
| 
 | 
 | ||||||
| 	adapter->total_rx_bytes += total_rx_bytes; | 	adapter->total_rx_bytes += total_rx_bytes; | ||||||
| 	adapter->total_rx_packets += total_rx_packets; | 	adapter->total_rx_packets += total_rx_packets; | ||||||
| 	netdev->stats.rx_bytes += total_rx_bytes; |  | ||||||
| 	netdev->stats.rx_packets += total_rx_packets; |  | ||||||
| 	return cleaned; | 	return cleaned; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -1057,8 +1055,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) | |||||||
| 	} | 	} | ||||||
| 	adapter->total_tx_bytes += total_tx_bytes; | 	adapter->total_tx_bytes += total_tx_bytes; | ||||||
| 	adapter->total_tx_packets += total_tx_packets; | 	adapter->total_tx_packets += total_tx_packets; | ||||||
| 	netdev->stats.tx_bytes += total_tx_bytes; |  | ||||||
| 	netdev->stats.tx_packets += total_tx_packets; |  | ||||||
| 	return count < tx_ring->count; | 	return count < tx_ring->count; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -1245,8 +1241,6 @@ next_desc: | |||||||
| 
 | 
 | ||||||
| 	adapter->total_rx_bytes += total_rx_bytes; | 	adapter->total_rx_bytes += total_rx_bytes; | ||||||
| 	adapter->total_rx_packets += total_rx_packets; | 	adapter->total_rx_packets += total_rx_packets; | ||||||
| 	netdev->stats.rx_bytes += total_rx_bytes; |  | ||||||
| 	netdev->stats.rx_packets += total_rx_packets; |  | ||||||
| 	return cleaned; | 	return cleaned; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -1426,8 +1420,6 @@ next_desc: | |||||||
| 
 | 
 | ||||||
| 	adapter->total_rx_bytes += total_rx_bytes; | 	adapter->total_rx_bytes += total_rx_bytes; | ||||||
| 	adapter->total_rx_packets += total_rx_packets; | 	adapter->total_rx_packets += total_rx_packets; | ||||||
| 	netdev->stats.rx_bytes += total_rx_bytes; |  | ||||||
| 	netdev->stats.rx_packets += total_rx_packets; |  | ||||||
| 	return cleaned; | 	return cleaned; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -3338,6 +3330,8 @@ int e1000e_up(struct e1000_adapter *adapter) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void e1000e_update_stats(struct e1000_adapter *adapter); | ||||||
|  | 
 | ||||||
| void e1000e_down(struct e1000_adapter *adapter) | void e1000e_down(struct e1000_adapter *adapter) | ||||||
| { | { | ||||||
| 	struct net_device *netdev = adapter->netdev; | 	struct net_device *netdev = adapter->netdev; | ||||||
| @ -3372,6 +3366,11 @@ void e1000e_down(struct e1000_adapter *adapter) | |||||||
| 	del_timer_sync(&adapter->phy_info_timer); | 	del_timer_sync(&adapter->phy_info_timer); | ||||||
| 
 | 
 | ||||||
| 	netif_carrier_off(netdev); | 	netif_carrier_off(netdev); | ||||||
|  | 
 | ||||||
|  | 	spin_lock(&adapter->stats64_lock); | ||||||
|  | 	e1000e_update_stats(adapter); | ||||||
|  | 	spin_unlock(&adapter->stats64_lock); | ||||||
|  | 
 | ||||||
| 	adapter->link_speed = 0; | 	adapter->link_speed = 0; | ||||||
| 	adapter->link_duplex = 0; | 	adapter->link_duplex = 0; | ||||||
| 
 | 
 | ||||||
| @ -3413,6 +3412,8 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) | |||||||
| 	adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; | 	adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; | ||||||
| 	adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; | 	adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; | ||||||
| 
 | 
 | ||||||
|  | 	spin_lock_init(&adapter->stats64_lock); | ||||||
|  | 
 | ||||||
| 	e1000e_set_interrupt_capability(adapter); | 	e1000e_set_interrupt_capability(adapter); | ||||||
| 
 | 
 | ||||||
| 	if (e1000_alloc_queues(adapter)) | 	if (e1000_alloc_queues(adapter)) | ||||||
| @ -3886,7 +3887,7 @@ release: | |||||||
|  * e1000e_update_stats - Update the board statistics counters |  * e1000e_update_stats - Update the board statistics counters | ||||||
|  * @adapter: board private structure |  * @adapter: board private structure | ||||||
|  **/ |  **/ | ||||||
| void e1000e_update_stats(struct e1000_adapter *adapter) | static void e1000e_update_stats(struct e1000_adapter *adapter) | ||||||
| { | { | ||||||
| 	struct net_device *netdev = adapter->netdev; | 	struct net_device *netdev = adapter->netdev; | ||||||
| 	struct e1000_hw *hw = &adapter->hw; | 	struct e1000_hw *hw = &adapter->hw; | ||||||
| @ -4285,7 +4286,9 @@ static void e1000_watchdog_task(struct work_struct *work) | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| link_up: | link_up: | ||||||
|  | 	spin_lock(&adapter->stats64_lock); | ||||||
| 	e1000e_update_stats(adapter); | 	e1000e_update_stats(adapter); | ||||||
|  | 	spin_unlock(&adapter->stats64_lock); | ||||||
| 
 | 
 | ||||||
| 	mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; | 	mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; | ||||||
| 	adapter->tpt_old = adapter->stats.tpt; | 	adapter->tpt_old = adapter->stats.tpt; | ||||||
| @ -4897,16 +4900,55 @@ static void e1000_reset_task(struct work_struct *work) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * e1000_get_stats - Get System Network Statistics |  * e1000_get_stats64 - Get System Network Statistics | ||||||
|  * @netdev: network interface device structure |  * @netdev: network interface device structure | ||||||
|  |  * @stats: rtnl_link_stats64 pointer | ||||||
|  * |  * | ||||||
|  * Returns the address of the device statistics structure. |  * Returns the address of the device statistics structure. | ||||||
|  * The statistics are actually updated from the timer callback. |  | ||||||
|  **/ |  **/ | ||||||
| static struct net_device_stats *e1000_get_stats(struct net_device *netdev) | struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, | ||||||
|  |                                              struct rtnl_link_stats64 *stats) | ||||||
| { | { | ||||||
| 	/* only return the current stats */ | 	struct e1000_adapter *adapter = netdev_priv(netdev); | ||||||
| 	return &netdev->stats; | 
 | ||||||
|  | 	memset(stats, 0, sizeof(struct rtnl_link_stats64)); | ||||||
|  | 	spin_lock(&adapter->stats64_lock); | ||||||
|  | 	e1000e_update_stats(adapter); | ||||||
|  | 	/* Fill out the OS statistics structure */ | ||||||
|  | 	stats->rx_bytes = adapter->stats.gorc; | ||||||
|  | 	stats->rx_packets = adapter->stats.gprc; | ||||||
|  | 	stats->tx_bytes = adapter->stats.gotc; | ||||||
|  | 	stats->tx_packets = adapter->stats.gptc; | ||||||
|  | 	stats->multicast = adapter->stats.mprc; | ||||||
|  | 	stats->collisions = adapter->stats.colc; | ||||||
|  | 
 | ||||||
|  | 	/* Rx Errors */ | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * RLEC on some newer hardware can be incorrect so build | ||||||
|  | 	 * our own version based on RUC and ROC | ||||||
|  | 	 */ | ||||||
|  | 	stats->rx_errors = adapter->stats.rxerrc + | ||||||
|  | 		adapter->stats.crcerrs + adapter->stats.algnerrc + | ||||||
|  | 		adapter->stats.ruc + adapter->stats.roc + | ||||||
|  | 		adapter->stats.cexterr; | ||||||
|  | 	stats->rx_length_errors = adapter->stats.ruc + | ||||||
|  | 					      adapter->stats.roc; | ||||||
|  | 	stats->rx_crc_errors = adapter->stats.crcerrs; | ||||||
|  | 	stats->rx_frame_errors = adapter->stats.algnerrc; | ||||||
|  | 	stats->rx_missed_errors = adapter->stats.mpc; | ||||||
|  | 
 | ||||||
|  | 	/* Tx Errors */ | ||||||
|  | 	stats->tx_errors = adapter->stats.ecol + | ||||||
|  | 				       adapter->stats.latecol; | ||||||
|  | 	stats->tx_aborted_errors = adapter->stats.ecol; | ||||||
|  | 	stats->tx_window_errors = adapter->stats.latecol; | ||||||
|  | 	stats->tx_carrier_errors = adapter->stats.tncrs; | ||||||
|  | 
 | ||||||
|  | 	/* Tx Dropped needs to be maintained elsewhere */ | ||||||
|  | 
 | ||||||
|  | 	spin_unlock(&adapter->stats64_lock); | ||||||
|  | 	return stats; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
| @ -5675,7 +5717,7 @@ static const struct net_device_ops e1000e_netdev_ops = { | |||||||
| 	.ndo_open		= e1000_open, | 	.ndo_open		= e1000_open, | ||||||
| 	.ndo_stop		= e1000_close, | 	.ndo_stop		= e1000_close, | ||||||
| 	.ndo_start_xmit		= e1000_xmit_frame, | 	.ndo_start_xmit		= e1000_xmit_frame, | ||||||
| 	.ndo_get_stats		= e1000_get_stats, | 	.ndo_get_stats64	= e1000e_get_stats64, | ||||||
| 	.ndo_set_multicast_list	= e1000_set_multi, | 	.ndo_set_multicast_list	= e1000_set_multi, | ||||||
| 	.ndo_set_mac_address	= e1000_set_mac, | 	.ndo_set_mac_address	= e1000_set_mac, | ||||||
| 	.ndo_change_mtu		= e1000_change_mtu, | 	.ndo_change_mtu		= e1000_change_mtu, | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user