Commit a0d2d97d authored by Bhaskar Upadhaya's avatar Bhaskar Upadhaya Committed by David S. Miller
Browse files

qede: add per queue coalesce support for qede driver



per queue coalescing allows better and more finegrained control
over interrupt rates.

Signed-off-by: default avatarBhaskar Upadhaya <bupadhaya@marvell.com>
Signed-off-by: default avatarIgor Russkikh <irusskikh@marvell.com>
Signed-off-by: default avatarAriel Elior <aelior@marvell.com>
Reported-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 961aa716
Loading
Loading
Loading
Loading
+124 −0
Original line number Diff line number Diff line
@@ -2105,6 +2105,126 @@ static int qede_get_dump_data(struct net_device *dev,
	return rc;
}

static int qede_set_per_coalesce(struct net_device *dev,
				 u32 queue,
				 struct ethtool_coalesce *coal)
{
	struct qede_dev *edev = netdev_priv(dev);
	struct qede_fastpath *fp;
	u16 rxc, txc;
	int rc = 0;

	if (coal->rx_coalesce_usecs > QED_COALESCE_MAX ||
	    coal->tx_coalesce_usecs > QED_COALESCE_MAX) {
		DP_INFO(edev,
			"Can't support requested %s coalesce value [max supported value %d]\n",
			coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx"
								   : "tx",
			QED_COALESCE_MAX);
		return -EINVAL;
	}

	rxc = (u16)coal->rx_coalesce_usecs;
	txc = (u16)coal->tx_coalesce_usecs;

	__qede_lock(edev);
	if (queue >= edev->num_queues) {
		DP_INFO(edev, "Invalid queue\n");
		rc = -EINVAL;
		goto out;
	}

	if (edev->state != QEDE_STATE_OPEN) {
		rc = -EINVAL;
		goto out;
	}

	fp = &edev->fp_array[queue];

	if (edev->fp_array[queue].type & QEDE_FASTPATH_RX) {
		rc = edev->ops->common->set_coalesce(edev->cdev,
						     rxc, 0,
						     fp->rxq->handle);
		if (rc) {
			DP_INFO(edev,
				"Set RX coalesce error, rc = %d\n", rc);
			goto out;
		}
	}

	if (edev->fp_array[queue].type & QEDE_FASTPATH_TX) {
		rc = edev->ops->common->set_coalesce(edev->cdev,
						     0, txc,
						     fp->txq->handle);
		if (rc) {
			DP_INFO(edev,
				"Set TX coalesce error, rc = %d\n", rc);
			goto out;
		}
	}
out:
	__qede_unlock(edev);

	return rc;
}

static int qede_get_per_coalesce(struct net_device *dev,
				 u32 queue,
				 struct ethtool_coalesce *coal)
{
	void *rx_handle = NULL, *tx_handle = NULL;
	struct qede_dev *edev = netdev_priv(dev);
	struct qede_fastpath *fp;
	u16 rx_coal, tx_coal;
	int rc = 0;

	rx_coal = QED_DEFAULT_RX_USECS;
	tx_coal = QED_DEFAULT_TX_USECS;

	memset(coal, 0, sizeof(struct ethtool_coalesce));

	__qede_lock(edev);
	if (queue >= edev->num_queues) {
		DP_INFO(edev, "Invalid queue\n");
		rc = -EINVAL;
		goto out;
	}

	if (edev->state != QEDE_STATE_OPEN) {
		rc = -EINVAL;
		goto out;
	}

	fp = &edev->fp_array[queue];

	if (fp->type & QEDE_FASTPATH_RX)
		rx_handle = fp->rxq->handle;

	rc = edev->ops->get_coalesce(edev->cdev, &rx_coal,
				     rx_handle);
	if (rc) {
		DP_INFO(edev, "Read Rx coalesce error\n");
		goto out;
	}

	fp = &edev->fp_array[queue];
	if (fp->type & QEDE_FASTPATH_TX)
		tx_handle = fp->txq->handle;

	rc = edev->ops->get_coalesce(edev->cdev, &tx_coal,
				      tx_handle);
	if (rc)
		DP_INFO(edev, "Read Tx coalesce error\n");

out:
	__qede_unlock(edev);

	coal->rx_coalesce_usecs = rx_coal;
	coal->tx_coalesce_usecs = tx_coal;

	return rc;
}

static const struct ethtool_ops qede_ethtool_ops = {
	.supported_coalesce_params	= ETHTOOL_COALESCE_USECS,
	.get_link_ksettings		= qede_get_link_ksettings,
@@ -2148,6 +2268,8 @@ static const struct ethtool_ops qede_ethtool_ops = {
	.set_fecparam			= qede_set_fecparam,
	.get_tunable			= qede_get_tunable,
	.set_tunable			= qede_set_tunable,
	.get_per_queue_coalesce		= qede_get_per_coalesce,
	.set_per_queue_coalesce		= qede_set_per_coalesce,
	.flash_device			= qede_flash_device,
	.get_dump_flag			= qede_get_dump_flag,
	.get_dump_data			= qede_get_dump_data,
@@ -2177,6 +2299,8 @@ static const struct ethtool_ops qede_vf_ethtool_ops = {
	.set_rxfh			= qede_set_rxfh,
	.get_channels			= qede_get_channels,
	.set_channels			= qede_set_channels,
	.get_per_queue_coalesce		= qede_get_per_coalesce,
	.set_per_queue_coalesce		= qede_set_per_coalesce,
	.get_tunable			= qede_get_tunable,
	.set_tunable			= qede_set_tunable,
};