Commit f27c75b3 authored by Himanshu Madhani's avatar Himanshu Madhani Committed by David S. Miller

qlcnic: Enhance ethtool Statistics for Multiple Tx queue.

o Enhance ethtool statistics to display multiple Tx queue stats for
  all supported adapters.
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 78ea2d97
...@@ -533,6 +533,14 @@ struct qlcnic_host_sds_ring { ...@@ -533,6 +533,14 @@ struct qlcnic_host_sds_ring {
char name[IFNAMSIZ + 12]; char name[IFNAMSIZ + 12];
} ____cacheline_internodealigned_in_smp; } ____cacheline_internodealigned_in_smp;
struct qlcnic_tx_queue_stats {
u64 xmit_on;
u64 xmit_off;
u64 xmit_called;
u64 xmit_finished;
u64 tx_bytes;
};
struct qlcnic_host_tx_ring { struct qlcnic_host_tx_ring {
int irq; int irq;
void __iomem *crb_intr_mask; void __iomem *crb_intr_mask;
...@@ -544,10 +552,7 @@ struct qlcnic_host_tx_ring { ...@@ -544,10 +552,7 @@ struct qlcnic_host_tx_ring {
u32 sw_consumer; u32 sw_consumer;
u32 num_desc; u32 num_desc;
u64 xmit_on; struct qlcnic_tx_queue_stats tx_stats;
u64 xmit_off;
u64 xmit_called;
u64 xmit_finished;
void __iomem *crb_cmd_producer; void __iomem *crb_cmd_producer;
struct cmd_desc_type0 *desc_head; struct cmd_desc_type0 *desc_head;
......
...@@ -27,43 +27,36 @@ static const u32 qlcnic_fw_dump_level[] = { ...@@ -27,43 +27,36 @@ static const u32 qlcnic_fw_dump_level[] = {
}; };
static const struct qlcnic_stats qlcnic_gstrings_stats[] = { static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
{"xmit_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
{"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
{"xmit_called", QLC_SIZEOF(stats.xmitcalled), {"xmit_called", QLC_SIZEOF(stats.xmitcalled),
QLC_OFF(stats.xmitcalled)}, QLC_OFF(stats.xmitcalled)},
{"xmit_finished", QLC_SIZEOF(stats.xmitfinished), {"xmit_finished", QLC_SIZEOF(stats.xmitfinished),
QLC_OFF(stats.xmitfinished)}, QLC_OFF(stats.xmitfinished)},
{"rx_dropped", QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)}, {"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
QLC_OFF(stats.tx_dma_map_error)},
{"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)},
{"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)}, {"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
{"csummed", QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)}, {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
QLC_OFF(stats.rx_dma_map_error)},
{"rx_pkts", QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)}, {"rx_pkts", QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)},
{"lro_pkts", QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
{"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)}, {"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
{"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)}, {"rx_dropped", QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)},
{"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
{"csummed", QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)},
{"lro_pkts", QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
{"lrobytes", QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)}, {"lrobytes", QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
{"lso_frames", QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)}, {"lso_frames", QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)},
{"xmit_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
{"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
{"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure), {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
QLC_OFF(stats.skb_alloc_failure)}, QLC_OFF(stats.skb_alloc_failure)},
{"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
{"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
QLC_OFF(stats.rx_dma_map_error)},
{"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
QLC_OFF(stats.tx_dma_map_error)},
{"mac_filter_limit_overrun", QLC_SIZEOF(stats.mac_filter_limit_overrun), {"mac_filter_limit_overrun", QLC_SIZEOF(stats.mac_filter_limit_overrun),
QLC_OFF(stats.mac_filter_limit_overrun)}, QLC_OFF(stats.mac_filter_limit_overrun)},
{"spurious intr", QLC_SIZEOF(stats.spurious_intr), {"spurious intr", QLC_SIZEOF(stats.spurious_intr),
QLC_OFF(stats.spurious_intr)}, QLC_OFF(stats.spurious_intr)},
}; };
static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = { static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
"rx unicast frames",
"rx multicast frames",
"rx broadcast frames",
"rx dropped frames",
"rx errors",
"rx local frames",
"rx numbytes",
"tx unicast frames", "tx unicast frames",
"tx multicast frames", "tx multicast frames",
"tx broadcast frames", "tx broadcast frames",
...@@ -71,6 +64,13 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = { ...@@ -71,6 +64,13 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
"tx errors", "tx errors",
"tx local frames", "tx local frames",
"tx numbytes", "tx numbytes",
"rx unicast frames",
"rx multicast frames",
"rx broadcast frames",
"rx dropped frames",
"rx errors",
"rx local frames",
"rx numbytes",
}; };
static const char qlcnic_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = { static const char qlcnic_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = {
...@@ -126,13 +126,16 @@ static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = { ...@@ -126,13 +126,16 @@ static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = {
#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) #define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
static const char qlcnic_tx_ring_stats_strings[][ETH_GSTRING_LEN] = { static const char qlcnic_tx_queue_stats_strings[][ETH_GSTRING_LEN] = {
"xmit_on", "xmit_on",
"xmit_off", "xmit_off",
"xmit_called", "xmit_called",
"xmit_finished", "xmit_finished",
"tx_bytes",
}; };
#define QLCNIC_TX_STATS_LEN ARRAY_SIZE(qlcnic_tx_queue_stats_strings)
static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = { static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
"ctx_rx_bytes", "ctx_rx_bytes",
"ctx_rx_pkts", "ctx_rx_pkts",
...@@ -1123,11 +1126,11 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) ...@@ -1123,11 +1126,11 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
QLCNIC_TEST_LEN * ETH_GSTRING_LEN); QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
break; break;
case ETH_SS_STATS: case ETH_SS_STATS:
num_stats = ARRAY_SIZE(qlcnic_tx_ring_stats_strings); num_stats = ARRAY_SIZE(qlcnic_tx_queue_stats_strings);
for (i = 0; i < adapter->max_drv_tx_rings; i++) { for (i = 0; i < adapter->max_drv_tx_rings; i++) {
for (index = 0; index < num_stats; index++) { for (index = 0; index < num_stats; index++) {
sprintf(data, "tx_ring_%d %s", i, sprintf(data, "tx_queue_%d %s", i,
qlcnic_tx_ring_stats_strings[index]); qlcnic_tx_queue_stats_strings[index]);
data += ETH_GSTRING_LEN; data += ETH_GSTRING_LEN;
} }
} }
...@@ -1225,6 +1228,36 @@ static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type) ...@@ -1225,6 +1228,36 @@ static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type)
return data; return data;
} }
static void qlcnic_update_stats(struct qlcnic_adapter *adapter)
{
struct qlcnic_host_tx_ring *tx_ring;
int ring;
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring];
adapter->stats.xmit_on += tx_ring->tx_stats.xmit_on;
adapter->stats.xmit_off += tx_ring->tx_stats.xmit_off;
adapter->stats.xmitcalled += tx_ring->tx_stats.xmit_called;
adapter->stats.xmitfinished += tx_ring->tx_stats.xmit_finished;
adapter->stats.txbytes += tx_ring->tx_stats.tx_bytes;
}
}
static u64 *qlcnic_fill_tx_queue_stats(u64 *data, void *stats)
{
struct qlcnic_host_tx_ring *tx_ring;
tx_ring = (struct qlcnic_host_tx_ring *)stats;
*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_on);
*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_off);
*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_called);
*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_finished);
*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.tx_bytes);
return data;
}
static void qlcnic_get_ethtool_stats(struct net_device *dev, static void qlcnic_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *data) struct ethtool_stats *stats, u64 *data)
{ {
...@@ -1232,19 +1265,20 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev, ...@@ -1232,19 +1265,20 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev,
struct qlcnic_host_tx_ring *tx_ring; struct qlcnic_host_tx_ring *tx_ring;
struct qlcnic_esw_statistics port_stats; struct qlcnic_esw_statistics port_stats;
struct qlcnic_mac_statistics mac_stats; struct qlcnic_mac_statistics mac_stats;
int index, ret, length, size, ring; int index, ret, length, size, tx_size, ring;
char *p; char *p;
memset(data, 0, adapter->max_drv_tx_rings * 4 * sizeof(u64)); tx_size = adapter->max_drv_tx_rings * QLCNIC_TX_STATS_LEN;
memset(data, 0, tx_size * sizeof(u64));
for (ring = 0, index = 0; ring < adapter->max_drv_tx_rings; ring++) { for (ring = 0, index = 0; ring < adapter->max_drv_tx_rings; ring++) {
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
tx_ring = &adapter->tx_ring[ring]; tx_ring = &adapter->tx_ring[ring];
*data++ = tx_ring->xmit_on; data = qlcnic_fill_tx_queue_stats(data, tx_ring);
*data++ = tx_ring->xmit_off; qlcnic_update_stats(adapter);
*data++ = tx_ring->xmit_called;
*data++ = tx_ring->xmit_finished;
} }
} }
memset(data, 0, stats->n_stats * sizeof(u64)); memset(data, 0, stats->n_stats * sizeof(u64));
length = QLCNIC_STATS_LEN; length = QLCNIC_STATS_LEN;
for (index = 0; index < length; index++) { for (index = 0; index < length; index++) {
......
...@@ -607,8 +607,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -607,8 +607,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
netif_tx_start_queue(tx_ring->txq); netif_tx_start_queue(tx_ring->txq);
} else { } else {
adapter->stats.xmit_off++; tx_ring->tx_stats.xmit_off++;
tx_ring->xmit_off++;
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
} }
...@@ -669,9 +668,8 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -669,9 +668,8 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (adapter->drv_mac_learn) if (adapter->drv_mac_learn)
qlcnic_send_filter(adapter, first_desc, skb); qlcnic_send_filter(adapter, first_desc, skb);
adapter->stats.txbytes += skb->len; tx_ring->tx_stats.tx_bytes += skb->len;
adapter->stats.xmitcalled++; tx_ring->tx_stats.xmit_called++;
tx_ring->xmit_called++;
qlcnic_update_cmd_producer(tx_ring); qlcnic_update_cmd_producer(tx_ring);
...@@ -805,8 +803,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter, ...@@ -805,8 +803,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
frag->dma = 0ULL; frag->dma = 0ULL;
} }
adapter->stats.xmitfinished++; tx_ring->tx_stats.xmit_finished++;
tx_ring->xmit_finished++;
dev_kfree_skb_any(buffer->skb); dev_kfree_skb_any(buffer->skb);
buffer->skb = NULL; buffer->skb = NULL;
} }
...@@ -823,8 +820,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter, ...@@ -823,8 +820,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
netif_carrier_ok(netdev)) { netif_carrier_ok(netdev)) {
if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
netif_tx_wake_queue(tx_ring->txq); netif_tx_wake_queue(tx_ring->txq);
adapter->stats.xmit_on++; tx_ring->tx_stats.xmit_on++;
tx_ring->xmit_on++;
} }
} }
adapter->tx_timeo_cnt = 0; adapter->tx_timeo_cnt = 0;
......
...@@ -2722,24 +2722,21 @@ static void qlcnic_tx_timeout(struct net_device *netdev) ...@@ -2722,24 +2722,21 @@ static void qlcnic_tx_timeout(struct net_device *netdev)
QLCNIC_FORCE_FW_DUMP_KEY); QLCNIC_FORCE_FW_DUMP_KEY);
} else { } else {
netdev_info(netdev, "Tx timeout, reset adapter context.\n"); netdev_info(netdev, "Tx timeout, reset adapter context.\n");
if (qlcnic_82xx_check(adapter)) { for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
for (ring = 0; ring < adapter->max_drv_tx_rings; tx_ring = &adapter->tx_ring[ring];
ring++) { netdev_info(netdev, "Tx ring=%d\n", ring);
tx_ring = &adapter->tx_ring[ring]; netdev_info(netdev,
dev_info(&netdev->dev, "ring=%d\n", ring); "crb_intr_mask=%d, producer=%d, sw_consumer=%d, hw_consumer=%d\n",
dev_info(&netdev->dev, "crb_intr_mask=%d\n", readl(tx_ring->crb_intr_mask),
readl(tx_ring->crb_intr_mask)); readl(tx_ring->crb_cmd_producer),
dev_info(&netdev->dev, "producer=%d\n", tx_ring->sw_consumer,
readl(tx_ring->crb_cmd_producer)); le32_to_cpu(*(tx_ring->hw_consumer)));
dev_info(&netdev->dev, "sw_consumer = %d\n", netdev_info(netdev,
tx_ring->sw_consumer); "xmit_finished=%llu, xmit_called=%llu, xmit_on=%llu, xmit_off=%llu\n",
dev_info(&netdev->dev, "hw_consumer = %d\n", tx_ring->tx_stats.xmit_finished,
le32_to_cpu(*(tx_ring->hw_consumer))); tx_ring->tx_stats.xmit_called,
dev_info(&netdev->dev, "xmit-on=%llu\n", tx_ring->tx_stats.xmit_on,
tx_ring->xmit_on); tx_ring->tx_stats.xmit_off);
dev_info(&netdev->dev, "xmit-off=%llu\n",
tx_ring->xmit_off);
}
} }
adapter->ahw->reset_context = 1; adapter->ahw->reset_context = 1;
} }
......
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