Commit 4eb7f20b authored by Mohsin Bashir's avatar Mohsin Bashir Committed by David S. Miller

eth: fbnic: Add support to fetch group stats

Add support for group stats for mac. The fbnic_set_counter help preserve
the default values for counters which are not touched by the driver.

The 'reset' flag in 'get_eth_mac_stats' allows to choose between
resetting the counter to recent most value or fetching the aggregated
values of the counter.

The 'fbnic_stat_rd64' read 64b stats counters in an atomic fashion using
read-read-read approach. This allows to isolate cases where counter is
moving too fast making accuracy of the counter questionable.

Command: ethtool -S eth0 --groups eth-mac
Example Output:
eth-mac-FramesTransmittedOK: 421644
eth-mac-FramesReceivedOK: 3849708
eth-mac-FrameCheckSequenceErrors: 0
eth-mac-AlignmentErrors: 0
eth-mac-OctetsTransmittedOK: 64799060
eth-mac-FramesLostDueToIntMACXmitError: 0
eth-mac-OctetsReceivedOK: 5134513531
eth-mac-FramesLostDueToIntMACRcvError: 0
eth-mac-MulticastFramesXmittedOK: 568
eth-mac-BroadcastFramesXmittedOK: 454
eth-mac-MulticastFramesReceivedOK: 276106
eth-mac-BroadcastFramesReceivedOK: 26119
eth-mac-FrameTooLongErrors: 0
Signed-off-by: default avatarMohsin Bashir <mohsin.bashr@gmail.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bd2557a5
...@@ -10,6 +10,7 @@ obj-$(CONFIG_FBNIC) += fbnic.o ...@@ -10,6 +10,7 @@ obj-$(CONFIG_FBNIC) += fbnic.o
fbnic-y := fbnic_devlink.o \ fbnic-y := fbnic_devlink.o \
fbnic_ethtool.o \ fbnic_ethtool.o \
fbnic_fw.o \ fbnic_fw.o \
fbnic_hw_stats.o \
fbnic_irq.o \ fbnic_irq.o \
fbnic_mac.o \ fbnic_mac.o \
fbnic_netdev.o \ fbnic_netdev.o \
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "fbnic_csr.h" #include "fbnic_csr.h"
#include "fbnic_fw.h" #include "fbnic_fw.h"
#include "fbnic_hw_stats.h"
#include "fbnic_mac.h" #include "fbnic_mac.h"
#include "fbnic_rpc.h" #include "fbnic_rpc.h"
...@@ -47,6 +48,9 @@ struct fbnic_dev { ...@@ -47,6 +48,9 @@ struct fbnic_dev {
/* Number of TCQs/RCQs available on hardware */ /* Number of TCQs/RCQs available on hardware */
u16 max_num_queues; u16 max_num_queues;
/* Local copy of hardware statistics */
struct fbnic_hw_stats hw_stats;
}; };
/* Reserve entry 0 in the MSI-X "others" array until we have filled all /* Reserve entry 0 in the MSI-X "others" array until we have filled all
......
...@@ -660,6 +660,43 @@ enum { ...@@ -660,6 +660,43 @@ enum {
#define FBNIC_SIG_PCS_INTR_MASK 0x11816 /* 0x46058 */ #define FBNIC_SIG_PCS_INTR_MASK 0x11816 /* 0x46058 */
#define FBNIC_CSR_END_SIG 0x1184e /* CSR section delimiter */ #define FBNIC_CSR_END_SIG 0x1184e /* CSR section delimiter */
#define FBNIC_CSR_START_MAC_STAT 0x11a00
#define FBNIC_MAC_STAT_RX_BYTE_COUNT_L 0x11a08 /* 0x46820 */
#define FBNIC_MAC_STAT_RX_BYTE_COUNT_H 0x11a09 /* 0x46824 */
#define FBNIC_MAC_STAT_RX_ALIGN_ERROR_L \
0x11a0a /* 0x46828 */
#define FBNIC_MAC_STAT_RX_ALIGN_ERROR_H \
0x11a0b /* 0x4682c */
#define FBNIC_MAC_STAT_RX_TOOLONG_L 0x11a0e /* 0x46838 */
#define FBNIC_MAC_STAT_RX_TOOLONG_H 0x11a0f /* 0x4683c */
#define FBNIC_MAC_STAT_RX_RECEIVED_OK_L \
0x11a12 /* 0x46848 */
#define FBNIC_MAC_STAT_RX_RECEIVED_OK_H \
0x11a13 /* 0x4684c */
#define FBNIC_MAC_STAT_RX_PACKET_BAD_FCS_L \
0x11a14 /* 0x46850 */
#define FBNIC_MAC_STAT_RX_PACKET_BAD_FCS_H \
0x11a15 /* 0x46854 */
#define FBNIC_MAC_STAT_RX_IFINERRORS_L 0x11a18 /* 0x46860 */
#define FBNIC_MAC_STAT_RX_IFINERRORS_H 0x11a19 /* 0x46864 */
#define FBNIC_MAC_STAT_RX_MULTICAST_L 0x11a1c /* 0x46870 */
#define FBNIC_MAC_STAT_RX_MULTICAST_H 0x11a1d /* 0x46874 */
#define FBNIC_MAC_STAT_RX_BROADCAST_L 0x11a1e /* 0x46878 */
#define FBNIC_MAC_STAT_RX_BROADCAST_H 0x11a1f /* 0x4687c */
#define FBNIC_MAC_STAT_TX_BYTE_COUNT_L 0x11a3e /* 0x468f8 */
#define FBNIC_MAC_STAT_TX_BYTE_COUNT_H 0x11a3f /* 0x468fc */
#define FBNIC_MAC_STAT_TX_TRANSMITTED_OK_L \
0x11a42 /* 0x46908 */
#define FBNIC_MAC_STAT_TX_TRANSMITTED_OK_H \
0x11a43 /* 0x4690c */
#define FBNIC_MAC_STAT_TX_IFOUTERRORS_L \
0x11a46 /* 0x46918 */
#define FBNIC_MAC_STAT_TX_IFOUTERRORS_H \
0x11a47 /* 0x4691c */
#define FBNIC_MAC_STAT_TX_MULTICAST_L 0x11a4a /* 0x46928 */
#define FBNIC_MAC_STAT_TX_MULTICAST_H 0x11a4b /* 0x4692c */
#define FBNIC_MAC_STAT_TX_BROADCAST_L 0x11a4c /* 0x46930 */
#define FBNIC_MAC_STAT_TX_BROADCAST_H 0x11a4d /* 0x46934 */
/* PUL User Registers */ /* PUL User Registers */
#define FBNIC_CSR_START_PUL_USER 0x31000 /* CSR section delimiter */ #define FBNIC_CSR_START_PUL_USER 0x31000 /* CSR section delimiter */
#define FBNIC_PUL_OB_TLP_HDR_AW_CFG 0x3103d /* 0xc40f4 */ #define FBNIC_PUL_OB_TLP_HDR_AW_CFG 0x3103d /* 0xc40f4 */
......
...@@ -16,8 +16,57 @@ fbnic_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) ...@@ -16,8 +16,57 @@ fbnic_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
sizeof(drvinfo->fw_version)); sizeof(drvinfo->fw_version));
} }
static void fbnic_set_counter(u64 *stat, struct fbnic_stat_counter *counter)
{
if (counter->reported)
*stat = counter->value;
}
static void
fbnic_get_eth_mac_stats(struct net_device *netdev,
struct ethtool_eth_mac_stats *eth_mac_stats)
{
struct fbnic_net *fbn = netdev_priv(netdev);
struct fbnic_mac_stats *mac_stats;
struct fbnic_dev *fbd = fbn->fbd;
const struct fbnic_mac *mac;
mac_stats = &fbd->hw_stats.mac;
mac = fbd->mac;
mac->get_eth_mac_stats(fbd, false, &mac_stats->eth_mac);
fbnic_set_counter(&eth_mac_stats->FramesTransmittedOK,
&mac_stats->eth_mac.FramesTransmittedOK);
fbnic_set_counter(&eth_mac_stats->FramesReceivedOK,
&mac_stats->eth_mac.FramesReceivedOK);
fbnic_set_counter(&eth_mac_stats->FrameCheckSequenceErrors,
&mac_stats->eth_mac.FrameCheckSequenceErrors);
fbnic_set_counter(&eth_mac_stats->AlignmentErrors,
&mac_stats->eth_mac.AlignmentErrors);
fbnic_set_counter(&eth_mac_stats->OctetsTransmittedOK,
&mac_stats->eth_mac.OctetsTransmittedOK);
fbnic_set_counter(&eth_mac_stats->FramesLostDueToIntMACXmitError,
&mac_stats->eth_mac.FramesLostDueToIntMACXmitError);
fbnic_set_counter(&eth_mac_stats->OctetsReceivedOK,
&mac_stats->eth_mac.OctetsReceivedOK);
fbnic_set_counter(&eth_mac_stats->FramesLostDueToIntMACRcvError,
&mac_stats->eth_mac.FramesLostDueToIntMACRcvError);
fbnic_set_counter(&eth_mac_stats->MulticastFramesXmittedOK,
&mac_stats->eth_mac.MulticastFramesXmittedOK);
fbnic_set_counter(&eth_mac_stats->BroadcastFramesXmittedOK,
&mac_stats->eth_mac.BroadcastFramesXmittedOK);
fbnic_set_counter(&eth_mac_stats->MulticastFramesReceivedOK,
&mac_stats->eth_mac.MulticastFramesReceivedOK);
fbnic_set_counter(&eth_mac_stats->BroadcastFramesReceivedOK,
&mac_stats->eth_mac.BroadcastFramesReceivedOK);
fbnic_set_counter(&eth_mac_stats->FrameTooLongErrors,
&mac_stats->eth_mac.FrameTooLongErrors);
}
static const struct ethtool_ops fbnic_ethtool_ops = { static const struct ethtool_ops fbnic_ethtool_ops = {
.get_drvinfo = fbnic_get_drvinfo, .get_drvinfo = fbnic_get_drvinfo,
.get_eth_mac_stats = fbnic_get_eth_mac_stats,
}; };
void fbnic_set_ethtool_ops(struct net_device *dev) void fbnic_set_ethtool_ops(struct net_device *dev)
......
#include "fbnic.h"
u64 fbnic_stat_rd64(struct fbnic_dev *fbd, u32 reg, u32 offset)
{
u32 prev_upper, upper, lower, diff;
prev_upper = rd32(fbd, reg + offset);
lower = rd32(fbd, reg);
upper = rd32(fbd, reg + offset);
diff = upper - prev_upper;
if (!diff)
return ((u64)upper << 32) | lower;
if (diff > 1)
dev_warn_once(fbd->dev,
"Stats inconsistent, upper 32b of %#010x updating too quickly\n",
reg * 4);
/* Return only the upper bits as we cannot guarantee
* the accuracy of the lower bits. We will add them in
* when the counter slows down enough that we can get
* a snapshot with both upper values being the same
* between reads.
*/
return ((u64)upper << 32);
}
#include <linux/ethtool.h>
#include "fbnic_csr.h"
struct fbnic_stat_counter {
u64 value;
union {
u32 old_reg_value_32;
u64 old_reg_value_64;
} u;
bool reported;
};
struct fbnic_eth_mac_stats {
struct fbnic_stat_counter FramesTransmittedOK;
struct fbnic_stat_counter FramesReceivedOK;
struct fbnic_stat_counter FrameCheckSequenceErrors;
struct fbnic_stat_counter AlignmentErrors;
struct fbnic_stat_counter OctetsTransmittedOK;
struct fbnic_stat_counter FramesLostDueToIntMACXmitError;
struct fbnic_stat_counter OctetsReceivedOK;
struct fbnic_stat_counter FramesLostDueToIntMACRcvError;
struct fbnic_stat_counter MulticastFramesXmittedOK;
struct fbnic_stat_counter BroadcastFramesXmittedOK;
struct fbnic_stat_counter MulticastFramesReceivedOK;
struct fbnic_stat_counter BroadcastFramesReceivedOK;
struct fbnic_stat_counter FrameTooLongErrors;
};
struct fbnic_mac_stats {
struct fbnic_eth_mac_stats eth_mac;
};
struct fbnic_hw_stats {
struct fbnic_mac_stats mac;
};
u64 fbnic_stat_rd64(struct fbnic_dev *fbd, u32 reg, u32 offset);
void fbnic_get_hw_stats(struct fbnic_dev *fbd);
...@@ -403,6 +403,21 @@ static void fbnic_mac_init_regs(struct fbnic_dev *fbd) ...@@ -403,6 +403,21 @@ static void fbnic_mac_init_regs(struct fbnic_dev *fbd)
fbnic_mac_init_txb(fbd); fbnic_mac_init_txb(fbd);
} }
static void __fbnic_mac_stat_rd64(struct fbnic_dev *fbd, bool reset, u32 reg,
struct fbnic_stat_counter *stat)
{
u64 new_reg_value;
new_reg_value = fbnic_stat_rd64(fbd, reg, 1);
if (!reset)
stat->value += new_reg_value - stat->u.old_reg_value_64;
stat->u.old_reg_value_64 = new_reg_value;
stat->reported = true;
}
#define fbnic_mac_stat_rd64(fbd, reset, __stat, __CSR) \
__fbnic_mac_stat_rd64(fbd, reset, FBNIC_##__CSR##_L, &(__stat))
static void fbnic_mac_tx_pause_config(struct fbnic_dev *fbd, bool tx_pause) static void fbnic_mac_tx_pause_config(struct fbnic_dev *fbd, bool tx_pause)
{ {
u32 rxb_pause_ctrl; u32 rxb_pause_ctrl;
...@@ -637,12 +652,47 @@ static void fbnic_mac_link_up_asic(struct fbnic_dev *fbd, ...@@ -637,12 +652,47 @@ static void fbnic_mac_link_up_asic(struct fbnic_dev *fbd,
wr32(fbd, FBNIC_MAC_COMMAND_CONFIG, cmd_cfg); wr32(fbd, FBNIC_MAC_COMMAND_CONFIG, cmd_cfg);
} }
static void
fbnic_mac_get_eth_mac_stats(struct fbnic_dev *fbd, bool reset,
struct fbnic_eth_mac_stats *mac_stats)
{
fbnic_mac_stat_rd64(fbd, reset, mac_stats->OctetsReceivedOK,
MAC_STAT_RX_BYTE_COUNT);
fbnic_mac_stat_rd64(fbd, reset, mac_stats->AlignmentErrors,
MAC_STAT_RX_ALIGN_ERROR);
fbnic_mac_stat_rd64(fbd, reset, mac_stats->FrameTooLongErrors,
MAC_STAT_RX_TOOLONG);
fbnic_mac_stat_rd64(fbd, reset, mac_stats->FramesReceivedOK,
MAC_STAT_RX_RECEIVED_OK);
fbnic_mac_stat_rd64(fbd, reset, mac_stats->FrameCheckSequenceErrors,
MAC_STAT_RX_PACKET_BAD_FCS);
fbnic_mac_stat_rd64(fbd, reset,
mac_stats->FramesLostDueToIntMACRcvError,
MAC_STAT_RX_IFINERRORS);
fbnic_mac_stat_rd64(fbd, reset, mac_stats->MulticastFramesReceivedOK,
MAC_STAT_RX_MULTICAST);
fbnic_mac_stat_rd64(fbd, reset, mac_stats->BroadcastFramesReceivedOK,
MAC_STAT_RX_BROADCAST);
fbnic_mac_stat_rd64(fbd, reset, mac_stats->OctetsTransmittedOK,
MAC_STAT_TX_BYTE_COUNT);
fbnic_mac_stat_rd64(fbd, reset, mac_stats->FramesTransmittedOK,
MAC_STAT_TX_TRANSMITTED_OK);
fbnic_mac_stat_rd64(fbd, reset,
mac_stats->FramesLostDueToIntMACXmitError,
MAC_STAT_TX_IFOUTERRORS);
fbnic_mac_stat_rd64(fbd, reset, mac_stats->MulticastFramesXmittedOK,
MAC_STAT_TX_MULTICAST);
fbnic_mac_stat_rd64(fbd, reset, mac_stats->BroadcastFramesXmittedOK,
MAC_STAT_TX_BROADCAST);
}
static const struct fbnic_mac fbnic_mac_asic = { static const struct fbnic_mac fbnic_mac_asic = {
.init_regs = fbnic_mac_init_regs, .init_regs = fbnic_mac_init_regs,
.pcs_enable = fbnic_pcs_enable_asic, .pcs_enable = fbnic_pcs_enable_asic,
.pcs_disable = fbnic_pcs_disable_asic, .pcs_disable = fbnic_pcs_disable_asic,
.pcs_get_link = fbnic_pcs_get_link_asic, .pcs_get_link = fbnic_pcs_get_link_asic,
.pcs_get_link_event = fbnic_pcs_get_link_event_asic, .pcs_get_link_event = fbnic_pcs_get_link_event_asic,
.get_eth_mac_stats = fbnic_mac_get_eth_mac_stats,
.link_down = fbnic_mac_link_down_asic, .link_down = fbnic_mac_link_down_asic,
.link_up = fbnic_mac_link_up_asic, .link_up = fbnic_mac_link_up_asic,
}; };
......
...@@ -78,6 +78,9 @@ struct fbnic_mac { ...@@ -78,6 +78,9 @@ struct fbnic_mac {
bool (*pcs_get_link)(struct fbnic_dev *fbd); bool (*pcs_get_link)(struct fbnic_dev *fbd);
int (*pcs_get_link_event)(struct fbnic_dev *fbd); int (*pcs_get_link_event)(struct fbnic_dev *fbd);
void (*get_eth_mac_stats)(struct fbnic_dev *fbd, bool reset,
struct fbnic_eth_mac_stats *mac_stats);
void (*link_down)(struct fbnic_dev *fbd); void (*link_down)(struct fbnic_dev *fbd);
void (*link_up)(struct fbnic_dev *fbd, bool tx_pause, bool rx_pause); void (*link_up)(struct fbnic_dev *fbd, bool tx_pause, bool rx_pause);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment