Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ddb08042 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ibmvnic-ethtool'



John Allen says:

====================
ibmvnic: Improve ethtool functionality

This patch series improves ibmvnic ethtool functionality by adding support
for ethtool -l and -g options, correcting existing statistics reporting,
and augmenting the existing statistics with counters for each tx and rx
queue.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d06c3583 c2dbeb67
Loading
Loading
Loading
Loading
+108 −7
Original line number Original line Diff line number Diff line
@@ -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)
	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)
	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)
	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)
		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++;
	}
	}


@@ -1694,18 +1729,36 @@ static u32 ibmvnic_get_link(struct net_device *netdev)
static void ibmvnic_get_ringparam(struct net_device *netdev,
static void ibmvnic_get_ringparam(struct net_device *netdev,
				  struct ethtool_ringparam *ring)
				  struct ethtool_ringparam *ring)
{
{
	ring->rx_max_pending = 0;
	struct ibmvnic_adapter *adapter = netdev_priv(netdev);
	ring->tx_max_pending = 0;

	ring->rx_max_pending = adapter->max_rx_add_entries_per_subcrq;
	ring->tx_max_pending = adapter->max_tx_entries_per_subcrq;
	ring->rx_mini_max_pending = 0;
	ring->rx_mini_max_pending = 0;
	ring->rx_jumbo_max_pending = 0;
	ring->rx_jumbo_max_pending = 0;
	ring->rx_pending = 0;
	ring->rx_pending = adapter->req_rx_add_entries_per_subcrq;
	ring->tx_pending = 0;
	ring->tx_pending = adapter->req_tx_entries_per_subcrq;
	ring->rx_mini_pending = 0;
	ring->rx_mini_pending = 0;
	ring->rx_jumbo_pending = 0;
	ring->rx_jumbo_pending = 0;
}
}


static void ibmvnic_get_channels(struct net_device *netdev,
				 struct ethtool_channels *channels)
{
	struct ibmvnic_adapter *adapter = netdev_priv(netdev);

	channels->max_rx = adapter->max_rx_queues;
	channels->max_tx = adapter->max_tx_queues;
	channels->max_other = 0;
	channels->max_combined = 0;
	channels->rx_count = adapter->req_rx_queues;
	channels->tx_count = adapter->req_tx_queues;
	channels->other_count = 0;
	channels->combined_count = 0;
}

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 +1766,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 +1809,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;
@@ -1745,7 +1824,26 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
	wait_for_completion(&adapter->stats_done);
	wait_for_completion(&adapter->stats_done);


	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] = be64_to_cpu(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 = {
@@ -1754,6 +1852,7 @@ static const struct ethtool_ops ibmvnic_ethtool_ops = {
	.set_msglevel		= ibmvnic_set_msglevel,
	.set_msglevel		= ibmvnic_set_msglevel,
	.get_link		= ibmvnic_get_link,
	.get_link		= ibmvnic_get_link,
	.get_ringparam		= ibmvnic_get_ringparam,
	.get_ringparam		= ibmvnic_get_ringparam,
	.get_channels		= ibmvnic_get_channels,
	.get_strings            = ibmvnic_get_strings,
	.get_strings            = ibmvnic_get_strings,
	.get_sset_count         = ibmvnic_get_sset_count,
	.get_sset_count         = ibmvnic_get_sset_count,
	.get_ethtool_stats	= ibmvnic_get_ethtool_stats,
	.get_ethtool_stats	= ibmvnic_get_ethtool_stats,
@@ -2050,6 +2149,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]);
+17 −0
Original line number Original line Diff line number Diff line
@@ -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 {
	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;