IPoIB: Support modifying IPoIB CQ event moderation
authorEli Cohen <eli@dev.mellanox.co.il>
Thu, 17 Apr 2008 04:09:33 +0000 (21:09 -0700)
committerRoland Dreier <rolandd@cisco.com>
Thu, 17 Apr 2008 04:09:33 +0000 (21:09 -0700)
This can be used to tune at run time the parameters controlling the
event (interrupt) generation rate and thus reduce the overhead
incurred by handling interrupts resulting in better throughput.  Since
IPoIB uses a single CQ for both RX and TX, RX is chosen to dictate
configuration for both RX and TX.

Signed-off-by: Eli Cohen <eli@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_ethtool.c

index 3524d65f2e5740a9a80483b448b4af504302c5a8..73b2b176ad0e45e98adbb257d724fb1f814f507a 100644 (file)
@@ -242,6 +242,11 @@ struct ipoib_cm_dev_priv {
        int                     num_frags;
 };
 
+struct ipoib_ethtool_st {
+       u16     coalesce_usecs;
+       u16     max_coalesced_frames;
+};
+
 /*
  * Device private locking: tx_lock protects members used in TX fast
  * path (and we use LLTX so upper layers don't do extra locking).
@@ -320,6 +325,7 @@ struct ipoib_dev_priv {
        struct dentry *path_dentry;
 #endif
        int     hca_caps;
+       struct ipoib_ethtool_st ethtool;
 };
 
 struct ipoib_ah {
index d46e6b7303b84b529eecb078aad826e7b946daae..9a47428366c91d0f35884ff2cecb0bbf49c41846 100644 (file)
@@ -42,9 +42,55 @@ static void ipoib_get_drvinfo(struct net_device *netdev,
        strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1);
 }
 
+static int ipoib_get_coalesce(struct net_device *dev,
+                             struct ethtool_coalesce *coal)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+
+       coal->rx_coalesce_usecs = priv->ethtool.coalesce_usecs;
+       coal->tx_coalesce_usecs = priv->ethtool.coalesce_usecs;
+       coal->rx_max_coalesced_frames = priv->ethtool.max_coalesced_frames;
+       coal->tx_max_coalesced_frames = priv->ethtool.max_coalesced_frames;
+
+       return 0;
+}
+
+static int ipoib_set_coalesce(struct net_device *dev,
+                             struct ethtool_coalesce *coal)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+       int ret;
+
+       /*
+        * Since IPoIB uses a single CQ for both rx and tx, we assume
+        * that rx params dictate the configuration.  These values are
+        * saved in the private data and returned when ipoib_get_coalesce()
+        * is called.
+        */
+       if (coal->rx_coalesce_usecs       > 0xffff ||
+           coal->rx_max_coalesced_frames > 0xffff)
+               return -EINVAL;
+
+       ret = ib_modify_cq(priv->cq, coal->rx_max_coalesced_frames,
+                          coal->rx_coalesce_usecs);
+       if (ret && ret != -ENOSYS) {
+               ipoib_warn(priv, "failed modifying CQ (%d)\n", ret);
+               return ret;
+       }
+
+       coal->tx_coalesce_usecs       = coal->rx_coalesce_usecs;
+       coal->tx_max_coalesced_frames = coal->rx_max_coalesced_frames;
+       priv->ethtool.coalesce_usecs       = coal->rx_coalesce_usecs;
+       priv->ethtool.max_coalesced_frames = coal->rx_max_coalesced_frames;
+
+       return 0;
+}
+
 static const struct ethtool_ops ipoib_ethtool_ops = {
        .get_drvinfo            = ipoib_get_drvinfo,
        .get_tso                = ethtool_op_get_tso,
+       .get_coalesce           = ipoib_get_coalesce,
+       .set_coalesce           = ipoib_set_coalesce,
 };
 
 void ipoib_set_ethtool_ops(struct net_device *dev)