Commit 3d52b594 authored by John Allen's avatar John Allen Committed by David S. Miller

ibmvnic: Implement per-queue statistics reporting

Add counters to report number of packets, bytes, and dropped packets for
each transmit queue and number of packets, bytes, and interrupts for each
receive queue. Modify ethtool callbacks to report the new statistics.
Signed-off-by: default avatarJohn Allen <jallen@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d06c3583
...@@ -346,6 +346,31 @@ static void replenish_pools(struct ibmvnic_adapter *adapter) ...@@ -346,6 +346,31 @@ static void replenish_pools(struct ibmvnic_adapter *adapter)
} }
} }
static void release_stats_buffers(struct ibmvnic_adapter *adapter)
{
kfree(adapter->tx_stats_buffers);
kfree(adapter->rx_stats_buffers);
}
static int init_stats_buffers(struct ibmvnic_adapter *adapter)
{
adapter->tx_stats_buffers =
kcalloc(adapter->req_tx_queues,
sizeof(struct ibmvnic_tx_queue_stats),
GFP_KERNEL);
if (!adapter->tx_stats_buffers)
return -ENOMEM;
adapter->rx_stats_buffers =
kcalloc(adapter->req_rx_queues,
sizeof(struct ibmvnic_rx_queue_stats),
GFP_KERNEL);
if (!adapter->rx_stats_buffers)
return -ENOMEM;
return 0;
}
static void release_stats_token(struct ibmvnic_adapter *adapter) static void release_stats_token(struct ibmvnic_adapter *adapter)
{ {
struct device *dev = &adapter->vdev->dev; struct device *dev = &adapter->vdev->dev;
...@@ -686,6 +711,7 @@ static void release_resources(struct ibmvnic_adapter *adapter) ...@@ -686,6 +711,7 @@ static void release_resources(struct ibmvnic_adapter *adapter)
release_rx_pools(adapter); release_rx_pools(adapter);
release_stats_token(adapter); release_stats_token(adapter);
release_stats_buffers(adapter);
release_error_buffers(adapter); release_error_buffers(adapter);
if (adapter->napi) { if (adapter->napi) {
...@@ -763,6 +789,10 @@ static int init_resources(struct ibmvnic_adapter *adapter) ...@@ -763,6 +789,10 @@ static int init_resources(struct ibmvnic_adapter *adapter)
if (rc) if (rc)
return rc; return rc;
rc = init_stats_buffers(adapter);
if (rc)
return rc;
rc = init_stats_token(adapter); rc = init_stats_token(adapter);
if (rc) if (rc)
return rc; return rc;
...@@ -1245,6 +1275,9 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -1245,6 +1275,9 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
netdev->stats.tx_packets += tx_packets; netdev->stats.tx_packets += tx_packets;
adapter->tx_send_failed += tx_send_failed; adapter->tx_send_failed += tx_send_failed;
adapter->tx_map_failed += tx_map_failed; adapter->tx_map_failed += tx_map_failed;
adapter->tx_stats_buffers[queue_num].packets += tx_packets;
adapter->tx_stats_buffers[queue_num].bytes += tx_bytes;
adapter->tx_stats_buffers[queue_num].dropped_packets += tx_dropped;
return ret; return ret;
} }
...@@ -1585,6 +1618,8 @@ static int ibmvnic_poll(struct napi_struct *napi, int budget) ...@@ -1585,6 +1618,8 @@ static int ibmvnic_poll(struct napi_struct *napi, int budget)
napi_gro_receive(napi, skb); /* send it up */ napi_gro_receive(napi, skb); /* send it up */
netdev->stats.rx_packets++; netdev->stats.rx_packets++;
netdev->stats.rx_bytes += length; netdev->stats.rx_bytes += length;
adapter->rx_stats_buffers[scrq_num].packets++;
adapter->rx_stats_buffers[scrq_num].bytes += length;
frames_processed++; frames_processed++;
} }
...@@ -1706,6 +1741,7 @@ static void ibmvnic_get_ringparam(struct net_device *netdev, ...@@ -1706,6 +1741,7 @@ static void ibmvnic_get_ringparam(struct net_device *netdev,
static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{ {
struct ibmvnic_adapter *adapter = netdev_priv(dev);
int i; int i;
if (stringset != ETH_SS_STATS) if (stringset != ETH_SS_STATS)
...@@ -1713,13 +1749,39 @@ static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) ...@@ -1713,13 +1749,39 @@ static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++, data += ETH_GSTRING_LEN) for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++, data += ETH_GSTRING_LEN)
memcpy(data, ibmvnic_stats[i].name, ETH_GSTRING_LEN); memcpy(data, ibmvnic_stats[i].name, ETH_GSTRING_LEN);
for (i = 0; i < adapter->req_tx_queues; i++) {
snprintf(data, ETH_GSTRING_LEN, "tx%d_packets", i);
data += ETH_GSTRING_LEN;
snprintf(data, ETH_GSTRING_LEN, "tx%d_bytes", i);
data += ETH_GSTRING_LEN;
snprintf(data, ETH_GSTRING_LEN, "tx%d_dropped_packets", i);
data += ETH_GSTRING_LEN;
}
for (i = 0; i < adapter->req_rx_queues; i++) {
snprintf(data, ETH_GSTRING_LEN, "rx%d_packets", i);
data += ETH_GSTRING_LEN;
snprintf(data, ETH_GSTRING_LEN, "rx%d_bytes", i);
data += ETH_GSTRING_LEN;
snprintf(data, ETH_GSTRING_LEN, "rx%d_interrupts", i);
data += ETH_GSTRING_LEN;
}
} }
static int ibmvnic_get_sset_count(struct net_device *dev, int sset) static int ibmvnic_get_sset_count(struct net_device *dev, int sset)
{ {
struct ibmvnic_adapter *adapter = netdev_priv(dev);
switch (sset) { switch (sset) {
case ETH_SS_STATS: case ETH_SS_STATS:
return ARRAY_SIZE(ibmvnic_stats); return ARRAY_SIZE(ibmvnic_stats) +
adapter->req_tx_queues * NUM_TX_STATS +
adapter->req_rx_queues * NUM_RX_STATS;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -1730,7 +1792,7 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev, ...@@ -1730,7 +1792,7 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
{ {
struct ibmvnic_adapter *adapter = netdev_priv(dev); struct ibmvnic_adapter *adapter = netdev_priv(dev);
union ibmvnic_crq crq; union ibmvnic_crq crq;
int i; int i, j;
memset(&crq, 0, sizeof(crq)); memset(&crq, 0, sizeof(crq));
crq.request_statistics.first = IBMVNIC_CRQ_CMD; crq.request_statistics.first = IBMVNIC_CRQ_CMD;
...@@ -1746,6 +1808,24 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev, ...@@ -1746,6 +1808,24 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++) for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++)
data[i] = IBMVNIC_GET_STAT(adapter, ibmvnic_stats[i].offset); data[i] = IBMVNIC_GET_STAT(adapter, ibmvnic_stats[i].offset);
for (j = 0; j < adapter->req_tx_queues; j++) {
data[i] = adapter->tx_stats_buffers[j].packets;
i++;
data[i] = adapter->tx_stats_buffers[j].bytes;
i++;
data[i] = adapter->tx_stats_buffers[j].dropped_packets;
i++;
}
for (j = 0; j < adapter->req_rx_queues; j++) {
data[i] = adapter->rx_stats_buffers[j].packets;
i++;
data[i] = adapter->rx_stats_buffers[j].bytes;
i++;
data[i] = adapter->rx_stats_buffers[j].interrupts;
i++;
}
} }
static const struct ethtool_ops ibmvnic_ethtool_ops = { static const struct ethtool_ops ibmvnic_ethtool_ops = {
...@@ -2050,6 +2130,8 @@ static irqreturn_t ibmvnic_interrupt_rx(int irq, void *instance) ...@@ -2050,6 +2130,8 @@ static irqreturn_t ibmvnic_interrupt_rx(int irq, void *instance)
struct ibmvnic_sub_crq_queue *scrq = instance; struct ibmvnic_sub_crq_queue *scrq = instance;
struct ibmvnic_adapter *adapter = scrq->adapter; struct ibmvnic_adapter *adapter = scrq->adapter;
adapter->rx_stats_buffers[scrq->scrq_num].interrupts++;
if (napi_schedule_prep(&adapter->napi[scrq->scrq_num])) { if (napi_schedule_prep(&adapter->napi[scrq->scrq_num])) {
disable_scrq_irq(adapter, scrq); disable_scrq_irq(adapter, scrq);
__napi_schedule(&adapter->napi[scrq->scrq_num]); __napi_schedule(&adapter->napi[scrq->scrq_num]);
......
...@@ -166,6 +166,20 @@ struct ibmvnic_statistics { ...@@ -166,6 +166,20 @@ struct ibmvnic_statistics {
u8 reserved[72]; u8 reserved[72];
} __packed __aligned(8); } __packed __aligned(8);
#define NUM_TX_STATS 3
struct ibmvnic_tx_queue_stats {
u64 packets;
u64 bytes;
u64 dropped_packets;
};
#define NUM_RX_STATS 3
struct ibmvnic_rx_queue_stats {
u64 packets;
u64 bytes;
u64 interrupts;
};
struct ibmvnic_acl_buffer { struct ibmvnic_acl_buffer {
__be32 len; __be32 len;
__be32 version; __be32 version;
...@@ -956,6 +970,9 @@ struct ibmvnic_adapter { ...@@ -956,6 +970,9 @@ struct ibmvnic_adapter {
int tx_send_failed; int tx_send_failed;
int tx_map_failed; int tx_map_failed;
struct ibmvnic_tx_queue_stats *tx_stats_buffers;
struct ibmvnic_rx_queue_stats *rx_stats_buffers;
int phys_link_state; int phys_link_state;
int logical_link_state; int logical_link_state;
......
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