net: wangxun: add coalesce options support
authorJiawen Wu <jiawenwu@trustnetic.com>
Wed, 3 Jan 2024 02:08:52 +0000 (10:08 +0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 4 Jan 2024 10:49:35 +0000 (10:49 +0000)
Support to show RX/TX coalesce with ethtool -c and set RX/TX
coalesce with ethtool -C.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
drivers/net/ethernet/wangxun/libwx/wx_lib.c
drivers/net/ethernet/wangxun/libwx/wx_lib.h
drivers/net/ethernet/wangxun/libwx/wx_type.h
drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c

index 225ce36586f8aa9e6173ba30a17362b16613aeac..7948d2a3a156f9433d1d99eb796abcf2eb8a985c 100644 (file)
@@ -8,6 +8,7 @@
 #include "wx_type.h"
 #include "wx_ethtool.h"
 #include "wx_hw.h"
+#include "wx_lib.h"
 
 struct wx_stats {
        char stat_string[ETH_GSTRING_LEN];
@@ -247,3 +248,103 @@ void wx_get_ringparam(struct net_device *netdev,
        ring->rx_jumbo_pending = 0;
 }
 EXPORT_SYMBOL(wx_get_ringparam);
+
+int wx_get_coalesce(struct net_device *netdev,
+                   struct ethtool_coalesce *ec,
+                   struct kernel_ethtool_coalesce *kernel_coal,
+                   struct netlink_ext_ack *extack)
+{
+       struct wx *wx = netdev_priv(netdev);
+
+       ec->tx_max_coalesced_frames_irq = wx->tx_work_limit;
+       /* only valid if in constant ITR mode */
+       if (wx->rx_itr_setting <= 1)
+               ec->rx_coalesce_usecs = wx->rx_itr_setting;
+       else
+               ec->rx_coalesce_usecs = wx->rx_itr_setting >> 2;
+
+       /* if in mixed tx/rx queues per vector mode, report only rx settings */
+       if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count)
+               return 0;
+
+       /* only valid if in constant ITR mode */
+       if (wx->tx_itr_setting <= 1)
+               ec->tx_coalesce_usecs = wx->tx_itr_setting;
+       else
+               ec->tx_coalesce_usecs = wx->tx_itr_setting >> 2;
+
+       return 0;
+}
+EXPORT_SYMBOL(wx_get_coalesce);
+
+int wx_set_coalesce(struct net_device *netdev,
+                   struct ethtool_coalesce *ec,
+                   struct kernel_ethtool_coalesce *kernel_coal,
+                   struct netlink_ext_ack *extack)
+{
+       struct wx *wx = netdev_priv(netdev);
+       u16 tx_itr_param, rx_itr_param;
+       struct wx_q_vector *q_vector;
+       u16 max_eitr;
+       int i;
+
+       if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count) {
+               /* reject Tx specific changes in case of mixed RxTx vectors */
+               if (ec->tx_coalesce_usecs)
+                       return -EOPNOTSUPP;
+       }
+
+       if (ec->tx_max_coalesced_frames_irq)
+               wx->tx_work_limit = ec->tx_max_coalesced_frames_irq;
+
+       if (wx->mac.type == wx_mac_sp)
+               max_eitr = WX_SP_MAX_EITR;
+       else
+               max_eitr = WX_EM_MAX_EITR;
+
+       if ((ec->rx_coalesce_usecs > (max_eitr >> 2)) ||
+           (ec->tx_coalesce_usecs > (max_eitr >> 2)))
+               return -EINVAL;
+
+       if (ec->rx_coalesce_usecs > 1)
+               wx->rx_itr_setting = ec->rx_coalesce_usecs << 2;
+       else
+               wx->rx_itr_setting = ec->rx_coalesce_usecs;
+
+       if (wx->rx_itr_setting == 1)
+               rx_itr_param = WX_20K_ITR;
+       else
+               rx_itr_param = wx->rx_itr_setting;
+
+       if (ec->tx_coalesce_usecs > 1)
+               wx->tx_itr_setting = ec->tx_coalesce_usecs << 2;
+       else
+               wx->tx_itr_setting = ec->tx_coalesce_usecs;
+
+       if (wx->tx_itr_setting == 1) {
+               if (wx->mac.type == wx_mac_sp)
+                       tx_itr_param = WX_12K_ITR;
+               else
+                       tx_itr_param = WX_20K_ITR;
+       } else {
+               tx_itr_param = wx->tx_itr_setting;
+       }
+
+       /* mixed Rx/Tx */
+       if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count)
+               wx->tx_itr_setting = wx->rx_itr_setting;
+
+       for (i = 0; i < wx->num_q_vectors; i++) {
+               q_vector = wx->q_vector[i];
+               if (q_vector->tx.count && !q_vector->rx.count)
+                       /* tx only */
+                       q_vector->itr = tx_itr_param;
+               else
+                       /* rx only or mixed */
+                       q_vector->itr = rx_itr_param;
+               wx_write_eitr(q_vector);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(wx_set_coalesce);
index 7651ec4b7dd95559a5f9d2d675da59557510a787..3cd0495a6fbbd63c822a8a68d3cf1920e689775e 100644 (file)
@@ -26,4 +26,12 @@ void wx_get_ringparam(struct net_device *netdev,
                      struct ethtool_ringparam *ring,
                      struct kernel_ethtool_ringparam *kernel_ring,
                      struct netlink_ext_ack *extack);
+int wx_get_coalesce(struct net_device *netdev,
+                   struct ethtool_coalesce *ec,
+                   struct kernel_ethtool_coalesce *kernel_coal,
+                   struct netlink_ext_ack *extack);
+int wx_set_coalesce(struct net_device *netdev,
+                   struct ethtool_coalesce *ec,
+                   struct kernel_ethtool_coalesce *kernel_coal,
+                   struct netlink_ext_ack *extack);
 #endif /* _WX_ETHTOOL_H_ */
index b0b1ac545d5db4d621c4a4af3758f56a7025de82..b738884c901a5d8d21ce216e2857164fab6b5044 100644 (file)
@@ -2082,7 +2082,7 @@ static void wx_set_ivar(struct wx *wx, s8 direction,
  * when it needs to update EITR registers at runtime.  Hardware
  * specific quirks/differences are taken care of here.
  */
-static void wx_write_eitr(struct wx_q_vector *q_vector)
+void wx_write_eitr(struct wx_q_vector *q_vector)
 {
        struct wx *wx = q_vector->wx;
        int v_idx = q_vector->v_idx;
index af1381c13d9ea55c37aa35c0a6a863e72dc969f6..ec909e876720ca05c709ffb59060d3a4e9546426 100644 (file)
@@ -21,6 +21,7 @@ void wx_free_irq(struct wx *wx);
 int wx_setup_isb_resources(struct wx *wx);
 void wx_free_isb_resources(struct wx *wx);
 u32 wx_misc_isb(struct wx *wx, enum wx_isb_idx idx);
+void wx_write_eitr(struct wx_q_vector *q_vector);
 void wx_configure_vectors(struct wx *wx);
 void wx_clean_all_rx_rings(struct wx *wx);
 void wx_clean_all_tx_rings(struct wx *wx);
index 24588bc1eb5770068eebafdf3fa711fabf5df7b8..17cdffe388d063eb9dfcb0589a8465b4d7748f72 100644 (file)
@@ -315,6 +315,7 @@ enum WX_MSCA_CMD_value {
 #define WX_PX_IVAR_ALLOC_VAL         0x80 /* Interrupt Allocation valid */
 #define WX_7K_ITR                    595
 #define WX_12K_ITR                   336
+#define WX_20K_ITR                   200
 #define WX_SP_MAX_EITR               0x00000FF8U
 #define WX_EM_MAX_EITR               0x00007FFCU
 
index 52d4167dcabecf7e8131da72bac66aa111e9bf04..81cb1c23fa845bfef70dcbc0b96ae710611bd818 100644 (file)
@@ -93,6 +93,8 @@ static int ngbe_set_ringparam(struct net_device *netdev,
 }
 
 static const struct ethtool_ops ngbe_ethtool_ops = {
+       .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
+                                    ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ,
        .get_drvinfo            = wx_get_drvinfo,
        .get_link               = ethtool_op_get_link,
        .get_link_ksettings     = wx_get_link_ksettings,
@@ -109,6 +111,8 @@ static const struct ethtool_ops ngbe_ethtool_ops = {
        .set_pauseparam         = wx_set_pauseparam,
        .get_ringparam          = wx_get_ringparam,
        .set_ringparam          = ngbe_set_ringparam,
+       .get_coalesce           = wx_get_coalesce,
+       .set_coalesce           = wx_set_coalesce,
 };
 
 void ngbe_set_ethtool_ops(struct net_device *netdev)
index bd817248a8311c26166458b20c7f2c27c06d8670..9a6856cca4119c7d5bb8840762ad1ebe45ed141b 100644 (file)
@@ -59,6 +59,8 @@ static int txgbe_set_ringparam(struct net_device *netdev,
 }
 
 static const struct ethtool_ops txgbe_ethtool_ops = {
+       .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
+                                    ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ,
        .get_drvinfo            = wx_get_drvinfo,
        .nway_reset             = wx_nway_reset,
        .get_link               = ethtool_op_get_link,
@@ -73,6 +75,8 @@ static const struct ethtool_ops txgbe_ethtool_ops = {
        .set_pauseparam         = wx_set_pauseparam,
        .get_ringparam          = wx_get_ringparam,
        .set_ringparam          = txgbe_set_ringparam,
+       .get_coalesce           = wx_get_coalesce,
+       .set_coalesce           = wx_set_coalesce,
 };
 
 void txgbe_set_ethtool_ops(struct net_device *netdev)