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

Signed-off-by: Bhaskar Upadhaya <bupadh...@marvell.com>
Signed-off-by: Igor Russkikh <irussk...@marvell.com>
Signed-off-by: Ariel Elior <ael...@marvell.com>
---
 .../net/ethernet/qlogic/qede/qede_ethtool.c   | 123 ++++++++++++++++++
 1 file changed, 123 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c 
b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index bedbb85a179a..522736968496 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -2105,6 +2105,125 @@ 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);
+       u16 rx_coal, tx_coal, rc = 0;
+       struct qede_fastpath *fp;
+
+       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 +2267,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 +2298,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,
 };
-- 
2.17.1

Reply via email to