#2 will add DIM for the HNS3 ethernet driver, then there will
be two implemation of IRQ adaptive coalescing (DIM and driver
custiom, so #1 adds a new netlink attribute to the
ETHTOOL_MSG_COALESCE_GET/ETHTOOL_MSG_COALESCE_SET commands
which controls the type of adaptive coalescing.
change log:
V2: fixes some problems in #1 reported by Andrew Lunn & Michal Kubecek.
previous version:
V1: https://patchwork.ozlabs.org/project/netdev/cover/[email protected]/
Huazhong Tan (2):
ethtool: add support for controling the type of adaptive coalescing
net: hns3: add support for dynamic interrupt moderation
Documentation/networking/ethtool-netlink.rst | 1 +
drivers/net/ethernet/hisilicon/Kconfig | 1 +
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 87 +++++++++++++++++++++-
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 4 +
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 25 ++++++-
include/linux/ethtool.h | 14 ++++
include/uapi/linux/ethtool_netlink.h | 1 +
net/ethtool/coalesce.c | 35 ++++++++-
net/ethtool/netlink.h | 2 +-
9 files changed, 165 insertions(+), 5 deletions(-)
--
2.7.4
Add dynamic interrupt moderation support for the HNS3 driver,
and add ethtool support for controlling the type of adaptive.
Signed-off-by: Huazhong Tan <[email protected]>
---
drivers/net/ethernet/hisilicon/Kconfig | 1 +
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 87 +++++++++++++++++++++-
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 4 +
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 25 ++++++-
4 files changed, 115 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig
index 44f9279..fa6025d 100644
--- a/drivers/net/ethernet/hisilicon/Kconfig
+++ b/drivers/net/ethernet/hisilicon/Kconfig
@@ -130,6 +130,7 @@ config HNS3_ENET
default m
depends on 64BIT && PCI
depends on INET
+ select DIMLIB
help
This selects the Ethernet Driver for Hisilicon Network Subsystem 3 for hip08
family of SoCs. This module depends upon HNAE3 driver to access the HNAE3
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 999a2aa..b08aea7 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -96,6 +96,7 @@ static irqreturn_t hns3_irq_handle(int irq, void *vector)
struct hns3_enet_tqp_vector *tqp_vector = vector;
napi_schedule_irqoff(&tqp_vector->napi);
+ tqp_vector->event_cnt++;
return IRQ_HANDLED;
}
@@ -199,6 +200,8 @@ static void hns3_vector_disable(struct hns3_enet_tqp_vector *tqp_vector)
disable_irq(tqp_vector->vector_irq);
napi_disable(&tqp_vector->napi);
+ cancel_work_sync(&tqp_vector->rx_group.dim.work);
+ cancel_work_sync(&tqp_vector->tx_group.dim.work);
}
void hns3_set_vector_coalesce_rl(struct hns3_enet_tqp_vector *tqp_vector,
@@ -3401,6 +3404,32 @@ static void hns3_update_new_int_gl(struct hns3_enet_tqp_vector *tqp_vector)
tqp_vector->last_jiffies = jiffies;
}
+static void hns3_update_rx_int_coalesce(struct hns3_enet_tqp_vector *tqp_vector)
+{
+ struct hns3_enet_ring_group *rx_group = &tqp_vector->rx_group;
+ struct dim_sample sample = {};
+
+ if (!rx_group->coal.adapt_enable)
+ return;
+
+ dim_update_sample(tqp_vector->event_cnt, rx_group->total_packets,
+ rx_group->total_bytes, &sample);
+ net_dim(&rx_group->dim, sample);
+}
+
+static void hns3_update_tx_int_coalesce(struct hns3_enet_tqp_vector *tqp_vector)
+{
+ struct hns3_enet_ring_group *tx_group = &tqp_vector->tx_group;
+ struct dim_sample sample = {};
+
+ if (!tx_group->coal.adapt_enable)
+ return;
+
+ dim_update_sample(tqp_vector->event_cnt, tx_group->total_packets,
+ tx_group->total_bytes, &sample);
+ net_dim(&tx_group->dim, sample);
+}
+
static int hns3_nic_common_poll(struct napi_struct *napi, int budget)
{
struct hns3_nic_priv *priv = netdev_priv(napi->dev);
@@ -3444,7 +3473,13 @@ static int hns3_nic_common_poll(struct napi_struct *napi, int budget)
if (napi_complete(napi) &&
likely(!test_bit(HNS3_NIC_STATE_DOWN, &priv->state))) {
- hns3_update_new_int_gl(tqp_vector);
+ if (priv->dim_enable) {
+ hns3_update_rx_int_coalesce(tqp_vector);
+ hns3_update_tx_int_coalesce(tqp_vector);
+ } else {
+ hns3_update_new_int_gl(tqp_vector);
+ }
+
hns3_mask_vector_irq(tqp_vector, 1);
}
@@ -3575,6 +3610,54 @@ static void hns3_nic_set_cpumask(struct hns3_nic_priv *priv)
}
}
+static void hns3_rx_dim_work(struct work_struct *work)
+{
+ struct dim *dim = container_of(work, struct dim, work);
+ struct hns3_enet_ring_group *group = container_of(dim,
+ struct hns3_enet_ring_group, dim);
+ struct hns3_enet_tqp_vector *tqp_vector = group->ring->tqp_vector;
+ struct dim_cq_moder cur_moder =
+ net_dim_get_rx_moderation(dim->mode, dim->profile_ix);
+
+ hns3_set_vector_coalesce_rx_gl(group->ring->tqp_vector, cur_moder.usec);
+ tqp_vector->rx_group.coal.int_gl = cur_moder.usec;
+
+ if (cur_moder.pkts < tqp_vector->rx_group.coal.int_ql_max) {
+ hns3_set_vector_coalesce_rx_ql(tqp_vector, cur_moder.pkts);
+ tqp_vector->rx_group.coal.int_ql = cur_moder.pkts;
+ }
+
+ dim->state = DIM_START_MEASURE;
+}
+
+static void hns3_tx_dim_work(struct work_struct *work)
+{
+ struct dim *dim = container_of(work, struct dim, work);
+ struct hns3_enet_ring_group *group = container_of(dim,
+ struct hns3_enet_ring_group, dim);
+ struct hns3_enet_tqp_vector *tqp_vector = group->ring->tqp_vector;
+ struct dim_cq_moder cur_moder =
+ net_dim_get_tx_moderation(dim->mode, dim->profile_ix);
+
+ hns3_set_vector_coalesce_tx_gl(tqp_vector, cur_moder.usec);
+ tqp_vector->tx_group.coal.int_gl = cur_moder.usec;
+
+ if (cur_moder.pkts < tqp_vector->tx_group.coal.int_ql_max) {
+ hns3_set_vector_coalesce_tx_ql(tqp_vector, cur_moder.pkts);
+ tqp_vector->tx_group.coal.int_ql = cur_moder.pkts;
+ }
+
+ dim->state = DIM_START_MEASURE;
+}
+
+static void hns3_nic_init_dim(struct hns3_enet_tqp_vector *tqp_vector)
+{
+ INIT_WORK(&tqp_vector->rx_group.dim.work, hns3_rx_dim_work);
+ tqp_vector->rx_group.dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
+ INIT_WORK(&tqp_vector->tx_group.dim.work, hns3_tx_dim_work);
+ tqp_vector->tx_group.dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
+}
+
static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv)
{
struct hnae3_ring_chain_node vector_ring_chain;
@@ -3589,6 +3672,7 @@ static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv)
tqp_vector = &priv->tqp_vector[i];
hns3_vector_coalesce_init_hw(tqp_vector, priv);
tqp_vector->num_tqps = 0;
+ hns3_nic_init_dim(tqp_vector);
}
for (i = 0; i < h->kinfo.num_tqps; i++) {
@@ -4161,6 +4245,7 @@ static int hns3_client_init(struct hnae3_handle *handle)
netdev->max_mtu = HNS3_MAX_MTU;
set_bit(HNS3_NIC_STATE_INITED, &priv->state);
+ priv->dim_enable = 1;
if (netif_msg_drv(handle))
hns3_info_show(priv);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
index 8d33652..4af11aa 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
@@ -4,6 +4,7 @@
#ifndef __HNS3_ENET_H
#define __HNS3_ENET_H
+#include <linux/dim.h>
#include <linux/if_vlan.h>
#include "hnae3.h"
@@ -449,6 +450,7 @@ struct hns3_enet_ring_group {
u64 total_packets; /* total packets processed this group */
u16 count;
struct hns3_enet_coalesce coal;
+ struct dim dim;
};
struct hns3_enet_tqp_vector {
@@ -471,6 +473,7 @@ struct hns3_enet_tqp_vector {
char name[HNAE3_INT_NAME_LEN];
unsigned long last_jiffies;
+ u64 event_cnt;
} ____cacheline_internodealigned_in_smp;
struct hns3_nic_priv {
@@ -486,6 +489,7 @@ struct hns3_nic_priv {
struct hns3_enet_tqp_vector *tqp_vector;
u16 vector_num;
u8 max_non_tso_bd_num;
+ u8 dim_enable:1;
u64 tx_timeout_count;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index c30d5d3..5cad027 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -1127,6 +1127,16 @@ static int hns3_get_coalesce(struct net_device *netdev,
return hns3_get_coalesce_per_queue(netdev, 0, cmd);
}
+static int hns3_get_ext_coalesce(struct net_device *netdev,
+ struct ethtool_ext_coalesce *cmd)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+
+ cmd->use_dim = priv->dim_enable;
+
+ return 0;
+}
+
static int hns3_check_gl_coalesce_para(struct net_device *netdev,
struct ethtool_coalesce *cmd)
{
@@ -1319,6 +1329,16 @@ static int hns3_set_coalesce(struct net_device *netdev,
return 0;
}
+static int hns3_set_ext_coalesce(struct net_device *netdev,
+ struct ethtool_ext_coalesce *cmd)
+{
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
+
+ priv->dim_enable = cmd->use_dim;
+
+ return 0;
+}
+
static int hns3_get_regs_len(struct net_device *netdev)
{
struct hnae3_handle *h = hns3_get_handle(netdev);
@@ -1520,7 +1540,8 @@ static int hns3_get_module_eeprom(struct net_device *netdev,
ETHTOOL_COALESCE_USE_ADAPTIVE | \
ETHTOOL_COALESCE_RX_USECS_HIGH | \
ETHTOOL_COALESCE_TX_USECS_HIGH | \
- ETHTOOL_COALESCE_MAX_FRAMES)
+ ETHTOOL_COALESCE_MAX_FRAMES | \
+ ETHTOOL_COALESCE_USE_DIM)
static const struct ethtool_ops hns3vf_ethtool_ops = {
.supported_coalesce_params = HNS3_ETHTOOL_COALESCE,
@@ -1572,7 +1593,9 @@ static const struct ethtool_ops hns3_ethtool_ops = {
.get_channels = hns3_get_channels,
.set_channels = hns3_set_channels,
.get_coalesce = hns3_get_coalesce,
+ .get_ext_coalesce = hns3_get_ext_coalesce,
.set_coalesce = hns3_set_coalesce,
+ .set_ext_coalesce = hns3_set_ext_coalesce,
.get_regs_len = hns3_get_regs_len,
.get_regs = hns3_get_regs,
.set_phys_id = hns3_set_phys_id,
--
2.7.4
Since the information whether the adaptive behavior is implemented
by DIM or driver custom is useful, so add new attribute to
ETHTOOL_MSG_COALESCE_GET/ETHTOOL_MSG_COALESCE_SET commands to control
the type of adaptive coalescing.
In order to compatible with ioctl code, add a extended coalescing
handler to deal with it in the netlink API, then other new extended
coalescing parameters can utiliaze it as well.
Suggested-by: Jakub Kicinski <[email protected]>
Signed-off-by: Huazhong Tan <[email protected]>
---
Documentation/networking/ethtool-netlink.rst | 1 +
include/linux/ethtool.h | 14 +++++++++++
include/uapi/linux/ethtool_netlink.h | 1 +
net/ethtool/coalesce.c | 35 ++++++++++++++++++++++++++--
net/ethtool/netlink.h | 2 +-
5 files changed, 50 insertions(+), 3 deletions(-)
diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst
index 30b9824..dae7145 100644
--- a/Documentation/networking/ethtool-netlink.rst
+++ b/Documentation/networking/ethtool-netlink.rst
@@ -928,6 +928,7 @@ Kernel response contents:
``ETHTOOL_A_COALESCE_TX_USECS_HIGH`` u32 delay (us), high Tx
``ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH`` u32 max packets, high Tx
``ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL`` u32 rate sampling interval
+ ``ETHTOOL_A_COALESCE_USE_DIM`` bool using DIM adaptive
=========================================== ====== =======================
Attributes are only included in reply if their value is not zero or the
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 6408b44..4426d65 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -215,6 +215,7 @@ bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32,
#define ETHTOOL_COALESCE_TX_USECS_HIGH BIT(19)
#define ETHTOOL_COALESCE_TX_MAX_FRAMES_HIGH BIT(20)
#define ETHTOOL_COALESCE_RATE_SAMPLE_INTERVAL BIT(21)
+#define ETHTOOL_COALESCE_USE_DIM BIT(22)
#define ETHTOOL_COALESCE_USECS \
(ETHTOOL_COALESCE_RX_USECS | ETHTOOL_COALESCE_TX_USECS)
@@ -241,6 +242,10 @@ bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32,
ETHTOOL_COALESCE_PKT_RATE_LOW | ETHTOOL_COALESCE_PKT_RATE_HIGH | \
ETHTOOL_COALESCE_RATE_SAMPLE_INTERVAL)
+struct ethtool_ext_coalesce {
+ __u32 use_dim;
+};
+
#define ETHTOOL_STAT_NOT_SET (~0ULL)
/**
@@ -298,9 +303,14 @@ struct ethtool_pause_stats {
* or zero.
* @get_coalesce: Get interrupt coalescing parameters. Returns a negative
* error code or zero.
+ * @get_ext_coalesce: Get extended interrupt coalescing parameters.
+ * Returns a negative error code or zero.
* @set_coalesce: Set interrupt coalescing parameters. Supported coalescing
* types should be set in @supported_coalesce_params.
* Returns a negative error code or zero.
+ * @set_ext_coalesce: Set extended interrupt coalescing parameters. Supported
+ * extended coalescing types should be set in @supported_coalesce_params.
+ * Returns a negative error code or zero.
* @get_ringparam: Report ring sizes
* @set_ringparam: Set ring sizes. Returns a negative error code or zero.
* @get_pause_stats: Report pause frame statistics. Drivers must not zero
@@ -437,7 +447,11 @@ struct ethtool_ops {
int (*set_eeprom)(struct net_device *,
struct ethtool_eeprom *, u8 *);
int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *);
+ int (*get_ext_coalesce)(struct net_device *,
+ struct ethtool_ext_coalesce *);
int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *);
+ int (*set_ext_coalesce)(struct net_device *,
+ struct ethtool_ext_coalesce *);
void (*get_ringparam)(struct net_device *,
struct ethtool_ringparam *);
int (*set_ringparam)(struct net_device *,
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index e2bf36e..e3458d9 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -366,6 +366,7 @@ enum {
ETHTOOL_A_COALESCE_TX_USECS_HIGH, /* u32 */
ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH, /* u32 */
ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL, /* u32 */
+ ETHTOOL_A_COALESCE_USE_DIM, /* u8 */
/* add new constants above here */
__ETHTOOL_A_COALESCE_CNT,
diff --git a/net/ethtool/coalesce.c b/net/ethtool/coalesce.c
index 1d6bc13..d4d8901 100644
--- a/net/ethtool/coalesce.c
+++ b/net/ethtool/coalesce.c
@@ -11,6 +11,7 @@ struct coalesce_reply_data {
struct ethnl_reply_data base;
struct ethtool_coalesce coalesce;
u32 supported_params;
+ struct ethtool_ext_coalesce ext_coalesce;
};
#define COALESCE_REPDATA(__reply_base) \
@@ -50,6 +51,7 @@ __CHECK_SUPPORTED_OFFSET(COALESCE_RX_MAX_FRAMES_HIGH);
__CHECK_SUPPORTED_OFFSET(COALESCE_TX_USECS_HIGH);
__CHECK_SUPPORTED_OFFSET(COALESCE_TX_MAX_FRAMES_HIGH);
__CHECK_SUPPORTED_OFFSET(COALESCE_RATE_SAMPLE_INTERVAL);
+__CHECK_SUPPORTED_OFFSET(COALESCE_USE_DIM);
const struct nla_policy ethnl_coalesce_get_policy[] = {
[ETHTOOL_A_COALESCE_HEADER] =
@@ -71,6 +73,14 @@ static int coalesce_prepare_data(const struct ethnl_req_info *req_base,
if (ret < 0)
return ret;
ret = dev->ethtool_ops->get_coalesce(dev, &data->coalesce);
+
+ if (dev->ethtool_ops->get_ext_coalesce) {
+ ret = dev->ethtool_ops->get_ext_coalesce(dev,
+ &data->ext_coalesce);
+ if (ret < 0)
+ return ret;
+ }
+
ethnl_ops_complete(dev);
return ret;
@@ -100,7 +110,8 @@ static int coalesce_reply_size(const struct ethnl_req_info *req_base,
nla_total_size(sizeof(u32)) + /* _RX_MAX_FRAMES_HIGH */
nla_total_size(sizeof(u32)) + /* _TX_USECS_HIGH */
nla_total_size(sizeof(u32)) + /* _TX_MAX_FRAMES_HIGH */
- nla_total_size(sizeof(u32)); /* _RATE_SAMPLE_INTERVAL */
+ nla_total_size(sizeof(u32)) + /* _RATE_SAMPLE_INTERVAL */
+ nla_total_size(sizeof(u8)); /* _USE_DIM */
}
static bool coalesce_put_u32(struct sk_buff *skb, u16 attr_type, u32 val,
@@ -124,6 +135,7 @@ static int coalesce_fill_reply(struct sk_buff *skb,
const struct ethnl_reply_data *reply_base)
{
const struct coalesce_reply_data *data = COALESCE_REPDATA(reply_base);
+ const struct ethtool_ext_coalesce *ext_coal = &data->ext_coalesce;
const struct ethtool_coalesce *coal = &data->coalesce;
u32 supported = data->supported_params;
@@ -170,7 +182,9 @@ static int coalesce_fill_reply(struct sk_buff *skb,
coalesce_put_u32(skb, ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH,
coal->tx_max_coalesced_frames_high, supported) ||
coalesce_put_u32(skb, ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL,
- coal->rate_sample_interval, supported))
+ coal->rate_sample_interval, supported) ||
+ coalesce_put_bool(skb, ETHTOOL_A_COALESCE_USE_DIM,
+ ext_coal->use_dim, supported))
return -EMSGSIZE;
return 0;
@@ -215,10 +229,12 @@ const struct nla_policy ethnl_coalesce_set_policy[] = {
[ETHTOOL_A_COALESCE_TX_USECS_HIGH] = { .type = NLA_U32 },
[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH] = { .type = NLA_U32 },
[ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL] = { .type = NLA_U32 },
+ [ETHTOOL_A_COALESCE_USE_DIM] = { .type = NLA_U8 },
};
int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info)
{
+ struct ethtool_ext_coalesce ext_coalesce = {};
struct ethtool_coalesce coalesce = {};
struct ethnl_req_info req_info = {};
struct nlattr **tb = info->attrs;
@@ -259,6 +275,12 @@ int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info)
if (ret < 0)
goto out_ops;
+ if (ops->get_ext_coalesce) {
+ ret = ops->get_ext_coalesce(dev, &ext_coalesce);
+ if (ret < 0)
+ goto out_ops;
+ }
+
ethnl_update_u32(&coalesce.rx_coalesce_usecs,
tb[ETHTOOL_A_COALESCE_RX_USECS], &mod);
ethnl_update_u32(&coalesce.rx_max_coalesced_frames,
@@ -303,6 +325,8 @@ int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info)
tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH], &mod);
ethnl_update_u32(&coalesce.rate_sample_interval,
tb[ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL], &mod);
+ ethnl_update_bool32(&ext_coalesce.use_dim,
+ tb[ETHTOOL_A_COALESCE_USE_DIM], &mod);
ret = 0;
if (!mod)
goto out_ops;
@@ -310,6 +334,13 @@ int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info)
ret = dev->ethtool_ops->set_coalesce(dev, &coalesce);
if (ret < 0)
goto out_ops;
+
+ if (ops->set_ext_coalesce) {
+ ret = ops->set_ext_coalesce(dev, &ext_coalesce);
+ if (ret < 0)
+ goto out_ops;
+ }
+
ethtool_notify(dev, ETHTOOL_MSG_COALESCE_NTF, NULL);
out_ops:
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index d8efec5..e63f44a 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -366,7 +366,7 @@ extern const struct nla_policy ethnl_rings_set_policy[ETHTOOL_A_RINGS_TX + 1];
extern const struct nla_policy ethnl_channels_get_policy[ETHTOOL_A_CHANNELS_HEADER + 1];
extern const struct nla_policy ethnl_channels_set_policy[ETHTOOL_A_CHANNELS_COMBINED_COUNT + 1];
extern const struct nla_policy ethnl_coalesce_get_policy[ETHTOOL_A_COALESCE_HEADER + 1];
-extern const struct nla_policy ethnl_coalesce_set_policy[ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL + 1];
+extern const struct nla_policy ethnl_coalesce_set_policy[ETHTOOL_A_COALESCE_USE_DIM + 1];
extern const struct nla_policy ethnl_pause_get_policy[ETHTOOL_A_PAUSE_HEADER + 1];
extern const struct nla_policy ethnl_pause_set_policy[ETHTOOL_A_PAUSE_TX + 1];
extern const struct nla_policy ethnl_eee_get_policy[ETHTOOL_A_EEE_HEADER + 1];
--
2.7.4
> @@ -310,6 +334,13 @@ int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info)
> ret = dev->ethtool_ops->set_coalesce(dev, &coalesce);
> if (ret < 0)
> goto out_ops;
> +
> + if (ops->set_ext_coalesce) {
> + ret = ops->set_ext_coalesce(dev, &ext_coalesce);
> + if (ret < 0)
> + goto out_ops;
> + }
> +
The problem here is, if ops->set_ext_coalesce() fails, you need to
undo what dev->ethtool_ops->set_coalesce() did. From the users
perspective, this should be atomic. It does everything, or it does
nothing and returns an error code.
And that is not easy given this structure of two op calls.
Andrew
On Fri, 20 Nov 2020 14:24:38 +0800 Huazhong Tan wrote:
> + ``ETHTOOL_A_COALESCE_USE_DIM`` bool using DIM adaptive
Sorry, I didn't get into the discussion on v1 in time.
I'd prefer this to be an enum (u8 or u32) the values can already be:
- device (HW / FW)
- driver specific
- DIM
On 2020/11/20 23:25, Andrew Lunn wrote:
>> @@ -310,6 +334,13 @@ int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info)
>> ret = dev->ethtool_ops->set_coalesce(dev, &coalesce);
>> if (ret < 0)
>> goto out_ops;
>> +
>> + if (ops->set_ext_coalesce) {
>> + ret = ops->set_ext_coalesce(dev, &ext_coalesce);
>> + if (ret < 0)
>> + goto out_ops;
>> + }
>> +
>
> The problem here is, if ops->set_ext_coalesce() fails, you need to
> undo what dev->ethtool_ops->set_coalesce() did. From the users
> perspective, this should be atomic. It does everything, or it does
> nothing and returns an error code.
>
> And that is not easy given this structure of two op calls.
>
> Andrew
>
yes, i will try what Michal suggested in V1.
Regards.
Huazhong.
> .
>