Commit 54a8997c authored by Jitendra Kalsaria's avatar Jitendra Kalsaria Committed by David S. Miller

qlcnic: Adding mac statistics to ethtool.

Signed-off-by: default avatarJitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Signed-off-by: default avatarAnirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b43e5ee7
...@@ -607,6 +607,7 @@ struct qlcnic_recv_context { ...@@ -607,6 +607,7 @@ struct qlcnic_recv_context {
#define QLCNIC_CDRP_CMD_CONFIG_PORT 0x0000002E #define QLCNIC_CDRP_CMD_CONFIG_PORT 0x0000002E
#define QLCNIC_CDRP_CMD_TEMP_SIZE 0x0000002f #define QLCNIC_CDRP_CMD_TEMP_SIZE 0x0000002f
#define QLCNIC_CDRP_CMD_GET_TEMP_HDR 0x00000030 #define QLCNIC_CDRP_CMD_GET_TEMP_HDR 0x00000030
#define QLCNIC_CDRP_CMD_GET_MAC_STATS 0x00000037
#define QLCNIC_RCODE_SUCCESS 0 #define QLCNIC_RCODE_SUCCESS 0
#define QLCNIC_RCODE_NOT_SUPPORTED 9 #define QLCNIC_RCODE_NOT_SUPPORTED 9
...@@ -1180,18 +1181,62 @@ struct qlcnic_esw_func_cfg { ...@@ -1180,18 +1181,62 @@ struct qlcnic_esw_func_cfg {
#define QLCNIC_STATS_ESWITCH 2 #define QLCNIC_STATS_ESWITCH 2
#define QLCNIC_QUERY_RX_COUNTER 0 #define QLCNIC_QUERY_RX_COUNTER 0
#define QLCNIC_QUERY_TX_COUNTER 1 #define QLCNIC_QUERY_TX_COUNTER 1
#define QLCNIC_ESW_STATS_NOT_AVAIL 0xffffffffffffffffULL #define QLCNIC_STATS_NOT_AVAIL 0xffffffffffffffffULL
#define QLCNIC_FILL_STATS(VAL1) \
(((VAL1) == QLCNIC_STATS_NOT_AVAIL) ? 0 : VAL1)
#define QLCNIC_MAC_STATS 1
#define QLCNIC_ESW_STATS 2
#define QLCNIC_ADD_ESW_STATS(VAL1, VAL2)\ #define QLCNIC_ADD_ESW_STATS(VAL1, VAL2)\
do { \ do { \
if (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) && \ if (((VAL1) == QLCNIC_STATS_NOT_AVAIL) && \
((VAL2) != QLCNIC_ESW_STATS_NOT_AVAIL)) \ ((VAL2) != QLCNIC_STATS_NOT_AVAIL)) \
(VAL1) = (VAL2); \ (VAL1) = (VAL2); \
else if (((VAL1) != QLCNIC_ESW_STATS_NOT_AVAIL) && \ else if (((VAL1) != QLCNIC_STATS_NOT_AVAIL) && \
((VAL2) != QLCNIC_ESW_STATS_NOT_AVAIL)) \ ((VAL2) != QLCNIC_STATS_NOT_AVAIL)) \
(VAL1) += (VAL2); \ (VAL1) += (VAL2); \
} while (0) } while (0)
struct qlcnic_mac_statistics{
__le64 mac_tx_frames;
__le64 mac_tx_bytes;
__le64 mac_tx_mcast_pkts;
__le64 mac_tx_bcast_pkts;
__le64 mac_tx_pause_cnt;
__le64 mac_tx_ctrl_pkt;
__le64 mac_tx_lt_64b_pkts;
__le64 mac_tx_lt_127b_pkts;
__le64 mac_tx_lt_255b_pkts;
__le64 mac_tx_lt_511b_pkts;
__le64 mac_tx_lt_1023b_pkts;
__le64 mac_tx_lt_1518b_pkts;
__le64 mac_tx_gt_1518b_pkts;
__le64 rsvd1[3];
__le64 mac_rx_frames;
__le64 mac_rx_bytes;
__le64 mac_rx_mcast_pkts;
__le64 mac_rx_bcast_pkts;
__le64 mac_rx_pause_cnt;
__le64 mac_rx_ctrl_pkt;
__le64 mac_rx_lt_64b_pkts;
__le64 mac_rx_lt_127b_pkts;
__le64 mac_rx_lt_255b_pkts;
__le64 mac_rx_lt_511b_pkts;
__le64 mac_rx_lt_1023b_pkts;
__le64 mac_rx_lt_1518b_pkts;
__le64 mac_rx_gt_1518b_pkts;
__le64 rsvd2[3];
__le64 mac_rx_length_error;
__le64 mac_rx_length_small;
__le64 mac_rx_length_large;
__le64 mac_rx_jabber;
__le64 mac_rx_dropped;
__le64 mac_rx_crc_error;
__le64 mac_align_error;
} __packed;
struct __qlcnic_esw_statistics { struct __qlcnic_esw_statistics {
__le16 context_id; __le16 context_id;
__le16 version; __le16 version;
...@@ -1512,6 +1557,7 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8, ...@@ -1512,6 +1557,7 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8,
int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8, int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8,
struct __qlcnic_esw_statistics *); struct __qlcnic_esw_statistics *);
int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8); int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *);
extern int qlcnic_config_tso; extern int qlcnic_config_tso;
/* /*
......
...@@ -905,6 +905,65 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, ...@@ -905,6 +905,65 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
return err; return err;
} }
/* This routine will retrieve the MAC statistics from firmware */
int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
struct qlcnic_mac_statistics *mac_stats)
{
struct qlcnic_mac_statistics *stats;
struct qlcnic_cmd_args cmd;
size_t stats_size = sizeof(struct qlcnic_mac_statistics);
dma_addr_t stats_dma_t;
void *stats_addr;
int err;
stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
&stats_dma_t, GFP_KERNEL);
if (!stats_addr) {
dev_err(&adapter->pdev->dev,
"%s: Unable to allocate memory.\n", __func__);
return -ENOMEM;
}
memset(stats_addr, 0, stats_size);
memset(&cmd, 0, sizeof(cmd));
cmd.req.cmd = QLCNIC_CDRP_CMD_GET_MAC_STATS;
cmd.req.arg1 = stats_size << 16;
cmd.req.arg2 = MSD(stats_dma_t);
cmd.req.arg3 = LSD(stats_dma_t);
qlcnic_issue_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (!err) {
stats = stats_addr;
mac_stats->mac_tx_frames = le64_to_cpu(stats->mac_tx_frames);
mac_stats->mac_tx_bytes = le64_to_cpu(stats->mac_tx_bytes);
mac_stats->mac_tx_mcast_pkts =
le64_to_cpu(stats->mac_tx_mcast_pkts);
mac_stats->mac_tx_bcast_pkts =
le64_to_cpu(stats->mac_tx_bcast_pkts);
mac_stats->mac_rx_frames = le64_to_cpu(stats->mac_rx_frames);
mac_stats->mac_rx_bytes = le64_to_cpu(stats->mac_rx_bytes);
mac_stats->mac_rx_mcast_pkts =
le64_to_cpu(stats->mac_rx_mcast_pkts);
mac_stats->mac_rx_length_error =
le64_to_cpu(stats->mac_rx_length_error);
mac_stats->mac_rx_length_small =
le64_to_cpu(stats->mac_rx_length_small);
mac_stats->mac_rx_length_large =
le64_to_cpu(stats->mac_rx_length_large);
mac_stats->mac_rx_jabber = le64_to_cpu(stats->mac_rx_jabber);
mac_stats->mac_rx_dropped = le64_to_cpu(stats->mac_rx_dropped);
mac_stats->mac_rx_crc_error = le64_to_cpu(stats->mac_rx_crc_error);
} else {
dev_info(&adapter->pdev->dev,
"%s: Get mac stats failed =%d.\n", __func__, err);
}
dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
stats_dma_t);
return err;
}
int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch, int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) { const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
...@@ -920,13 +979,13 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch, ...@@ -920,13 +979,13 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
return -EIO; return -EIO;
memset(esw_stats, 0, sizeof(u64)); memset(esw_stats, 0, sizeof(u64));
esw_stats->unicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL; esw_stats->unicast_frames = QLCNIC_STATS_NOT_AVAIL;
esw_stats->multicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL; esw_stats->multicast_frames = QLCNIC_STATS_NOT_AVAIL;
esw_stats->broadcast_frames = QLCNIC_ESW_STATS_NOT_AVAIL; esw_stats->broadcast_frames = QLCNIC_STATS_NOT_AVAIL;
esw_stats->dropped_frames = QLCNIC_ESW_STATS_NOT_AVAIL; esw_stats->dropped_frames = QLCNIC_STATS_NOT_AVAIL;
esw_stats->errors = QLCNIC_ESW_STATS_NOT_AVAIL; esw_stats->errors = QLCNIC_STATS_NOT_AVAIL;
esw_stats->local_frames = QLCNIC_ESW_STATS_NOT_AVAIL; esw_stats->local_frames = QLCNIC_STATS_NOT_AVAIL;
esw_stats->numbytes = QLCNIC_ESW_STATS_NOT_AVAIL; esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL;
esw_stats->context_id = eswitch; esw_stats->context_id = eswitch;
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
......
...@@ -78,8 +78,46 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = { ...@@ -78,8 +78,46 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
"tx numbytes", "tx numbytes",
}; };
#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) static const char qlcnic_mac_stats_strings [][ETH_GSTRING_LEN] = {
"mac_tx_frames",
"mac_tx_bytes",
"mac_tx_mcast_pkts",
"mac_tx_bcast_pkts",
"mac_tx_pause_cnt",
"mac_tx_ctrl_pkt",
"mac_tx_lt_64b_pkts",
"mac_tx_lt_127b_pkts",
"mac_tx_lt_255b_pkts",
"mac_tx_lt_511b_pkts",
"mac_tx_lt_1023b_pkts",
"mac_tx_lt_1518b_pkts",
"mac_tx_gt_1518b_pkts",
"mac_rx_frames",
"mac_rx_bytes",
"mac_rx_mcast_pkts",
"mac_rx_bcast_pkts",
"mac_rx_pause_cnt",
"mac_rx_ctrl_pkt",
"mac_rx_lt_64b_pkts",
"mac_rx_lt_127b_pkts",
"mac_rx_lt_255b_pkts",
"mac_rx_lt_511b_pkts",
"mac_rx_lt_1023b_pkts",
"mac_rx_lt_1518b_pkts",
"mac_rx_gt_1518b_pkts",
"mac_rx_length_error",
"mac_rx_length_small",
"mac_rx_length_large",
"mac_rx_jabber",
"mac_rx_dropped",
"mac_rx_crc_error",
"mac_align_error",
};
#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
#define QLCNIC_MAC_STATS_LEN ARRAY_SIZE(qlcnic_mac_stats_strings)
#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats) #define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats)
#define QLCNIC_TOTAL_STATS_LEN QLCNIC_STATS_LEN + QLCNIC_MAC_STATS_LEN
static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = { static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
"Register_Test_on_offline", "Register_Test_on_offline",
...@@ -644,8 +682,8 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset) ...@@ -644,8 +682,8 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset)
return QLCNIC_TEST_LEN; return QLCNIC_TEST_LEN;
case ETH_SS_STATS: case ETH_SS_STATS:
if (adapter->flags & QLCNIC_ESWITCH_ENABLED) if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
return QLCNIC_STATS_LEN + QLCNIC_DEVICE_STATS_LEN; return QLCNIC_TOTAL_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
return QLCNIC_STATS_LEN; return QLCNIC_TOTAL_STATS_LEN;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -851,7 +889,7 @@ static void ...@@ -851,7 +889,7 @@ static void
qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data) qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
{ {
struct qlcnic_adapter *adapter = netdev_priv(dev); struct qlcnic_adapter *adapter = netdev_priv(dev);
int index, i; int index, i, j;
switch (stringset) { switch (stringset) {
case ETH_SS_TEST: case ETH_SS_TEST:
...@@ -864,6 +902,11 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data) ...@@ -864,6 +902,11 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
qlcnic_gstrings_stats[index].stat_string, qlcnic_gstrings_stats[index].stat_string,
ETH_GSTRING_LEN); ETH_GSTRING_LEN);
} }
for (j = 0; j < QLCNIC_MAC_STATS_LEN; index++, j++) {
memcpy(data + index * ETH_GSTRING_LEN,
qlcnic_mac_stats_strings[j],
ETH_GSTRING_LEN);
}
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
return; return;
for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) { for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
...@@ -874,22 +917,64 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data) ...@@ -874,22 +917,64 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
} }
} }
#define QLCNIC_FILL_ESWITCH_STATS(VAL1) \
(((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) ? 0 : VAL1)
static void static void
qlcnic_fill_device_stats(int *index, u64 *data, qlcnic_fill_stats(int *index, u64 *data, void *stats, int type)
struct __qlcnic_esw_statistics *stats)
{ {
int ind = *index; int ind = *index;
data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->unicast_frames); if (type == QLCNIC_MAC_STATS) {
data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->multicast_frames); struct qlcnic_mac_statistics *mac_stats =
data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->broadcast_frames); (struct qlcnic_mac_statistics *)stats;
data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->dropped_frames); data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames);
data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->errors); data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes);
data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->local_frames); data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts);
data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->numbytes); data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts);
data[ind++] =
QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts);
data[ind++] =
QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts);
data[ind++] =
QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts);
data[ind++] =
QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts);
data[ind++] =
QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts);
data[ind++] =
QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error);
data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_align_error);
} else if (type == QLCNIC_ESW_STATS) {
struct __qlcnic_esw_statistics *esw_stats =
(struct __qlcnic_esw_statistics *)stats;
data[ind++] = QLCNIC_FILL_STATS(esw_stats->unicast_frames);
data[ind++] = QLCNIC_FILL_STATS(esw_stats->multicast_frames);
data[ind++] = QLCNIC_FILL_STATS(esw_stats->broadcast_frames);
data[ind++] = QLCNIC_FILL_STATS(esw_stats->dropped_frames);
data[ind++] = QLCNIC_FILL_STATS(esw_stats->errors);
data[ind++] = QLCNIC_FILL_STATS(esw_stats->local_frames);
data[ind++] = QLCNIC_FILL_STATS(esw_stats->numbytes);
}
*index = ind; *index = ind;
} }
...@@ -900,6 +985,7 @@ qlcnic_get_ethtool_stats(struct net_device *dev, ...@@ -900,6 +985,7 @@ qlcnic_get_ethtool_stats(struct net_device *dev,
{ {
struct qlcnic_adapter *adapter = netdev_priv(dev); struct qlcnic_adapter *adapter = netdev_priv(dev);
struct qlcnic_esw_statistics port_stats; struct qlcnic_esw_statistics port_stats;
struct qlcnic_mac_statistics mac_stats;
int index, ret; int index, ret;
for (index = 0; index < QLCNIC_STATS_LEN; index++) { for (index = 0; index < QLCNIC_STATS_LEN; index++) {
...@@ -911,6 +997,11 @@ qlcnic_get_ethtool_stats(struct net_device *dev, ...@@ -911,6 +997,11 @@ qlcnic_get_ethtool_stats(struct net_device *dev,
sizeof(u64)) ? *(u64 *)p:(*(u32 *)p); sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
} }
/* Retrieve MAC statistics from firmware */
memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));
qlcnic_get_mac_stats(adapter, &mac_stats);
qlcnic_fill_stats(&index, data, &mac_stats, QLCNIC_MAC_STATS);
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
return; return;
...@@ -920,14 +1011,14 @@ qlcnic_get_ethtool_stats(struct net_device *dev, ...@@ -920,14 +1011,14 @@ qlcnic_get_ethtool_stats(struct net_device *dev,
if (ret) if (ret)
return; return;
qlcnic_fill_device_stats(&index, data, &port_stats.rx); qlcnic_fill_stats(&index, data, &port_stats.rx, QLCNIC_ESW_STATS);
ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func, ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
QLCNIC_QUERY_TX_COUNTER, &port_stats.tx); QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
if (ret) if (ret)
return; return;
qlcnic_fill_device_stats(&index, data, &port_stats.tx); qlcnic_fill_stats(&index, data, &port_stats.tx, QLCNIC_ESW_STATS);
} }
static int qlcnic_set_led(struct net_device *dev, static int qlcnic_set_led(struct net_device *dev,
......
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